/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * LEXICAL SCANNER */ LOCAL te_dp_event yylex(void) { lastToken = DP_EV_INVALID; scanAgain: /* * Start the process of locating a token. * We branch here after skipping over a comment * or processing a directive (which may change our context). */ if (IS_WHITESPACE_CHAR(*pCurCtx->pzScan)) trim_whitespace(); switch (*pCurCtx->pzScan) { case NUL: /* * IF we are not inside an include context, * THEN go finish. */ if (pCurCtx->pCtx == NULL) goto lex_done; pop_context(); goto scanAgain; case '#': { extern char * processDirective(char*); char * pz = processDirective(pCurCtx->pzScan+1); /* * Ensure that the compiler doesn't try to save a copy of * "pCurCtx" in a register. It must be reloaded from memory. */ pCurCtx->pzScan = pz; goto scanAgain; } case '{': SET_LIT_TKN(O_BRACE); break; case '=': SET_LIT_TKN(EQ); break; case '}': SET_LIT_TKN(C_BRACE); break; case '[': SET_LIT_TKN(OPEN_BKT); break; case ']': SET_LIT_TKN(CLOSE_BKT); break; case ';': SET_LIT_TKN(SEMI); break; case ',': SET_LIT_TKN(COMMA); break; case '\'': case '"': { char* pz = ao_string_cook(pCurCtx->pzScan, &(pCurCtx->lineNo)); if (pz == NULL) goto NUL_error; pz_token = pCurCtx->pzScan; lastToken = DP_EV_STRING; pCurCtx->pzScan = pz; break; } case '<': switch (lex_here_string()) { case SUCCESS: break; case FAILURE: goto BrokenToken; case PROBLEM: return DP_EV_INVALID; } break; case '(': loadScheme(); break; case '\\': if (strncmp(pCurCtx->pzScan+1, "'(", (size_t)2) == 0) { alist_to_autogen_def(); goto scanAgain; } lex_escaped_char(); break; case '`': switch (lex_backquote()) { case FAILURE: goto NUL_error; case PROBLEM: goto scanAgain; case SUCCESS: break; } break; case '/': switch (lex_comment()) { case SUCCESS: goto scanAgain; default: break; } /* FALLTHROUGH */ /* to Invalid input char */ default: BrokenToken: pCurCtx->pzScan = assembleName(pCurCtx->pzScan, &lastToken); break; } /* switch (*pCurCtx->pzScan) */ return lastToken; NUL_error: AG_ABEND(aprf(zErrMsg, pzProg, "unterminated quote in definition", pCurCtx->pzCtxFname, pCurCtx->lineNo)); return DP_EV_INVALID; lex_done: /* * First time through, return the DP_EV_END token. * Second time through, we really finish. */ if (pCurCtx->pzScan == zNil) { pCurCtx->pCtx = pDoneCtx; pDoneCtx = pCurCtx; return DP_EV_INVALID; } pCurCtx->pzScan = (char*)zNil; return DP_EV_END; }
shared_ptr <FlashcardsDatabase> DatabaseParser::parseDatabase (QString fileName, const QString& fileContents, shared_ptr <FlashcardsDatabase> appendTo, shared_ptr <VariableStack> variableStack) { if (!appendTo) appendTo.reset (new FlashcardsDatabase (variableStack)); currentDatabase = appendTo.get(); int currentDirectoryPushId = FileReaderSingletone::instance().pushFileSearchPath (QFileInfo (fileName).absolutePath(), DATABASE_INCLUDE_DIRECTORIES_CONTEXT); QStringList lines = fileContents.split ('\n'); currentBlock.clear(); currentFileName = fileName; currentEntryTag = "no-tag"; bool cPlusPlusCommentOpen = false; for (int lineNumber = 0; lineNumber < lines.size(); lineNumber++) { QString& line = lines[lineNumber]; if (cPlusPlusCommentOpen) { int commentClosing = line.indexOf ("*/"); if (commentClosing != -1) { line = line.right (line.size() - commentClosing - 2); cPlusPlusCommentOpen = false; } else { line = ""; } } bool directive = false; if (!line.isEmpty() && line[0] == '#') { directive = true; } else { int lineCommentOpening = line.indexOf ("//"); if (lineCommentOpening != -1) line = line.left (lineCommentOpening); int cPlusPlusCommentOpening = line.indexOf ("/*"); if (cPlusPlusCommentOpening != -1) { line = line.left (cPlusPlusCommentOpening); cPlusPlusCommentOpen = true; } line = line.trimmed(); if (!line.isEmpty()) { if (currentBlock.isEmpty()) currentBlockFirstLine = lineNumber + 1; currentBlock.push_back (line); } } if ((directive || line.isEmpty() || lineNumber + 1 == lines.size()) && !currentBlock.empty()) { try { processCurrentBlock(); } catch (DatabaseParserException&) {} currentBlock.clear(); } if (directive) { currentBlockFirstLine = lineNumber + 1; try { processDirective (line, appendTo); } catch (DatabaseParserException&) {} } } FileReaderSingletone::instance().popFileSearchPath (currentDirectoryPushId); currentDatabase = nullptr; return appendTo; }