summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rwxr-xr-xsrc/conflicts.sh4
-rw-r--r--src/main.ml6
-rw-r--r--src/parser.mly85
-rw-r--r--src/pretty.ml4
-rwxr-xr-xsrc/test.sh27
5 files changed, 91 insertions, 35 deletions
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;