/* HandleAction() - handle a TK_ACTION token in a rule. * * There is a default action that gets reused for any rule that * has no trailing action. */ static void HandleAction(TToken LhsToken, TToken ActionToken, TRule* Rule) { int IsDefault; TSymbol* Symbol; TToken ActionName; IsDefault = TokenEqual(ActionToken, DefActToken); if(IsDefault) ActionName = ActionToken; else ActionName = FakeActionToken(); /* turn action into a hidden non-terminal with an empty rule */ Symbol = AcceptRhs(LhsToken, ActionName, Rule); assert(SymbolGetBit(Symbol, SYM_TERMINAL) == FALSE); if(Symbol->Action) assert(IsDefault); else { Symbol->Action = NEW(TAction); assert(Symbol->Action != NULL); Symbol->Action->Action = ActionToken; Globals.Actions = SymbolListAdd(Globals.Actions, Symbol); Symbol->Action->Number = SymbolListCount(Globals.Actions); /* do not assign Action->ArgCount here, grammar rewriting may change it! */ /* nonterminal representing action gets a null rule */ SymbolNewRule(Symbol); } }
void ParseDirective(TokenVector tokens, TokenVector* fileTokens, int index, PrepocContext* context){ if(tokens.length < 2 || !TOKEN_IS(tokens.vals[0], "#")){ printf("\n\nError: malformed preproc directive (length %d): \n", tokens.length); for(int i = 0; i < tokens.length; i++){ printf("'%.*s', ", tokens.vals[i].length, tokens.vals[i].start); } printf("\n"); } Token directiveType = tokens.vals[1]; //printf("Directive type: '%.*s'\n", tokens.vals[1].length, tokens.vals[1].start); if(context->ifLevels > 0){ if(TOKEN_IS(directiveType, "if")){ context->ifLevels++; } else if(TOKEN_IS(directiveType, "ifdef")){ context->ifLevels++; } else if(TOKEN_IS(directiveType, "ifndef")){ context->ifLevels++; } else if(TOKEN_IS(directiveType, "endif")){ context->ifLevels--; } } else{ if(TOKEN_IS(directiveType, "include")){ Token data = tokens.vals[2]; if(TOKEN_IS(data, "<")){ //TODO: Fix up issues } else{ int fileOpenIdx = -1; for(int i = 0; i < openFiles.length; i++){ if(data.start > openFiles.vals[i].start && data.start < (openFiles.vals[i].start + openFiles.vals[i].length)){ fileOpenIdx = i; break; } } Token currentFileName = openFiles.vals[fileOpenIdx].fileName; while(currentFileName.length > 0 && currentFileName.start[currentFileName.length] != '/'){ currentFileName.length--; } char path[256] = {0}; snprintf(path, 256, "%.*s/%.*s", currentFileName.length, currentFileName.start, data.length - 2, data.start + 1); int fileSize; char* fileBuffer = ReadTextFile(path, &fileSize); OpenFileInfo fileOp = {fileBuffer, fileSize, {data.start+1, data.length-2}}; VectorAddOpenFileInfo(&openFiles, fileOp); printf("About to process included file.\n"); TokenVector lexedIncludedFile = PreprocessString(fileBuffer); printf("Processed included file.\n"); VectorInsertVectorToken(fileTokens, index, lexedIncludedFile); printf("Added included tokens.\n"); } } else if(TOKEN_IS(directiveType, "define")){ Token macroName = tokens.vals[2]; if(tokens.length > 3 && TOKEN_IS(tokens.vals[3], "(") && tokens.vals[2].start + tokens.vals[2].length == tokens.vals[3].start){ //printf("Preproc func\n"); PreprocDefFunc defFunc = {0}; defFunc.name = macroName; int i = 4; for( ; i < tokens.length; i++){ if(TOKEN_IS(tokens.vals[i], ")")){ i++; break; } else if(!TOKEN_IS(tokens.vals[i], ",")){ VectorAddToken(&defFunc.args, tokens.vals[i]); } } for( ; i < tokens.length; i++){ VectorAddToken(&defFunc.result, tokens.vals[i]); } VectorAddPreprocDefFunc(&context->funcDefs, defFunc); } else{ //printf("Preproc subst def.\n"); PreprocDef def = {0}; def.name = macroName; for(int i = 3; i < tokens.length; i++){ VectorAddToken(&def.val, tokens.vals[i]); } //printf("Preproc define '%.*s' && '%.*s'\n", def.name.length, def.name.start, def.val.vals[0].length, def.val.vals[0].start); VectorAddPreprocDef(&context->simpleDefs, def); } } else if(TOKEN_IS(directiveType, "if")){ } else if(TOKEN_IS(directiveType, "ifdef")){ int isDefined = 0; for(int i = 0; i < context->simpleDefs.length; i++){ if(TokenEqual(context->simpleDefs.vals[i].name, tokens.vals[2])){ isDefined = 1; break; } } for(int i = 0; i < context->funcDefs.length; i++){ if(TokenEqual(context->funcDefs.vals[i].name, tokens.vals[2])){ isDefined = 1; break; } } if(!isDefined){ printf("Found ifdef that is not defined.\n"); context->ifLevels = 1; } } else if(TOKEN_IS(directiveType, "ifndef")){ int isDefined = 0; for(int i = 0; i < context->simpleDefs.length; i++){ if(TokenEqual(context->simpleDefs.vals[i].name, tokens.vals[2])){ isDefined = 1; break; } } for(int i = 0; i < context->funcDefs.length; i++){ if(TokenEqual(context->funcDefs.vals[i].name, tokens.vals[2])){ isDefined = 1; break; } } if(isDefined){ context->ifLevels = 1; } } else if(TOKEN_IS(directiveType, "line")){ //TODO } else if(TOKEN_IS(directiveType, "undef")){ for(int i = 0; i < context->simpleDefs.length; i++){ if(TokenEqual(context->simpleDefs.vals[i].name, tokens.vals[2])){ VectorRemovePreprocDef(&context->simpleDefs, i); break; } } for(int i = 0; i < context->funcDefs.length; i++){ if(TokenEqual(context->funcDefs.vals[i].name, tokens.vals[2])){ VectorRemovePreprocDefFunc(&context->funcDefs, i); break; } } } else if(TOKEN_IS(directiveType, "endif")){ //Do nothing, we're closing off an active if block } } }
TokenVector PreprocessString(char* string){ PrepocContext context = {0}; TokenVector lexedFile = LexString(string); for(int i = 0; i < lexedFile.length; i++){ Token tok = lexedFile.vals[i]; //printf("Tok: '%.*s'\n", tok.length, tok.start); if(TOKEN_IS(tok, "#")){ TokenVector directiveToks = GetAndRemoveDirectiveTokens(&lexedFile, i); //printf("Directive toks (length %d):\n", directiveToks.length); ParseDirective(directiveToks, &lexedFile, i, &context); i--; } else if(context.ifLevels > 0){ //printf("Removing token: '%.*s'\n", tok.length, tok.start); VectorRemoveToken(&lexedFile, i); i--; } else{ int expandDef = 0; for(int j = 0; j < context.simpleDefs.length; j++){ if(TokenEqual(tok, context.simpleDefs.vals[j].name)){ VectorRemoveToken(&lexedFile, i); VectorInsertVectorToken(&lexedFile, i, context.simpleDefs.vals[j].val); expandDef = 1; break; } } for(int j = 0; j < context.funcDefs.length; j++){ if(TokenEqual(tok, context.funcDefs.vals[j].name)){ //printf("FOUND ARG FUNC.\n"); int endIdx = i + 1; while(!TOKEN_IS(lexedFile.vals[endIdx], ")")){ endIdx++; } TokenVectorVector argList = {0}; TokenVector emptyVec = {0}; VectorAddTokenVector(&argList, emptyVec); int argIdx = 0; for(int k = i + 2; k < endIdx; k++){ if(TOKEN_IS(lexedFile.vals[k], ",")){ argIdx++; VectorAddTokenVector(&argList, emptyVec); } else{ VectorAddToken(&argList.vals[argIdx], lexedFile.vals[k]); } } for(int k = i; k <= endIdx; k++){ VectorRemoveToken(&lexedFile, i); } for(int funcIdx = context.funcDefs.vals[j].result.length - 1; funcIdx >= 0; funcIdx--){ int isArg = 0; for(int argIdx = 0; argIdx < context.funcDefs.vals[j].args.length; argIdx++){ if(TokenEqual(context.funcDefs.vals[j].args.vals[argIdx], context.funcDefs.vals[j].result.vals[funcIdx])){ VectorInsertVectorToken(&lexedFile, i, argList.vals[argIdx]); isArg = 1; break; } } if (!isArg) { //printf("lexedFile.length ~: %d\n", lexedFile.length); VectorInsertToken(&lexedFile, i, context.funcDefs.vals[j].result.vals[funcIdx]); } } expandDef = 1; break; } } if(expandDef){ i--; } } } return lexedFile; }