%{ open Ident open Static open Ast open Location open Misc let fresh_param () = mk_static_exp (SVar ("_n"^(Misc.gen_symbol ()))) %} %token INLINED ROM RAM WHERE END CONST PROBING %token LPAREN RPAREN COLON COMMA EQUAL REG OR XOR NAND AND POWER SLASH %token EOF RBRACKET LBRACKET GREATER LESS NOT SEMICOL PLUS MINUS STAR %token IF THEN ELSE LEQ DOT DOTDOT %token NAME %token STRING %token INT %token BOOL_INT %token BOOL %left DOT %left OR PLUS %left LEQ EQUAL %right MINUS %left NAND XOR AND %left STAR SLASH %right NOT REG %right POWER %start program %type program %% /** Tools **/ %inline slist(S, x) : l=separated_list(S, x) {l} %inline snlist(S, x) : l=separated_nonempty_list(S, x) {l} %inline tuple(x) : LPAREN h=x COMMA t=snlist(COMMA,x) RPAREN { h::t } %inline tag_option(P,x): |/* empty */ { None } | P v=x { Some(v) } localize(x): y=x { y, (Loc($startpos(y),$endpos(y))) } program: | c=const_decs n=node_decs EOF { mk_program c n } const_decs: c=list(const_dec) {c} const_dec: | CONST n=name EQUAL se=static_exp option(SEMICOL) { mk_const_dec ~loc:(Loc($startpos,$endpos)) n se } name: n=NAME { n } ident: | n=name { ident_of_string n } type_ident: LBRACKET se=static_exp RBRACKET { TBitArray se } node_name: | n=name { reset_symbol_table (); n } node_decs: ns=list(node_dec) { ns } node_dec: inlined=inlined_status n=node_name p=params LPAREN args=args RPAREN EQUAL out=node_out WHERE b=block probes=probe_decls END WHERE option(SEMICOL) { mk_node n (Loc ($startpos,$endpos)) inlined args out p b probes } node_out: | a=arg { [a] } | LPAREN out=args RPAREN { out } inlined_status: | INLINED { Inlined } | /*empty*/ { NotInlined } params: | /*empty*/ { [] } | LESS pl=snlist(COMMA,param) GREATER { pl } param: n=NAME { mk_param n } args: vl=slist(COMMA, arg) { vl } arg: | n=ident COLON t=type_ident { mk_var_dec n t } | n=ident { mk_var_dec n TBit } block: | eqs=equs { BEqs (eqs, []) } | IF se=static_exp THEN thenb=block ELSE elseb=block END IF { BIf(se, thenb, elseb) } equs: eq=equ tl=equ_tail { eq::tl } equ_tail: | /*empty*/ { [] } | SEMICOL { [] } | SEMICOL eq=equ tl=equ_tail { eq::tl } equ: p=pat EQUAL e=exp { mk_equation p e } pat: | n=ident { Evarpat n } | LPAREN p=snlist(COMMA, ident) RPAREN { Etuplepat p } static_exp: se=_static_exp { mk_static_exp ~loc:(Loc ($startpos,$endpos)) se } _static_exp : | i=INT { SInt i } | n=NAME { SVar n } | LPAREN se=_static_exp RPAREN { se } /*integer ops*/ | se1=static_exp POWER se2=static_exp { SBinOp(SPower, se1, se2) } | se1=static_exp PLUS se2=static_exp { SBinOp(SAdd, se1, se2) } | se1=static_exp MINUS se2=static_exp { SBinOp(SMinus, se1, se2) } | se1=static_exp STAR se2=static_exp { SBinOp(SMult, se1, se2) } | se1=static_exp SLASH se2=static_exp { SBinOp(SDiv, se1, se2) } /*bool ops*/ | se1=static_exp EQUAL se2=static_exp { SBinOp(SEqual, se1, se2) } | se1=static_exp LEQ se2=static_exp { SBinOp(SLeq, se1, se2) } exps: LPAREN e=slist(COMMA, exp) RPAREN {e} exp: e=_exp { mk_exp ~loc:(Loc ($startpos,$endpos)) e } _exp: | e=_simple_exp { e } | c=const { Econst c } | REG e=exp { Ereg e } | n=NAME p=call_params a=exps { Ecall (n, p, a) } | e1=exp PLUS e2=exp { Ecall ("or", [], [e1; e2]) } | e1=exp OR e2=exp { Ecall ("or", [], [e1; e2]) } | e1=exp AND e2=exp { Ecall ("and", [], [e1; e2]) } | e1=exp POWER e2=exp { Ecall("xor", [], [e1; e2]) } | e1=exp XOR e2=exp { Ecall ("xor", [], [e1; e2]) } | e1=exp NAND e2=exp { Ecall ("nand", [], [e1; e2]) } | NOT a=exp { Ecall ("not", [], [a])} | e1=exp DOT e2=exp { Ecall("concat", [fresh_param(); fresh_param(); fresh_param ()], [e1; e2]) } | e1=simple_exp LBRACKET idx=static_exp RBRACKET { Ecall ("select", [idx; fresh_param()], [e1]) } | e1=simple_exp LBRACKET low=static_exp DOTDOT high=static_exp RBRACKET { Ecall("slice", [low; high; fresh_param()], [e1]) } | e1=simple_exp LBRACKET low=static_exp DOTDOT RBRACKET { let n = fresh_param () in let high = mk_static_exp (SBinOp(SMinus, n, mk_static_exp (SInt 1))) in Ecall("slice", [low; high; n], [e1]) } | e1=simple_exp LBRACKET DOTDOT high=static_exp RBRACKET { let params = [mk_static_exp (SInt 0); high; fresh_param ()] in Ecall("slice", params, [e1]) } | ro=rom_or_ram LESS addr_size=static_exp COMMA word_size=static_exp input_file=tag_option(COMMA, STRING) GREATER a=exps { Emem(ro, addr_size, word_size, input_file, a) } simple_exp: e=_simple_exp { mk_exp ~loc:(Loc ($startpos,$endpos)) e } _simple_exp: | n=ident { Evar n } | LPAREN e=_exp RPAREN { e } const: | b=BOOL { VBit b } | b=BOOL_INT { VBitArray (bool_array_of_string b) } | i=INT { match i with | 0 -> VBit false | 1 -> VBit true | _ -> raise Parsing.Parse_error } | LBRACKET RBRACKET { VBitArray (Array.make 0 false) } rom_or_ram : | ROM { MRom } | RAM { MRam } call_params: | /*empty*/ { [] } | LESS pl=snlist(COMMA,static_exp) GREATER { pl } probe_decls: | /*empty*/ { [] } | PROBING l=separated_nonempty_list(COMMA, ident) { l } %%