Beispiel #1
1
/**
 * ParamList = "(" [ ( Param [{ "," Param }] [ "," "..." ] ) | "..." | "void" ] ")"
 */
void parserParamList (parserCtx* ctx, ast* Node, bool inDecl) {
    debugEnter("ParamList");

    tokenMatchPunct(ctx, punctLParen);

    if (!tokenIsPunct(ctx, punctRParen)) {
        tokenLocation voidloc = ctx->location;

        bool end = false;

        /*Either an empty prototype declaration,
          or the beginning of a void* parameter*/
        if (tokenTryMatchKeyword(ctx, keywordVoid)) {
            if (!tokenIsPunct(ctx, punctRParen)) {
                ast* basic = astCreateLiteralIdent(voidloc, strdup("void"));
                ast* expr = parserDeclExpr(ctx, inDecl, symParam);
                ast* param = astCreateParam(voidloc, basic, expr);
                param->symbol = basic->symbol = symFind(ctx->scope, "void");
                astAddChild(Node, param);

                if (!tokenTryMatchPunct(ctx, punctComma))
                    end = true;

            } else
                end = true;
        }

        if (!end) do {
            if (tokenIsPunct(ctx, punctEllipsis)) {
                astAddChild(Node, astCreate(astEllipsis, ctx->location));
                tokenMatch(ctx);
                break;

            } else
                astAddChild(Node, parserParam(ctx, inDecl));

        } while (tokenTryMatchPunct(ctx, punctComma));
    }

    tokenMatchPunct(ctx, punctRParen);

    debugLeave();
}
Beispiel #2
0
Datei: ast.c Projekt: 8l/fcc
ast* astCreateTOP (tokenLocation location, ast* cond, ast* l, ast* r) {
    ast* Node = astCreate(astTOP, location);
    astAddChild(Node, cond);
    Node->l = l;
    Node->r = r;
    return Node;
}
Beispiel #3
0
/**
 * StructOrUnion = "struct" | "union" Name# ^ ( "{" [{ Field }] "}" )
 *
 * Name is told to create a symbol of the tag indicated by the first
 * token.
 */
static struct ast* parserStructOrUnion (parserCtx* ctx) {
    debugEnter("StructOrUnion");

    tokenLocation loc = ctx->location;

    symTag tag =   tokenTryMatchKeyword(ctx, keywordStruct)
                 ? symStruct
                 : (tokenMatchKeyword(ctx, keywordUnion), symUnion);

    ast* name;

    /*Name*/

    if (tokenIsIdent(ctx))
        name = parserName(ctx, true, tag);

    /*Anonymous struct, will require a body*/
    else {
        name = astCreateEmpty(loc);
        name->literal = strdup("");
        name->symbol = symCreateNamed(tag, ctx->scope, "");
    }

    ast* Node = (tag == symStruct ? astCreateStruct : astCreateUnion)
                (loc, name);
    Node->symbol = Node->l->symbol;
    sym* OldScope = scopeSet(ctx, Node->symbol);

    /*Body*/
    if (Node->l->tag == astEmpty || tokenIsPunct(ctx, punctLBrace)) {
        /*Only error if not already errored for wrong tag*/
        if (Node->symbol->impl && Node->symbol->tag == tag)
            errorReimplementedSym(ctx, Node->symbol);

        else
            Node->symbol->impl = Node;

        tokenMatchPunct(ctx, punctLBrace);

        Node->symbol->complete = true;

        /*Eat fields*/
        while (!tokenIsPunct(ctx, punctRBrace))
            astAddChild(Node, parserField(ctx));

        tokenMatchPunct(ctx, punctRBrace);
    }

    ctx->scope = OldScope;

    debugLeave();

    return Node;
}
Beispiel #4
0
/**
 * Decl = Storage DeclBasic ";" | ( DeclExpr#   ( [{ "," DeclExpr# }] ";" )
 *                                            | FnImpl )
 *
 * DeclExpr is told to require identifiers, allow initiations and
 * create symbols.
 */
ast* parserDecl (parserCtx* ctx, bool module) {
    debugEnter("Decl");

    tokenLocation loc = ctx->location;

    symTag tag = symId;
    ast* storage = parserStorage(ctx, &tag);
    ast* Node = astCreateDecl(loc, parserDeclBasic(ctx));
    Node->r = storage;

    /*Declares no symbols*/
    if (tokenTryMatchPunct(ctx, punctSemicolon))
        ;

    else {
        astAddChild(Node, parserDeclExpr(ctx, true, tag));

        /*Function*/
        if (tokenIsPunct(ctx, punctLBrace)) {
            if (!module)
                errorIllegalOutside(ctx, "function implementation", "module level code");

            Node = parserFnImpl(ctx, Node);

        /*Regular decl*/
        } else {
            while (tokenTryMatchPunct(ctx, punctComma))
                astAddChild(Node, parserDeclExpr(ctx, true, tag));

            tokenMatchPunct(ctx, punctSemicolon);
        }
    }

    debugLeave();

    return Node;
}
Beispiel #5
0
/**
 * Field = DeclBasic [ DeclExpr# [{ "," DeclExpr# }] ] ";"
 *
 * DeclExpr is told to require idents and create symbols.
 */
static ast* parserField (parserCtx* ctx) {
    debugEnter("Field");

    tokenLocation loc = ctx->location;
    ast* Node = astCreateDecl(loc, parserDeclBasic(ctx));

    if (!tokenIsPunct(ctx, punctSemicolon)) do {
        astAddChild(Node, parserDeclExpr(ctx, true, symId));
    } while (tokenTryMatchPunct(ctx, punctComma));

    tokenMatchPunct(ctx, punctSemicolon);

    debugLeave();

    return Node;
}
Beispiel #6
0
/**
 * Enum = "enum" Name# ^ ( "{" EnumField [{ "," EnumField }] [ "," ] "}" )
 */
static struct ast* parserEnum (parserCtx* ctx) {
    debugEnter("Enum");

    tokenLocation loc = ctx->location;
    tokenMatchKeyword(ctx, keywordEnum);

    /*Name*/

    ast* name;

    if (tokenIsIdent(ctx))
        name = parserName(ctx, true, symEnum);

    else {
        name = astCreateEmpty(loc);
        name->literal = strdup("");
        name->symbol = symCreateNamed(symEnum, ctx->scope, "");
    }

    ast* Node = astCreateEnum(loc, name);
    Node->symbol = Node->l->symbol;
    Node->symbol->complete = true;

    /*Body*/
    if (Node->l->tag == astEmpty || tokenIsPunct(ctx, punctLBrace)) {
        /*Only error if not already errored for wrong tag*/
        if (Node->symbol->impl && Node->symbol->tag == symEnum)
            errorReimplementedSym(ctx, Node->symbol);

        else
            Node->symbol->impl = Node;

        tokenMatchPunct(ctx, punctLBrace);

        if (!tokenIsPunct(ctx, punctRBrace)) do {
            astAddChild(Node, parserEnumField(ctx));
        } while (tokenTryMatchPunct(ctx, punctComma) && !tokenIsPunct(ctx, punctRBrace));

        tokenMatchPunct(ctx, punctRBrace);
    }

    debugLeave();

    return Node;
}