/** * 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(); }
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; }
/** * 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; }
/** * 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; }
/** * 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; }
/** * 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; }