/* Web Polygraph http://www.web-polygraph.org/
* (C) 2003-2006 The Measurement Factory
* Licensed under the Apache License, Version 2.0 */
#include "xparser/xparser.h"
#include "xparser/TokenSym.h"
#include "xparser/GParser.h"
#ifndef DEBUGPRINT
#define DEBUGPRINT 0
#endif
GParser::GParser(Lexer *aLexer): lexer(aLexer) {
peek();
}
GParser::~GParser() {
}
const SynSym *GParser::parse() {
int nextState;
ReduceInfo *p;
SynSym *n_sym;
push(1);
#if DEBUGPRINT
cerr << here "push 1" << endl;
#endif
for (;;) {
// A transition to a state number greater than the maximum number of
// states indicates dynamic conflict resolution.
nextState = actionTable(top(), lexer->symbol());
#if DEBUGPRINT
cerr << tokenLoc() << "state: " << nextState
<< ", symbol " << lexer->symbol() << endl;
#endif
if ((nextState = actionTable(top(), lexer->symbol())) >= maxState) {
// Where conditionals exist, each predicate is attempted in
// sequence. Where none of the predicates evaluate to true,
// the parsing action might also default to a normal shift
// or reduce.
int a, i = nextState-maxState;
while ((a = condTable[i])) {
if (a < 0) {
nextState = a;
// normal reduce action found
goto to_reduce;
} else if (a >= maxState) {
p = reduceTable(a-maxState);
if ((*(p->conditional))(sem_top(p->semItems))) {
nextState = maxState-a;
// conflict resolved, production to be used
// has been decided
goto to_reduce;
} else
i++;
} else {
nextState = a;
// normal shift action found
goto to_shift;
}
}
// since we cannot resolve the conflict, and no
// normal actions are available, we report error
goto to_error;
} else
if (nextState > 0) {
// For a conventional shift action, shifting to the accept
// state indicates a successful parser.
to_shift:
if (nextState == acceptState)
return theSemStack.empty() ? 0 : *sem_top(0);
#if DEBUGPRINT
cerr << tokenLoc() << "term: " << lexer->symbol()
<< " goto " << nextState << endl;
#endif
push(nextState);
sem_push(new TokenSym(lexer->spelling(), lexer->symbol()));
peek();
} else
if (nextState < 0) {
to_reduce:
p = reduceTable(-nextState);
// A negative number of parse items to be removed indicates
// the evaluation of inherited attributes.
if (p->parseItems < 0) {
cerr << here << "inherited symbols are not supported" << endl << xabort;
} else {
// Where reductions involve attribute evaluation, these are
// performed before stack rearrangement is effected.
if (p->action) {
// normal reduce with action routine
SynSym **base = sem_top(p->semItems);
n_sym = (*(p->action))(base);
if (!n_sym)
cerr << here << "null symbol on parsing stack :(" << endl << xabort;
if (!n_sym->loc() && p->semItems > 0 && base[1])
n_sym->loc(base[1]->loc());
} else {
// normal reduce without action routine
// should not happened in this version!
n_sym = 0;
}
sem_throwAway(p->semItems);
sem_push(n_sym);
if (p->parseItems - p->semItems)
cerr << here << "inherited symbols are not supported" << endl << xabort;
#if DEBUGPRINT
cerr << tokenLoc() << "pop " << p->parseItems << endl;
#endif
throwAway(p->parseItems);
}
#if DEBUGPRINT
cerr << tokenLoc() << "state: " << top()
<< " NT " << p->head
<< " goto " << actionTable(top(), p->head) << endl;
#endif
push(actionTable(top(), p->head));
} else {
to_error:
// are we printing current location here?
cerr << tokenLoc() << "syntax error";
if (lexer->token().spell())
cerr << " near `" << lexer->spelling() << "'";
cerr << endl << xexit;
}
}
}
void GParser::sem_push(SynSym *x) {
if (!x)
cerr << here << "null symbol on parsing stack :(" << endl << xabort;
if (!x->loc())
x->loc(tokenLoc());
if (theSemStack.count() >= 4096)
cerr << tokenLoc() << "parsing stack grew suspiciously large (" << theSemStack.count() << " symbols)" << endl << xexit;
theSemStack.push(x);
}
void GParser::sem_throwAway(int x) {
while (x-- > 0)
delete theSemStack.pop();
}
void GParser::peek() {
lexer->nextToken();
}
syntax highlighted by Code2HTML, v. 0.9.1