Beispiel #1
0
PUBLIC int ecGetRegExpToken(EcCompiler *cp, wchar *prefix)
{
    EcToken     *token, *tp;
    EcStream    *stream;
    wchar       *pp;
    int         c;

    stream = cp->stream;
    tp = token = cp->token;
    assert(tp != 0);

    initializeToken(tp, stream);

    for (pp = prefix; pp && *pp; pp++) {
        addCharToToken(tp, *pp);
    }
    while (1) {
        c = getNextChar(stream);
        switch (c) {
        case -1:
            return makeToken(tp, 0, T_ERR, 0);

        case 0:
            if (stream->flags & EC_STREAM_EOL) {
                return makeToken(tp, 0, T_NOP, 0);
            }
            return makeToken(tp, 0, T_EOF, 0);

        case '/':
            addCharToToken(tp, '/');
            while (1) {
                c = getNextChar(stream);
                if (c != 'g' && c != 'i' && c != 'm' && c != 'y' && c != 'x' && c != 'X' && c != 'U' && c != 's') {
                    putBackChar(stream, c);
                    break;
                }
                addCharToToken(tp, c);
            }
            return makeToken(tp, 0, T_REGEXP, 0);

        case '\\':
            c = getNextChar(stream);
            if (c == '\r' || c == '\n' || c == 0) {
                ecError(cp, "Warning", &stream->loc, "Illegal newline in regular expression");
                return makeToken(tp, 0, T_ERR, 0);
            }
            addCharToToken(tp, '\\');
            addCharToToken(tp, c);
            break;

        case '\r':
        case '\n':
            ecError(cp, "Warning", &stream->loc, "Illegal newline in regular expression");
            return makeToken(tp, 0, T_ERR, 0);

        default:
            addCharToToken(tp, c);
        }
    }
}
Beispiel #2
0
static void compileError(EcCompiler *cp, cchar *fmt, ...)
{
    va_list     args;


    cp->errorCount++;
    cp->error = 1;
    va_start(args, fmt);
    ecError(cp, "Error", NULL, fmt, args);
    va_end(args);
}
Beispiel #3
0
/*
    C, C++ and doc style comments. Return token or zero for no token.
 */
static int getComment(EcCompiler *cp, EcToken *tp, int c)
{
    EcStream    *stream;
    int         form, startLine;

    startLine = cp->stream->loc.lineNumber;
    stream = cp->stream;
    form = c;

    for (form = c; c > 0;) {
        c = getNextChar(stream);
        if (c <= 0) {
            /*
                Unterminated Comment
             */
            addFormattedStringToToken(tp, "Unterminated comment starting on line %d", startLine);
            makeToken(tp, 0, form == '/' ? T_EOF: T_ERR, 0);
            return 1;
        }
        if (form == '/') {
            if (c == '\n' || c == '\r') {
                break;
            }
        } else {
            if (c == '*') {
                c = getNextChar(stream);
                if (c == '/') {
                    break;
                }
                addCharToToken(tp, '*');
                putBackChar(stream, c);

            } else if (c == '/') {
                c = getNextChar(stream);
                if (c == '*') {
                    /*
                        Nested comment
                     */
                    if (cp->warnLevel > 0) {
                        ecError(cp, "Warning", &stream->loc, "Possible nested comment");
                    }
                }
                addCharToToken(tp, '/');
            }
        }
        addCharToToken(tp, c);
    }
    return 0;
}
Beispiel #4
0
static int compileInner(EcCompiler *cp, int argc, char **argv)
{
    Ejs         *ejs;
    EjsModule   *mp;
    MprList     *nodes;
    EjsBlock    *block;
    EcLocation  loc;
    cchar       *ext;
    char        *msg;
    int         next, i, j, nextModule, lflags, rc, paused;

    ejs = cp->ejs;
    if ((nodes = mprCreateList(-1, 0)) == 0) {
        return EJS_ERR;
    }
    cp->nodes = nodes;

    /*
        Warn about source files mentioned multiple times.
        TODO OPT. This is slow.
     */
    for (i = 0; i < argc; i++) {
        for (j = 0; j < argc; j++) {
            if (i == j) {
                continue;
            }
            if (mprSamePath(argv[i], argv[j])) {
                compileError(cp, "Loading source %s multiple times. Ignoring extra copies.", argv[i]);
                return EJS_ERR;
            }
        }
        if (cp->outputFile && mprSamePath(cp->outputFile, argv[i])) {
            compileError(cp, "Output file is the same as input file: %s", argv[i]);
            return EJS_ERR;
        }
    }

    /*
        Compile source files and load any module files
     */
    for (i = 0; i < argc && !cp->fatalError; i++) {
        ext = mprGetPathExt(argv[i]);
        if (scasecmp(ext, "mod") == 0 || scasecmp(ext, BIT_SHOBJ) == 0) {
            nextModule = mprGetListLength(ejs->modules);
            lflags = cp->strict ? EJS_LOADER_STRICT : 0;
            if ((rc = ejsLoadModule(cp->ejs, ejsCreateStringFromAsc(ejs, argv[i]), -1, -1, lflags)) < 0) {
                msg = sfmt("Error initializing module %s\n%s", argv[i], ejsGetErrorMsg(cp->ejs, 1));
                memset(&loc, 0, sizeof(EcLocation));
                loc.filename = sclone(argv[i]);
                if (rc == MPR_ERR_CANT_INITIALIZE) {
                    ecError(cp, "Error", &loc, msg);
                } else {
                    ecError(cp, "Error", &loc, msg);
                }
                cp->nodes = NULL;
                return EJS_ERR;
            }
            if (cp->merge) {
                /*
                    If merging, we must emit the loaded module into the output. So add to the compiled modules list.
                 */
                for (next = nextModule; (mp = mprGetNextItem(ejs->modules, &next)) != 0; ) {
                    if (mprLookupItem(cp->modules, mp) < 0 && mprAddItem(cp->modules, mp) < 0) {
                        compileError(cp, "Can't add module %s", mp->name);
                    }
                }
            }
            mprAddItem(nodes, 0);
        } else  {
            mprAssert(!MPR->marking);
            paused = ejsBlockGC(ejs);
            mprAddItem(nodes, ecParseFile(cp, argv[i]));
            ejsUnblockGC(ejs, paused);
        }
        mprAssert(!MPR->marking);
    }
    mprAssert(ejs->result == 0 || (MPR_GET_GEN(MPR_GET_MEM(ejs->result)) != MPR->heap->dead));


    /*
        Allocate the eval frame stack. This is used for property lookups. We have one dummy block at the top always.
     */
    block = ejsCreateBlock(ejs, 0);
    mprSetName(block, "Compiler");
    ejsPushBlock(ejs, block);
    
    /*
        Process the internal representation and generate code
     */
    paused = ejsBlockGC(ejs);
    if (!cp->parseOnly && cp->errorCount == 0) {
        ecResetParser(cp);
        if (ecAstProcess(cp) < 0) {
            ejsPopBlock(ejs);
            cp->nodes = NULL;
            ejsUnblockGC(ejs, paused);
            return EJS_ERR;
        }
        if (cp->errorCount == 0) {
            ecResetParser(cp);
            if (ecCodeGen(cp) < 0) {
                ejsPopBlock(ejs);
                cp->nodes = NULL;
                ejsUnblockGC(ejs, paused);
                return EJS_ERR;
            }
        }
    }
    ejsPopBlock(ejs);
    mprAssert(ejs->result == 0 || (MPR_GET_GEN(MPR_GET_MEM(ejs->result)) != MPR->heap->dead));

    /*
        Add compiled modules to the interpreter
     */
    for (next = 0; ((mp = (EjsModule*) mprGetNextItem(cp->modules, &next)) != 0); ) {
        ejsAddModule(cp->ejs, mp);
    }
    cp->nodes = NULL;
    ejsUnblockGC(ejs, paused);
    if (!paused) {
        mprYield(0);
    }
    mprAssert(ejs->result == 0 || (MPR_GET_GEN(MPR_GET_MEM(ejs->result)) != MPR->heap->dead));
    return (cp->errorCount > 0) ? EJS_ERR: 0;
}