HSG |
|
Der Scanner liefert dem Parser die Tokens. Der Parser versucht diese Tokenfolge gemäß seiner Grammatik abzuleiten. Die Grammatik steht übersichtlich am Anfang der von PLY erzeugten Datei parser.out.
Created by PLY version 3.4 (http://www.dabeaz.com/ply) Grammar Rule 0 S' -> start Rule 1 start -> kette Rule 2 kette -> befehl kette Rule 3 kette ->Rule 4 befehl -> whileAnw Rule 5 befehl -> ifAnw Rule 6 befehl -> zuw Rule 7 befehl -> PASS Rule 8 whileAnw -> WHILE cond : kette END Rule 9 ifAnw -> IF cond : kette ELSE : kette END Rule 10 cond -> VAR OP VAR Rule 11 cond -> VAR OP NUM Rule 12 cond -> NUM OP VAR Rule 13 zuw -> VAR = ausdruck Rule 14 ausdruck -> NUM Rule 15 ausdruck -> VAR Rule 16 ausdruck -> VAR + NUM Rule 17 ausdruck -> VAR - NUM Rule 18 ausdruck -> NUM + VAR Rule 19 ausdruck -> VAR + VAR Rule 20 ausdruck -> VAR - VAR Terminals, with rules where they appear + : 16 18 19 - : 17 20 : : 8 9 9 = : 13 ELSE : 9 END : 8 9 IF : 9 NUM : 11 12 14 16 17 18 OP : 10 11 12 PASS : 7 VAR : 10 10 11 12 13 15 16 17 18 19 19 20 20 WHILE : 8 error : Nonterminals, with rules where they appear ausdruck : 13 befehl : 2 cond : 8 9 ifAnw : 5 kette : 1 2 8 9 9 start : 0 whileAnw : 4 zuw : 6
Um das Zusammenwirken von Scanner und Parser zu zeigen, wurden bei jedem Token und bei jeder Anwendung einer Grammatikregel print-Anweisungen eingefügt. Dafür musste dann auch der Komfort der literalen Token geopfert werden.
tokens = ['VAR','NUM','END','OP', 'ISTGLEICH','DOPPELPUNKT','PLUS','MINUS'] + list(reserved.values()) # literals = "=:+-" def t_ISTGLEICH(t): r'=' print(t) return t def t_DOPPELPUNKT(t): r':' print(t) return t def t_PLUS(t): r'\+' print(t) return t def t_MINUS(t): r'\-' print(t) return t
Test des Parsers minipythonparse.py
>>> p.parse("""a = 23 b = 5 q = 0 r = a while r>=b: r = r-b q = q+1 #end print(q) print(r)""") LexToken(VAR,'a',1,0) LexToken(ISTGLEICH,'=',1,2) LexToken(NUM,23,1,4) LexToken(VAR,'b',2,7) ausdruck : NUM zuw : VAR ISTGLEICH ausdruck befehl : zuw LexToken(ISTGLEICH,'=',2,9) LexToken(NUM,5,2,11) LexToken(VAR,'q',4,14) ausdruck : NUM zuw : VAR ISTGLEICH ausdruck befehl : zuw LexToken(ISTGLEICH,'=',4,16) LexToken(NUM,0,4,18) LexToken(VAR,'r',5,20) ausdruck : NUM zuw : VAR ISTGLEICH ausdruck befehl : zuw LexToken(ISTGLEICH,'=',5,22) LexToken(VAR,'a',5,24) LexToken(WHILE,'while',6,26) ausdruck : VAR zuw : VAR ISTGLEICH ausdruck befehl : zuw LexToken(VAR,'r',6,32) LexToken(OP,'>=',6,33) LexToken(VAR,'b',6,35) LexToken(DOPPELPUNKT,':',6,36) cond : VAR OP VAR LexToken(VAR,'r',7,42) LexToken(ISTGLEICH,'=',7,44) LexToken(VAR,'r',7,46) LexToken(MINUS,'-',7,47) LexToken(VAR,'b',7,48) LexToken(VAR,'q',8,54) ausdruck : VAR MINUS VAR zuw : VAR ISTGLEICH ausdruck befehl : zuw LexToken(ISTGLEICH,'=',8,56) LexToken(VAR,'q',8,58) LexToken(PLUS,'+',8,59) LexToken(NUM,1,8,60) LexToken(END,'#end',9,62) ausdruck : VAR PLUS NUM zuw : VAR ISTGLEICH ausdruck befehl : zuw kette : kette : befehl kette kette : befehl kette LexToken(IGN,'print(q)',11,69) LexToken(IGN,'print(r)',12,78) whileAnw : WHILE cond DOPPELPUNKT kette END befehl : whileAnw kette : kette : befehl kette kette : befehl kette kette : befehl kette kette : befehl kette kette : befehl kette start : kette >>>
Teste den Parser an kleinen Programmen. Wann versagt er, wann muss er versagen?