 |
Das deutsche QBasic- und FreeBASIC-Forum Für euch erreichbar unter qb-forum.de, fb-forum.de und freebasic-forum.de!
|
Vorheriges Thema anzeigen :: Nächstes Thema anzeigen |
Autor |
Nachricht |
Matrix

Anmeldungsdatum: 28.06.2011 Beiträge: 10
|
Verfasst am: 28.06.2011, 20:05 Titel: IF Schleifen in einem Interpreter |
|
|
Hallo,
als ich gestern mit FreeBasic angefangen habe, habe ich mir u.a. dem Beispielcode des 4 Befehl Interpreters Runtergeladen und mich dazu entschlossen diesen weiterzuentwickeln bis ich in FreeBasic Flüssig genug bin um evtl. darauf umzusteigen. Ziemlich schnell hab ich mir jedoch die Frage gestellt wie ich die IF Schleifen am besten umsetze, daher meine Frage an euch:
Hat jemand sowas schonmal verwirklicht, und wenn ja wer kann und will mir dabei nen bisschen auf die Sprünge helfen? _________________ "Die Gefahr, dass der Computer so wird wie der Mensch ist nicht so groß, wie die Gefahr, dass der Mensch so wird wie der Computer." - Konrad Zuse |
|
Nach oben |
|
 |
MOD Fleißiger Referenzredakteur

Anmeldungsdatum: 10.09.2007 Beiträge: 1003
|
Verfasst am: 28.06.2011, 20:18 Titel: |
|
|
Falls du dich auf diesen Code beziehst, dabei handelt es sich nicht wirklich um einen Interpreter, sondern viel mehr um ein Beispiel für Stringmanipulation.
Ein echter Interpreter ist keine leichte Aufgabe und eignet sich kaum als Projekt für einen Anfänger. Dazu müsstest du erstmal einen Parser/Lexer programmieren, um Codezeilen ordnungsgemäß zu analysieren und das war noch lange nicht alles.
Besser wäre es wohl ein Hangmanspiel, ein 4-gewinnt oder ähnliches zu erstellen. |
|
Nach oben |
|
 |
Matrix

Anmeldungsdatum: 28.06.2011 Beiträge: 10
|
Verfasst am: 28.06.2011, 20:32 Titel: |
|
|
Den habe ich gemeint, ich bin ja auch kein Programmieränfänger, und da es sich dabei nur um einen Semi Interpreter handelt werde ich immer wieder auf Probleme stoßen, nur mir steht in meiner bevorzugten Programmiersprache keine Konsole zur Verfügung (warte auf das Update und das kann noch dauern...). Daher wollte ich MIR einen kleinen "Interpreter" schreiben um mir die Konsole zur Verfügung zu stellen. Hab zwar auch ne Dll die das könnte, aber leider hängts da an der Dll Schnittstelle...  _________________ "Die Gefahr, dass der Computer so wird wie der Mensch ist nicht so groß, wie die Gefahr, dass der Mensch so wird wie der Computer." - Konrad Zuse |
|
Nach oben |
|
 |
nemored

Anmeldungsdatum: 22.02.2007 Beiträge: 4704 Wohnort: ~/
|
Verfasst am: 28.06.2011, 20:43 Titel: |
|
|
Es gab da mal einen QB-/FB-Wettbewerb zum Thema Interpreter. Wenn ich mich nicht ganz täusche, ist in mindestens einem eine Bedingungsabhandlung dabei:
http://www.qb-wettbewerb.de/index.php?c=showaufg&id=2 _________________ Deine Chance beträgt 1:1000. Also musst du folgendes tun: Vergiss die 1000 und konzentriere dich auf die 1. |
|
Nach oben |
|
 |
MOD Fleißiger Referenzredakteur

Anmeldungsdatum: 10.09.2007 Beiträge: 1003
|
Verfasst am: 28.06.2011, 20:44 Titel: |
|
|
Wenn du das mit Stringmanipulation lösen, empfehle ich hier die zwei Tutorials zu dem Thema im Portal.
Für das IF-Problem könntest ab dem 'IF' bis zum Auftauchen des 'THEN' den Text herausnehmen, mit TRIM die Leerzeichen abtrennen und dann mittels INSTR den Vergleichsoperator heraussuchen. Links und rechts davon hast du deine Vergleichswerte die du nun einfach vergleichen kannst.
Bei TRUE springst du direkt in die nächste Zeile, ansonsten suchst du nach dem nächsten 'ELSE', 'ELSEIF' oder 'ENDIF'.
Wie gesagt, dieses Verfahren ist alles andere als schön und ist auch bestimmt fehleranfällig, aber sei's drum, der Zweck heiligt die Mittel.  |
|
Nach oben |
|
 |
Matrix

Anmeldungsdatum: 28.06.2011 Beiträge: 10
|
Verfasst am: 28.06.2011, 20:51 Titel: |
|
|
Dann erstmal Danke für die schnelle Hilfe, und ich werd mich heut abend mal da durchforsten, die Interpreter sehen Interressant aus, aber die Version mit dem Then wird´s wohl eher werden... Ich meld mich... _________________ "Die Gefahr, dass der Computer so wird wie der Mensch ist nicht so groß, wie die Gefahr, dass der Mensch so wird wie der Computer." - Konrad Zuse |
|
Nach oben |
|
 |
ThePuppetMaster

Anmeldungsdatum: 18.02.2007 Beiträge: 1839 Wohnort: [JN58JR]
|
Verfasst am: 28.06.2011, 21:22 Titel: |
|
|
ganz so einfach ist das dann doch nicht mit dem suchen nach dem nächsten if - elseif.
du solltest dir ersteinmal gedanken darüber machen, wie weit dein interpreter gehen soll.
du könntest einen einfachen interpreter konstuieren, der schnell ist, aber diverse einschränkungen hat, allerdings leicht für dich zu programmieren ist. So kannst du dann z.B. auf die Hirarische suche nach IF Strukturen (do loop, for next, usw.) verzichten. Der vorteil liegt hier in der einfachen suche nach dem elseif endif usw. du kannst ebenfalls gotos sehr einfach realisieren ohne durch scopes in probleme zu geraten.
hierbei darfst du dann z.B. keine 2te if in eien bestehende einfügen. das erleichtert den parsing und interpretieungsaufwand enorm!!!
die alternative hierzu ist dann schon [u]weitaus[u] komplexer. Der halbwegs vernümpftige interpreter.
bei diesem musst du scopes beachten. Das heist, du kannt nicht einfach nach dem nächsten if - elseif (do, loop, next usw.) suchen, sondern musst Datenbereiche realisieren.
als beispiel:
du schreibst einen einfachen code wie diesen hier:
Code: |
dim a as integer
dim x as integer
for x = 1 to 10
if a = x then
print "ok"
else
dim y as integer
y = x - a
if y = 5 then
print "nop"
end if
end if
next
print a
print x
print y
|
hier hast du einen scope mit "dim y as integer"
diese Variable besteht ausschliesslich wärend die For-next schleife arbeitet. Im letzten print y ist diese variable nicht länger vorhanden und muss folglich nach dem "end if" zerstört werden.
eine leichte umsetzung derartiger strukturen kann man mit rekursiver funktionsaufrufe realisieren.
du beginnst strukturiert den quellcode ersteinmal in ein array (linkedList) einzulesen.
Es hat sich als sehr hilfreich erwiesen, gleich beim einlesen die Zeilen zu unteruschen und auf spezielle statements zu achten wie z.B. dem ":"
Code: |
dim a as string: s = "abc"
|
wenn du diese zeile einliest, solltest du sie schon in 2 seperate einträge im array hinterlegen.
Code: |
dim a as string
s = abc"
|
vorteilhafter ist hier übrigens die verwednugn einer typenstruktur für jeden array-eintrage (besser linkedList), in welcher du nicth nur die code-zeile speicherst, sondern auch die vortlaufende zeilennummer um beim debugging einen ansatzpunkt zu haben.
auserdem wäre es sinvoll das "_" auszuwerten (mehrzeilige anweisungen)
REM's (') bzw. "/'" für mehrzeilige kommentare (wenn es FreeBasic like sein soll)
der nächste schritt sieht vor dieses array von der ersten zeile aus abzuarbeiten.
hierbei ruft man die rekursive verarbeitungssub (funktion) auf.
diese Liest die aktuelle zeile ein, analysiert diese und führt die aufgabe aus.
beim eintreten eines if, do, for, usw. rufst du erneut die rekursive funktion auf. hiermit hast du einen scope auf einfache weise realisiert.
in dieser rekursiven sub devinierst du anschliessend array's oder LinkedLists (besser) um Lokale "scope" Variablen hinterlegen zu können. (ist hilfreich, wenn du dir funktionen scheibst, die variablenerstellung, benennung, und die datenspeicherung übernehmen)
zusätzlich übergibst du der aufrufenden sub einmal die globale variablenliste (shared) udn die variablenliste des verherigem scope's. Diese vorherigen variablen musst du anschliessend in deine eigene scope-variablenliste kopieren und markieren diese beim verlassen der sub nicht zu löschen. da du sonst scopeübergreifende variablen löschst, und das is nicht gut
um nun im speziellen IF zu realisieren ist es sinvoll, vor dem erneutem rekrusiven aufruf nach dem nächsten ElseIf, else oder endif in der gleichen ebene in der hirarischen struktur zu suchen. (hier könnte man einen baumstruktur für eine linkedlist einsetzen, wenn der quellcode nicht zu gross wird, ist aber nicht ratsam, da es zu pointerfehler kommen könnte und die abarbeitung sehr kompliziert werden kann).
wen du diese punkte gefunden hast, speicherst du sie zwischen und rufst die rekursion auf.
wird diese durchlaufen udn beendet, kommst du folglich zurück und kannst nun die bedingung der rückgabe der rekursion auswerten. Je nach ergebniss springst du dann entweder IN den Codeteil (ebenfalls via rekursivem aufruf) oder springst zum nächsten eintrage (elseif, else, endif). wenn die bedinung erfüllt war und der rekursive aufruf ebenfalls zurück kommt, dann entsprechend zum endif.
das mal als keine strukturierungshilfe.
MfG
TPM _________________ [ WebFBC ][ OPS ][ ToOFlo ][ Wiemann.TV ] |
|
Nach oben |
|
 |
XOR
Anmeldungsdatum: 23.07.2010 Beiträge: 161
|
Verfasst am: 28.06.2011, 22:23 Titel: |
|
|
ich hatte leztlich mal nen interpreter zusammengebastelt.
fuer das speichern der variablen und functionen habe ich einen tabellentype benutzt. variablen muessen nicht definiert werden und sind so lange forhanden bis die function fertig ist. man kann variablen zahlen oder strings zuweisen. und es gibt keine fehlerabfrage.
da ich mich an C syntaxen orintiert habe weiss man immer sehr einfach wann ein block anfaengt { oder aufhoert }.
beim laden des scripttextes hatte ich den dann unterschiedlich behandelt:
auf unterster ebene:
> ist in der zeile ein = hat man eine globale variable mit dem wert rechts
> hat man kein = hat man eine function.
auf zweiter und hoeheren ebenen:
> zeile wird in meinen zeilentype eingefuegt.
> kommt eine { dann ist der string ein leerstring und es wird ein zeiger auf den hoeheren block abgelegt.
> kommt ein } dann ist der block beendet und man geht eine hohe runter.
beim interpretieren hatte ich es mit den ifs so gemacht:
ich habe mir die zuweisungsvariable vom letzten befehl gemerkt. kommt nun ein leerstring was bedeuter das man einen block hat schaue ich ob die letzte zuweisung true war, wenn ja gehe ich in den block wenn nicht nicht.
wenn man also nur
var=1;
{
...
schreiben wuerde wuerde man in den block kommen.
die function if gibt als -1 bei wahr zurueck und 0 bei falsch. ausserdem gibt sie dem LastIfFailed dann noch -1 bei 0 oder 0 bei -1.
das nachste elseif schaut sich dann das LastIfFailed an und gibt dann entsprechend -1 oder 0 zurueck. ferlaesst man einen block wird LastIfFailed = 0.
es wahr nur eine einfache scriptsprache aber bei groesseren habe ich einfach immer sehr grosse probleme bekommen.
wenn du dich interresierst hier die links:
Tabelle.bi
Script.bi
so gut wie TPM habe ich das jetzt natuerlich nicht erklearen koennen aber noch schell ein beispiel:
Code: | Facultaet(i)
{
if(i<=1)
{
return = 1;
}
else
{
return = Facultaet(i-1)*i;
}
}
WriteZahlen(l,h)
{
for(i=l,i>h,i=i+1)
{
write(i);
}
}
start(n)
{
screen(800,600,n);
} |
Code: | #Define BR Chr(13,10)
#Include "Script.bi"
Dim S As SCRIPT
Sub Script_Write ( ByVal In As SCRIPT_VARIANT )
Print "write: "+In
End Sub
Sub Script_Screen ( ByVal In1 As SCRIPT_VARIANT, ByVal In2 As SCRIPT_VARIANT, ByVal In3 As SCRIPT_VARIANT )
ScreenRes In1, In2, 32
WindowTitle In3
End Sub
S.Create()
S.Register ( "write" , 1 , 0 , @Script_Write )
S.Register ( "screen" , 3 , 0 , @Script_Screen )
S.CompileFromFile ( "Script.txt" )
S.CallSub ( "Start","%s","WindowXXX" )
Print S.CallFunc ( "Facultaet","%i",4 )
S.CallSub ( "WriteZahlen","%i %i",4,10 )
Print S.GetErrors()
S.Destroy ()
Sleep
|
fuer groessere scriptsprachen wuerde ich fuer den globalen speicher auf tabellen setzen, da man dann z.b. sagen kann Tabelle.Item(Name+".type") = "var"
Tabelle.Item(Name+".struct") = "string"
Tabelle.Item(Name+".val") = "was weiss ich" |
|
Nach oben |
|
 |
Matrix

Anmeldungsdatum: 28.06.2011 Beiträge: 10
|
Verfasst am: 29.06.2011, 17:46 Titel: |
|
|
Hab jetzt mal nen bisschen rumgebastelt, aber wirklich was dabei rausgekommen ist nichts... Selbst ein simples "If A = B then Befehl" krieg ich nicht hin... Kann mir jemand helfen wie ich zumindest so nen "billigen" if befehl hinkriege?
Bin dafür wirklich zu neu in FB, ich komm mit der bezeichnung/verwendung von den Variablen nicht zurecht. Keine "" oder '' oder §§ oder $$ oder [] oder () noch sonstwas. Was spätestens zu richtigen Problemen führt wenn ich die Variablen einprogrammieren will, aber da lass ich mir noch nen paar tage Zeit...
Der Interpreter soll eigentlich nur Text Ein und Ausgeben, verarbeiten (egal wie) und die möglichkeit haben über eine umgebungsvariable mit andren programmen/meinen programmen zu kommunzieren. was ganz simples (brauch kein elseif und auch keine Datentypen bei variablen - obwohl FB mich wohl dazu zwingen wird...), hauptsache ich kann die konsole nutzen, ausbauen kann man immer noch nen bisschen...net viel... _________________ "Die Gefahr, dass der Computer so wird wie der Mensch ist nicht so groß, wie die Gefahr, dass der Mensch so wird wie der Computer." - Konrad Zuse |
|
Nach oben |
|
 |
MOD Fleißiger Referenzredakteur

Anmeldungsdatum: 10.09.2007 Beiträge: 1003
|
Verfasst am: 29.06.2011, 18:33 Titel: |
|
|
Ein simples If mit A = A da ohne Variablen A niemals gleich B ist:
Code: | Sub durchlaufen(zeile() As String, ByRef i As Integer)
If UCase(Left(Trim(zeile(i)), 2)) = "IF" Then
Dim As Integer thenFund = InStr(UCase(Trim(zeile(i))), "THEN")
If thenFund = 0 Then
Print "Syntaxfehler: IF ohne THEN"
Else
Dim As String mittelTeil = Trim(Mid(Trim(zeile(i)), 3, thenFund - 3))
Dim As String links, rechts
If InStr(mittelTeil, "=") Then
links = Trim(Left(mittelTeil, InStr(mittelTeil, "=") - 1))
rechts = Trim(Right(mittelTeil, Len(mittelTeil) - InStr(mittelTeil, "=")))
If links <> rechts Then
Do While UCase(zeile(i)) <> "ENDIF" And i <= UBound(zeile)
i += 1
Loop
Else
If i < UBound(zeile) Then
i += 1
durchlaufen(zeile(), i)
EndIf
EndIf
EndIf
EndIf
ElseIf UCase(Left(Trim(zeile(i)), 5)) = "PRINT" Then
Print Trim(Trim(Right(Trim(zeile(i)), Len(Trim(zeile(i))) - 5)), """")
EndIf
End Sub
Dim As String zeile(1 To 3)
zeile(1) = "If A = A then"
zeile(2) = " Print ""A ist A"""
zeile(3) = "EndIf"
For i As Integer = LBound(zeile) To UBound(zeile)
durchlaufen(zeile(), i)
Next
Print "Ende"
Sleep |
Sehr ekliger Code aber gut, wenn du es unbedingt so haben willst.
Viel interessanter wäre, was du für Probleme mit der Syntax hast. Für solche Probleme gibt es die Befehlsreferenz. Dort kann man alles nachsehen. die verlinkten Tutorials vom letzten Mal sollten ihr übriges tun. |
|
Nach oben |
|
 |
Lutz Ifer Grillmeister

Anmeldungsdatum: 23.09.2005 Beiträge: 555
|
Verfasst am: 29.06.2011, 19:30 Titel: |
|
|
Bau Dir nen Parser und nen Lexer und mach' 'nen AST draus.
http://llvm.org/docs/tutorial/ <- nur ohne llvm-Backend, sondern direkt ausführen. _________________ Wahnsinn ist nur die Antwort einer gesunden Psyche auf eine kranke Gesellschaft. |
|
Nach oben |
|
 |
Matrix

Anmeldungsdatum: 28.06.2011 Beiträge: 10
|
Verfasst am: 29.06.2011, 20:20 Titel: |
|
|
Nen Parser und nen Lexer ist wohl dann eher das übernächste Projekt mit FB, aber danke für den Link.
Genau so einen "ekligen" Code hab ich gemeint, werd mich heut abend damit bechäftigen wie der Funktioniert, danke! _________________ "Die Gefahr, dass der Computer so wird wie der Mensch ist nicht so groß, wie die Gefahr, dass der Mensch so wird wie der Computer." - Konrad Zuse |
|
Nach oben |
|
 |
|
|
Du kannst keine Beiträge in dieses Forum schreiben. Du kannst auf Beiträge in diesem Forum nicht antworten. Du kannst deine Beiträge in diesem Forum nicht bearbeiten. Du kannst deine Beiträge in diesem Forum nicht löschen. Du kannst an Umfragen in diesem Forum nicht mitmachen.
|
|