Scanner für einen Compiler

Hier könnt Ihr gute, von Euch geschriebene Codes posten. Sie müssen auf jeden Fall funktionieren und sollten möglichst effizient, elegant und beispielhaft oder einfach nur cool sein.
Benutzeravatar
coMstructor
Beiträge: 130
Registriert: 04.07.2006 20:10
Kontaktdaten:

Scanner für einen Compiler

Beitrag von coMstructor »

Hi,
habe mal meinen Scanner ein bisschen kommentiert, hoffe es interessiert wen, ist aber nicht so anspruchsvoll, von daher leicht zu kapieren.

Code: Alles auswählen

; Prozeduren, die für uns wichtig werden

Procedure.b IsNumeric(Expression.s)
  If FindString("0123456789",expression,1) 
      ProcedureReturn 1
  Else 
      ProcedureReturn 0
  EndIf 
EndProcedure 

 
Procedure.f IsOperator(Expression.s) 
    If Expression = "+" Or Expression = "-" Or Expression = "*" Or Expression = "/" Or Expression = "=" Or Expression = "&"
        ProcedureReturn 1
    Else 
        ProcedureReturn 0
    EndIf 
EndProcedure 

; Scanner (Hauptquellcode)

Global NewList symb.s() 

file$=OpenFileRequester("Bitte Datei zum Laden auswählen", "","Text (*.txt)|*.txt|Alle Dateien (*.*)|*.*" , 0)
If file$
OpenFile(0,file$)

    Repeat   
        
        Line.s=ReadString(0)                      ; Hier wird Zeile für Zeile eingelesen
    
        For i = 1 To Len(Line)                     ; Hier wird Zeichen für Zeichen bearbeitet
     
        ThisChar.s = Mid(Line, i, 1)              
        
     
        If IsOperator(ThisChar)=1               ; Falls Zeichen ein Operator ist 
         
            If WasOperator = 1  
                MessageRequester("Syntaxfehler","Fehler: Unerwarteter Operator.")                             
            Else 
                AddElement(Symb()):Symb() = ThisChar 
                WasOperator = 1 
            EndIf 
         
        ElseIf ThisChar = "(" Or ThisChar = ")"   ; Falls Zeichen eine Klammer ist
                  AddElement(symb()):Symb() = ThisChar
                  WasOperator = 0 
                     
        ElseIf ThisChar = Chr(34)         ; Falls Zeichen ein Anführungszeichen ist

            AddElement(symb()):Symb() = Chr(34)
         
            For j = (i + 1) To Len(Line) 
         
                ThisChar = Mid(Line, j, 1) 
                 
                If ThisChar = Chr(34)  
                    Symb() = Symb()+ ThisChar
                    i = j: Break  
                Else 
                    Symb() = Symb()+ ThisChar
                EndIf 
             
            Next j
             
        WasOperator = 0 
         
        ElseIf IsNumeric(ThisChar)   ; Falls Zeichen eine Zahl ist
         
            AddElement(symb()):Symb() = "" 
            
            For j = i To Len(Line)       ; Verhalten für die folgenden Zeichen nach der Zahl
             
                ThisChar = Mid(Line, j, 1) 
                 
                If IsNumeric(ThisChar)  
                    Symb() = Symb() + ThisChar 

                ElseIf ThisChar = " " 
                
                    i = j: Goto Skip 
                    
                ElseIf IsOperator(ThisChar) Or ThisChar = ")" Or ThisChar = "(" 
                    
                    i = (j - 1): Goto Skip 
                Else 
                    
                    MessageRequester("Syntaxfehler","Fehler: Unerwartetes Zeichen.")     
                      
                EndIf 
             
            Next j 
             
            SymbNo = SymbNo + 1 
            
            WasOperator = 0 
             
        ElseIf ThisChar = " "   ; Leerzeichen überspringen

        Else                         ; Falls Zeichen ein Buchstabe ist
            AddElement(symb()):Symb() = "" 
         
            For j = i To Len(Line) 
             
                ThisChar = Mid(Line, j, 1) 
                 
                If IsOperator(ThisChar) Or ThisChar = ")" Or ThisChar = "(" 
                    SymbNo = SymbNo + 1: i = (j - 1): Goto Skip 
                    
                ElseIf ThisChar = " "  
                    SymbNo = SymbNo + 1: i = j: Goto Skip 
                    
                Else 
                    Symb() = Symb() + LCase(ThisChar) 

                EndIf 
             
            Next j 
             
            i = j 
             
Skip: 
         
            WasOperator = 0 
 
        EndIf 
        
        
    Next i 
    
        
    Until Eof(0)
    CloseFile(0) 
    
  Else
    MessageRequester("Info","Datei nicht gefunden/konnte nicht geöffnet werden!")
  EndIf

; Dieser Abschnitt nur zur Anzeige von den Token wichtig

ForEach symb()
	Debug symb()
Next
Um den Code zu testen empfehle ich euch ne datei anzulegen mit dem Inhalt

Code: Alles auswählen

33+asdfdsaf-(hallo)*"Welt"/kaiser.s
In dieser Zeile sollte schon aufgezeigt werden wie der Scanner die Zeichen einteilt.