diff options
-rw-r--r-- | .gitignore | 2 | ||||
-rwxr-xr-x | src/conflicts.sh | 4 | ||||
-rw-r--r-- | src/main.ml | 6 | ||||
-rw-r--r-- | src/parser.mly | 85 | ||||
-rw-r--r-- | src/pretty.ml | 4 | ||||
-rwxr-xr-x | src/test.sh | 27 |
6 files changed, 93 insertions, 35 deletions
@@ -2,3 +2,5 @@ _build *.byte .depend *.swp +src/parser.automaton +src/parser.conflicts diff --git a/src/conflicts.sh b/src/conflicts.sh new file mode 100755 index 0000000..49d5a25 --- /dev/null +++ b/src/conflicts.sh @@ -0,0 +1,4 @@ +#!/bin/sh + +menhir -v parser.mly +rm parser.mli parser.ml diff --git a/src/main.ml b/src/main.ml index 719dcae..4ebcbb3 100644 --- a/src/main.ml +++ b/src/main.ml @@ -2,6 +2,7 @@ open Format open Lexing let parse_only = ref false +let dump = ref false let ifile = ref "" @@ -16,7 +17,8 @@ let localisation pos = !ifile l (c-1) c let options = [ - "-parse-only", Arg.Set parse_only, "Stops after parsing of the input file." + "-parse-only", Arg.Set parse_only, "Stops after parsing of the input file."; + "-dump", Arg.Set dump, "Dump the AST after parsing." ] let localisation pos = @@ -43,7 +45,7 @@ let () = let p = Parser.prog Lexer.token buf in close_in f; - Pretty.print_prog p; + if !dump then Pretty.print_prog p; with | Lexer.Lexing_error s -> localisation (Lexing.lexeme_start_p buf); diff --git a/src/parser.mly b/src/parser.mly index c3e5be6..194a899 100644 --- a/src/parser.mly +++ b/src/parser.mly @@ -48,7 +48,6 @@ %left LT LE GT GE %left PLUS MINUS %left TIMES DIV MOD -%right UNARY %left RARROW DOT LPAREN %start <Ast.program> prog @@ -104,12 +103,10 @@ block: ; statement: -| SEMICOLON - { SEmpty } -| e = expression SEMICOLON { SExpr(e) } +| k = common_statement { k } | IF LPAREN c = expression RPAREN s = statement { SIf(c, s, SEmpty) } -| IF LPAREN c = expression RPAREN s = statement ELSE t = statement +| IF LPAREN c = expression RPAREN s = no_if_statement ELSE t = statement { SIf(c, s, t) } | WHILE LPAREN c = expression RPAREN s = statement { SWhile(c, s) } @@ -118,6 +115,23 @@ statement: r = separated_list(COMMA, expression) RPAREN b = statement { SFor(k, c, r, b) } +; + +no_if_statement: +| WHILE LPAREN c = expression RPAREN s = no_if_statement + { SWhile(c, s) } +| FOR LPAREN k = separated_list(COMMA, expression) SEMICOLON + c = expression? SEMICOLON + r = separated_list(COMMA, expression) RPAREN + b = no_if_statement + { SFor(k, c, r, b) } +| c = common_statement { c } +; + +common_statement: +| SEMICOLON + { SEmpty } +| e = expression SEMICOLON { SExpr(e) } | b = block { SBlock (b) } | RETURN e = expression? SEMICOLON @@ -127,41 +141,50 @@ statement: ; expression: +| e1 = expression ASSIGN e2 = expression { EAssign(e1, e2) } +| a = expression b = binop c = expression { EBinary(a, b, c) } +| a = expression LPAREN arg = separated_list(COMMA, expression) RPAREN { ECall(a, arg) } +| a = unop { a } +; + +primary: | NULL { ENull } | i = INTVAL { EInt(i) } | TRUE { EBool(true) } | FALSE { EBool(false) } | i = IDENT { EIdent(i) } -| e1 = expression ASSIGN e2 = expression { EAssign(e1, e2) } -| b = binop { b } -| a = unop { a } | LPAREN e = expression RPAREN { e } ; -binop: -| a = expression EQ b = expression { EBinary(a, Equal, b) } -| a = expression NE b = expression { EBinary(a, NotEqual, b) } -| a = expression LAND b = expression { EBinary(a, Land, b) } -| a = expression LOR b = expression { EBinary(a, Lor, b) } -| a = expression GT b = expression { EBinary(a, Gt, b) } -| a = expression GE b = expression { EBinary(a, Ge, b) } -| a = expression LT b = expression { EBinary(a, Lt, b) } -| a = expression LE b = expression { EBinary(a, Le, b) } -| a = expression PLUS b = expression { EBinary(a, Add, b) } -| a = expression MINUS b = expression { EBinary(a, Sub, b) } -| a = expression TIMES b = expression { EBinary(a, Mul, b) } -| a = expression DIV b = expression { EBinary(a, Div, b) } -| a = expression MOD b = expression { EBinary(a, Modulo, b) } +%inline binop: +| EQ {Equal } +| NE { NotEqual } +| LAND { Land } +| LOR { Lor } +| GT { Gt } +| GE { Ge } +| LT { Lt } +| LE { Le } +| PLUS { Add } +| MINUS { Sub } +| TIMES { Mul } +| DIV { Div } +| MOD { Modulo } ; unop: -| NOT e = expression { EUnary(Not, e) } %prec UNARY -| MINUS e = expression { EUnary(Minus, e) } %prec UNARY -| PLUS e = expression { EUnary(Plus, e) } %prec UNARY -| REF e = expression { EUnary(Ref, e) } %prec UNARY -| TIMES e = expression { EUnary(Deref, e) } %prec UNARY -| INCR e = expression { EUnary(PreIncr, e) } %prec UNARY -| e = expression INCR { EUnary(PostIncr, e) } -| DECR e = expression { EUnary(PreDecr, e) } %prec UNARY -| e = expression DECR { EUnary(PostDecr, e) } +| e = lunop { e } +| e = unop INCR { EUnary(PostIncr, e) } +| e = unop DECR { EUnary(PostDecr, e) } +; + +lunop: +| NOT e = lunop { EUnary(Not, e) } +| MINUS e = lunop { EUnary(Minus, e) } +| PLUS e = lunop { EUnary(Plus, e) } +| REF e = lunop { EUnary(Ref, e) } +| TIMES e = lunop { EUnary(Deref, e) } +| INCR e = lunop { EUnary(PreIncr, e) } +| DECR e = lunop { EUnary(PreDecr, e) } +| e = primary { e } ; diff --git a/src/pretty.ml b/src/pretty.ml index dd36422..8553c81 100644 --- a/src/pretty.ml +++ b/src/pretty.ml @@ -80,7 +80,7 @@ let rec expr_string = function | ENull -> "NULL" | EIdent(i) -> i | EAssign(k, p) -> "(" ^ (expr_string k) ^ " = " ^ (expr_string p) ^ ")" - | ECall(e, f) -> (expr_string e) ^ (List.fold_left (fun x k -> x ^ ", " ^ (expr_string k)) "" f) ^ ")" + | ECall(e, f) -> (expr_string e) ^ "(" ^ (List.fold_left (fun x k -> x ^ ", " ^ (expr_string k)) "" f) ^ ")" | EUnary(e, f) -> (unop_str e) ^ (expr_string f) | EBinary(e1, o, e2) -> "(" ^ (expr_string e1) ^ " " ^ (binop_str o) ^ " " ^ (expr_string e2) ^ ")" @@ -91,7 +91,7 @@ let rec print_stmt l x = | SExpr(e) -> print_string ((expr_string e) ^ "\n") | SIf(e, a, b) -> print_string ("if " ^ (expr_string e) ^ "\n"); print_stmt (l+1) a; - for i = 0 to l do print_string " " done; + for i = 1 to l do print_string " " done; print_string "else\n"; print_stmt (l+1) b | SWhile(e, a) -> print_string ("while " ^ (expr_string e) ^ "\n"); diff --git a/src/test.sh b/src/test.sh new file mode 100755 index 0000000..13b1c47 --- /dev/null +++ b/src/test.sh @@ -0,0 +1,27 @@ +#!/bin/bash + +# Test syntax +echo "Testing SYNTAX/" + +for a in ../tests/syntax/good/*.cpp; do + if ./main.byte -parse-only $a; + then echo "OK $a"; + else echo "FAIL $a"; + fi; +done; + +for a in ../tests/syntax/bad/*.cpp; do + if ./main.byte -parse-only $a 2> /dev/null; + then echo "FAIL $a"; + else echo "OK $a"; + fi; +done; + +echo "---" +echo "Testing TYPING/ only against parsing" +for a in ../tests/typing/*/*.cpp; do + if ./main.byte -parse-only $a; + then echo "OK $a"; + else echo "FAIL $a"; + fi; +done; |