1 / 18

WS 2002/2003 Programmierung 1 - Repetitorium Andreas Augustin und Marc Wagner

WS 2002/2003 Programmierung 1 - Repetitorium Andreas Augustin und Marc Wagner Homepage: http://info1.marcwagner.info. Dienstag, den 15.04.03 Kapitel 12 Syntax. 12.1 Übersicht. Die Abstrakte Syntax liefert die Baumdarstellung von Phrasen.

jamar
Download Presentation

WS 2002/2003 Programmierung 1 - Repetitorium Andreas Augustin und Marc Wagner

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. WS 2002/2003 Programmierung 1 - Repetitorium Andreas Augustin und Marc Wagner Homepage: http://info1.marcwagner.info

  2. Dienstag, den 15.04.03 Kapitel 12 Syntax

  3. 12.1 Übersicht Die Abstrakte Syntax liefert die Baumdarstellung von Phrasen. Die Konkrete Syntax besteht aus der lexikalischen und der phrasalen Syntax. Die Lexikalische Syntax regelt, welche Wörter für die Darstellung von Phrasen zur Verfügung stehen und wie Wörter durch Zeichenreihen darzustellen sind. Die Phrasale Syntax regelt, wie Phrasen durch Wortfolgen dargestellt werden. Eine konkrete Syntax muss eindeutig und durch einen Parser realisierbar sein, der zu einer vorgelegten Zeichenreihe entscheidet, ob es sich um die Darstellung einer Phrase handelt und gegebenenfalls die Baumdarstellung der Phrase liefert.

  4. 12.2 Lexikalische Syntax Die lexikalische Syntax klassifiziert die Wörter von F in • Symbolische Wörter (“+“ , “-“ , “*“ , “<=“ , “(“ , “)“ , “:“ , “->“ , “=>“) • Zahlkonstanten (nichtleere Zeichenreihen aus Ziffern) • Alpha-numerische Wörter (alle Wörter aus Buchstaben und Ziffern, die mit • einem Buchstaben beginnen) • 4. Leerzeichen (“ “ , “\t“ , “\n“) “if x<=2 then 1 else 2+y“ ist die Wortfolge “if“,“x“,“<=“,“2“,“then“,“1“,“else“,“2“,“+“,“y“ Die Trennungsregel besagt, dass zwei Wörter ohne trennendes Leerzeichen direkt hintereinander geschrieben werden dürfen, wenn es kein Wort gibt, das mit dem Zeichen des ersten Wortes und dem ersten Zeichen des zweiten Wortes beginnt. Kommentare “(*“ ... “*)“ dürfen nur balanciert auftreten und sind in der Wortdarstellung nicht sichtbar. Symbolische Wörter sind alle nichtleeren Zeichenreihen von ! % & $ # + - / : < = > ? @ \ ~ ‘ ^ | * Alpha-numerische Wörter dürfen “ ‘ “ , “ _ “ und “ . “ enthalten.

  5. 12.3 Lexer Ein Lexer ist eine Prozedur, die zu einer vorgelegten Zeichenfolge entscheidet, ob sie lexikalisch zulässig ist, und gegebenenfalls die dargestellte Wortfolge liefert. Der Lexer liest die vorgelegte Zeichenfolge von links nach rechts. Die leere Zeichenfolge ist zulässig. Leerzeichen werden überlesen. Wenn das erste Zeichen kein Leerzeichen ist, muss ein Wort überlesen werden. Zunächst wird geprüft, ob ein symbolisches Wort überlesen werden kann. Wenn kein symbolisches Wort überlesen werden kann, verbleiben für eine zulässige Zeichenfolge nur 3 Möglichkeiten : • Die Zeichenfolge beginnt mit “~“. In diesem Fall muss eine möglichst lange • negative Zahlkonstante überlesen werden. • Die Zeichenfolge beginnt mit einer Ziffer. In diesem Fall muss eine möglichst • lange einfache Zahlkonstante überlesen werden. • Die Zeichenfolge beginnt mit einem Buchstaben. In diesem Fall muss ein • möglichst langes alpha-numerisches Wort überlesen werden. Der Lexer liefert die gelesenen Wörter als Werte des Konstruktortyps token.

  6. 12.3 Lexer datatype token = ICON of int | ID of string | ADD | SUB | MUL | LPAR | RPAR | LEQ | FALSE | TRUE | IF | THEN | ELSE | FN | COLON | ARROW | DARROW “if ~17 <= xy then bool else 1 +“ liefert [ IF , ICON ~17 , LEQ , ID „xy“ , THEN , ID „bool“ , ELSE , ICON 1 , ADD ] lex : token list → char list → token list (*Error,Overflow*) Akkumulator (reversierte Ordnung) noch zu lesende Zeichenfolge lexA : token list → char list → char list → token list Akkumulator bereits gelesene Zeichen noch zu lesenden Zeichen

  7. 12.3 Lexer lexN : token list → int → int → char list → token list Akkumulator bereits gelesenes Vorzeichen noch zu lesenden Zeichen Zahl der bereits gelesenen Ziffern Dependenzgraph der Prozedur des Lexers : lex lexA lexN lexA‘

  8. 12.3 Lexer val ord0 = ord #“0“ fun lex ts nil = rev ts | lex ts (#“ “::cr) = lex ts cr | lex ts (#“\n“::cr) = lex ts cr | lex ts (#“\t“::cr) = lex ts cr | lex ts (#“<“::#“=“::cr) = lex (LEQ::ts) cr | lex ts (#“-“::#“>“::cr) = lex (ARROW::ts) cr | lex ts (#“=“::#“>“::cr) = lex (DARROW::ts) cr | lex ts (#“+“::cr) = lex (ADD::ts) cr | lex ts (#“-“::cr) = lex (SUB::ts) cr | lex ts (#“*“::cr) = lex (MUL::ts) cr | lex ts (#“:“::cr) = lex (COLON::ts) cr | lex ts (#“(“::cr) = lex (LPAR::ts) cr | lex ts (#“)“::cr) = lex (RPAR::ts) cr | lex ts (#“~“::c::cr) = if Char.isDigit c then lexN ts ~1 0 (c::cr) else raise Error | ...

  9. 12.3 Lexer ...| lex ts (c::cr) = if Char.isDigit c then lexN ts 1 0 (c::cr) else if Char.isAlpha c then lexA ts [c] cr else raise Error and lexN ts s n cs = if not (null cs) andalso Char.isDigit(hd cs) then lexN ts s (10*n + (ord(hd cs) – ord 0)) (tl cs) else lex (ICON(s*n)::ts) cs and lexA ts xs cs = if not (null cs) andalso Char.isAlphanum(hd cs) then lexA ts (hd cs::xs) (tl cs) else lex (lexA‘ (implode (rev xs))::ts) cs and lexA‘ “if“ = IF | lexA‘ “then“ = THEN | lexA‘ “else“ = ELSE | lexA‘ “fn“ = FN | lexA‘ “false“ = FALSE | lexA‘ “true“ = TRUE | lexA‘ x = ID x

  10. 12.4 Kontextfreie Syntax für Typen ty “→“ atty “bool“ “int“ “(“ “)“ ty = atty | atty “→“ ty Typ atty = “bool“ | “int“ | “(“ ty “)“ atomarer Typ Terminal Nonterminal Eine Grammatik beschreibt eine Menge von Syntaxbäumen. Syntaxbäume sind geordnete Bäume : • Jedes Blatt ist mit einem Wort markiert. • Die Wurzel und die inneren Knoten sind mit Nonterminalen markiert. • Für jeden mit einem Nonterminal markierten Knoten gilt : • Wenn N die Marke des Knotens ist und S1, ... , Sn die Marken der • Nachfolger des Knotens sind, dann spezifiziert die Grammatik für • das Nonterminal N die Alternative S1 , ... , Sn.

  11. 12.4 Kontextfreie Syntax für Typen Jeder Syntaxbaum hat also mindestens zwei Knoten. Die Grenze eines Syntaxbaum bezeichnen wir als den durch den Baum dargestellten Satz. ty atty ty ty atty atty ty ty atty atty “(“ “int“ “→“ “int“ “)“ “→“ “int“ “→“ “int“

  12. 12.4 Kontextfreie Syntax für Typen Für die syntaktische Analyse benötigen wir einen Parser, der prüft, ob eine Wortfolge einen Typ darstellt und diesen im Erfolgsfall liefert. Als algorithmische Technik verwenden wir den rekursiven Abstieg mit „Ein-Wort-Vorrausschau“. Zusammenhang : Satz Syntaxbäume eindeutige kontextfreie Grammatik Phrasen abstrakte Grammatik

  13. 12.4 Kontextfreie Syntax für Typen fun match (a,ts) t = if null ts orelse hd ts <> t then raise Error else ( a , tl ts ) fun combine a ts p f = let val (a‘,tr) = p ts in ( f(a,a‘) , tr ) end fun ty ts = case atty ts of ( a , ARROW :: tr ) => combine a tr ty Arrow | ats => ats and atty (ID “int“ :: ts) = (Int , ts) | atty (ID “bool“ :: ts) = (Bool , ts) | atty (LPAR :: ts) = match (ty ts) RPAR | atty _ => raise Error fun parse ts = case ty ts of ( a , [] ) => a | _ => raise Error val parse : token list → ty

  14. 12.5 Kontextfreie Syntax für arithmetische Ausdrücke exp = asexp [ “<=“ asexp ] asexp = [ asexp ( “+“ | “-“ ) ] mulexp mulexp = [ mulexp “*“ ] atexp atexp = constant | identifier | “(“ exp “)“ exp asexp mulexp atexp “ <= “ “ + “ “ - “ “ * “ “ ( “ “ ) “ constant identifier Bei der Realisierung des Parsers muss die störende Linksrekursion von asexp und mulexp entfernt werden, da diese sonst zur Divergenz führen.

  15. 12.5 Kontextfreie Syntax für arithmetische Ausdrücke Zur Behebung des Problems führen wir Hilfsnonterminale ein, welche Epsilon-Blätter im Syntaxbaum darstellen. exp = asexp [ “<=“ asexp ] asexp = mulexp asexp‘ asexp‘ = [ ( “+“ | “-“ ) mulexp asexp‘ ] mulexp = atexp mulexp‘ mulexp‘ = [ “*“ atexp mulexp‘ ] atexp = constant | identifier | “(“ exp “)“

  16. 12.5 Kontextfreie Syntax für arithmetische Ausdrücke fun match (a,ts) t = if null ts orelse hd ts <> t then raise Error else (a, tl ts) fun combine a ts p f = let val (a’,tr) = p ts in (f(a,a’), tr) end fun opa ops (a,a’) = Op(a,ops,a’) fun exp ts = case asexp ts of (a, LEQ::tr) => combine a tr asexp (opa Leq) | ats => ats and asexp ts = asexp’ (mulexp ts) and asexp’(a, ADD::ts) = asexp’(combine a ts mulexp (opa Add)) | asexp’(a, SUB::ts) = asexp’(combine a ts mulexp (opa Sub)) | asexp’ ats = ats and mulexp ts = mulexp’(atexp ts) and mulexp’(a, MUL::ts) = mulexp’(combine a ts atexp (opa Mul)) | mulexp’ ats = ats ...

  17. 12.5 Kontextfreie Syntax für arithmetische Ausdrücke ... and atexp (FALSE ::ts) = (Con False, ts) | atexp (TRUE ::ts) = (Con True , ts) | atexp (ICON n::ts) = (Con(IC n), ts) | atexp (ID s ::ts) = (Id s , ts) | atexp (LPAR ::ts) = match (exp ts) RPAR | atexp _ = raise Error fun parse ts = case exp ts of (a, nil) => a | _ => raise Error val parse : token list → exp

  18. 12.6 Bemerkungen zur konkreten Syntax von SML Die Rangfolge und die Gruppierung der Infixoperatoren für SML Ausdrücke ist wie folgt: rechtsassoziativ : orelse andalso :: @ linksassoziativ : before o := = <> < > <= >= + - ^ * / div mod Dabei ist zu beachten, dass orelse und andalso semantisch gesehen keine Operationen sind, sondern aus Konditionalen abgeleitete Formen sind.

More Related