summaryrefslogblamecommitdiff
path: root/minijazz/src/parser/parser.mly
blob: 126ab366d1a4e48cdffc11532d97aa4c0579e7c8 (plain) (tree)
























































































































































































                                                                                       
%{

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 <string> NAME
%token <string> STRING
%token <int> INT
%token <string> BOOL_INT
%token <bool> 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 <Ast.program> 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 }
%%