bool PreProcessor::elif_directive() { assert(tokenit.is(_PP_ELIF)); tokenit.next(); if (ifBlockEnables.empty()) { ERROR("'if' directive is not found"); return false; } bool if_is_enable = ifBlockEnables.back(); if (if_is_enable) { TokenIterator tag = tokenit; skipUntilElseOrEnd(); tag.erase(tokenit-tag); } else { AST *ast = expression(); if (!ast) { return false; } if (eval(ast)) { ifBlockEnables.pop_back(); ifBlockEnables.push_back(true); } else { TokenIterator tag = tokenit; skipUntilElseOrEnd(); tag.erase(tokenit-tag); } } return true; }
void PreProcessor::applyMacro(const String &ident, const ref<MacroDef> ¯o) { assert(tokenit.is(_IDENT)); DBG("apply macro: %s", ident.c_str()); if (macro->params.empty()) { tokenit.erase(1);//erase identifier tokenit.insert(macro->tokens); } else { TokenIterator tag = tokenit; tokenit.next(); //get caller params if (tokenit.is(_LPAREN)) { tokenit.next(); List<List<Token> > caller_params; if (!parseFunctionParams(caller_params)) { ERROR("failed to parse function macro"); return; } if (macro->params.size() != caller_params.size()) { ERROR("macro %s requres %d parameters", ident.c_str(), macro->params.size()); return; } tag.erase(tokenit-tag);//erase function call tokens //replace macro params List<Token> replace_tokens = replaceMacroParams(macro->tokens, caller_params); tokenit.insert(replace_tokens); //tokenit.next(); } } }
bool PreProcessor::else_directive() { assert(tokenit.is(_PP_ELSE)); tokenit.next(); if (!tokenit.is(_PP_END)) { //TODO: warning } tokenit.skipUntil({_PP_END}, true); tokenit.next(); if (ifBlockEnables.empty()) { ERROR("'if' directive is not found (before 'else')"); return false; } bool if_is_enable = ifBlockEnables.back(); if (if_is_enable) { TokenIterator tag = tokenit; skipUntilElseOrEnd(); tag.erase(tokenit-tag); } else { ifBlockEnables.pop_back(); ifBlockEnables.push_back(true); } return true; }
List<Token> PreProcessor::replaceMacroParams(const List<Token> &mtokens, const List<List<Token>> &caller_params) { //FIXME: nested macro //i.e. FUNC(x, FUNC(x,y)) List<Token> replace = mtokens; TokenIterator it; it.setTokens(&replace); while (!it.eof()) { if (it.is(_PP_MACRO_PARAM)) { int index = it.val()->toInt(); const List<Token> ¶m = caller_params.at(index); it.erase(1); it.insert(param); } it.next(); } return replace; }
bool PreProcessor::if_directive() { assert(tokenit.is(_PP_IF)); tokenit.next(); AST *ast = expression(); if (!ast) { return false; } if (eval(ast)) { ifBlockEnables.push_back(true); } else { ifBlockEnables.push_back(false); TokenIterator tag = tokenit; skipUntilElseOrEnd(); tag.erase(tokenit-tag); } return true; }