{ Sample macros for Pascal parsers. } { This first group is not used much. } begin_comment = '{'; char_quote = ''''; { for C, which makes a distinction } end_comment = '}'; string_quote = ''''; zero_origin = 'false'; { don't force zero origin for arrays } { Apply cases: Either a nop is generated (when there are 0 flags), or a case for each flag. #N stands for the flag name, and #P for the whole production. Note that there will be trouble if the production has token(s) with a closing curly brace. } apply_case = "case pflag of#{ #N: { #P } begin writeln(rfile, '#N applied.') end#^;#} end { apply case }; "; apply_nop = "{ no tagged productions } "; { Array inits (including token tables). } token_table_init = { section which defines the tok table. #N is the token name, #V is the token value (which the same as the index), and #X is the cumulative character count, plus one for a terminator. } "{ initialize the token tables. }#{ puttok('#N', #V, #X);#} "; array_names = { array names, in the traditional order. } 'STATEX, MAP, POPNO, STK_STATE, STK_TOSTATE, TOKNUM, TOSTATE, INSYM, PRODX, PRODS'; array_types = { array type names, in the same order } 'state_array, reduce_array, pop_array, ss_array, ss_array, token_array, tostate_array, insym_array, reduce_array, prod_array'; array_line_break = '#- { #3I: } '; { stuff to be inserted when the elt count overflows } array_static_init = { template for Turbo Pascal typed consts. translated starting from the #{, it means start loop, print the line break string if on the first or nth element, print the value, exit if none left, print ", ", and terminate the loop. } '#N: #T = (#{#10@#V#^, #}); '; array_assignment_init = { set of subscripted assignments for array initialization } "{ initialize the #N array }#{ #N[#I] := #V;#} "; { Symbol table initialization } symbol_table_init = { section which defines reserved wds. one putsym call per symbol; #N is name, and #V is value (#I is also available). } "{ initialize keywords in the symbol table. }#{ putsym('#N', #V);#} "; { scanner stuff } char_case = { character case in the scanner } "'#C': #S { '#C' character case }; "; char_next_char = { start working on the next character position. } "begin nextch; #S end"; char_assignment = "token := #V { '#N' }"; { when the token is known } char_test = { the character in the current position is ambiguous. If the next token starts with #C, then start working on the next character position; else try the next possibility for this character position. this form is repeated until the ambiguity quits. } "if ch = '#C' then #S else #~"; char_error = { when there is no token which matches the prefix scanned. } " begin error('Illegal character'); nextch; get_token; end";