summaryrefslogtreecommitdiff
path: root/examples/decaf_parser.py
diff options
context:
space:
mode:
Diffstat (limited to 'examples/decaf_parser.py')
-rw-r--r--examples/decaf_parser.py266
1 files changed, 176 insertions, 90 deletions
diff --git a/examples/decaf_parser.py b/examples/decaf_parser.py
index e6b1abb..be3a1e9 100644
--- a/examples/decaf_parser.py
+++ b/examples/decaf_parser.py
@@ -12,46 +12,75 @@
"""
Program ::= Decl+
Decl ::= VariableDecl | FunctionDecl | ClassDecl | InterfaceDecl
- VariableDecl ::= Variable ;
- Variable ::= Type ident
- Type ::= int | double | bool | string | ident | Type []
- FunctionDecl ::= Type ident ( Formals ) StmtBlock | void ident ( Formals ) StmtBlock
- Formals ::= Variable+, | e
- ClassDecl ::= class ident <extends ident> <implements ident + ,> { Field* }
- Field ::= VariableDecl | FunctionDecl
- InterfaceDecl ::= interface ident { Prototype* }
- Prototype ::= Type ident ( Formals ) ; | void ident ( Formals ) ;
- StmtBlock ::= { VariableDecl* Stmt* }
- Stmt ::= <Expr> ; | IfStmt | WhileStmt | ForStmt | BreakStmt | ReturnStmt | PrintStmt | StmtBlock
- IfStmt ::= if ( Expr ) Stmt <else Stmt>
- WhileStmt ::= while ( Expr ) Stmt
- ForStmt ::= for ( <Expr> ; Expr ; <Expr> ) Stmt
- ReturnStmt ::= return <Expr> ;
- BreakStmt ::= break ;
- PrintStmt ::= Print ( Expr+, ) ;
+ VariableDecl ::= Variable ;
+ Variable ::= Type ident
+ Type ::= int | double | bool | string | ident | Type []
+ FunctionDecl ::= Type ident ( Formals ) StmtBlock | void ident ( Formals ) StmtBlock
+ Formals ::= Variable+, | e
+ ClassDecl ::= class ident <extends ident> <implements ident + ,> { Field* }
+ Field ::= VariableDecl | FunctionDecl
+ InterfaceDecl ::= interface ident { Prototype* }
+ Prototype ::= Type ident ( Formals ) ; | void ident ( Formals ) ;
+ StmtBlock ::= { VariableDecl* Stmt* }
+ Stmt ::= <Expr> ; | IfStmt | WhileStmt | ForStmt | BreakStmt | ReturnStmt | PrintStmt | StmtBlock
+ IfStmt ::= if ( Expr ) Stmt <else Stmt>
+ WhileStmt ::= while ( Expr ) Stmt
+ ForStmt ::= for ( <Expr> ; Expr ; <Expr> ) Stmt
+ ReturnStmt ::= return <Expr> ;
+ BreakStmt ::= break ;
+ PrintStmt ::= Print ( Expr+, ) ;
Expr ::= LValue = Expr | Constant | LValue | this | Call
- | ( Expr )
- | Expr + Expr | Expr - Expr | Expr * Expr | Expr / Expr | Expr % Expr | - Expr
- | Expr < Expr | Expr <= Expr | Expr > Expr | Expr >= Expr | Expr == Expr | Expr != Expr
- | Expr && Expr | Expr || Expr | ! Expr
- | ReadInteger ( ) | ReadLine ( ) | new ident | NewArray ( Expr , Typev)
- LValue ::= ident | Expr . ident | Expr [ Expr ]
- Call ::= ident ( Actuals ) | Expr . ident ( Actuals )
- Actuals ::= Expr+, | e
+ | ( Expr )
+ | Expr + Expr | Expr - Expr | Expr * Expr | Expr / Expr | Expr % Expr | - Expr
+ | Expr < Expr | Expr <= Expr | Expr > Expr | Expr >= Expr | Expr == Expr | Expr != Expr
+ | Expr && Expr | Expr || Expr | ! Expr
+ | ReadInteger ( ) | ReadLine ( ) | new ident | NewArray ( Expr , Typev)
+ LValue ::= ident | Expr . ident | Expr [ Expr ]
+ Call ::= ident ( Actuals ) | Expr . ident ( Actuals )
+ Actuals ::= Expr+, | e
Constant ::= intConstant | doubleConstant | boolConstant | stringConstant | null
"""
import pyparsing as pp
from pyparsing import pyparsing_common as ppc
+
pp.ParserElement.enablePackrat()
# keywords
-keywords = (VOID, INT, DOUBLE, BOOL, STRING, CLASS, INTERFACE, NULL, THIS, EXTENDS, IMPLEMENTS, FOR, WHILE,
- IF, ELSE, RETURN, BREAK, NEW, NEWARRAY, PRINT, READINTEGER, READLINE, TRUE, FALSE) = map(pp.Keyword,
- """void int double bool string class interface null this extends implements or while
- if else return break new NewArray Print ReadInteger ReadLine true false""".split())
+keywords = (
+ VOID,
+ INT,
+ DOUBLE,
+ BOOL,
+ STRING,
+ CLASS,
+ INTERFACE,
+ NULL,
+ THIS,
+ EXTENDS,
+ IMPLEMENTS,
+ FOR,
+ WHILE,
+ IF,
+ ELSE,
+ RETURN,
+ BREAK,
+ NEW,
+ NEWARRAY,
+ PRINT,
+ READINTEGER,
+ READLINE,
+ TRUE,
+ FALSE,
+) = map(
+ pp.Keyword,
+ """void int double bool string class interface null this extends implements or while
+ if else return break new NewArray Print ReadInteger ReadLine true false""".split(),
+)
keywords = pp.MatchFirst(list(keywords))
-LPAR, RPAR, LBRACE, RBRACE, LBRACK, RBRACK, DOT, EQ, COMMA, SEMI = map(pp.Suppress, "(){}[].=,;")
+LPAR, RPAR, LBRACE, RBRACE, LBRACK, RBRACK, DOT, EQ, COMMA, SEMI = map(
+ pp.Suppress, "(){}[].=,;"
+)
hexConstant = pp.Regex(r"0[xX][0-9a-fA-F]+").addParseAction(lambda t: int(t[0][2:], 16))
intConstant = hexConstant | ppc.integer
doubleConstant = ppc.real
@@ -59,7 +88,7 @@ boolConstant = TRUE | FALSE
stringConstant = pp.dblQuotedString
null = NULL
constant = doubleConstant | boolConstant | intConstant | stringConstant | null
-ident = ~keywords + pp.Word(pp.alphas, pp.alphanums+'_')
+ident = ~keywords + pp.Word(pp.alphas, pp.alphanums + "_")
type_ = pp.Group((INT | DOUBLE | BOOL | STRING | ident) + pp.ZeroOrMore("[]"))
variable = type_ + ident
@@ -68,86 +97,142 @@ variable_decl = variable + SEMI
expr = pp.Forward()
expr_parens = pp.Group(LPAR + expr + RPAR)
actuals = pp.Optional(pp.delimitedList(expr))
-call = pp.Group(ident("call_ident") + LPAR + actuals("call_args") + RPAR
- | (expr_parens + pp.ZeroOrMore(DOT + ident))("call_ident_expr") + LPAR + actuals("call_args") + RPAR)
-lvalue = ((ident | expr_parens)
- + pp.ZeroOrMore(DOT + (ident | expr_parens))
- + pp.ZeroOrMore(LBRACK + expr + RBRACK))
+call = pp.Group(
+ ident("call_ident") + LPAR + actuals("call_args") + RPAR
+ | (expr_parens + pp.ZeroOrMore(DOT + ident))("call_ident_expr")
+ + LPAR
+ + actuals("call_args")
+ + RPAR
+)
+lvalue = (
+ (ident | expr_parens)
+ + pp.ZeroOrMore(DOT + (ident | expr_parens))
+ + pp.ZeroOrMore(LBRACK + expr + RBRACK)
+)
assignment = pp.Group(lvalue("lhs") + EQ + expr("rhs"))
read_integer = pp.Group(READINTEGER + LPAR + RPAR)
read_line = pp.Group(READLINE + LPAR + RPAR)
new_statement = pp.Group(NEW + ident)
new_array = pp.Group(NEWARRAY + LPAR + expr + COMMA + type_ + RPAR)
rvalue = constant | call | read_integer | read_line | new_statement | new_array | ident
-arith_expr = pp.infixNotation(rvalue,
+arith_expr = pp.infixNotation(
+ rvalue,
[
- ('-', 1, pp.opAssoc.RIGHT,),
- (pp.oneOf("* / %"), 2, pp.opAssoc.LEFT,),
- (pp.oneOf("+ -"), 2, pp.opAssoc.LEFT,),
- ])
-comparison_expr = pp.infixNotation(arith_expr,
+ ("-", 1, pp.opAssoc.RIGHT,),
+ (pp.oneOf("* / %"), 2, pp.opAssoc.LEFT,),
+ (pp.oneOf("+ -"), 2, pp.opAssoc.LEFT,),
+ ],
+)
+comparison_expr = pp.infixNotation(
+ arith_expr,
[
- ('!', 1, pp.opAssoc.RIGHT,),
- (pp.oneOf("< > <= >="), 2, pp.opAssoc.LEFT,),
- (pp.oneOf("== !="), 2, pp.opAssoc.LEFT,),
- (pp.oneOf("&&"), 2, pp.opAssoc.LEFT,),
- (pp.oneOf("||"), 2, pp.opAssoc.LEFT,),
- ])
-expr <<= (assignment
- | call
- | THIS
- | comparison_expr
- | arith_expr
- | lvalue
- | constant
- | read_integer
- | read_line
- | new_statement
- | new_array
- )
+ ("!", 1, pp.opAssoc.RIGHT,),
+ (pp.oneOf("< > <= >="), 2, pp.opAssoc.LEFT,),
+ (pp.oneOf("== !="), 2, pp.opAssoc.LEFT,),
+ (pp.oneOf("&&"), 2, pp.opAssoc.LEFT,),
+ (pp.oneOf("||"), 2, pp.opAssoc.LEFT,),
+ ],
+)
+expr <<= (
+ assignment
+ | call
+ | THIS
+ | comparison_expr
+ | arith_expr
+ | lvalue
+ | constant
+ | read_integer
+ | read_line
+ | new_statement
+ | new_array
+)
stmt = pp.Forward()
-print_stmt = pp.Group(PRINT("statement") + LPAR + pp.Group(pp.Optional(pp.delimitedList(expr)))("args") + RPAR + SEMI)
+print_stmt = pp.Group(
+ PRINT("statement")
+ + LPAR
+ + pp.Group(pp.Optional(pp.delimitedList(expr)))("args")
+ + RPAR
+ + SEMI
+)
break_stmt = pp.Group(BREAK("statement") + SEMI)
return_stmt = pp.Group(RETURN("statement") + expr + SEMI)
-for_stmt = pp.Group(FOR("statement") + LPAR + pp.Optional(expr) + SEMI + expr + SEMI + pp.Optional(expr) + RPAR + stmt)
+for_stmt = pp.Group(
+ FOR("statement")
+ + LPAR
+ + pp.Optional(expr)
+ + SEMI
+ + expr
+ + SEMI
+ + pp.Optional(expr)
+ + RPAR
+ + stmt
+)
while_stmt = pp.Group(WHILE("statement") + LPAR + expr + RPAR + stmt)
-if_stmt = pp.Group(IF("statement")
- + LPAR + pp.Group(expr)("condition") + RPAR
- + pp.Group(stmt)("then_statement")
- + pp.Group(pp.Optional(ELSE + stmt))("else_statement"))
-stmt_block = pp.Group(LBRACE + pp.ZeroOrMore(variable_decl) + pp.ZeroOrMore(stmt) + RBRACE)
-stmt <<= (if_stmt
- | while_stmt
- | for_stmt
- | break_stmt
- | return_stmt
- | print_stmt
- | stmt_block
- | pp.Group(expr + SEMI)
- )
+if_stmt = pp.Group(
+ IF("statement")
+ + LPAR
+ + pp.Group(expr)("condition")
+ + RPAR
+ + pp.Group(stmt)("then_statement")
+ + pp.Group(pp.Optional(ELSE + stmt))("else_statement")
+)
+stmt_block = pp.Group(
+ LBRACE + pp.ZeroOrMore(variable_decl) + pp.ZeroOrMore(stmt) + RBRACE
+)
+stmt <<= (
+ if_stmt
+ | while_stmt
+ | for_stmt
+ | break_stmt
+ | return_stmt
+ | print_stmt
+ | stmt_block
+ | pp.Group(expr + SEMI)
+)
formals = pp.Optional(pp.delimitedList(variable))
-prototype = pp.Group((type_ | VOID)("return_type")
- + ident("function_name")
- + LPAR + formals("args") + RPAR + SEMI)("prototype")
-function_decl = pp.Group((type_ | VOID)("return_type") + ident("function_name")
- + LPAR + formals("args") + RPAR
- + stmt_block("body"))("function_decl")
+prototype = pp.Group(
+ (type_ | VOID)("return_type")
+ + ident("function_name")
+ + LPAR
+ + formals("args")
+ + RPAR
+ + SEMI
+)("prototype")
+function_decl = pp.Group(
+ (type_ | VOID)("return_type")
+ + ident("function_name")
+ + LPAR
+ + formals("args")
+ + RPAR
+ + stmt_block("body")
+)("function_decl")
-interface_decl = pp.Group(INTERFACE + ident("interface_name")
- + LBRACE + pp.ZeroOrMore(prototype)("prototypes") + RBRACE)("interface")
+interface_decl = pp.Group(
+ INTERFACE
+ + ident("interface_name")
+ + LBRACE
+ + pp.ZeroOrMore(prototype)("prototypes")
+ + RBRACE
+)("interface")
field = variable_decl | function_decl
-class_decl = pp.Group(CLASS + ident("class_name")
- + pp.Optional(EXTENDS + ident)("extends")
- + pp.Optional(IMPLEMENTS + pp.delimitedList(ident))("implements")
- + LBRACE + pp.ZeroOrMore(field)("fields") + RBRACE)("class_decl")
+class_decl = pp.Group(
+ CLASS
+ + ident("class_name")
+ + pp.Optional(EXTENDS + ident)("extends")
+ + pp.Optional(IMPLEMENTS + pp.delimitedList(ident))("implements")
+ + LBRACE
+ + pp.ZeroOrMore(field)("fields")
+ + RBRACE
+)("class_decl")
decl = variable_decl | function_decl | class_decl | interface_decl | prototype
program = pp.OneOrMore(pp.Group(decl))
decaf_parser = program
-stmt.runTests("""\
+stmt.runTests(
+ """\
sin(30);
a = 1;
b = 1 + 1;
@@ -158,7 +243,8 @@ stmt.runTests("""\
a[100] = b;
a[0][0] = 2;
a = 0x1234;
-""")
+"""
+)
test_program = """
void getenv(string var);