summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaweł Dybiec <pdybiec@stud.cs.uni.wroc.pl>2018-11-05 01:10:25 +0100
committerPaweł Dybiec <pdybiec@stud.cs.uni.wroc.pl>2018-11-05 01:10:25 +0100
commitd3519fcd2076e6fb1b0bb01757fa0373b464dd28 (patch)
tree505d782f8c48d0e9049f7592d0de412a98facb06
parentfc004d69245b3d7af7326298d2bdbdb259127a68 (diff)
Add more expressions and statements
-rw-r--r--source/mod_student/lexer.mll26
-rw-r--r--source/mod_student/parser.mly54
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>INT
%token <string>IDENTIFIER
+%token <string>STRING
%token <char>CHAR
%token <bool>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