diff --git a/lib/modules/LR.pmod/parser.pike b/lib/modules/LR.pmod/parser.pike index 37987033fd5b8355991458086186e10316b44ba8..691f4e1614d04273dd4f8189ad104b9d4d72d8eb 100644 --- a/lib/modules/LR.pmod/parser.pike +++ b/lib/modules/LR.pmod/parser.pike @@ -1,5 +1,5 @@ /* - * $Id: parser.pike,v 1.11 1998/11/14 15:47:58 grubba Exp $ + * $Id: parser.pike,v 1.12 1998/11/14 18:52:47 grubba Exp $ * * A BNF-grammar in Pike. * Compiles to a LALR(1) state-machine. @@ -9,7 +9,7 @@ //. //. File: parser.pike -//. RCSID: $Id: parser.pike,v 1.11 1998/11/14 15:47:58 grubba Exp $ +//. RCSID: $Id: parser.pike,v 1.12 1998/11/14 18:52:47 grubba Exp $ //. Author: Henrik Grubbström (grubba@infovav.se) //. //. Synopsis: LALR(1) parser and compiler. @@ -86,6 +86,10 @@ class kernel { //. object(rule) REDUCE according to this rule on this symbol. mapping(int|string : object(kernel)|object(rule)) action = ([]); + //. + closure_set + //. The symbols that closure has been called on. + multiset closure_set = (<>); + /* * Functions */ @@ -118,6 +122,7 @@ class kernel { //. nonterminal to make the closure on. void closure(int nonterminal) { + closure_set[nonterminal] = 1; if (grammar[nonterminal]) { foreach (grammar[nonterminal], object(rule) r) { if (!rules[r]) { @@ -134,7 +139,8 @@ class kernel { add_item(new_item); - if (sizeof(r->symbols) && intp(r->symbols[0])) { + if (sizeof(r->symbols) && intp(r->symbols[0]) && + !closure_set[r->symbols[0]]) { closure(r->symbols[0]); } } @@ -506,7 +512,7 @@ void add_rule(object(rule) r) /* Then see if it is nullable */ if (!r->has_tokens) { - object(Stack.stack) new_nullables = Stack.stack(); + object(Stack.stack) new_nullables = Stack.stack(1024); foreach (r->symbols, symbol) { if (nullable[symbol]) { @@ -711,7 +717,7 @@ static private void shift_conflict(int empty) static private void handle_shift_conflicts() { - item_stack = Stack.stack(); + item_stack = Stack.stack(131072); /* Initialize the counter */ for (int index = 0; index < s_q->tail; index++) { @@ -742,7 +748,7 @@ static private void follow_conflict(int empty) static private void handle_follow_conflicts() { - item_stack = Stack.stack(); + item_stack = Stack.stack(131072); /* Initialize the counter */ for (int index = 0; index < s_q->tail; index++) { @@ -1403,8 +1409,8 @@ int compile() mixed parse(object|function(void:string|array(string|mixed)) scanner, void|object action_object) { - object(Stack.stack) value_stack = Stack.stack(); - object(Stack.stack) state_stack = Stack.stack(); + object(Stack.stack) value_stack = Stack.stack(4096); + object(Stack.stack) state_stack = Stack.stack(4096); object(kernel) state = start_state; string input; @@ -1432,8 +1438,6 @@ mixed parse(object|function(void:string|array(string|mixed)) scanner, mixed a = state->action[input]; if (object_program(a) == rule) { - /* REDUCE */ - function (mixed ...:mixed) func = 0; if (verbose) { werror(sprintf("Reducing according to rule\n%s\n", @@ -1441,48 +1445,69 @@ mixed parse(object|function(void:string|array(string|mixed)) scanner, } if (a->action) { - if (functionp(a->action)) { - func = a->action; - } else if (stringp(a->action)) { + /* REDUCE */ + string|function (mixed ...:mixed) func = 0; + + if (stringp(func = a->action)) { if (action_object) { func = action_object[a->action]; - if (!func) { - werror(sprintf("Missing action \"%s\" in object\n", - a->action)); - error |= ERROR_MISSING_ACTION; - } else if (!functionp(func)) { - werror(sprintf("Bad type (%s) for action \"%s\" in object\n", - typeof(func), a->action)); - error |= ERROR_BAD_ACTION_TYPE; - func = 0; + if (!functionp(func)) { + if (!func) { + werror(sprintf("Missing action \"%s\" in object\n", + a->action)); + error |= ERROR_MISSING_ACTION; + } else { + werror(sprintf("Bad type (%s) for action \"%s\" in object\n", + typeof(func), a->action)); + error |= ERROR_BAD_ACTION_TYPE; + func = 0; + } } } else { werror(sprintf("Missing object for action \"%s\"\n", a->action)); error |= ERROR_NO_OBJECT; + func = 0; } - } else { - werror(sprintf("Unsupported action type \"%s\" (%s)\n", - a->action, typeof(a->action))); - error |= ERROR_BAD_ACTION_TYPE; } - } - if (func) { - if (sizeof(a->symbols)) { - value_stack->push(a->action(@value_stack->pop(sizeof(a->symbols)))); + if (func) { + if (sizeof(a->symbols)) { + value_stack->push(func(@value_stack->pop(sizeof(a->symbols)))); + state = state_stack->pop(sizeof(a->symbols))[0]; + } else { + value_stack->push(a->action()); + } } else { - value_stack->push(a->action()); + // Default action. + if (sizeof(a->symbols)) { +#if 0 + value_stack->push(value_stack->pop(sizeof(a->symbols))[0]); +#else /* !0 */ + if (sizeof(a->symbols) > 1) { + value_stack->quick_pop(sizeof(a->symbols) - 1); + } +#endif /* 0 */ + state = state_stack->pop(sizeof(a->symbols))[0]; + } else { + value_stack->push(0); + } } } else { + // Default action. if (sizeof(a->symbols)) { +#if 0 value_stack->push(value_stack->pop(sizeof(a->symbols))[0]); +#else /* !0 */ + if (sizeof(a->symbols) > 1) { + value_stack->quick_pop(sizeof(a->symbols) - 1); + } +#endif /* 0 */ + state = state_stack->pop(sizeof(a->symbols))[0]; } else { value_stack->push(0); } } - if (sizeof(a->symbols)) { - state = state_stack->pop(sizeof(a->symbols))[0]; - } + state_stack->push(state); state = state->action[a->nonterminal]; /* Goto */ } else if (a) {