/* Copyright (c) <2009> * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages * arising from the use of this software. * * Permission is granted to anyone to use this software for any purpose, * including commercial applications, and to alter it and redistribute it * freely */ // // Auto generated Parser Generator class: $(className).cpp // $(userCode) #include "$(className).h" #include #define MAX_USER_PARAM 64 enum $(className)::ActionType { dSHIFT = 0, dREDUCE, dACCEPT, dERROR }; class $(className)::dActionEntry { public: dActionEntry (short token, char errorItem, char stateType, short nextState, short ruleSymbols, short ruleIndex) :m_token(token), m_errorRule(errorItem), m_stateType (stateType), m_nextState(nextState), m_ruleSymbols(ruleSymbols), m_ruleIndex(ruleIndex) { } short m_token; char m_errorRule; char m_stateType;// 0 = shift, 1 = reduce, 2 = accept short m_nextState; short m_ruleSymbols; short m_ruleIndex; }; class $(className)::dGotoEntry { public: dGotoEntry (short token, short nextState) :m_token(token), m_nextState(nextState) { } short m_token; short m_nextState; }; class $(className)::dStackPair { public: dStackPair() :m_state(0), m_scannerLine(0), m_scannerIndex(0), m_token(dToken (0)), m_value() { } int m_state; int m_scannerLine; int m_scannerIndex; dToken m_token; dUserVariable m_value; }; $(className)::$(className)() { } $(className)::~$(className)() { } const $(className)::dActionEntry* $(className)::FindAction (const dActionEntry* const actionList, int count, dToken token) const { int i0 = 0; int i1 = count - 1; while ((i1 - i0) >= 4) { int i = (i1 + i0 + 1)>>1; const dActionEntry& action = actionList[i]; dToken actionToken (dToken(action.m_token)); if (token <= actionToken) { i1 = i; } else { i0 = i; } } for (int i = i0; i <= i1; i ++) { const dActionEntry& action = actionList[i]; dToken actionToken (dToken(action.m_token)); if (token == actionToken) { return& action; } } return NULL; } const $(className)::dGotoEntry* $(className)::FindGoto (const dGotoEntry* const gotoList, int count, dToken token) const { int i0 = 0; int i1 = count - 1; while ((i1 - i0) >= 4) { int i = (i1 + i0 + 1)>>1; const dGotoEntry& action = gotoList[i]; dToken actionToken (dToken(action.m_token)); if (token <= actionToken) { i1 = i; } else { i0 = i; } } for (int i = i0; i <= i1; i ++) { const dGotoEntry& action = gotoList[i]; dToken actionToken (dToken(action.m_token)); if (token == actionToken) { return &action; } } dAssert (0); return NULL; } const $(className)::dActionEntry* $(className)::GetNextAction (dList& stack, dToken token, $(scannerClass)& scanner) const { static short actionsCount[] = {$(actionsCount)}; static short actionsStart[] = {$(actionsStart)}; static dActionEntry actionTable[] = {$(actionTable)}; bool errorMode = false; const dStackPair& stackTop = stack.GetLast()->GetInfo(); int state = stackTop.m_state; int start = actionsStart[state]; int count = actionsCount[state]; const dActionEntry* const table = &actionTable[start]; const dActionEntry* action = FindAction (table, count, token); while (!action && (stack.GetCount() > 1)) { errorMode = true; // we found a syntax error, go into error recovering mode and find the token mark by a ". error" rule stack.Remove (stack.GetLast()); const dStackPair& stackTop = stack.GetLast()->GetInfo(); int state = stackTop.m_state; int start = actionsStart[state]; int count = actionsCount[state]; const dActionEntry* const table = &actionTable[start]; action = FindAction (table, count, ERROR_TOKEN); if (action && !action->m_errorRule) { action = NULL; } } if (errorMode && action) { dStackPair& stackTop = stack.GetLast()->GetInfo(); stackTop.m_token = ERROR_TOKEN; int state = action->m_nextState; int start = actionsStart[state]; int count = actionsCount[state]; const dActionEntry* const table = &actionTable[start]; // find the next viable token to continues parsing while (!FindAction (table, count, token)) { token = dToken (scanner.NextToken()); if (token == -1) { // reached end of the file, can not recover from this error; return NULL; } } action = FindAction (table, count, token); dStackPair& entry = stack.Append()->GetInfo(); entry.m_state = state; entry.m_scannerLine = stackTop.m_scannerLine; entry.m_scannerIndex = stackTop.m_scannerIndex; entry.m_value = dUserVariable (ERROR_TOKEN, "error", entry.m_scannerLine, entry.m_scannerIndex); entry.m_token = token; } return action; } bool $(className)::Parse($(scannerClass)& scanner) { static short gotoCount[] = {$(gotoCount)}; static short gotoStart[] = {$(gotoStart)}; static dGotoEntry gotoTable[] = {$(gotoTable)}; dList stack; const int lastToken = &(lastTerminalToken); stack.Append (); m_grammarError = false; dToken token = dToken (scanner.NextToken()); #ifdef D_DEBUG_PARCEL int oldLine = scanner.GetLineNumber(); #endif for (bool terminate = false; !terminate;) { const dActionEntry* const action = GetNextAction (stack, token, scanner); if (!action) { terminate = true; fprintf (stderr, "unrecoverable parser error\n"); dTrace (("unrecoverable parser error\n")); } else { switch (action->m_stateType) { case dSHIFT: { dStackPair& entry = stack.Append()->GetInfo(); entry.m_state = action->m_nextState; entry.m_scannerLine = scanner.GetLineNumber(); entry.m_scannerIndex = scanner.GetIndex(); entry.m_value = dUserVariable (token, scanner.GetTokenString(), entry.m_scannerLine, entry.m_scannerIndex); #ifdef D_DEBUG_PARCEL if (scanner.GetLineNumber() != oldLine) { oldLine = scanner.GetLineNumber(); dTrace (("\n")); } dTrace (("%s ", scanner.GetTokenString())); #endif token = dToken (scanner.NextToken()); entry.m_token = token; if (token == -1) { token = ACCEPTING_TOKEN; } break; } case dREDUCE: { dStackPair parameter[MAX_USER_PARAM]; int reduceCount = action->m_ruleSymbols; dAssertE (reduceCount < sizeof (parameter) / sizeof (parameter[0])); for (int i = 0; i < reduceCount; i ++) { parameter[reduceCount - i - 1] = stack.GetLast()->GetInfo(); stack.Remove (stack.GetLast()); } const dStackPair& stackTop = stack.GetLast()->GetInfo(); int start = gotoStart[stackTop.m_state]; int count = gotoCount[stackTop.m_state]; const dGotoEntry* const table = &gotoTable[start]; const dGotoEntry* const gotoEntry = FindGoto (table, count, dToken (action->m_nextState + lastToken)); dStackPair& entry = stack.Append()->GetInfo(); entry.m_state = gotoEntry->m_nextState; entry.m_scannerLine = scanner.GetLineNumber(); entry.m_scannerIndex = scanner.GetIndex(); entry.m_token = dToken (gotoEntry->m_token); switch (action->m_ruleIndex) { //do user semantic Actions $(semanticActionsCode) default:; } break; } case dACCEPT: // 2 = accept { // program parsed successfully, exit with successful code terminate = true; break; } default: { dAssertE (0); // syntax error parsing program //if (!ErrorHandler ("error")) { //} terminate = true; m_grammarError = true; break; } } } } return !m_grammarError; }