-- CS471 Fall 2002 -- A simple language is described through a concrete syntax. A parser -- generates abstract syntax trees which are passed to an interpreter -- for the language -- -- -- A grammar for a simple language -- No rules are recursive (EBNF-style with mutual recursion -- between rules) -- Multiple occurrences of recursion are handled with a suffix -- on the rule name, e.g. Prog1 and Prog2 are recursive back to -- the Prog rule. -- -- -- Prog ::= {Stmt;}*Stmt -- Stmt ::= Assign|Cond|Loop -- Assign ::= Id=Exp -- Cond ::= if Bool then Prog1 else Prog2 end -- Loop ::= while Bool do Prog end -- Bool ::= Equal|Gt|Lt|And|Or|Not -- Equal ::= Id==Exp -- Gt ::= Id>Exp -- Lt ::= Id' 0 'do' p '=' p '+' y';' n '=' n '-' 1 'end' ); -- $Prog := #Prog(x '=' 0 ';' y '=' 0 ';' 'if' x '>' 0 'then' y '=' 2 'else' y '=' 3 'end'); -- $Prog := #Prog( p '=' 0 ';' p '=' p '+' 1 ); PRINT $Prog; -- #DEBUG(RULES); #Interpret($Prog) ## #Prog (+ $Stmts !.:= #Stmt + ';') /RETURN $Stmts/ ## #Stmt $Stmt := (#Assign ! #Cond ! #Loop) / RETURN $Stmt / ## #Assign $Id '=' $Exp := #Exp / RETURN ASSIGN::<.ID:$Id,EXP:$Exp.>/ ## #Cond 'if' $Test := #Bool 'then' $Then := #Prog 'else' $Else := #Prog 'end' / RETURN COND::<.TEST:$Test,THEN:$Then,ELSE:$Else.> / ## #Loop 'while' $Test := #Bool 'do' $Body := #Prog 'end' / RETURN WHILE::<.TEST:$Test,BODY:$Body.> / ## #Bool $Bool := (#Equal ! #Gt ! #Lt ! #And ! #Or ! #Not) / RETURN $Bool / ## #Equal $Id '==' $Exp := #Exp / RETURN EQUAL::<.ID:$Id,EXP:$Exp.> / ## #Gt $Id '>' $Exp := #Exp / RETURN GT::<.ID:$Id,EXP:$Exp.> / ## #Lt $Id '<' $Exp := #Exp / RETURN LT::<.ID:$Id,EXP:$Exp.> / ## #And $B1 := #Bool 'and' $B2 := #Bool / RETURN LAND::<.B1:$B1,B2:$B2.> / ## #Or $B1 := #Bool 'or' $B2 := #Bool / RETURN LOR::<.B1:$B1,B2:$B2.> / ## #Not 'not' $B := #Bool / RETURN LNOT::<.B:$B.> / ## #Exp $Exp := (#Add ! #Sub ! #Simple) / RETURN $Exp/ ## #Simple $Id / RETURN $Id / ;; $Num / RETURN $Num / ## #Add $E1 := #Simple '+' $E2 := #Exp / RETURN ADD::<.E1:$E1,E2:$E2.> / ## #Sub $E1 := #Simple '-' $E2 := #Exp / RETURN SUB::<.E1:$E1,E2:$E2.> / ## -- -- The interpreter -- The result of running the interpreter is a tree that represents -- the store: a collection of all the variables and their values -- e.g. <. x : 0, y : 1 .> is a store with x bound to 0 and -- y bound to 1. -- #Interpret #IntProg / PRINT $Store / ## #IntProg (. (* #IntStmt *) .) ## #IntStmt (#IntAssign ! #IntCond ! #IntLoop) ## #IntAssign ASSIGN::<.ID:$Id,EXP:$Val := #IntExp.> / LAST #Interpret $Store ++:= <.$Id:$Val.>; PRINT LAST #Interpret $Store / ## #IntExp ADD::<.E1:$V1 := #IntExp,E2:$V2 := #IntExp.> / RETURN $V1 + $V2 / ;; SUB::<.E1:$V1 := #IntExp,E2:$V2 := #IntExp.> / RETURN $V1 - $V2 / ;; $Id / RETURN LAST #Interpret $Store.$Id / ;; $N / RETURN $N / ## #IntCond COND::<.TEST:$B := #IntBool,THEN:$Then,ELSE:$Else.> / IF $B -> #IntProg($Then) ELSIF T -> #IntProg($Else) FI / ## #IntLoop WHILE::<.TEST:$B := #IntBool,BODY:$Body.> / IF $B -> #IntProg($Body);#IntLoop($) FI / ## #IntBool EQUAL::<.ID:$Id,EXP:$Val := #IntExp.> / IF LAST #Interpret $Store.$Id = $Val -> RETURN T FI / ;; GT::<.ID:$Id,EXP:$Val := #IntExp.> / IF LAST #Interpret $Store.$Id > $Val -> PRINT LAST #Interpret $Store.$Id;RETURN T FI / ;; LT::<.ID:$Id,EXP:$Val := #IntExp.> / IF LAST #Interpret $Store.$Id < $Val -> RETURN T FI / ;; LAND::<.B1:$B1 := #IntBool,B2:$B2 := #IntBool.> / RETURN $B1 AND B2 / LOR::<.B1:$B1 := #IntBool,B2:$B2 := #IntBool.> / RETURN $B1 OR B2 / LNOT::<.B:$B1 := #IntBool.> / RETURN NOT $B / ##