
#vim: set syntax=rules:

init_code:
{
   string[] tabs;
}

terminals:
   single_char_const {'\''.!'\0'.'\''}
   octal_char_const {'\''.'\\'.<07>.(<07>+e).(<07>+e).'\''}
   hex_char_const {'\''.'\\'.'x'.(<09>+<af>+<AF>).(<09>+<af>+<AF>+e).'\''}
   backslash_char_const {'\''.'\\'.[abfnrtv\\?\'"].'\''}

   oct_int_const {'0'.<07>*}
   dec_int_const {<19>.d*}
   hex_int_const {'0'.[xX].(<09>+<af>+<AF>).(<09>+<af>+<AF>)*}

   oct_long_int_const {'0'.<07>.<07>*.[lL]}
   dec_long_int_const {<19>.d*.[lL]}
   hex_long_int_const {'0'.[xX].(<09>+<af>+<AF>).(<09>+<af>+<AF>)*.[lL]}

   oct_unsigned_int_const {'0'.<07>.<07>*.[uU]}
   dec_unsigned_int_const {<19>.d*.[uU]}
   hex_unsigned_int_const {'0'.[xX].(<09>+<af>+<AF>).(<09>+<af>+<AF>)*.[uU]}

   oct_unsigned_long_int_const {'0'.<07>.<07>*.[uU].[lL]}
   dec_unsigned_long_int_const {<19>.d*.[uU].[lL]}
   hex_unsigned_long_int_const {'0'.[xX].(<09>+<af>+<AF>).(<09>+<af>+<AF>)*.[uU].[lL]}

   double_const {(d*.((d.'.')+('.'.d)).d*)+((d*.((d.'.')+('.'.d)+d).d*).[eE].([+-]+e).d.d*)}
   float_const {((d*.((d.'.')+('.'.d)).d*)+((d*.((d.'.')+('.'.d)+d).d*).[eE].([+-]+e).d.d*)).[fF]}
   long_double_const {((d*.((d.'.')+('.'.d)).d*)+((d*.((d.'.')+('.'.d)+d).d*).[eE].([+-]+e).d.d*)).[lL]}

   string_const {'"'.(|\\\"|+(('\\'.<07>.(<07>+e).(<07>+e))+('\\'.'x'.(<09>+<af>+<AF>).(<09>+<af>+<AF>+e))+('\\'.[abfnrtv\\?\'"])))*.'"'}

   id {('_'+l).('_'+l+d)*}

   fun {"fun"}
   struct {"struct"}

   lr_br {'('}
   rr_br {')'}

   lc_br {'{'}
   rc_br {'\}'}

   le_br {'['}
   re_br {']'}

   comma {','}
   semicolon {';'}

   if {"if"}
   else {"else"}
   do {"do"}
   while {"while"}
   break {"break"}
   continue {"continue"}
   return {"return"}

   new {"new"}
   this {"this"}
   thread {"thread"}
   dsp_block {"dsp_block"}

   char {"char"}
   int {"int"}
   double {"double"}
   array {"array"}

   equal {'='}
   plus_equal {"+="}
   minus_equal {"-="}
   asterisk_equal {"*="}
   slash_equal {"/="}
   percent_equal {"%="}
   double_ls_br_equal {"<<="}
   double_rs_br_equal {">>="}
   ampersand_equal {"&="}
   pipe_equal {"|="}
   circumflex_equal {"^="}
   double_ampersand {"&&"}
   double_pipe {"||"}
   ampersand {'&'}
   pipe {'|'}
   circumflex {'^'}
   double_equal {"=="}
   exclamation_equal {"!="}
   rs_br {'>'}
   ls_br {'<'}
   rs_br_equal {">="}
   ls_br_equal {"<="}
   double_rs_br {">>"}
   double_ls_br {"<<"}
   plus {'+'}
   minus {'-'}
   dot {'.'}
   dash_rs_br {"->"}
   asterisk {'*'}
   slash {'/'}
   percent {'%'}
   double_plus {"++"}
   double_minus {"--"}
   exclamation {'!'}
   tilde {'~'}

   _SKIP_ {w.w*}
   _SKIP__ {'#'.!'\n'*.'\n'}
   _SKIP___ {"//".!'\n'*.'\n'}
   _SKIP____ {"/*".(!'*'+('*'.!'/'))*."*/"}
   _END_ {'\0'}

nonterminals:
   <start>

   <program>
   <pb_list>
   <pb_element>

   <struct_def>
   <struct_name>
   <struct_body>
   <sb_element>
   <sb_var_list>

   <fun_def>
   <fun_name>
   <fun_parms>
   <fun_parm_list>
   <fun_parm>
   <fun_body>

   <cmd_block>
   <cmd_block_begin>

   <cmd_list>
   <cmd>

   <if_cond>
   <if_body>
   <if_else>

   <do_begin>
   <do_cond>
   <do_exp>

   <while_cond>
   <while_exp>

   <exp>
   <H>
   <G>
   <F>
   <E>
   <D>
   <C>
   <B>
   <A>
   
   <fcall_parms>
   <fcall_parms_begin>
   <fcall_parm_list>

   <struct_member>

   <mcall_parms>
   <mcall_parms_begin>
   <mcall_parm_list>

   <thread_def_begin>
   <thread_parms>
   <thread_parm_list>
   <thread_body>

   <array_type>
   <array_element_begin>
   <array_element_list>

rules:
   <start> -> <program> ->> {null}

   <program> -> <pb_list> _END_ ->> {null}
   <program> -> _END_ ->> {null}

   <pb_list> -> <pb_element> <pb_list> ->> {null}
   <pb_list> -> <pb_element> ->> {null}

   <pb_element> -> <struct_def> ->> {null}
   <pb_element> -> <fun_def> ->> {null}
   <pb_element> -> <cmd> ->> {null}

   $ -- zapis definice struktury --
   <struct_def> -> <struct_name> lc_br <struct_body> rc_br ->> {pop(tabs);out(tabs,"definition_struct_end\n");}
   <struct_name> -> struct id ->> {out(tabs,"definition_struct_begin: ",rule_body(1),"\n");push(tabs,"   ");}

   <struct_body> -> <struct_body> <sb_element> ->> {null}
   <struct_body> -> <sb_element> ->> {null}

   <sb_element> -> <sb_var_list> semicolon ->> {null}
   <sb_element> -> <fun_def> ->> {null}

   <sb_var_list> -> id ->> {out(tabs,"definition_struct_variable: ",rule_body(0),"\n");}
   <sb_var_list> -> <sb_var_list> comma id ->> {out(tabs,"definition_struct_variable: ",rule_body(2),"\n");}

   $ -- zapis definice funkce --
   <fun_def> -> <fun_name> <fun_parms> rr_br <fun_body> ->> {pop(tabs);out(tabs,"definition_fun_end\n");}
   <fun_name> -> fun id ->> {out(tabs,"definition_fun_begin: ",rule_body(1),"\n");push(tabs,"   ");}

   <fun_parms> -> lr_br ->> {out(tabs,"definition_fun_params\n");}
   <fun_parms> -> lr_br <fun_parm_list> ->> {out(tabs,"definition_fun_params\n");}

   <fun_parm_list> -> <fun_parm_list> comma <fun_parm> ->> {null}
   <fun_parm_list> -> <fun_parm> ->> {null}

   <fun_parm> -> id ->> {out(tabs,"definition_fun_parameter: ",rule_body(0),"\n");}
   <fun_parm> -> ampersand id ->> {out(tabs,"definition_fun_ref_parameter: ",rule_body(1),"\n");}

   <fun_body> -> lc_br rc_br ->> {null}
   <fun_body> -> lc_br <cmd_list> rc_br ->> {null}

   $ -- blok prikazu --
   <cmd_block> -> lc_br rc_br ->> {null}
   <cmd_block> -> <cmd_block_begin> <cmd_list> rc_br ->> {pop(tabs);out(tabs,"definition_cmd_block_end\n");}
   <cmd_block_begin> -> lc_br ->> {out(tabs,"definition_cmd_block_begin\n");push(tabs,"   ");}

   $ -- vetveni prikazu --
   <cmd_list> -> <cmd_list> <cmd> ->> {null}
   <cmd_list> -> <cmd> ->> {null}

   $ -- zapis bloku prikazu --
   <cmd> -> <cmd_block> ->> {null}

   $ -- zapis podmineneho vetveni --
   <cmd> -> if <if_cond> <if_body> ->> {out(tabs,"if_end\n");}
   <if_cond> -> lr_br <exp> rr_br ->> {out(tabs,"if_cond\n");}
   <if_body> -> <cmd> ->> {null}
   <if_body> ->  <if_else> <cmd> ->> {null}
   <if_else> -> <cmd> else ->> {out(tabs,"if_else\n");}

   $ -- zapis cyklu do - while --
   <cmd> -> <do_begin> <cmd> while <do_cond> semicolon ->> {null}
   <do_begin> -> do ->> {out(tabs,"do_begin\n");}
   <do_cond> -> <do_exp> <exp> rr_br ->> {out(tabs,"do_cond\n");}
   <do_exp> -> lr_br ->> {out(tabs,"do_exp\n");}

   $ -- zapis cyklu while --
   <cmd> -> while <while_cond> <cmd> ->> {out(tabs,"while_end\n");}
   <while_cond> -> <while_exp> <exp> rr_br ->> {out(tabs,"while_cond\n");}
   <while_exp> -> lr_br ->> {out(tabs,"while_exp\n");}

   $ -- zapis klicoveho slova break --
   <cmd> -> break semicolon ->> {out(tabs,"cmd_break\n");}
   
   $ -- zapis klicoveho slova continue --
   <cmd> ->  continue semicolon ->> {out(tabs,"cmd_continue\n");}

   $ -- zaps klicoveho slova return --
   <cmd> -> return <exp> semicolon ->> {out(tabs,"cmd_return\n");}

   $ -- zapis vyrazu --
   <cmd> -> <exp> semicolon ->> {out(tabs," - exp_end\n");}
   <exp> -> <H> ->> {null}

   $ -- operatory --
  
   <H> -> <H> equal <H> ->> {out(tabs," - operator_binary_equal\n");}
   <H> -> <H> plus_equal <H> ->> {out(tabs," - operator_binary_plus_equal\n");}
   <H> -> <H> minus_equal <H> ->> {out(tabs," - operator_binary_minus_equal\n");}
   <H> -> <H> asterisk_equal <H> ->> {out(tabs," - operator_binary_asterisk_equal\n");}
   <H> -> <H> slash_equal <H> ->> {out(tabs," - operator_binary_slash_equal\n");}
   <H> -> <H> percent_equal <H> ->> {out(tabs," - operator_binary_pecent_equal\n");}
   <H> -> <H> double_ls_br_equal <H> ->> {out(tabs," - operator_binary_double_ls_br_equal\n");}
   <H> -> <H> double_rs_br_equal <H> ->> {out(tabs," - operator_binary_double_rs_br_equal\n");}
   <H> -> <H> ampersand_equal <H> ->> {out(tabs," - operator_binary_ampersand_equal\n");}
   <H> -> <H> pipe_equal <H> ->> {out(tabs," - operator_binary_pipe_equal\n");}
   <H> -> <H> circumflex_equal <H> ->> {out(tabs," - operator_binary_circumflex_equal\n");}
   <H> -> <G> ->> {null}

   <G> -> <G> double_ampersand <G> ->> {out(tabs," - operator_binary_double_ampersand\n");}
   <G> -> <G> double_pipe <G> ->> {out(tabs," - operator_binary_double_pipe\n");}
   <G> -> <F> ->> {null}

   <F> -> <F> ampersand <F> ->> {out(tabs," - operator_binary_ampersand\n");}
   <F> -> <F> pipe <F> ->> {out(tabs," - operator_binary_pipe\n");}
   <F> -> <F> circumflex <F> ->> {out(tabs," - operator_binary_circumflex\n");}
   <F> -> <E> ->> {null}

   <E> -> <E> double_equal <E> ->> {out(tabs," - operator_binary_double_equal\n");}
   <E> -> <E> exclamation_equal <E> ->> {out(tabs," - operator_binary_exclamation_equal\n");}
   <E> -> <E> rs_br <E> ->> {out(tabs," - operator_binary_rs_br\n");}
   <E> -> <E> ls_br <E> ->> {out(tabs," - operator_binary_ls_br\n");}
   <E> -> <E> rs_br_equal <E> ->> {out(tabs," - operator_binary_rs_br_equal\n");}
   <E> -> <E> ls_br_equal <E> ->> {out(tabs," - operator_binary_ls_br_equal\n");}
   <E> -> <D> ->> {null}

   <D> -> <D> double_rs_br <D> ->>{out(tabs," - operator_binary_double_rs_br\n");}
   <D> -> <D> double_ls_br <D> ->>{out(tabs," - operator_binary_double_ls_br\n");}
   <D> -> <C> ->> {null}

   <C> -> <C> plus <C> ->> {out(tabs," - operator_binary_plus\n");}
   <C> -> <C> minus <C> ->> {out(tabs," - operator_binary_minus\n");}
   <C> -> <B> ->> {null}

   <B> -> <B> asterisk <B> ->> {out(tabs," - operator_binary_asterisk\n");}
   <B> -> <B> slash <B> ->> {out(tabs," - operator_binary_slash\n");}
   <B> -> <B> percent <B> ->> {out(tabs," - operator_binary_percent\n");}

   <B> -> <B> double_plus ->> {out(tabs," - operator_unary_post_double_plus\n");}
   <B> -> <B> double_minus ->> {out(tabs," - operator_unary_post_double_minus\n");}
   <B> -> double_plus <B> ->> {out(tabs," - operator_unary_pre_double_plus\n");}
   <B> -> double_minus <B> ->> {out(tabs," - operator_unary_pre_double_minus\n");}
   <B> -> plus <B> ->> {out(tabs," - operator_unary_pre_plus\n");}
   <B> -> minus <B> ->> {out(tabs," - operator_unary_pre_minus\n");}
   <B> -> exclamation <B> ->> {out(tabs," - operator_unary_pre_exclamation\n");}
   <B> -> tilde <B> ->> {out(tabs," - operator_unary_pre_tilde\n");}
   <B> -> <A> ->> {null}

   <A> -> <A> le_br <H> re_br ->> {out(tabs," - operator_binary_le_br_re_br\n");}

   $ -- zapis identifikatoru --
   <A> -> id ->> {out(tabs," - identifier: ",rule_body(0),"\n");}

   $ -- zapis volani funkce --
   <A> -> id <fcall_parms> rr_br ->> {out(tabs,"function_call: ",rule_body(0),"\n");}

   <fcall_parms> -> <fcall_parms_begin> ->> {null}
   <fcall_parms> -> <fcall_parms_begin> <fcall_parm_list> ->> {null}

   <fcall_parms_begin> -> lr_br ->> {out(tabs,"fcall_param_begin\n");}

   <fcall_parm_list> -> <fcall_parm_list> comma <exp> ->> {out(tabs,"fcall_parameter\n");}
   <fcall_parm_list> -> <exp> ->> {out(tabs,"fcall_parameter\n");}

   $ -- zapis vyzvednuti promenne ze struktury --
   <A> -> <struct_member> ->> {out(tabs," - struct_element\n");}

   $ -- zapis volani metody --
   <A> -> <struct_member> <mcall_parms> rr_br ->> {out(tabs,"method_call\n");}

   <struct_member> -> <A> dot id ->> {out(tabs,"struct_member: ",rule_body(2),"\n");}

   <mcall_parms> -> <mcall_parms_begin> ->> {null}
   <mcall_parms> -> <mcall_parms_begin> <mcall_parm_list> ->> {null}

   <mcall_parms_begin> -> lr_br ->> {out(tabs,"mcall_param_begin\n");}

   <mcall_parm_list> -> <mcall_parm_list> comma <exp> ->> {out(tabs,"mcall_parameter\n");}
   <mcall_parm_list> -> <exp> ->> {out(tabs,"mcall_parameter\n");}

   $ -- zapis vytvoreni noveho objektu podle struktury --
   <A> -> new id ->> {out(tabs,"new_object: ->",rule_body(1),"<-\n");}

   $ -- zapis oznaceni this promenne v metode struktury --
   <A> -> this ->> {out(tabs," - this\n");}

   $ -- zapis vytvoreni noveho vlakna --
   <A> -> <thread_def_begin> <thread_parms> rr_br <thread_body> ->> {pop(tabs);out(tabs,"thread_def_end\n");}
   
   <thread_def_begin> -> thread ->> {out(tabs,"thread_def_begin\n");push(tabs,"   ");}

   <thread_parms> -> lr_br ->> {out(tabs,"thread_def_parameters\n");}
   <thread_parms> -> lr_br <thread_parm_list> ->> {out(tabs,"thread_def_parameters\n");}

   <thread_parm_list> -> <thread_parm_list> comma id ->> {out(tabs,"thread_parameter: ",rule_body(2),"\n");}
   <thread_parm_list> -> id ->> {out(tabs,"thread_parameter: ",rule_body(0),"\n");}

   <thread_body> -> lc_br rc_br ->> {null}
   <thread_body> -> lc_br <cmd_list> rc_br ->> {null}

   $ -- zapis vytvoreni nove dsp operace --
   <A> -> dsp_block ->> {out(tabs,"dsp_block join point\n");}

   $ -- zapis vytvoreni noveho pole --
   <A> -> <array_type> <array_element_begin> rr_br ->> {null}

   <array_type> -> char ->> {out(tabs,"new_char_array\n");}
   <array_type> -> int ->> {out(tabs,"new_int_array\n");}
   <array_type> -> double ->> {out(tabs,"new_double_array\n");}
   <array_type> -> array ->> {out(tabs,"new_array\n");}

   $ -- zapis prvku poli a seznamu --
   <array_element_begin> -> lr_br ->> {null}
   <array_element_begin> -> lr_br <array_element_list> ->> {null}

   <array_element_list> -> <array_element_list> comma <exp> ->> {out(tabs," - array_element\n");}
   <array_element_list> -> <exp> ->> {out(tabs," - array_element\n");}

   $ -- zapisy zakladnich konstantnich hodnot --
   <A> -> single_char_const ->> {out(tabs," - single_char_const: ->",rule_body(0),"<-\n");}
   <A> -> octal_char_const ->> {out(tabs," - octal_char_const: ->",rule_body(0),"<-\n");}
   <A> -> hex_char_const ->> {out(tabs," - hex_char_const: ->",rule_body(0),"<-\n");}
   <A> -> backslash_char_const ->> {out(tabs," - backslash_char_const: ->",rule_body(0),"<-\n");}

   <A> -> oct_int_const ->> {out(tabs," - oct_int_const: ->",rule_body(0),"<-\n");}
   <A> -> dec_int_const ->> {out(tabs," - dec_int_const: ->",rule_body(0),"<-\n");}
   <A> -> hex_int_const ->> {out(tabs," - hex_int_const: ->",rule_body(0),"<-\n");}

   <A> -> oct_long_int_const ->> {out(tabs," - oct_long_int_const: ->",rule_body(0),"<-\n");}
   <A> -> dec_long_int_const ->> {out(tabs," - dec_long_int_const: ->",rule_body(0),"<-\n");}
   <A> -> hex_long_int_const ->> {out(tabs," - hex_long_int_const: ->",rule_body(0),"<-\n");}

   <A> -> oct_unsigned_int_const ->> {out(tabs," - oct_unsigned_int_const: ->",rule_body(0),"<-\n");}
   <A> -> dec_unsigned_int_const ->> {out(tabs," - dec_unsigned_int_const: ->",rule_body(0),"<-\n");}
   <A> -> hex_unsigned_int_const ->> {out(tabs," - hex_unsigned_int_const: ->",rule_body(0),"<-\n");}

   <A> -> oct_unsigned_long_int_const ->> {out(tabs," - oct_unsigned_long_int_const: ->",rule_body(0),"<-\n");}
   <A> -> dec_unsigned_long_int_const ->> {out(tabs," - dec_unsigned_long_int_const: ->",rule_body(0),"<-\n");}
   <A> -> hex_unsigned_long_int_const ->> {out(tabs," - hex_unsigned_long_int_const: ->",rule_body(0),"<-\n");}

   <A> -> double_const ->> {out(tabs," - double_const: ->",rule_body(0),"<-\n");}
   <A> -> float_const ->> {out(tabs," - float_const: ->",rule_body(0),"<-\n");}
   <A> -> long_double_const ->> {out(tabs," - long_double_const: ->",rule_body(0),"<-\n");}

   <A> -> string_const ->> {out(tabs," - string_const: ->",rule_body(0),"<-\n");}

   <A> -> lr_br <H> rr_br ->> {null}
