[C++] Implement ifdef
diff --git a/parser.cc b/parser.cc
index 00339c0..2bd0169 100644
--- a/parser.cc
+++ b/parser.cc
@@ -1,5 +1,6 @@
#include "parser.h"
+#include <stack>
#include <unordered_map>
#include "ast.h"
@@ -17,11 +18,19 @@
};
class Parser {
+ struct IfState {
+ IfAST* ast;
+ bool is_in_else;
+ int num_nest;
+ };
+
public:
Parser(StringPiece buf, const char* filename, vector<AST*>* asts)
: buf_(buf),
state_(ParserState::NOT_AFTER_RULE),
+ asts_(asts),
out_asts_(asts),
+ num_if_nest_(0),
loc_(filename, 0),
fixed_lineno_(false) {
}
@@ -52,6 +61,9 @@
(*make_directives_)["-include"] = &Parser::ParseInclude;
(*make_directives_)["sinclude"] = &Parser::ParseInclude;
(*make_directives_)["define"] = &Parser::ParseDefine;
+ (*make_directives_)["ifdef"] = &Parser::ParseIfdef;
+ (*make_directives_)["ifndef"] = &Parser::ParseIfdef;
+ (*make_directives_)["endif"] = &Parser::ParseEndif;
shortest_directive_len_ = 9999;
longest_directive_len_ = 0;
@@ -216,6 +228,45 @@
define_name_.clear();
}
+ void ParseIfdef(StringPiece line, StringPiece directive) {
+ IfAST* ast = new IfAST();
+ ast->set_loc(loc_);
+ ast->op = directive[2] == 'n' ? CondOp::IFNDEF : CondOp::IFDEF;
+ ast->lhs = ParseExpr(line, false);
+ ast->rhs = NULL;
+ out_asts_->push_back(ast);
+
+ IfState* st = new IfState();
+ st->ast = ast;
+ st->is_in_else = false;
+ st->num_nest = num_if_nest_;
+ out_asts_ = &ast->true_stmts;
+ }
+
+ void ParseEndif(StringPiece, StringPiece) {
+ CheckIfStack("endif");
+ IfState st = *if_stack_.top();
+ for (int t = 0; t <= st.num_nest; t++) {
+ delete if_stack_.top();
+ if_stack_.pop();
+ if (if_stack_.empty()) {
+ out_asts_ = asts_;
+ } else {
+ IfState* st = if_stack_.top();
+ if (st->is_in_else)
+ out_asts_ = &st->ast->false_stmts;
+ else
+ out_asts_ = &st->ast->true_stmts;
+ }
+ }
+ }
+
+ void CheckIfStack(const char* keyword) {
+ if (if_stack_.empty()) {
+ Error(StringPrintf("*** extraneous `%s'.", keyword));
+ }
+ }
+
bool HandleDirective(StringPiece line) {
if (line.size() < shortest_directive_len_)
return false;
@@ -237,11 +288,16 @@
size_t l_;
ParserState state_;
+ vector<AST*>* asts_;
vector<AST*>* out_asts_;
+
StringPiece define_name_;
size_t define_start_;
int define_start_line_;
+ int num_if_nest_;
+ stack<IfState*> if_stack_;
+
Loc loc_;
bool fixed_lineno_;