<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <meta content="text/html; charset=ISO-8859-1" http-equiv="content-type"> <title>manual.html</title> </head> <body> <div style="text-align: center;"> <big><big><span style="font-weight: bold;">DParser Manual<br> </span></big></big> <div style="text-align: left;"><big><br> <br> <span style="font-weight: bold;">Contents</span><br> </big> <ol> <li>Installation</li> <li>Getting Started</li> <li>Comments<br> </li> <li>Productions</li> <li>Global Code<br> </li> <li>Terminals</li> <ol> <li>Strings</li> <li>Regular Expressions</li> <li>Naming tokens<br> </li> <li>External (C) scanners</li> <li>Tokenizers</li> <li>Longest Match<br> </li> </ol> <li>Priorities and Associativity</li> <ol> <li>Token Priorities</li> <li>Operator Priorities</li> <li>Rule Priorities</li> </ol> <li>Actions</li> <ol> <li>Speculative Actions</li> <li>Final Actions</li> <li>Embedded<br> </li> <li>Pass Actions<br> </li> <li>Default Actions<br> </li> </ol> <li>Attributes and Action Specifiers</li> <ol> <li>Global State</li> <li>Parse Nodes</li> <li>Misc</li> </ol> <li>Symbol Table</li> <li>Whitespace</li> <li>Ambiguities</li> <li>Error Recovery</li> <li>Parsing Options<br> </li> <li>Grammar Grammar<br> </li> </ol> <span style="font-weight: bold;">1. Installation</span><br> <br> To build: 'gmake' (only available with source code package)<br> <br> To test: 'gmake test' (only available with source code package)<br> <br> To install, 'gmake install' (binary or source code packages)<br> <br> <span style="font-weight: bold;">2. Getting Started<span style="font-weight: bold;"></span><span style="font-weight: bold;"></span></span><span style="font-weight: bold;"></span><br> <br> 2.1. Create your grammar, for example, in the file "my.g":<br> <br> E: E '+' E | "[abc]";<br> <br> 2.2. Convert grammar into parsing tables:<br> <br> % make_dparser my.g<br> <br> 2.3. Create a driver program, for example, in the file "my.c": <br> <br> #include <stdio.h><br> #include <dparse.h><br> extern D_ParserTables parser_tables_gram;<br> int<br> main(int argc, char *argv[]) {<br> char s[256], *ss;<br> D_Parser *p = new_D_Parser(&parser_tables_gram, 0);<br> if (fgets(s,255,stdin) && dparse(p, s, strlen(s)) && !p->syntax_errors)<br> printf("success\n");<br> else<br> printf("failure\n");<br> }<br> <br> 2.4. Compile:<br> <br> % cc -I/usr/local/include my.c my.g.d_parser.c -L/usr/local/lib -ldparse<br> <br> 2.5. Run:<br> <br> % a.out<br> a=<br> syntax error, '' line 1<br> failure<br> %<br> <br> % a.out<br> a+b<br> success<br> %<br> <br> We'll come back to this example later.<br> <br> <span style="font-weight: bold;">3. Comments</span><br> <br> Grammars can include C/C++ style comments.<br> <br> EXAMPLE<br> <br> // My first grammar<br> E: E '+' E | "[abc]";<br> /* is this right? */<br> <br> <span style="font-weight: bold;">4. Productions</span><br> <br> 4.1. The first production is the root of your grammar (what you will be trying to parse).<br> 4.2. Productions start with the non-terminal being defined followed by a colon ':', a set of right hand sides seperated by '|' (or) consisting of elements (non-terminals or terminals).<br> 4.3. Elements can be grouped with parens '(', and the normal regular expression symbols can be used ('+' '*' '?' '|').<br> <br> EXAMPLE<br> <br> program: statements+ | comment* (function | procedure)?;<br> <br> 4.4. <span style="font-weight: bold;">NOTE:</span> Instead of using '[' ']' for optional elements we use the more familar and consistent '?' operator. The square brackets are reserved for speculative actions (below).<br> <br> <span style="font-weight: bold;">5. Global Code</span><br> <br> Global (or static) C code can be intermixed with productions by surrounding the code with brackets '{'.<br> <br> EXAMPLE<br> <br> { void dr_s() { printf("Dr. S\n"); }<br> S: 'the' 'cat' 'and' 'the' 'hat' { dr_s(); } | T;<br> { void twain() { printf("Mark Twain\n"); }<br> T: 'Huck' 'Finn' { twain(); };<br> <br> <span style="font-weight: bold;">6. Terminals</span><br> <br> 6.1. Strings terminals are surrounded with single quotes. For example:<br> <br> <span style="font-weight: bold;"></span>block: '{' statements* '}';<br> whileblock: 'while' '(' expression ')' block;<br> <br> 6.2. Regular expressions are surrounded with double quotes. For example:<br> <br> hexint: "(0x|0X)[0-9a-fA-F]+[uUlL]?";<br> <br> <span style="font-weight: bold;">NOTE: </span>only the simple regular expression operators are currently supported (v1.3). This include parens, square parens, ranges, and '*', '+', '?'. If you need something more, request a feature or implement it yourself; the code is in scan.c.<br> <br> 6.3 Terminal modifiers<br> <br> Terminals can contain embbed escape codes. Including the standard C escape codes, the codes \x and \d permit inserting hex and decimal ASCII characters directly.<br> <br> Tokens can be given a name by appending the $name option. This is useful when you have several<br> tokens which which represent the same string (e.g. ','). For example,<br> <br> function_call: function '(' parameter ( ',' $name 'parameter_comma' parameter) ')';<br> <br> It is now possible to use $0.symbol == ${string parameter_comma} to differentiate ParseNode ($0) between<br> a parameter comma node and say an initialization comma.<br> <br> Terminals ending in '/i' are case insensitive. For example 'hi'/i matches 'HI', 'Hi' and "hI' in addition to 'hi'.<br> <br> 6.3. External (C) Scanners<br> <br> There are two types of external scanners, those which read a single terminal, and those which are global (called for every terminal). Here is an example of a scanner for a single terminal. Notice how it can be mixed with regular string terminals.<br> <br> {<br> extern char *ops;<br> extern void *ops_cache;<br> int ops_scan(char *ops, void *ops_cache, char **as,<br> int *col, int *line, unsigned short *op_assoc, int *op_priority);<br> }<br> <br> X: '1' (${scan ops_scan(ops, ops_cache)} '2')*;<br> <br> The user provides the 'ops_scan' function. This example is from tests/g4.test.g in the source distribution.<br> <br> The second type of scanner is a global scanner:<br> <br> {<br> #include "g7.test.g.d_parser.h"<br> int myscanner(char **s, int *col, int *line, unsigned short *symbol,<br> int *term_priority, unsigned short *op_assoc, int *op_priority)<br> {<br> if (**s == 'a') {<br> (*s)++;<br> *symbol = A;<br> return 1;<br> } else if (**s == 'b') {<br> (*s)++;<br> *symbol = BB;<br> return 1;<br> } else if (**s == 'c') {<br> (*s)++;<br> *symbol = CCC;<br> return 1;<br> } else if (**s == 'd') {<br> (*s)++;<br> *symbol = DDDD;<br> return 1;<br> } else<br> return 0;<br> }<br> ${scanner myscanner}<br> ${token A BB CCC DDDD}<br> <br> S: A (BB CCC)+ SS;<br> SS: DDDD;<br> <br> Notice how the you need to include the header file generated by <span style="font-weight: bold;">make_dparser</span> which contains the token definitions.<br> <br> 6.4. Tokenizers<br> <br> Tokenizers are non-context sensitive global scanners which produce only one token for any given input string. Some programming languages (for example <span style="font-weight: bold;">C</span>) are easier to specify using a tokenizer because (for example) reserved words can be handled simply by lowering the terminal priority for identifiers.<br> <br> EXAMPLE:<br> <br> S : 'if' '(' S ')' S ';' | 'do' S 'while' '(' S ')' ';' | ident;<br> ident: "[a-z]+" $term -1;<br> <br> The sentence: <span style="font-weight: bold;">if ( while ) a;</span> is legal because <span style="font-weight: bold;">while</span> cannot appear at the start of <span style="font-weight: bold;">S</span> and so it doesn't conflict with the parsing of <span style="font-weight: bold;">while</span> as an <span style="font-weight: bold;">ident</span> in that position. However, if a tokenizer is specified, all tokens will be possible at each position and the sentense will produce a syntax error.<br> <br> <span style="font-weight: bold;">DParser</span> provides two ways to specify tokenizers: globally as an option (-T) to <span style="font-weight: bold;">make_dparser</span> and locally with a ${declare tokenize ...} specifier (see the ANSI C grammar for an example). The ${declare tokenize ...} declartion allows a tokenizer to be specified over a subset of the parsing states so that (for example) ANSI C could be a subgrammar of another larger grammar. Currently the parse states are not split so that the productions for the substates must be disjoint.<br> <br> 6.5 Longest Match<br> <br> Longest match lexical ambiguity resolution is a technique used by seperate phase lexers to help decide (along<br> with lexical priorities) which single token to select for a given input string. It is used in the definition of ANSI-C, but not in C++ because of a snafu in the definition of templates whereby templates of templates (List<List <Int>>) can end with the right shift token ('>>"). Since <span style="font-weight: bold;">DParser</span> does not have a seperate lexical phase, it does not require longest match disambiguation, but provides it as an option.<br> <br> There are two ways to specify longest match disabiguation: globally as an option (-l) to <span style="font-weight: bold;">make_dparser</span> or locally with with a ${declare ... longest_match}. If global longest match disambiguation is <span style="font-weight: bold;">ON</span>, it can be locally disabled with {$declare ... all_matches} . As with Tokenizers above, local declarations operate on disjoint subsets of parsing states.<br> <br> <span style="font-weight: bold;">7. Priorities and Associativity<br> <br> </span> Priorities can very from MININT to MAXINT and are specified as integers. Associativity can take the values:<br> <br> assoc : '$unary_op_right' | '$unary_op_left' | '$binary_op_right'<br> | '$binary_op_left' | '$unary_right' | '$unary_left'<br> | '$binary_right' | '$binary_left' | '$right' | '$left' ;<br> <br> 7.1. Token Prioritites<br> <br> Termininal priorities apply after the set of matching strings has been found and the terminal(s) with the highest priority is selected.<br> Terminal priorities are introduced after a terminal by the specifier <span style="font-weight: bold;">$term</span>. We saw an example of token priorities with the definition of <span style="font-weight: bold;">ident</span>.<br> <br> EXAMPLE:<br> <br> S : 'if' '(' S ')' S ';' | 'do' S 'while' '(' S ')' ';' | ident;<br> ident: "[a-z]+" $term -1;<br> <br> 7.2. Operator Priorities<br> <br> Operator priorities specify the priority of a operator symbol (either a terminal or a non-terminal). This corresponds to the <span style="font-style: italic;">yacc</span> or <span style="font-style: italic;">bison</span> <span style="font-weight: bold;">%left</span> etc. declaration. However, since <span style="font-weight: bold;">DParser</span> is doesn't require a global tokenizer, operator priorities and associativities are specified on the reduction which creates the token. Moreover, the associativity includes the operator usage as well since it cannot be infered from rule context. Possible operator associativies are:<br> <br> operator_assoc : '$unary_op_right' | '$unary_op_left' | '$binary_op_right'<br> | '$binary_op_left' | '$unary_right' | '$unary_left'<br> | '$binary_right' | '$binary_left';<br> <br> EXAMPLE:<br> <br> E: ident op ident;<br> ident: '[a-z]+';<br> <span style="font-weight: bold;"></span>op: '*' $binary_op_left 2 |<br> '+' $binary_op_left 1;<br> <br> 7.3. Rule Priorities<br> <br> Rule priorities specify the priority of the reduction itself and have the possible associativies:<br> <br> rule_assoc: '$right' | '$left';<br> <br> Rule and operator priorities can be intermixed and are interpreted at run time (<span style="font-weight: bold;">not</span> when the tables are built). This make it possible for user-defined scanners to return the associativities and priorities of tokens.<br> <br> <span style="font-weight: bold;">8. Actions<br> <br> </span> Actions are the bits of code which run when a reduction occurs.<br> <br> EXAMPLE<br> <br> S: this | that;<br> this: 'this' { printf("got this\n"); };<br> that: 'that' { printf("got that\n"); };<br> <br> 8.1 Speculative Action<br> <br> Speculative actions occur when the reduction takes place during the speculative parsing process. It is possible<br> that the reduction will not be part of the final parse or that it will occur a different number of times. For example:<br> <br> S: this | that;<br> this: hi 'mom';<br> that: ho 'dad';<br> ho: 'hello' [ printf("ho\n"); ];<br> hi: 'hello' [ printf("hi\n"); ];<br> <br> Will print both 'hi' and 'ho' when given the input 'hello dad' because at the time hello is reduced, the following token is not known.<br> <br> 8.2 Final Actions<br> <br> Final actions occur only when the reduction must be part of any legal final parse (committed). It is possible to do final actions during parsing or delay them till the entire parse tree is constructed (see Options). Final actions are executed in order and in number according the the single final unambiguous parse.<br> <br> S: A S 'b' | 'x';<br> A: [ printf("speculative e-reduce A\n"); ] <br> { printf("final e-reduce A\n"); };<br> <br> On input:<br> <br> xbbb<br> <br> Will produce:<br> <br> speculative e-reduce A<br> final e-reduce A<br> final e-reduce A<br> final e-reduce A<br> <br> 8.3 Embedded Actions<br> <br> Actions can be embedded into rule. These actions are executed as if they were replaced with a synthetic production with a single null rule containing the actions. For example:<br> <br> S: A { printf("X"); } B;<br> A: 'a' { printf("a"); };<br> B: 'b' { printf("b"); };<br> <br> On input:<br> <br> ab<br> <br> Will produce:<br> <br> aXb<br> <br> 8.4 Pass Actions<br> <br> <span style="font-weight: bold;">DParser</span> supports multiple pass compilation. The passes are declared at the top of the grammar, and the actions are associated with individual rules.<br> <br> EXAMPLE<br> <br> ${pass sym for_all postorder}<br> ${pass gen for_all postorder}<br> <br> translation_unit: statement*;<br> <br> statement<br> : expression ';' {<br> d_pass(${parser}, &$n, ${pass sym});<br> d_pass(${parser}, &$n, ${pass gen});<br> }<br> ;<br> <br> expression : integer<br> gen: { printf("gen integer\n"); }<br> sym: { printf("sym integer\n"); }<br> | expression '+' expression $right 2<br> sym: { printf("sym +\n"); }<br> ;<br> <br> A pass name then a colon indicate that the following action is associated with a particular pass. Passes can be either <span style="font-weight: bold;">for_all</span> or <span style="font-weight: bold;">for_undefined</span> (which means that the automatic traversal only applies to rules without actions defined for this pass). Furthermore, passes can be <span style="font-weight: bold;">postorder</span>, <span style="font-weight: bold;">preorder</span>, and <span style="font-weight: bold;">manual</span> (you have to call <span style="font-weight: bold;">d_pass</span> yourself). Passes can be initiated in the final action of any rule.<br> <br> 8.5 Default Actions<br> <br> The special production "<span style="font-weight: bold;">_</span>" can be defined with a single rule whose actions become the default when no other action is specified. Default actions can be specified for speculative, final and pass actions and apply to each seperately.<br> <br> EXAMPLE<br> <br> _: { printf("final action"); }<br> gen: { printf("default gen action"); }<br> sym: { printf("default sym action"); }<br> ;<br> <span style="font-weight: bold;"></span><br> <span style="font-weight: bold;">9. Attributes and Action Specifiers</span><br> <br> 9.1. Global State (<span style="font-weight: bold;">$g</span>)<br> <br> Global state is declared by <span style="font-weight: bold;">define</span>'ing<span style="font-weight: bold;"> D_ParseNodeGlobals</span> (see the ANSI C grammar for a similar declaration for symbols). Global state can be accessed in any action with <span style="font-weight: bold;">$g</span>. Because <span style="font-weight: bold;">DParser</span> handles ambiguous parsing global state can be accessed on different speculative parses. In the future automatic splitting of global state may be implemented (if there is demand). Currently, the global state can be copied and assigned to <span style="font-weight: bold;">$g</span> to ensure that the changes made only effect subsequent speculative parses derived from the particular parse.<br> <br> EXAMPLE<br> <br> [ $g = copy_globals($g);<br> $g->my_variable = 1;<br> ]<br> <br> The symbol table (Section 10) can be used to manage state information safely for different speculative parses.<br> <br> 9.2. Parse Node State<br> <br> Each parse node includes a set of system state variables and can have a set of user-defined state variables. User defined parse node state is declared by <span style="font-weight: bold;">define</span>'ing<span style="font-weight: bold;"> D_ParseNodeUser</span>. Parse node state is accessed with:<br> <br> <span style="font-weight: bold;">$#</span> - number of child nodes<br> <span style="font-weight: bold;">$$</span> - user parse node state for parent node (non-terminal defined by the production)<br> <span style="font-weight: bold;">$X</span> (where X is a number) - the user parse node state of element X of the production<br> <span style="font-weight: bold;">$nX</span> - the system parse node state of element X of the production<br> <br> The system parse node state is defined in <span style="font-weight: bold;">dparse.h</span> which is installed with <span style="font-weight: bold;">DParser</span>. It contains such information as the symbol, the location of the parsed string, and pointers to the start and end of the parsed string.<br> <br> 9.3. Misc<br> <br> <span style="font-weight: bold;">${scope}</span> - the current symbol table scope<br> <span style="font-weight: bold;">${reject}</span> - in speculative actions permits the current parse to be rejected<br> <br> <span style="font-weight: bold;">10. Symbol Table</span><br> <br> <span style="font-weight: bold;"></span> The symbol table can be updated down different speculative paths while sharing the bulk of the data. It defines the following functions in the file (dsymtab.h):<br> <br> struct D_Scope *new_D_Scope(struct D_Scope *st);<br> struct D_Scope *enter_D_Scope(struct D_Scope *current, struct D_Scope *scope);<br> D_Sym *NEW_D_SYM(struct D_Scope *st, char *name, char *end);<br> D_Sym *find_D_Sym(struct D_Scope *st, char *name, char *end);<br> D_Sym *UPDATE_D_SYM(struct D_Scope *st, D_Sym *sym);<br> D_Sym *current_D_Sym(struct D_Scope *st, D_Sym *sym);<br> D_Sym *find_D_Sym_in_Scope(struct D_Scope *st, char *name, char *end);<br> <br> 'new_D_Scope' creates a new scope below 'st' or NULL for a 'top level' scope. 'enter_D_Scope' returns to a previous scoping level. NOTE: do not simply assign ${scope} to a previous scope as any updated symbol information will be lost. 'commit_D_Scope' can be used in final actions to compress the update list for the top level scope and improve efficiency.<br> <br> 'find_D_Sym' finds the most current version of a symbol in a given scope. 'UPDATE_D_SYM' updates the value of symbol (creates a difference record on the current speculative parse path). 'current_D_Sym' is used to retrive the current version of a symbol, the pointer to which may have been stored in some other attribute or variable. Symbols with the same name should not be created in the same scope. The function 'find_D_Sym_in_Scope' is provided to detect this case. <br> <br> User data can be attached to symbols by <span style="font-weight: bold;">define</span>'ing <span style="font-weight: bold;">D_UserSym</span>. See the ANSI C grammar for an example. <br> <br> Here is a full example of scope usage (from tests/g29.test.g):<br> <br> <span style="font-family: monospace;">#include <stdio.h><br> <br> typedef struct My_Sym {<br> int value;<br> } My_Sym;<br> #define D_UserSym My_Sym<br> typedef struct My_ParseNode {<br> int value;<br> struct D_Scope *scope;<br> } My_ParseNode;<br> #define D_ParseNode_User My_ParseNode<br> }<br> <br> translation_unit: statement*;<br> <br> statement <br> : expression ';' <br> { printf("%d\n", $0.value); }<br> | '{' new_scope statement* '}'<br> [ ${scope} = enter_D_Scope(${scope}, $n0.scope); ]<br> { ${scope} = commit_D_Scope(${scope}); }<br> ;<br> <br> new_scope: [ ${scope} = new_D_Scope(${scope}); ];<br> <br> expression <br> : identifier ':' expression <br> [ <br> D_Sym *s;<br> if (find_D_Sym_in_Scope(${scope}, $n0.start_loc.s, $n0.end))<br> printf("duplicate identifier line %d\n", $n0.start_loc.line);<br> s = NEW_D_SYM(${scope}, $n0.start_loc.s, $n0.end);<br> s->user.value = $2.value;<br> $$.value = s->user.value;<br> ]<br> | identifier '=' expression<br> [ D_Sym *s = find_D_Sym(${scope}, $n0.start_loc.s, $n0.end);<br> s = UPDATE_D_SYM(${scope}, s);<br> s->user.value = $2.value;<br> $$.value = s->user.value;<br> ]<br> | integer <br> [ $$.value = atoi($n0.start_loc.s); ]<br> | identifier <br> [ D_Sym *s = find_D_Sym(${scope}, $n0.start_loc.s, $n0.end);<br> if (s)<br> $$.value = s->user.value;<br> ]<br> | expression '+' expression<br> [ $$.value = $0.value + $1.value; ]<br> ;<br> <br> integer: "-?([0-9]|0(x|X))[0-9]*(u|U|b|B|w|W|L|l)*" $term -1;<br> identifier: "[a-zA-Z_][a-zA-Z_0-9]*";<br> <br> </span> <br> <span style="font-weight: bold;">11. Whitespace</span><br> <br> Whitespace can be specified two ways: C function which can be user-defined, or as a subgrammar. The default whitespace parser is compatible with C/C++ #line directives and comments. It can be replaced with any user specified function as a parsing option (see Options).<br> <br> Additionally, if the (optionally) reserved production <span style="font-weight: bold;">whitespace</span> is defined, the subgrammar it defines will be used to consume whitespace for the main grammar. This subgrammar can include normal actions.<br> <br> EXAMPLE<br> <br> <span style="font-weight: bold;"></span>S: 'a' 'b' 'c';<br> whitespace: "[ \t\n]*";<br> <br> Whitespace can be accessed on a per parse node basis using the functions: <span style="font-weight: bold;">d_ws_before</span> and <span style="font-weight: bold;">d_ws_after</span>, which return the start of the whitespace before <span style="font-weight: bold;">start_loc.s</span> and after <span style="font-weight: bold;">end</span> respectively. <br> <br> <span style="font-weight: bold;">12. Ambiguities<br> </span> <br> Ambiguities are resolved automatically based on priorities and associativities. In addition, when the other resolution techniques fail, user defined ambiguity resolution is possible. The default ambiguity handler produces a fatal error on an unresolved ambiguity. This behavior can be replaced with a user defined resolvers the signature of which is provided in <span style="font-weight: bold;">dparse.h</span>.<br> <br> If the <span style="font-weight: bold;">verbose_level</span> flag is set, the default ambiguity handler will print out parenthesized versions of the ambiguous parse trees. This may be of some assistence in disambiguating a grammar.<br> <br> <span style="font-weight: bold;">13. Error Recovery<br> <br> DParser</span> implements an error recovery scheme appropriate to scannerless parsers. I haven't had time to investigate all the prior work in this area, so I am not sure if it is novel. Suffice for now that it is optional and works well with C/C++ like grammars.<br> <br> <span style="font-weight: bold;">14. Parsing Options</span><br> <br> Parser are instantiated with the function <span style="font-style: italic;">new_D_Parser<span style="font-weight: bold;">. </span></span> The resulting data structure contains a number of user configurable options (see <span style="font-weight: bold;">dparser.h</span>). These are provided reasonable default values and include:<br> <ul> <li><span style="font-weight: bold;">initial_globals</span> - the initial global variables accessable through <span style="font-weight: bold;">$g</span></li> <li><span style="font-weight: bold;"></span><span style="font-weight: bold;">initial_skip_space_fn</span> - the initial whitespace function</li> <li><span style="font-family: monospace;"></span><span style="font-weight: bold;">initial_scope</span> - the initial symbol table scope</li> <li><span style="font-weight: bold;"></span><span style="font-weight: bold;">syntax_error_fn</span> - the function called on a syntax error</li> <li><span style="font-weight: bold;">ambiguity_fn</span> - the function called on an unresolved ambiguity</li> <li><span style="font-weight: bold;">loc</span> - the initial location (set on an error).</li> </ul> In addtion, there are the following user configurables:<br> <ul> <li><span style="font-weight: bold;">sizeof_user_parse_node</span> - the sizeof <span style="font-weight: bold;">D_ParseNodeUser</span></li> <li><span style="font-weight: bold;">save_parse_tree</span> - whether or not the parse tree should be save once the final actions have been executed</li> <li><span style="font-style: italic;"></span><span style="font-weight: bold;">dont_fixup_internal_productions</span> - to not convert the Kleene star into a variable number of children from a tree of reductions</li> <li><span style="font-weight: bold;">dont_merge_epsilon_trees</span> - to not automatically remove ambiguities which result from trees of epsilon reductions without actions</li> <li><span style="font-weight: bold;">dont_use_eagerness_for_disambiguation</span> - do not use the rule that the longest parse which reduces to the same token should be used to disambiguate parses. This rule is used to handle the case (<span style="font-weight: bold;">if then else?</span>) relatively cleanly.</li> <li><span style="font-weight: bold;">dont_use_height_for_disambiguation</span> - do not use the rule that the least deep parse which reduces to the same token should be used to disabiguate parses. This rule is used to handle recursive grammars relatiively cleanly.</li> <li><span style="font-weight: bold;">dont_compare_stacks</span> - disables comparing stacks to handle certain exponential cases during ambiguous operator priority resolution. This feature is relatively new, and this disables the new code.<br> </li> <li><span style="font-weight: bold;">commit_actions_interval</span> - how often to commit final actions (0 is immediate, MAXINT is essentially not till the end of parsing)</li> <li><span style="font-weight: bold;"></span><span style="font-weight: bold;">error_recovery</span> - whether or not to use error recovery (defaults ON)</li> </ul> An the following result values:<br> <ul> <li><span style="font-weight: bold;">syntax_errors</span> - how many syntax errors (if <span style="font-weight: bold;">error_recovery</span> was on)</li> </ul> This final value should be checked to see if parse was successful.<br> <br> <span style="font-weight: bold;">15. Grammar Grammar</span><br> <br> <span style="font-weight: bold;">DParser</span> is fully self-hosted (would you trust a parser generator which wasn't?). The grammar grammar is <a href="grammar.g">here (Grammar Grammar)</a>. <span style="font-weight: bold;"></span><br> <span style="font-weight: bold;"></span><br> <span style="font-weight: bold;"><br> </span><big><big><span style="font-weight: bold;"></span></big></big></div> </div> </body> </html>