From d3519fcd2076e6fb1b0bb01757fa0373b464dd28 Mon Sep 17 00:00:00 2001 From: Paweł Dybiec Date: Mon, 5 Nov 2018 01:10:25 +0100 Subject: Add more expressions and statements --- source/mod_student/lexer.mll | 26 +++++++++++++++++++-- source/mod_student/parser.mly | 54 +++++++++++++++++++++++++++++++++++++++---- 2 files changed, 74 insertions(+), 6 deletions(-) diff --git a/source/mod_student/lexer.mll b/source/mod_student/lexer.mll index ae11472..d26912f 100644 --- a/source/mod_student/lexer.mll +++ b/source/mod_student/lexer.mll @@ -19,7 +19,27 @@ (* vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv * Miejsce na twój kod w Ocamlu *) - +let explode s = + let rec exp i l = + if i < 0 then l else exp (i - 1) (s.[i] :: l) in + exp (String.length s - 1) [];; +let implode l = + let res = Bytes.create (List.length l) in + let rec imp i = function + | [] -> res + | c :: l -> Bytes.set res i c; imp (i + 1) l in + Bytes.to_string(imp 0 l);; + + let unescape str = + let rec aux x= match x with + | ['"'] -> [] + | '\\'::'\\'::xs ->'\\'::(aux xs) + | '\\'::'n'::xs ->'\n'::(aux xs) + | '\\'::'"'::xs ->'"'::(aux xs) + | x::xs ->x::(aux xs) + | [] -> failwith "missing \" in escaped string" + in implode (aux (List.tl (explode str) ) ) ;; + (* ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ----------------------------------------------------------------------------- *) @@ -31,7 +51,8 @@ *) let identifier = ['a'-'z' '_' 'A' - 'Z']['_' 'A' - 'Z' 'a'-'z' '0'-'9']* - let integer = ['0'-'9']* + let integer = ['0'-'9']+ + let str = "\""(([^ '\n''"''\\'])|('\\'['n''\\''"']))*"\"" (* ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ----------------------------------------------------------------------------- *) @@ -55,6 +76,7 @@ (* vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv * Miejsce na twoje reguły *) + | str as e { STRING (unescape e) } | "," { COMMA } | "(" { LPAREN } | ")" { RPAREN } diff --git a/source/mod_student/parser.mly b/source/mod_student/parser.mly index 76d7fe6..f516a9a 100644 --- a/source/mod_student/parser.mly +++ b/source/mod_student/parser.mly @@ -60,6 +60,7 @@ let mkTag = %token LENGTH %token INT %token IDENTIFIER +%token STRING %token CHAR %token BOOL %token T_BOOL @@ -83,12 +84,18 @@ file: { ModuleDefinition {global_declarations=[] } } func: - | id=identifier LPAREN parameters=separated_list(COMMA,argument) RPAREN return=separated_list(COMMA,typ) body=option(statement_block) + | id=identifier LPAREN parameters=separated_list(COMMA,var_decl) RPAREN return=return_type body=option(statement_block) { GDECL_Function { loc=mkLocation $startpos; id=id;formal_parameters=parameters; return_types=return;body=body} } -argument: +var_decl: | id = identifier COLON t=typ { VarDecl {loc=mkLocation $startpos;id=id;tp=t} } +return_type: + | return = option(preceded(COLON,separated_list(COMMA,typ) ) ) + { match return with + | None -> [] + | Some l -> l + } typ: | t=base_type { t } | t=typ LSBRACKET dim=option(expression) RSBRACKET @@ -131,7 +138,7 @@ expression_eq: | node=expression_cmp {node} | left=expression_eq op=op_eq_prec right=expression_cmp {EXPR_Relation {tag=mkTag ();loc=mkLocation $startpos; - op=RELOP_Eq;lhs=left;rhs=right } } + op=op;lhs=left;rhs=right } } expression_cmp: | node=expression_add {node} | left=expression_cmp op=op_cmp_prec right=expression_add @@ -153,8 +160,14 @@ expression_unary: {EXPR_Unop {tag=mkTag ();loc=mkLocation $startpos; op=op;sub=right } } expression_highest_prec: + | node=expression_base { node } + | node=expression_call { node } + | node=expression_length { node } +expression_base: | node=expression_integer { node } | node=expression_identifier { node } + | node=expression_string { node } + | LPAREN node=expression RPAREN { node } (* TODO Add calls and arrays and other constants *) expression_integer: | value=INT { EXPR_Int {tag= mkTag ();loc=mkLocation $startpos; @@ -162,14 +175,47 @@ expression_integer: expression_identifier: | id=identifier { EXPR_Id {tag= mkTag ();loc=mkLocation $startpos; id=id} } +expression_string: + | value=str { EXPR_String {tag= mkTag ();loc=mkLocation $startpos; + value=value} } +expression_call: + | value=call { EXPR_Call value } +expression_length: + | LENGTH LPAREN argument=expression RPAREN + { EXPR_Length { tag=mkTag (); loc=mkLocation $startpos; + arg=argument } } statement_block: | LBRACKET body=list(statement) RBRACKET { STMTBlock { loc=mkLocation $startpos;body=body } } statement: - | block=statement_block {STMT_Block block } + | left=lvalue ASSIGN right=expression { STMT_Assign {loc=mkLocation $startpos; + lhs=left;rhs=right} } + | block=statement_block {STMT_Block block } + | call=call {STMT_Call call } + | var=var_decl init=option(preceded(ASSIGN,expression)) + {STMT_VarDecl { var=var;init=init } } + | WHILE cond=expression body=statement + { STMT_While {loc=mkLocation $startpos;cond=cond;body=body } } + | IF cond=expression then_branch=statement else_branch=option(preceded(ELSE,statement)) + { STMT_If {loc=mkLocation $startpos;cond=cond;then_branch=then_branch; + else_branch=else_branch } } + | RETURN values=separated_list(COMMA,expression) + { STMT_Return {loc=mkLocation $startpos;values=values } } +call: + | callee=identifier LPAREN arguments=separated_list(COMMA,expression) RPAREN + { Call { tag=mkTag (); loc=mkLocation $startpos; + callee=callee; arguments=arguments } } + (* TODO Add other statements *) +lvalue: + | id=identifier {LVALUE_Id {loc=mkLocation $startpos;id=id} } + (* TODO lvalue index *) + identifier: | IDENTIFIER { Identifier $1 } +str: + | STRING + { $1 } (* ** przykład użycia mkLocation -- cgit 1.4.1