# # --------------------------------------------------------------------- # # GRAMMAR SECTION # # --------------------------------------------------------------------- # # --------------------------------------------------------------------- # ::= [{ | | }] EOF # # grammar ::= out_header [{ (assignment | wc) flush }] [ '%%' [{ . }] ] ( eoi out_footer | error( 'Syntax error' ) ); # --------------------------------------------------------------------- # ::= '#' ~[{ not '\n' }]~ '\n' # # where the internal routine 'commentchars' does a transparent parse on # the expression '~[{ not '\n' }]~'. # comment ::= '##' ignorechars '\n' | '#' out_comment_begin commentchars '\n' out_comment_end; # --------------------------------------------------------------------- # ::= [] ('=' | '::=') ';' # assignment ::= out_func_type name [wc] ( '=' | '::=' | error( ' \'=\' or \'::=\' expected' ) ) out_func_begin expression ( ';' inc_rule | error( '\';\' expected' ) ) out_func_end; # --------------------------------------------------------------------- # ::= term [{ '|' term }] # expression ::= ( [wc] ( out_or_begin term {[wc] '|' [wc] out_or_operator term} out_or_end | term ) [wc] ) | error('Expression expected'); # --------------------------------------------------------------------- # ::= | | # term ::= ordinary_and | swapped_and | factor; # --------------------------------------------------------------------- # ::= factor { wc } # ordinary_and ::= out_and_begin factor out_and_1 { wc factor out_and_2 } out_and_end; # --------------------------------------------------------------------- # ::= factor { '#' } # swapped_and ::= out_swp_begin factor out_swp_1 { [wc] '#' [wc] out_swp_2 factor out_swp_3 | wc factor out_swp_4 } out_swp_end; # --------------------------------------------------------------------- # ::= | ident | '(' expression rparen | option | repetition # # postfix operators are quite time consuming :( factor ::= '!' [wc] simple_factor # The 'not' operator. | simple_factor [ [wc] ('*'|'+') ]; # Kleene's '*' and '+'. simple_factor ::= IO | function | identifier | option | repetition | '(' expression rparen; # -------------------------------------------------------------------- # ::= | | | '.' | # IO ::= input | output | trans | '.' out_trans_char | syntax_error; # --------------------------------------------------------------------- # input ::= ['in' [wc] '(' [wc]] [ [wc] rparen] # input ::= 'in' [wc] '(' [wc] out_str_begin string out_str_end [wc] rparen | out_str_begin string out_str_end; # --------------------------------------------------------------------- # output ::= 'out' [] '(' [] [] rparen # | '`' [{o_stringchar}] '`' # output ::= 'out' out_out_1_begin [wc] '(' [wc] string [wc] rparen out_out_1_end | '`' out_out_2_begin [{o_stringchar}] ( '`' out_out_2_end | error( 'Unterminated output string' ) ); # --------------------------------------------------------------------- # trans ::= 'trans' [] '(' [] [] rparen # | '\"' [{t_stringchar}] '\"' # trans ::= out_tran_1_begin 'trans' [wc] '(' [wc] string [wc] rparen out_tran_1_end | '\"' out_tran_2_begin [{t_stringchar}] ( '\"' out_tran_2_end | error( 'Unterminated trans string' ) ); # --------------------------------------------------------------------- # syntax_error ::= 'error' [wc] '(' [wc] string [wc] rparen # syntax_error ::= 'error' [wc] '(' [wc] out_err_begin string [wc] rparen out_err_end; # --------------------------------------------------------------------- # There is NO white allowed between name and '(', or we would # have a serious problem. still I think that this solution is # NOT clear, and this should be changed in the future... # function ::= valid_name | name '(' expression rparen; # --------------------------------------------------------------------- # ::= # identifier ::= valid_name | out_call_begin name out_call_end; # -------------------------------------------------------------------- # # valid_name = '__BNF_' error( 'names beginning with \'__BNF_\' are reserved' ); # --------------------------------------------------------------------- #