Пример #1
0
/**
 * DeclAtom = [ ( "(" DeclExpr ")" ) | Name ]
 *
 * This is where the inDecl/tag stuff we've been keeping track of
 * comes into play. If outside a declaration, idents are not allowed.
 * Inside a declaration, an ident is *required* unless in the parameters,
 * where they are optional (even outside a prototype...).
 */
static ast* parserDeclAtom (parserCtx* ctx, bool inDecl, symTag tag) {
    debugEnter("DeclAtom");

    ast* Node;

    if (tokenTryMatchPunct(ctx, punctLParen)) {
        Node = parserDeclExpr(ctx, inDecl, tag);
        tokenMatchPunct(ctx, punctRParen);

    } else if (tokenIsIdent(ctx)) {
        if (inDecl || tag == symParam)
            Node = parserName(ctx, inDecl, tag);

        else {
            Node = astCreateInvalid(ctx->location);
            errorIllegalOutside(ctx, "identifier", "a declaration");
            tokenNext(ctx);
        }

    } else if (inDecl && tag != symParam)
        Node = parserName(ctx, inDecl, tag);

    else
        Node = astCreateEmpty(ctx->location);

    debugLeave();

    return Node;
}
Пример #2
0
parserResult parse (sym* global, lexerCtx* lexer) {
    parserCtx ctx = parserInit(global, lexer);
    ast* tree = parseS(&ctx);

    if (!tree) {
        errprintf("No syntax tree created\n");
        tree = astCreateInvalid();
    }

    parserResult result = {
        .tree = tree,
        .errors = ctx.errors
    };

    parserFree(&ctx);

    return result;
}
Пример #3
0
/**
 * Pattern = <Name>
 */
static ast* parserPattern (parserCtx* ctx) {
    ast* node;

    //todo accept only [\w\d-]

    if (see_kind(ctx, tokenNormal)) {
        sym* symbol = symAdd(ctx->scope, ctx->current.buffer);
        accept(ctx);

        node = astCreateSymbol(symbol);

    } else {
        expected(ctx, "function argument");
        node = astCreateInvalid();
    }

    return node;
}
Пример #4
0
/**
 * DeclBasic = [ "const" ] <Ident> | StructUnion | Enum
 */
static ast* parserDeclBasic (parserCtx* ctx) {
    debugEnter("DeclBasic");

    ast* Node;

    tokenLocation constloc = ctx->location;
    bool isConst = tokenTryMatchKeyword(ctx, keywordConst);

    if (tokenIsKeyword(ctx, keywordStruct) || tokenIsKeyword(ctx, keywordUnion))
        Node = parserStructOrUnion(ctx);

    else if (tokenIsKeyword(ctx, keywordEnum))
        Node = parserEnum(ctx);

    else {
        tokenLocation loc = ctx->location;
        sym* Symbol = symFind(ctx->scope, ctx->lexer->buffer);

        if (Symbol) {
            Node = astCreateLiteralIdent(loc, tokenDupMatch(ctx));
            Node->symbol = Symbol;

        } else {
            if (tokenIsIdent(ctx)) {
                errorUndefType(ctx);
                tokenNext(ctx);

            } else
                errorExpected(ctx, "type name");

            Node = astCreateInvalid(loc);
        }
    }

    if (isConst) {
        Node = astCreateConst(constloc, Node);
        Node->symbol = Node->r->symbol;
    }

    debugLeave();

    return Node;
}
Пример #5
0
/**
 * FnApp = { Atom | ( "`" Atom "`" ) }
 *
 * A series of at least one expr-atom. If multiple, then the last is a
 * function to which the others are applied. Instead, one of them may
 * be explicitly marked in backticks as the function.
 */
static ast* parseFnApp (parserCtx* ctx) {
    /*Filled iff there is a backtick function*/
    ast* fn = 0;

    vector(ast*) nodes = vectorInit(3, malloc);

    /*Require at least one expr*/
    if (!see(ctx, "!"))
        vectorPush(&nodes, parseAtom(ctx));

    while (waiting_for_delim(ctx)) {
        if (try_match(ctx, "!")) {
            if (fn) {
                error(ctx)("Multiple explicit functions: '%s'\n", ctx->current.buffer);
                vectorPush(&nodes, fn);
            }

            fn = parseAtom(ctx);

        } else
            vectorPush(&nodes, parseAtom(ctx));
    }

    if (fn)
        return astCreateFnApp(nodes, fn);

    else if (nodes.length == 0) {
        /*Shouldn't happen due to the way it parses*/
        errprintf("FnApp took no AST nodes");
        return astCreateInvalid();

    } else if (nodes.length == 1) {
        /*No application*/
        ast* node = vectorPop(&nodes);
        vectorFree(&nodes);
        return node;

    } else {
    	/*The last node is the fn*/
        fn = vectorPop(&nodes);
        return astCreateFnApp(nodes, fn);
    }
}
Пример #6
0
/**
 * Name = <UnqualifiedIdent>
 *
 * If inDecl, creates a symbol, adding it to the list of declarations
 * if already created.
 */
static ast* parserName (parserCtx* ctx, bool inDecl, symTag tag) {
    debugEnter("Name");

    ast* Node;

    if (tokenIsIdent(ctx)) {
        tokenLocation loc = ctx->location;
        Node = astCreateLiteralIdent(loc, tokenDupMatch(ctx));

        /*Check for a collision only in this scope, will shadow any
          other declarations elsewhere.*/
        sym* Symbol = symFind(ctx->scope, (char*) Node->literal);

        if (Symbol) {
            Node->symbol = Symbol;
            symChangeParent(Symbol, ctx->scope);

            if (Node->symbol->tag != tag && !isTypedefException(Node->symbol, tag))
                errorRedeclaredSymAs(ctx, Node->symbol, tag);

        } else if (inDecl)
            Node->symbol = symCreateNamed(tag, ctx->scope, (char*) Node->literal);

        if (Node->symbol) {
            /*Can't tell whether this is a duplicate declaration
              or a (matching) redefinition*/
            vectorPush(&Node->symbol->decls, Node);
        }

    } else {
        errorExpected(ctx, "name");
        Node = astCreateInvalid(ctx->location);
        Node->literal = strdup("");
        Node->symbol = symCreateNamed(tag, ctx->scope, "");
    }

    debugLeave();

    return Node;
}
Пример #7
0
/**
 * Atom =   ( "(" [ Expr [{ "," Expr }] ] ")" )
 *        | ( "[" [{ Expr }] "]" )
 *        | FnLit | Path | <Str> | <Symbol>
 */
static ast* parseAtom (parserCtx* ctx) {
    ast* node;

    if (try_match(ctx, "(")) {
        /*Empty brackets => unit literal*/
        if (see(ctx, ")"))
            node = astCreateUnitLit();

        else {
            node = parseExpr(ctx);

            /*Tuple literal*/
            if (see(ctx, ",")) {
                vector(ast*) nodes = vectorInit(3, malloc);
                vectorPush(&nodes, node);

                while (try_match(ctx, ","))
                    vectorPush(&nodes, parseExpr(ctx));

                node = astCreateTupleLit(nodes);
            }
        }

        match(ctx, ")");

    /*List literal*/
    } else if (try_match(ctx, "[")) {
        vector(ast*) nodes = vectorInit(4, malloc);

        if (waiting_for(ctx, "]")) do {
            vectorPush(&nodes, parseExpr(ctx));
        } while (try_match(ctx, ","));

        node = astCreateListLit(nodes);

        match(ctx, "]");

    } else if (see(ctx, "\\")) {
        node = parseFnLit(ctx);

    } else if (see(ctx, "true") || see(ctx, "false")) {
        node = astCreateBoolLit(see(ctx, "true"));
        accept(ctx);

    } else if (see_kind(ctx, tokenIntLit)) {
        node = astCreateIntLit(atoi(ctx->current.buffer));
        accept(ctx);

    } else if (see_kind(ctx, tokenStrLit)) {
        node = astCreateStrLit(ctx->current.buffer);
        accept(ctx);

    } else if (see_kind(ctx, tokenNormal)) {
        sym* symbol;

        if (isPathToken(ctx->current.buffer))
            node = parsePath(ctx);

        else if ((symbol = symLookup(ctx->scope, ctx->current.buffer)))
            node = astCreateSymbol(symbol);

        else
            node = astCreateFileLit(ctx->current.buffer);

        accept(ctx);

    } else {
        expected(ctx, "expression");
        node = astCreateInvalid();
    }

    return node;
}