Code: Alles auswählen
; *******************************************************************
; * Parser Version TTCP 0.5 *
; * *
; * ist das Include-File: Parser05.pbi *
; * ^^^^^^^^^^^^ *
; *******************************************************************
DeclareModule TTCParser05
; =
; = Public Declarations =============================================
; =
; --- Start-Prozedur ---
Declare Start(file_name.s)
EndDeclareModule
Module TTCParser05
; =
; = Private Declarations ============================================
; =
; --- globale Variablen ---
Global AssemblerFile ; Handle des Assembler-Files
Structure gv ; Struktur einer globalen
Typ.i ; Variable
Index.i
EndStructure
Global NewMap GlobalVar.gv() ; enthält Variablenname + Typ
; + Index
Global GlobalStringIndex ; die jeweiligen Index-Nummern
Global GlobalIntegerIndex
; --- notwendige Declares (eine Halde) ---
;{
Declare SimpleExpression(expr_typ)
Declare ValueFactor(expr_typ)
Declare StringValueFactor(expr_typ)
Declare Input_Function(expr_typ=0)
Declare Parantheses(expr_typ)
Declare StringExpression(expr_typ)
Declare Negation(expr_typ)
Declare Assignment_Statement()
Declare StringParantheses(expr_typ)
Declare StrCmp_Function(expr_typ=0)
Declare Expression(expr_typ)
;}
; =
; = PROGRAMM =======================================================
; =
; - Versionskontrolle -----------------------------------------------
; -
; Es gibt: TTC 0.5, 1.0 zur Auswahl
#Version = 0.5
; - Token-Stream-Kontrolle ------------------------------------------
; -
Procedure TestToken(token)
If Scanner::Token<>token
Scanner::Expected(#DQUOTE$+Chr(token)+#DQUOTE$+
" statt "+#DQUOTE$+Chr(Scanner::Token)+#DQUOTE$)
EndIf
EndProcedure
; - Code-Ausgabe-Prozeduren ins ASM-File ----------------------------
; -
Procedure Emit(typ='',code.s="",x.s="") ; Spaces+Typ+Opcode+(cut)+Kommentar
WriteStringN(AssemblerFile,Space(8)+LSet(Chr(typ)+code,35," ")+x)
EndProcedure
Procedure EmitS(typ,code.s) ; Spaces + Typ + Opcode (re. unbeschnitten)
WriteStringN(AssemblerFile,Space(8)+Chr(typ)+code)
EndProcedure
Procedure EmitC(code.s) ; Spaces + (kein Typ) + Opcode (re. unbeschnitten)
WriteStringN(AssemblerFile,Space(8)+code)
EndProcedure
Procedure EmitL(label.s) ; [ + LABEL + ]
WriteStringN(AssemblerFile,"["+UCase(label)+"]")
EndProcedure
Procedure EmitX(x.s="") ; ohne Spaces, einfache Ausgabe
WriteStringN(AssemblerFile,x)
EndProcedure
; - Verzweigungen ---------------------------------------------------
; -
Procedure Goto_Statement() ; springt zu Sprungmarke
; Sprungmarken-Name holen und als ASM-Code ausgeben
Scanner::GetName()
EmitC("j UL_"+UCase(Scanner::Lexem))
; Leere Zeile im ASM-File ausgeben zur Übersichtlichkeit
EmitX()
; Nächstes Token-Lexem-Paar laden
Scanner::GetToken()
EndProcedure
Procedure GoSub_Statement() ; -"-, aber merkt sich Return-Adressse
; Sprungmarken-Name holen und als ASM-Code ausgeben
Scanner::GetName()
EmitC("call UL_"+UCase(Scanner::Lexem))
; Leere Zeile im ASM-File ausgeben zur Übersichtlichkeit
EmitX()
; Nächstes Token-Lexem-Paar laden
Scanner::GetToken()
EndProcedure
Procedure Return_Statement() ; Return von GoSub
; ASM-Code ausgeben
EmitC("ret")
; Leere Zeile im ASM-File ausgeben zur Übersichtlichkeit
EmitX()
; Nächstes Token-Lexem-Paar laden
Scanner::GetToken()
EndProcedure
Procedure End_Statement() ; Rücksprung aus dem Script in die VM
; ASM-Code ausgeben
EmitC("end")
; Leere Zeile im ASM-File ausgeben zur Übersichtlichkeit
EmitX()
; Nächstes Token-Lexem-Paar laden
Scanner::GetToken()
EndProcedure
; - bedingte Anweisungen, Verzweigungen und Schleifen ---------------
; -
Procedure If_Statement()
; Klammer holen
Scanner::GetToken()
TestToken('(')
Scanner::GetToken()
; Condition ermitteln
Debug Scanner::Lexem
End
EndProcedure
; - Globale Variablen verwalten -------------------------------------
; -
Procedure NewGlobalVar(var_name.s,var_typ) ; legt neue Variable an
; Variable bereits vorhanden? -> Fehler!
If FindMapElement(GlobalVar(),var_name)
Scanner::Error("Die globale Variable "+#DQUOTE$+
var_name+#DQUOTE$+
" ist bereits deklariert.")
EndIf
; lege neue Variable an und trage Typ und Index in Map ein
; erhöhe nach Eintrag den Index für das nächste Mal
GlobalVar(var_name)\Typ=var_typ
If var_typ='i': GlobalVar(var_name)\Index=GlobalIntegerIndex
GlobalIntegerIndex+1
ElseIf var_typ='s': GlobalVar(var_name)\Index=GlobalStringIndex
GlobalStringIndex+1
EndIf
EndProcedure
Procedure IsGlobalVar(var_name.s) ; Var. deklariert?
; falls Variable nicht deklariert wurde --> Fehler
If Not FindMapElement(GlobalVar(),var_name)
Scanner::Error("Die globale Variable "+#DQUOTE$+var_name+
#DQUOTE$+"' wird verwendet, ohne zuvor"+
" deklariert worden zu sein.")
EndIf
EndProcedure
; Nein -> Fehler
; - String - Funktionen ---------------------------------------------
Procedure StrCmp_Function(expr_typ=0)
; '(' testen und überspringen
Scanner::GetOther(): TestToken('('): Scanner::GetToken()
; StringExpression() aufrufen
StringExpression('s')
; ')' testen, NICHT überspringen (macht ValueFactor)
TestToken(')')
EndProcedure
; - Typ-Umwandlungs - Funktionen ------------------------------------
Procedure Str_Function(expr_typ=0)
; '(' testen und überspringen
Scanner::GetOther(): TestToken('('): Scanner::GetToken()
; Expression() aufrufen
Expression(expr_typ)
; Umwandlungs-Opcode
EmitC("i2s")
; ')' testen, NICHT überspringen (macht ValueFactor)
TestToken(')')
EndProcedure
Procedure Val_Function(expr_typ=0)
; '(' testen und überspringen
Scanner::GetOther(): TestToken('('): Scanner::GetToken()
; Expression() aufrufen
StringExpression('s')
; Umwandlungs-Opcode
EmitC("s2i")
; ')' testen, NICHT überspringen (macht ValueFactor)
TestToken(')')
EndProcedure
; - IO-Prozeduren/Functions -----------------------------------------
; -
Procedure Print_Statement(nl)
; "print" überspringen
Scanner::GetToken()
; String Expression holen
StringExpression('s')
; Top of Stack printen, Parameter nl: 'l'ine, 'n'ewline
Emit(nl,"print")
; Leere Zeile im ASM-File ausgeben zur Übersichtlichkeit
EmitX()
EndProcedure
Procedure Input_Function(expr_typ=0)
; --> Der Typ-Parameter steuert das Pullen vom Stack
; '(' testen und überspringen
Scanner::GetOther(): TestToken('('): Scanner::GetToken()
; Ausgabe des ASM-Codes
EmitC("input")
; ')' testen, NICHT überspringen (macht StringValueFactor)
TestToken(')')
; testet, ob Zuweisung vorliegt
; keine String-Zuweisung (expr_typ=0) -> Stack durch pull bereinigen
If expr_typ=0
; unspezifisches "pull"
EmitC("pull")
; neues Token-Lexem laden, weil Input_Function() wurde nicht
; aus einer String-Expression heraus aufgerufen
Scanner::GetToken()
; Leere Zeile im ASM-File ausgeben zur Übersichtlichkeit
EmitX()
EndIf
EndProcedure
; - mathematischer Parser -------------------------------------------
; -
; ** Version 0.5 **
CompilerIf #Version = 0.5 Or #Version= 1.0
Procedure Expression(expr_typ)
; Abstieg zu SimpleExpression()
SimpleExpression(expr_typ)
EndProcedure
Procedure SimpleExpression(expr_typ)
; --> Token/Lexem steht auf Value
; Abstieg zu Negation()
Negation(expr_typ)
; Ist irgendein Operator in Token/Lexem?
While Scanner::Token='+' Or Scanner::Token='-' Or
Scanner::Token='*' Or Scanner::Token='/' Or
Scanner::Token='%' Or
Scanner::Token='=' Or Scanner::Token='u' Or
Scanner::Token='<' Or Scanner::Token='>' Or
Scanner::Token='k' Or Scanner::Token='g' Or
Scanner::Lexem="and" Or
Scanner::Lexem="or" Or
Scanner::Lexem="xor"
; 'and', 'or', 'xor' hier vor Ort zu einem Token machen
If Scanner::Lexem="and" : Scanner::Token='a'
ElseIf Scanner::Lexem="or" : Scanner::Token='o'
ElseIf Scanner::Lexem="xor" : Scanner::Token='x'
EndIf
; Operator merken
operator = Scanner::Token
; vor Abstieg nächstes Token (=Value) holen
Scanner::GetToken()
; Abstieg zu Negation()
Negation(expr_typ)
; Ausgabe des ASM-Codes des Operators
; mit gemerktem Operator
Select operator
Case '+' : Emit(expr_typ,"add")
Case '-' : Emit(expr_typ,"sub")
Case '*' : Emit(expr_typ,"mul")
Case '/' : Emit(expr_typ,"div")
Case '%' : Emit(expr_typ,"mod")
Case 'a' : Emit(expr_typ,"and") ; boolesches and: "and"
Case 'o' : Emit(expr_typ,"or" ) ; boolesches or: "or"
Case 'x' : Emit(expr_typ,"xor") ; boolesches xor : "xor"
Case '=' : Emit(expr_typ,"eq" ) ; equal, gleich: "="
Case 'u' : Emit(expr_typ,"ne" ) ; not equal: "<>"
Case '<' : Emit(expr_typ,"lt" ) ; lower than: "<="
Case '>' : Emit(expr_typ,"gt" ) ; greater than: ">"
Case 'k' : Emit(expr_typ,"le" ) ; lower or equal "<="
Case 'g' : Emit(expr_typ,"ge" ) ; greater or equal ">="
EndSelect
Wend
; --> in Token/Lexem ist Token/Lexem nach dem Value
; --> Aufstieg zu Expression()
EndProcedure
Procedure Negation(expr_typ)
; --> Token-Lexem steht auf Value ODER
; --> auf unary + | unary -
Select Scanner::Token
; Ist ein 'unary -' vor ValueFactor?
Case '-':
Scanner::GetToken() ; '-' überspringen
Parantheses(expr_typ) ; Abstieg zu Parantheses()
Emit(expr_typ,"neg") ; bei Rückkehr negieren
; Ist ein 'unary +' vor ValueFactor?
Case '+':
Scanner::GetToken() ; '+' überspringen
Parantheses(expr_typ) ; Abstieg zu Parantheses()
; bei Rückkehr nichts tun
; 'normaler' ValueFactor
Default
Parantheses(expr_typ) ; Abstieg zu Parantheses()
EndSelect
; --> in Token/Lexem ist Token-Lexem nach Value
; --> wenn die Expression weitergeht, ist das ein Operator
; --> Aufstieg zu SimpleExpression()
EndProcedure
Procedure Parantheses(expr_typ)
; --> Token-Lexem steht auf Value ODER
; --> auf '('
; Klammerausdruck beginnt mit "("
If Scanner::Token ='('
Scanner::GetToken() ; '(' überspringen und
; nächstes Token-Lexem laden
Expression(expr_typ) ; ------> Expression() ineinander
; verschachtelt
TestToken(')') ; ')' überspringen, dann
Scanner::GetToken() ; Aufstieg zu Negation
; keine Klammer
Else
ValueFactor(expr_typ) ; weiterer Abstieg zu ValueFactor()
EndIf
; --> Aufstieg zu Negation()
EndProcedure
Macro ValueFactor_N()
; Ist Name-Token eine Variable?
If FindMapElement(GlobalVar(),Scanner::Lexem)
; Fehler, wenn die Variable keine 'i'-Variable ist
If GlobalVar(Scanner::Lexem)\typ<>'i'
Scanner::Error("Die Variable "+#DQUOTE$+Scanner::Lexem+
#DQUOTE$+" ist keine Integer-Variable.")
EndIf
; alles In Ordnung, pushe Index der Variable auf den Stack
Emit(expr_typ,"pushg "+GlobalVar(Scanner::Lexem)\index,"// "+Scanner::Lexem)
; Ist Name-Token eine Interne Funktion?
ElseIf Scanner::Lexem="strcmp": StrCmp_Function(expr_typ)
ElseIf Scanner::Lexem="val" : Val_Function(expr_typ)
; Sonst Fehler
Else
Scanner::Error("Compiler: "+#DQUOTE$+Scanner::Lexem+#DQUOTE$+
Scanner::Lexem+#DQUOTE$+" ist kein Integervariablen- oder Funktionsname"+
" und darf in einem mathemat. Ausdruck nicht verwendet werden")
EndIf
EndMacro
Procedure ValueFactor(expr_typ)
; je Token-Art: Ausgabe des Values als ASM-Code
Select Scanner::Token
Case 'I':
Emit(expr_typ,"pushc "+Scanner::Lexem)
Case 'N':
ValueFactor_N()
Default:
Scanner::Expected("Korrekter Operand (Konstante Zahl"+
", Variablen- oder Funktionsname)")
EndSelect
; holt nächstes Token
Scanner::GetToken()
; --> in Token/Lexem ist Token/Lexem nach Value
; --> wenn die Expression weitergeht, ist das ein Operator
; --> Aufstieg zu Negation()
EndProcedure
CompilerEndIf
; ** Version 1.0 **
; - Stringausdrucks-Parser ------------------------------------------
; -
; ** Version 0.5 **
CompilerIf #Version = 0.5 Or #Version= 1.0
Procedure StringExpression(expr_typ)
; --> Token/Lexem steht auf Value
; Abstieg zu StringParantheses()
StringParantheses(expr_typ)
; Ist '+'-Operator in Token/Lexem?
While Scanner::Token='+' Or
Scanner::Token='=' Or
Scanner::Token='u'
; Operator merken
operator = Scanner::Token
; vor Abstieg nächstes Token (=Value) holen
Scanner::GetToken()
; Abstieg zu StringParantheses()
StringParantheses(expr_typ)
; Ausgabe des ASM-Codes des Operators
; mit gemerktem Operator
Select operator
Case '+' : EmitC("sadd")
Case '=' : EmitC("seq")
Case 'u' : EmitC("sne")
EndSelect
Wend
; --> in Token/Lexem ist Token/Lexem nach dem Value
; --> Aufstieg zu Expression()
EndProcedure
Procedure StringParantheses(expr_typ)
; --> Token-Lexem steht auf Value ODER
; --> auf '('
; Klammerausdruck beginnt mit "("
If Scanner::Token ='('
Scanner::GetToken() ; '(' überspringen und
; nächstes Token-Lexem laden
StringExpression(expr_typ) ; ------> StringExpression() ineinander
; verschachtelt
TestToken(')') ; ')' überspringen, dann
Scanner::GetToken() ; Aufstieg zu Negation
; keine Klammer
Else
StringValueFactor(expr_typ) ; weiterer Abstieg zu ValueFactor()
EndIf
; --> Aufstieg zu Negation()
EndProcedure
Macro StringValueFactor_N()
; Ist Name-Token eine Variable?
If FindMapElement(GlobalVar(),Scanner::Lexem)
; Fehler, wenn die Variable keine 's'-Variable ist
If GlobalVar(Scanner::Lexem)\typ<>'s'
Scanner::Error("Die Variable "+#DQUOTE$+Scanner::Lexem+
#DQUOTE$+" ist keine String-Variable.")
EndIf
; alles In Ordnung, pushe Index der Variable auf den Stack
Emit(expr_typ,"pushg "+GlobalVar(Scanner::Lexem)\index,
"// "+Scanner::Lexem)
; Ist Name-Token eine Interne Funktion?
ElseIf Scanner::Lexem="input": Input_Function(expr_typ)
ElseIf Scanner::Lexem="str" : Str_Function(expr_typ)
; Sonst Fehler
Else
Scanner::Error("Compiler: "+#DQUOTE$+Scanner::Lexem+#DQUOTE$+
" ist kein Stringvariablen- oder Funktionsname"+
" und darf in einem Stringausdruck nicht verwendet werden")
EndIf
EndMacro
Procedure StringValueFactor(expr_typ)
; je Token-Art: Ausgabe des Values als ASM-Code
Select Scanner::Token
Case 'S':
EmitC("spushc "+#DQUOTE$+Scanner::Lexem+#DQUOTE$)
Case 'N':
StringValueFactor_N()
Default:
Scanner::Expected("Korrekter Operand (String in "+#DQUOTE$+
"..."+#DQUOTE$+", Stringvariablen- oder Funktionsname)")
EndSelect
; holt nächstes Token, überspringe eventuell ")"
Scanner::GetToken()
; --> in Token/Lexem ist Token/Lexem nach Value
; --> wenn die StringExpression weitergeht, ist das ein Operator
; --> Aufstieg zu StringExpression()
EndProcedure
CompilerEndIf
; ** Version 1.0 **
; - Variablen anlegen & Werte zuweisen ------------------------------
; -
; ** Version 0.5 **
CompilerIf #Version = 0.5
Procedure Declare_Statement(var_typ) ; deklariert Variable mit typ
; 'int' oder 'string' überspringen
Scanner::GetToken()
; Variable anlegen, Variablen-Name ist in Lexem
; Variablen-Typ wird weitergereicht
; If FindMapElement(GlobalVar(),Scanner::Lexem)
; Scanner::Error("Die globale Variable "+#DQUOTE$+Scanner::Lexem+
; #DQUOTE$+" ist bereits deklariert.")
; EndIf
NewGlobalVar(Scanner::Lexem,var_typ)
; am Ende nächstes Token-Lexem-Paar holen
Scanner::GetToken()
EndProcedure
Procedure Assignment_Statement() ; weist Var eine Expression zu
; --> Variablenname in Lexem
; Variablenname merken, testen
var_name.s = Scanner::Lexem
IsGlobalVar(var_name)
; Den Typ der Expression herausfinden,
; d.i. der Typ der Variablen, dem das Ergebnis zugewiesen wird
expr_typ = GlobalVar(var_name)\typ
; '=' überspringen
Scanner::GetOther(): TestToken('='): Scanner::GetToken()
; Passende Expression aufrufen und Typ übergeben
; In Token-Lexem ist das erste Element der Expression
If expr_typ='i': Expression(expr_typ)
ElseIf expr_typ='s': StringExpression(expr_typ)
EndIf
; Wert der Expression (liegt am Stack) der Variable zuweisen
; für Variable (Name oben gemerkt) wird Index verwendet
Emit(expr_typ,"pullg "+GlobalVar(var_name)\index,"// "+var_name)
; Leere Zeile im ASM-File ausgeben zur Übersichtlichkeit
EmitX()
; --> Token-Lexem ist bereits von Expression
; --> richtig auf das nächste vorbereitet
EndProcedure
CompilerEndIf
; ** Version 1.0 **
CompilerIf #Version = 1.0
Procedure Declare_Statement(var_typ) ; deklariert Variable mit typ
; 'int' oder 'string' überspringen, Variablen-Name ist in Lexem
Scanner::GetToken()
; Schleife, die z.B. ein "int a,b=23,c=40+21+x" usw. ermöglicht
Repeat
; Wenn Look=',' -> überspringen
If Scanner::Token=','
Scanner::GetName() ; Variablen-Name holen
EndIf
; Variable anlegen, Variablen-Name ist in Lexem
; Variablen-Typ wird weitergereicht
NewGlobalVar(Scanner::Lexem,var_typ)
; Wenn Look = '=', dann Declare + Assignment (zB int a=3)
If Scanner::Look='='
Assignment_Statement(); Variablenname ist in Lexem
; Sonst am Ende nächstes Token-Lexem-Paar holen
; UNTIL überprüft, ob es ein ',' ist
Else
Scanner::GetToken()
EndIf
Until Scanner::Token<>','
EndProcedure
Procedure Assignment_Statement() ; weist Var eine Expression zu
; --> Variablenname in Lexem
; Variablenname merken, testen
; ( scheint unnötig, aber eine Assignment muss
; nicht von Declare_Statement() kommen )
var_name.s = Scanner::Lexem
IsGlobalVar(var_name)
; den Typ der Expression herausfinden
; d.i. der Typ der Variablen, dem das Ergebnis zugewiesen wird
expr_typ = GlobalVar(var_name)\typ
; '=' überspringen
Scanner::GetOther(): TestToken('='): Scanner::GetToken()
; Passende Expression aufrufen und Typ übergeben
; In Token-Lexem ist das erste Element der Expression
If expr_typ='i': Expression(expr_typ)
ElseIf expr_typ='s': StringExpression(expr_typ)
EndIf
; Wert der Expression (liegt am Stack) der Variable zuweisen
; für Variable (Name oben gemerkt) wird Index verwendet
Emit(expr_typ,"pullg "+GlobalVar(var_name)\index,"// "+var_name)
; Leere Zeile im ASM-File ausgeben zur Übersichtlichkeit
EmitX()
; --> Token-Lexem ist bereits von Expression
; --> richtig auf das nächste vorbereitet
EndProcedure
CompilerEndIf
; - Statement, Block ------------------------------------------------
; -
; ** Version 0.5 **
CompilerIf #Version = 0.5
Procedure Statement() ; erkennt Statement -> Statement-Prozedur
; DEBUG
Debug " | "+Chr(Scanner::Token)+ ; CHAR des Token-Codes
" | "+RSet(Str(Scanner::Token),3," ")+ ; Code-Nr des Tokens
" | "+Scanner::Lexem ; Lexem
; je nach Statement Aktionen setzen
Select Scanner::Lexem
; Statements
Case "int" : Declare_Statement('i')
Case "string" : Declare_Statement('s')
Case "print" : Print_Statement('l')
Case "printn" : Print_Statement('n')
Case "if" : If_Statement()
Case "goto" : Goto_Statement()
Case "gosub" : GoSub_Statement()
Case "return" : Return_Statement()
Case "end" : End_Statement()
; interne Funktionen
Case "input" : Input_Function() ; ohne Parameter
; ...
Default : Assignment_Statement()
EndSelect
EndProcedure
CompilerEndIf
; ** Version 1.0 **
CompilerIf #Version = 1.0
Macro Default_Statement()
; Sprungmarke (Label)
If Scanner::Look=':'
EmitL("UL_"+Scanner::Lexem)
Scanner::GetOther() ; ':' überspringen
Scanner::GetToken()
; Assignment
Else
Assignment_Statement()
EndIf
EndMacro
Procedure Statement() ; erkennt Statement -> Statement-Prozedur
; DEBUG
Debug " | "+Chr(Scanner::Token)+ ; CHAR des Token-Codes
" | "+RSet(Str(Scanner::Token),3," ")+ ; Code-Nr des Tokens
" | "+Scanner::Lexem ; Lexem
; je nach Statement Aktionen setzen
Select Scanner::Lexem
; Statements
Case "int" : Declare_Statement('i')
Case "string" : Declare_Statement('s')
Case "print" : Print_Statement('l')
Case "printn" : Print_Statement('n')
Case "if" : If_Statement()
Case "goto" : Goto_Statement()
Case "gosub" : GoSub_Statement()
Case "return" : Return_Statement()
Case "end" : End_Statement()
; interne Funktionen
Case "input" : Input_Function() ; ohne Parameter
; ...
Default : Default_Statement()
EndSelect
EndProcedure
CompilerEndIf
; ===================================================================
; START (~MAIN) PROZEDUR
; ===================================================================
Procedure Start(file_name.s)
; Open .ttca-File
AssemblerFile = CreateFile(#PB_Any,GetFilePart(file_name,
#PB_FileSystem_NoExtension)+".ttca")
If Not AssemblerFile
Scanner::Error("Parser: Assembler-File konnte nicht erstellt werden.")
EndIf
; Starte Scanner-Modul (1. Token-Lexem liegt danach im Stream)
Scanner::Start(file_name)
; Inits
ClearMap(GlobalVar())
GlobalStringIndex = 0
GlobalIntegerIndex = 0
; Prolog vorbereiten
EmitX(Space(100)) ; reserviert für setGlobalIntSize usw.
EmitX("// Beginn des Programms")
EmitX()
; so lange, bis Token = 0-Byte
Debug "========================================"
Debug " PARSER - START"
While ( Scanner::Token<>0 )
Statement()
Wend
Debug " PARSER - STOP"
Debug "----------------------------------------"
; Prolog schreiben
FileSeek(AssemblerFile,0)
EmitC("setGlobalIntSize "+GlobalIntegerIndex)
EmitC("setGlobalStringSize "+GlobalStringIndex)
; Stoppe Scanner-Modul (free Memory-Bereich im Scanner)
Scanner::Stop()
; Close .ttca-File
CloseFile(AssemblerFile)
; DEBUG
Debug "----------------------------------------"
Debug " GLOBALE VARIABLEN IN 'GLOBALVAR()'"
Debug "----------------------------------------"
Debug "Typ | Index | Name"
Debug "----------------------------------------"
ForEach GlobalVar()
Debug RSet("'"+Chr(GlobalVar()\typ)+"'",3," ")+
" | "+RSet(Str(GlobalVar()\index),5," ")+
" | "+MapKey(GlobalVar())
Next
EndProcedure
EndModule