diff --git a/Evaluator/Class.java b/Evaluator/Class.java new file mode 100644 index 0000000..80acb4e --- /dev/null +++ b/Evaluator/Class.java @@ -0,0 +1,15 @@ +class Point{ + // Point class + i=10; + s="tt"; + Int test(){ + i=5; + } + static String test(){ + s="test"; + // comment + this.test(); + /* multi line comment + */ + } +} diff --git a/Main/Compile.ml b/Main/Compile.ml index 47f38dd..6ad3b33 100644 --- a/Main/Compile.ml +++ b/Main/Compile.ml @@ -1,33 +1,33 @@ -open LexicalAnalyser -open SyntaxAnalyser -open Expression - -let print_expressions_or_classes exp = - (* Print the AST *) - print_string (string_of_expr exp) - -(* verbose is a boolean that you can use to switch to a verbose output (for example, to dump all the ast) *) -let execute lexbuf verbose = - - try - (* to enable LexicalAnalyser, plase un comment this block *) - (* print_endline ("Doing LexicalAnalyser...."); - LexicalAnalyser.examine_all lexbuf; - print_string "\n"; *) - print_endline ("Doing SyntaxAnalyser...."); - let exp_list = SyntaxAnalyser.expression nexttoken lexbuf in - print_endline("Start printing AST..."); - List.iter print_expressions_or_classes exp_list; - print_newline(); - with - | LexicalAnalyser.Error (kind, s, e) -> - print_string("LexicalAnalyser error: "); - report_error kind; - let pos = Location.curr lexbuf in - Location.print pos; - print_newline(); - | Error -> - print_string("SyntaxAnalyser error: "); - let pos = Location.curr lexbuf in - Location.print pos; - | _ -> print_string("Unknown error") +open LexicalAnalyser +open SyntaxAnalyser +open Expression + +let print_expressions_or_classes exp = + (* Print the AST *) + print_string (string_of_class_or_expr exp) + +(* verbose is a boolean that you can use to switch to a verbose output (for example, to dump all the ast) *) +let execute lexbuf verbose = + + try + (* to enable LexicalAnalyser, plase un comment this block *) + (* print_endline ("Doing LexicalAnalyser...."); + LexicalAnalyser.examine_all lexbuf; + print_string "\n"; *) + print_endline ("Doing SyntaxAnalyser...."); + let exp_list = SyntaxAnalyser.content nexttoken lexbuf in + print_endline("Start printing AST..."); + List.iter print_expressions_or_classes exp_list; + print_newline(); + with + | LexicalAnalyser.Error (kind, s, e) -> + print_string("LexicalAnalyser error: "); + report_error kind; + let pos = Location.curr lexbuf in + Location.print pos; + print_newline(); + | Error -> + print_string("SyntaxAnalyser error: "); + let pos = Location.curr lexbuf in + Location.print pos; + | _ -> print_string("Unknown error") diff --git a/Parsing/Expression.ml b/Parsing/Expression.ml index af6f3fc..412b297 100644 --- a/Parsing/Expression.ml +++ b/Parsing/Expression.ml @@ -1,84 +1,147 @@ -type binop = - | Badd | Bsub | Bmul | Bdiv | Bmod - | Bgt | Blt | Bge | Ble | Bequal | Bnotequal - | Band | Bor - -type unop = - | Uplus | Uminus | Unot | Uincre | Udecre - -type postfix = - | Pincre | Pdecre - -type expression = - | Int of int - | Var of string - | Bool of bool - | Null - | String of string - | Assign of string * expression - | Binop of binop * expression * expression - | Unop of unop * expression - | Postop of expression * postfix - | Semi of expression - | IfThen of expression * expression - | IfThenElse of expression * expression * expression - - -exception Unbound_variable of string - -let get_op_u = function - | Uplus -> fun x -> x - | Uminus -> fun x -> -x - (* | Unot -> fun x -> not x *) - | Uincre -> fun x -> x + 1 - | Udecre -> fun x -> x - 1 - -let get_op_b op x y = - match op with - | Badd -> x + y - | Bsub -> x - y - | Bmul -> x * y - | Bdiv -> x / y - | Bmod -> x mod y - -let string_of_op_u = function - | Uplus -> "+" - | Uminus -> "-" - | Unot -> "not" - | Uincre -> "++" - | Udecre -> "--" - - let string_of_op_p = function - | Pincre -> "++" - | Pdecre -> "--" - -let string_of_op_b = function - | Badd -> "+" - | Bsub -> "-" - | Bmul -> "*" - | Bdiv -> "/" - | Bmod -> "%" - | Bgt -> " > " - | Blt -> " < " - | Bge -> " >= " - | Ble -> " <= " - | Bequal -> " = " - | Bnotequal -> " != " - | Band -> " && " - | Bor -> " || " - -let rec string_of_expr exp = - match exp with - | Int c -> "Int("^string_of_int c^")" - | Var v -> "Var("^v^")" - | Bool b -> string_of_bool b - | Null -> "null" - | String s -> "String("^s^")" - | Binop(op, e1, e2) -> "(" ^(string_of_expr e1)^ (string_of_op_b op) ^(string_of_expr e2)^ ")" - | Unop(op, e) -> "(" ^ (string_of_op_u op) ^(string_of_expr e)^ ")" - | Postop(e, op) -> "(" ^ (string_of_expr e) ^(string_of_op_p op)^ ")" - | Assign(s,e) -> "Assign(" ^s^ "=" ^(string_of_expr e)^ ")" - | Semi(e1) -> (string_of_expr e1)^ ";\n" - | IfThen(e1,e2) -> "If("^(string_of_expr e1)^") {\n"^(string_of_expr e2 )^" })\n" - | IfThenElse(e1,e2,e3) -> "If("^(string_of_expr e1)^") {\n"^(string_of_expr e2 )^" } Else {\n"^(string_of_expr e3)^" })\n" - \ No newline at end of file +type binop = + | Badd | Bsub | Bmul | Bdiv | Bmod + | Bgt | Blt | Bge | Ble | Bequal | Bnotequal + | Band | Bor + +type unop = + | Uplus | Uminus | Unot | Uincre | Udecre + +type postfix = + | Pincre | Pdecre + +type expression = + | Int of int + | Var of string + | Bool of bool + | Null + | String of string + | Assign of string * expression + | Binop of binop * expression * expression + | Unop of unop * expression + | Postop of expression * postfix + | Semi of expression + | IfThen of expression * expression + | IfThenElse of expression * expression * expression + | New of string + | This + | Invoke of expression * string * expression list + +type param = + | Param of string * string + +type mthd = + | Method of bool * string * string * (param list) * expression list + +type attr = + | Attr of string + | AttrWithAssign of string + +type attr_or_method = + | Attribute of attr + | Method_t of mthd + +type class_ = + | Class_ of string* attr_or_method list + +type class_or_expr = + | Class of class_ + | Expr of expression + +exception Unbound_variable of string + +let get_op_u = function + | Uplus -> fun x -> x + | Uminus -> fun x -> -x + (* | Unot -> fun x -> not x *) + | Uincre -> fun x -> x + 1 + | Udecre -> fun x -> x - 1 + +let get_op_b op x y = + match op with + | Badd -> x + y + | Bsub -> x - y + | Bmul -> x * y + | Bdiv -> x / y + | Bmod -> x mod y + +let string_of_op_u = function + | Uplus -> "+" + | Uminus -> "-" + | Unot -> "not" + | Uincre -> "++" + | Udecre -> "--" + +let string_of_op_p = function + | Pincre -> "++" + | Pdecre -> "--" + +let string_of_op_b = function + | Badd -> "+" + | Bsub -> "-" + | Bmul -> "*" + | Bdiv -> "/" + | Bmod -> "%" + | Bgt -> " > " + | Blt -> " < " + | Bge -> " >= " + | Ble -> " <= " + | Bequal -> " = " + | Bnotequal -> " != " + | Band -> " && " + | Bor -> " || " + +let rec string_of_expr exp = + match exp with + | Int c -> "Int("^string_of_int c^")" + | Var v -> "Var("^v^")" + | Bool b -> string_of_bool b + | Null -> "null" + | String s -> "String("^s^")" + | Binop(op, e1, e2) -> "(" ^(string_of_expr e1)^ (string_of_op_b op) ^(string_of_expr e2)^ ")" + | Unop(op, e) -> "(" ^ (string_of_op_u op) ^(string_of_expr e)^ ")" + | Postop(e, op) -> "(" ^ (string_of_expr e) ^(string_of_op_p op)^ ")" + | Assign(s,e) -> "Assign(" ^s^ "=" ^(string_of_expr e)^ ")" + | Semi(e1) -> (string_of_expr e1)^ ";\n" + | IfThen(e1,e2) -> "If("^(string_of_expr e1)^") {\n"^(string_of_expr e2 )^" })\n" + | IfThenElse(e1,e2,e3) -> "If("^(string_of_expr e1)^") {\n"^(string_of_expr e2 )^" } Else {\n"^(string_of_expr e3)^" })\n" + | This -> "This(this)" + | Invoke(e, s, l) -> "Invoke("^(string_of_expr e)^"."^s^"("^(string_of_exprs l)^"))" + +and string_of_exprs = function + | [] -> "" + | e::l -> string_of_expr e ^ string_of_exprs l + +let rec string_of_param p = match p with + | Param(t,id) -> t^" "^id + +let rec string_of_params params = match params with + | [] -> "" + | (p :: l) -> string_of_param(p) ^ ", " ^ string_of_params l + +let string_of_static_bool = function + | true -> "static" + | false -> "non-static" + +let string_of_method = function + | Method(static,s1,s2,p,e) -> "Method("^string_of_static_bool static^ " " ^s1^" "^s2^"(Params("^(string_of_params p)^")){"^(string_of_exprs e)^"})" + +let string_of_attr = function + | Attr a -> "Attr" ^a + | AttrWithAssign a -> "AttrWithAssign" ^a + +let string_of_attr_or_method = function + | Attribute a -> string_of_attr a + | Method_t m -> string_of_method m + +let rec string_of_attrs_or_methods = function + | [] -> "" + | a::l -> (string_of_attr_or_method a) ^ " " ^ (string_of_attrs_or_methods l) + +let string_of_class = function + | Class_(id,am) -> "Class(" ^id^ "{" ^ (string_of_attrs_or_methods am) ^ " })" + +let string_of_class_or_expr = function + | Class c -> string_of_class c + | Expr e -> string_of_expr e + + diff --git a/Parsing/LexicalAnalyser.mll b/Parsing/LexicalAnalyser.mll index d17fbce..617fb50 100644 --- a/Parsing/LexicalAnalyser.mll +++ b/Parsing/LexicalAnalyser.mll @@ -1,125 +1,145 @@ -{ - open SyntaxAnalyser - - let print_lexeme = function - | EOL -> print_string "EOL" - | EOF -> print_string "EOF" - | PLUS -> print_string "PLUS" - | MINUS -> print_string "MINUS" - | DIV -> print_string "DIV" - | TIMES -> print_string "TIMES" - | INCRE -> print_string "INCRE" - | DECRE -> print_string "DECRE" - | ASSIGN -> print_string "ASSIGN" - | GT -> print_string "GT" - | LT -> print_string "LT" - | NOT -> print_string "NOT" - | EQUAL -> print_string "EQUAL" - | NOTEQUAL -> print_string "NOTEQUAL" - | LE -> print_string "LE" - | GE -> print_string "GE" - | AND -> print_string "AND" - | OR -> print_string "OR" - | INT i -> print_string "INT("; print_int i; print_string ")" - | ENDOFLINECOMMENT ic -> print_string "ENDOFLINECOMMENT("; print_string ic; print_string ")" - | TRADITIONALCOMMENT mc -> print_string "TRADITIONALCOMMENT("; print_string mc; print_string ")" - | IF -> print_string "IF" - | ELSE -> print_string "ELSE" - | LOWERIDENT s -> print_string "LOWERIDENT("; print_string s; print_string ")" - | UPPERIDENT s -> print_string "UPPERIDENT("; print_string s; print_string ")" - | SEMICOLON -> print_string "SEMICOLON" - | LBRACE -> print_string "LBRACE" - | RBRACE -> print_string "RBRACE" - | LPAR -> print_string "LPAR" - | RPAR -> print_string "RPAR" - | BOOLEAN b -> print_string "BOOL("; print_string(string_of_bool b); print_string ")" - | NULL -> print_string "NULL" - - open Lexing - exception Eof - - type error = - | Illegal_character of char - | Illegal_int of string - exception Error of error * position * position - - let raise_error err lexbuf = - raise (Error(err, lexeme_start_p lexbuf, lexeme_end_p lexbuf)) - - (* Les erreurs. *) - let report_error = function - | Illegal_character c -> - print_string "Illegal character '"; - print_char c; - print_string "' " - | Illegal_int nb -> - print_string "The int "; - print_string nb; - print_string " is illegal " -} - -let lower_ch = ['a'-'z'] -let upper_ch = ['A'-'Z'] -let digit = ['0'-'9'] -let integer = digit+ -let lower_id = lower_ch (lower_ch | upper_ch | digit | '_')* -let upper_id = upper_ch (lower_ch | upper_ch | digit | '_')* -(* Literal *) -let str = '"' ([^ '"'] |'\092''"')* '"' -let boolean = "true" | "false" -let space = [' ' '\009' '\012'] -let newline = ('\010' | '\013' | "\013\010") -let not_newline = [^ '\n' '\r'] -(* Comments *) -let endofline_comment = "//" not_newline* -let not_star = [^ '*'] -let not_star_not_slash = [^ '*' '/'] -let traditional_comment = "/*" not_star* "*"+ (not_star_not_slash not_star* "*"+)* "/" - -rule nexttoken = parse - | newline { Location.incr_line lexbuf; nexttoken lexbuf } - | space+ { nexttoken lexbuf } - | endofline_comment as c { ENDOFLINECOMMENT c} - | traditional_comment as c { TRADITIONALCOMMENT c} - | "if" { IF } - | "else" { ELSE } - | boolean as bl { BOOLEAN (bool_of_string bl) } - | "null" { NULL } - | str as st { STRING st} - | eof { EOF } - | "++" { INCRE } - | "--" { DECRE } - | "+" { PLUS } - | "-" { MINUS } - | "/" { DIV } - | "*" { TIMES } - | "%" { MOD } - | "=" { ASSIGN } - | ">" { GT } - | "<" { LT } - | "!" { NOT } - | "==" { EQUAL } - | "!=" { NOTEQUAL } - | "<=" { LE } - | ">=" { GE } - | "&&" { AND } - | "||" { OR } - | ";" { SEMICOLON } - | "{" { LBRACE } - | "}" { RBRACE } - | "(" { LPAR } - | ")" { RPAR } - | integer as nb { try INT (int_of_string nb) with Failure "int_of_string" -> raise_error (Illegal_int(nb)) lexbuf } - | lower_id as str { LOWERIDENT str } - | upper_id as str { UPPERIDENT str } - | _ as c { raise_error (Illegal_character(c)) lexbuf } - - { - let rec examine_all lexbuf = - let res = nexttoken lexbuf in - print_lexeme res; - print_string " "; - match res with - | EOF -> () - | _ -> examine_all lexbuf - } +{ + open SyntaxAnalyser + + let print_lexeme = function + | EOL -> print_string "EOL" + | EOF -> print_string "EOF" + | PLUS -> print_string "PLUS" + | MINUS -> print_string "MINUS" + | DIV -> print_string "DIV" + | TIMES -> print_string "TIMES" + | INCRE -> print_string "INCRE" + | DECRE -> print_string "DECRE" + | ASSIGN -> print_string "ASSIGN" + | GT -> print_string "GT" + | LT -> print_string "LT" + | NOT -> print_string "NOT" + | EQUAL -> print_string "EQUAL" + | NOTEQUAL -> print_string "NOTEQUAL" + | LE -> print_string "LE" + | GE -> print_string "GE" + | AND -> print_string "AND" + | OR -> print_string "OR" + | INT i -> print_string "INT("; print_int i; print_string ")" + | ENDOFLINECOMMENT ic -> print_string "ENDOFLINECOMMENT("; print_string ic; print_string ")" + | TRADITIONALCOMMENT mc -> print_string "TRADITIONALCOMMENT("; print_string mc; print_string ")" + | IF -> print_string "IF" + | ELSE -> print_string "ELSE" + | LOWERIDENT s -> print_string "LOWERIDENT("; print_string s; print_string ")" + | UPPERIDENT s -> print_string "UPPERIDENT("; print_string s; print_string ")" + | SEMICOLON -> print_string "SEMICOLON" + | LBRACE -> print_string "LBRACE" + | RBRACE -> print_string "RBRACE" + | LPAR -> print_string "LPAR" + | RPAR -> print_string "RPAR" + | BOOLEAN b -> print_string "BOOL("; print_string(string_of_bool b); print_string ")" + | NULL -> print_string "NULL" + | COMMA -> print_string "COMMA" + | STRING s-> print_string "STRING("; print_string s; print_string ")"; + + (*Class print*) + | CLASS -> print_string "CLASS" + | NEW -> print_string "NEW" + | THIS -> print_string "THIS" + | STATIC -> print_string "STATIC" + | DOT -> print_string "." + + + open Lexing + exception Eof + + type error = + | Illegal_character of char + | Illegal_int of string + exception Error of error * position * position + + let raise_error err lexbuf = + raise (Error(err, lexeme_start_p lexbuf, lexeme_end_p lexbuf)) + + (* Les erreurs. *) + let report_error = function + | Illegal_character c -> + print_string "Illegal character '"; + print_char c; + print_string "' " + | Illegal_int nb -> + print_string "The int "; + print_string nb; + print_string " is illegal " +} + +let lower_ch = ['a'-'z'] +let upper_ch = ['A'-'Z'] +let digit = ['0'-'9'] +let integer = digit+ +let lower_id = lower_ch (lower_ch | upper_ch | digit | '_')* +let upper_id = upper_ch (lower_ch | upper_ch | digit | '_')* +(* Literal *) +let str = '"' ([^ '"'] |'\092''"')* '"' +let boolean = "true" | "false" +let space = [' ' '\009' '\012'] +let newline = ('\010' | '\013' | "\013\010") +let not_newline = [^ '\n' '\r'] +(* Comments *) +let endofline_comment = "//" not_newline* +let not_star = [^ '*'] +let not_star_not_slash = [^ '*' '/'] +let traditional_comment = "/*" not_star* "*"+ (not_star_not_slash not_star* "*"+)* "/" + +rule nexttoken = parse + (*Class*) + | "class" { CLASS } + | "new" { NEW } + | "this" { THIS } + | "." { DOT } + | "," { COMMA} + | "static" { STATIC } + + | newline { Location.incr_line lexbuf; nexttoken lexbuf } + | space+ { nexttoken lexbuf } + | endofline_comment as c { ENDOFLINECOMMENT c} + | traditional_comment as c { TRADITIONALCOMMENT c} + | "if" { IF } + | "else" { ELSE } + | boolean as bl { BOOLEAN (bool_of_string bl) } + | "null" { NULL } + | str as st { STRING st} + | eof { EOF } + | "++" { INCRE } + | "--" { DECRE } + | "+" { PLUS } + | "-" { MINUS } + | "/" { DIV } + | "*" { TIMES } + | "%" { MOD } + | "=" { ASSIGN } + | ">" { GT } + | "<" { LT } + | "!" { NOT } + | "==" { EQUAL } + | "!=" { NOTEQUAL } + | "<=" { LE } + | ">=" { GE } + | "&&" { AND } + | "||" { OR } + | ";" { SEMICOLON } + | "{" { LBRACE } + | "}" { RBRACE } + | "(" { LPAR } + | ")" { RPAR } + | integer as nb { try INT (int_of_string nb) with Failure "int_of_string" -> raise_error (Illegal_int(nb)) lexbuf } + | lower_id as str { LOWERIDENT str } + | upper_id as str { UPPERIDENT str } + | _ as c { raise_error (Illegal_character(c)) lexbuf } + + + + { + let rec examine_all lexbuf = + let res = nexttoken lexbuf in + print_lexeme res; + print_string " "; + match res with + | EOF -> () + | _ -> examine_all lexbuf + } diff --git a/Parsing/SyntaxAnalyser.mly b/Parsing/SyntaxAnalyser.mly index 0d0fae3..8824646 100644 --- a/Parsing/SyntaxAnalyser.mly +++ b/Parsing/SyntaxAnalyser.mly @@ -1,121 +1,189 @@ -/* Headers */ -%{ - open Expression -%} - -/* Tokens */ -/* Seperators */ -%token EOF EOL LPAR RPAR SEMICOLON LBRACE RBRACE - -/* Operators*/ -%token ASSIGN -%token PLUS MINUS TIMES DIV MOD -%token INCRE DECRE NOT -%token GT LT EQUAL NOTEQUAL LE GE -%token AND OR - -/* Literals */ -%token INT -%token STRING -%token BOOLEAN -%token NULL - -/* Comments */ -%token ENDOFLINECOMMENT -%token TRADITIONALCOMMENT - -/* Identifiers*/ -%token LOWERIDENT UPPERIDENT - -/* Keywords */ -%token IF ELSE - -/* Start symbols and types */ -%start expression -%type < Expression.expression list> expression - -/* Priority and associativity */ -%right SEMICOLON -%right ASSIGN -%left OR -%left AND -%left EQUAL NOTEQUAL -%left GT GE LT LE -%left PLUS MINUS -%left TIMES DIV MOD -%right UMINUS UPLUS NOT INCRE DECRE -%left PINCRE PDECRE - -/* End of Declarations */ -%% - -/* Start of Rules */ -expression: - - | comment* EOF {[]} - | e=comment_or_expression r=expression EOF - { e::r } - -comment: - | ENDOFLINECOMMENT {} - | TRADITIONALCOMMENT {} - -comment_or_expression: - | comment* e=expr { e } - - -expr: - | e1=expr SEMICOLON - { Semi(e1)} - | LPAR e=expr RPAR - { e } - | o=uop e=expr - { Unop(o,e) } - | MINUS e=expr %prec UMINUS - { Unop(Uminus,e) } - | PLUS e=expr %prec UPLUS - { Unop(Uplus,e) } - | e=expr INCRE %prec PINCRE - { Postop(e,Pincre) } - | e=expr DECRE %prec PDECRE - { Postop(e,Pdecre) } - | e1=expr o=bop e2=expr - { Binop(o,e1,e2) } - | i=INT - { Int i } - | b=BOOLEAN - { Bool b } - | n=NULL - { Null } - | s=STRING - { String s} - | id=LOWERIDENT - { Var id } - | id=LOWERIDENT ASSIGN e=expr - { Assign(id, e) } - | IF LPAR e1=expr RPAR LBRACE e2=expr RBRACE - { IfThen(e1, e2) } - | IF LPAR e1=expr RPAR LBRACE e2=expr RBRACE ELSE LBRACE e3=expr RBRACE - { IfThenElse(e1, e2, e3) } - -%inline uop: - | NOT {Unot} - | INCRE {Uincre} - | DECRE {Udecre} - -%inline bop: - | MINUS { Bsub } - | PLUS { Badd } - | TIMES { Bmul } - | DIV { Bdiv } - | MOD { Bmod } - | GT { Bgt } - | LT { Blt } - | GE { Bge } - | LE { Ble } - | EQUAL { Bequal } - | NOTEQUAL { Bnotequal } - | OR { Bor } - | AND { Band } - -%% +/* Headers */ +%{ + open Expression +%} + +/* Class Keywords */ +%token CLASS NEW THIS + +/* Tokens */ +/* Seperators */ +%token EOF EOL LPAR RPAR SEMICOLON LBRACE RBRACE COMMA + +/* Operators*/ +%token ASSIGN +%token PLUS MINUS TIMES DIV MOD +%token INCRE DECRE NOT +%token GT LT EQUAL NOTEQUAL LE GE +%token AND OR +%token DOT + +/* Literals */ +%token INT +%token STRING +%token BOOLEAN +%token NULL + +/* Comments */ +%token ENDOFLINECOMMENT +%token TRADITIONALCOMMENT + +/* Identifiers*/ +%token LOWERIDENT UPPERIDENT + +/* Keywords */ +%token IF ELSE STATIC + + +/* Priority and associativity */ +%right SEMICOLON +%right ASSIGN +%left OR +%left AND +%left EQUAL NOTEQUAL +%left GT GE LT LE +%left PLUS MINUS +%left TIMES DIV MOD +%right UMINUS UPLUS NOT INCRE DECRE +%left PINCRE PDECRE + +/* End of Declarations */ + + +/* Start symbols and types */ +%start content +%type < Expression.class_or_expr list> content + +%% + +/* Start of Rules */ +content: + | comment* EOF {[]} + | c=class_or_expression r=content EOF + { c::r } + +class_or_expression: + | e=comment_or_expression {e} + | c=comment_or_class {c} + +comment: + | ENDOFLINECOMMENT {} + | TRADITIONALCOMMENT {} + +comment_or_expression: + | comment* e=expr { Expr(e) } + +comment_or_class: + | comment* c=class_ { Class(c) } + +class_: + | CLASS id=UPPERIDENT LBRACE a=attributes_or_methods RBRACE + { Class_(id,a) } + +attributes_or_methods: + | comment* { [] } + | a=attribute_or_method r=attributes_or_methods { a::r } + +attribute_or_method: + | comment* a=attribute SEMICOLON { Attribute(a) } + | comment* m=method1 { Method_t(m) } + +attribute: + | id=LOWERIDENT {Attr(id)} + | id=LOWERIDENT ASSIGN expr {AttrWithAssign(id)} + +method1: + | STATIC t=UPPERIDENT id=LOWERIDENT LPAR p=params RPAR LBRACE e=exprs RBRACE + { Method(true, t, id, p, e) } + | STATIC t=UPPERIDENT id=LOWERIDENT LPAR RPAR LBRACE e=exprs RBRACE + { Method(true, t, id, [], e) } + | t=UPPERIDENT id=LOWERIDENT LPAR p=params RPAR LBRACE e=exprs RBRACE + { Method(false, t, id, p, e) } + | t=UPPERIDENT id=LOWERIDENT LPAR RPAR LBRACE e=exprs RBRACE + { Method(false, t, id, [], e) } + +exprs: + | {[]} + | e = expr r=exprs {e::r} + +param: + | t=UPPERIDENT id=LOWERIDENT + { Param(t,id) } + +params: + | { [] } + | t=UPPERIDENT id=LOWERIDENT + { [Param(t,id)] } + | t=UPPERIDENT id=LOWERIDENT COMMA r=param+ + { Param(t,id) :: r} + +expr: + | comment+ e=expr + { e } + | e=expr comment+ + { e } + | e1=expr SEMICOLON + { Semi(e1)} + | LPAR e=expr RPAR + { e } + | o=uop e=expr + { Unop(o,e) } + | MINUS e=expr %prec UMINUS + { Unop(Uminus,e) } + | PLUS e=expr %prec UPLUS + { Unop(Uplus,e) } + | e=expr INCRE %prec PINCRE + { Postop(e,Pincre) } + | e=expr DECRE %prec PDECRE + { Postop(e,Pdecre) } + | e1=expr o=bop e2=expr + { Binop(o,e1,e2) } + | i=INT + { Int i } + | b=BOOLEAN + { Bool b } + | n=NULL + { Null } + | s=STRING + { String s} + | id=LOWERIDENT + { Var id } + | id=LOWERIDENT ASSIGN e=expr + { Assign(id, e) } + | IF LPAR e1=expr RPAR LBRACE e2=expr RBRACE + { IfThen(e1, e2) } + | IF LPAR e1=expr RPAR LBRACE e2=expr RBRACE ELSE LBRACE e3=expr RBRACE + { IfThenElse(e1, e2, e3) } + | THIS { This } + | e=expr DOT mthd=LOWERIDENT LPAR args_=args RPAR + { Invoke(e, mthd, args_) } + | NEW t =UPPERIDENT + { New(t)} + +args: + | { [] } + | e=expr { [e] } + | e=expr COMMA res=args { e :: res} + +%inline uop: + | NOT {Unot} + | INCRE {Uincre} + | DECRE {Udecre} + +%inline bop: + | MINUS { Bsub } + | PLUS { Badd } + | TIMES { Bmul } + | DIV { Bdiv } + | MOD { Bmod } + | GT { Bgt } + | LT { Blt } + | GE { Bge } + | LE { Ble } + | EQUAL { Bequal } + | NOTEQUAL { Bnotequal } + | OR { Bor } + | AND { Band } + + +%% diff --git a/build-local b/build-local new file mode 100644 index 0000000..7d12830 --- /dev/null +++ b/build-local @@ -0,0 +1,2 @@ +#!/bin/bash +ocamlbuild Main.byte diff --git a/test-local b/test-local new file mode 100644 index 0000000..54dac45 --- /dev/null +++ b/test-local @@ -0,0 +1,10 @@ +#!/bin/bash +ocamlbuild Main.byte && +FILES=./Evaluator/* +for f in $FILES +do + echo -e "\033[31m Unit test of $f ..." + # take action on each file. $f store current file name + echo -e "\033[0m" + ./_build/Main/Main.byte $f +done