Пример #1
0
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 *
 *   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;
}