diff options
author | Shinichiro Hamaji <shinichiro.hamaji@gmail.com> | 2015-06-17 17:51:24 +0900 |
---|---|---|
committer | Shinichiro Hamaji <shinichiro.hamaji@gmail.com> | 2015-06-18 11:25:44 +0900 |
commit | d146f4c482adb0c51bfc1bef101361845f74407c (patch) | |
tree | bf2f649f66ce5ddbdb3fafbed6fbf12163c4b5a1 | |
parent | eb2b3d0a6a18e2eff96ba64abf5604011c2fbf2d (diff) | |
download | kati-d146f4c482adb0c51bfc1bef101361845f74407c.tar.gz |
[C++] Implement ifeq
-rw-r--r-- | eval.cc | 8 | ||||
-rw-r--r-- | parser.cc | 68 | ||||
-rw-r--r-- | value.cc | 21 | ||||
-rw-r--r-- | value.h | 4 |
4 files changed, 83 insertions, 18 deletions
@@ -107,18 +107,20 @@ void Evaluator::EvalCommand(const CommandAST* ast) { void Evaluator::EvalIf(const IfAST* ast) { bool is_true; - StringPiece lhs = Intern(*ast->lhs->Eval(this)); switch (ast->op) { case CondOp::IFDEF: case CondOp::IFNDEF: { + StringPiece lhs = Intern(*ast->lhs->Eval(this)); Var* v = LookupVarInCurrentScope(lhs); shared_ptr<string> s = v->Eval(this); - is_true = s->empty() == (ast->op == CondOp::IFNDEF); + is_true = (s->empty() == (ast->op == CondOp::IFNDEF)); break; } case CondOp::IFEQ: case CondOp::IFNEQ: { - ERROR("TODO"); + shared_ptr<string> lhs = ast->lhs->Eval(this); + shared_ptr<string> rhs = ast->rhs->Eval(this); + is_true = ((*lhs == *rhs) == (ast->op == CondOp::IFEQ)); break; } default: @@ -67,6 +67,8 @@ class Parser { (*make_directives_)["define"] = &Parser::ParseDefine; (*make_directives_)["ifdef"] = &Parser::ParseIfdef; (*make_directives_)["ifndef"] = &Parser::ParseIfdef; + (*make_directives_)["ifeq"] = &Parser::ParseIfeq; + (*make_directives_)["ifneq"] = &Parser::ParseIfeq; (*make_directives_)["else"] = &Parser::ParseElse; (*make_directives_)["endif"] = &Parser::ParseEndif; @@ -244,6 +246,15 @@ class Parser { define_name_.clear(); } + void EnterIf(IfAST* ast) { + IfState* st = new IfState(); + st->ast = ast; + st->is_in_else = false; + st->num_nest = num_if_nest_; + if_stack_.push(st); + out_asts_ = &ast->true_asts; + } + void ParseIfdef(StringPiece line, StringPiece directive) { IfAST* ast = new IfAST(); ast->set_loc(loc_); @@ -251,13 +262,56 @@ class Parser { ast->lhs = ParseExpr(line, false); ast->rhs = NULL; out_asts_->push_back(ast); + EnterIf(ast); + } - IfState* st = new IfState(); - st->ast = ast; - st->is_in_else = false; - st->num_nest = num_if_nest_; - if_stack_.push(st); - out_asts_ = &ast->true_asts; + bool ParseIfEqCond(StringPiece s, IfAST* ast) { + if (s.empty()) { + return false; + } + + if (s[0] == '(' && s[s.size() - 1] == ')') { + s = s.substr(1, s.size() - 2); + char terms[] = {',', '\0'}; + size_t n; + ast->lhs = ParseExprImpl(s, terms, false, &n, true); + if (s[n] != ',') + return false; + s = TrimLeftSpace(s.substr(n+1)); + ast->rhs = ParseExprImpl(s, NULL, false, &n); + return TrimSpace(s.substr(n)) == ""; + } else { + for (int i = 0; i < 2; i++) { + if (s.empty()) + return false; + char quote = s[0]; + if (quote != '\'' && quote != '"') + return false; + size_t end = s.find(quote, 1); + if (end == string::npos) + return false; + Value* v = ParseExpr(s.substr(1, end - 1), false); + if (i == 0) + ast->lhs = v; + else + ast->rhs = v; + s = TrimLeftSpace(s.substr(end+1)); + } + return s.empty(); + } + } + + void ParseIfeq(StringPiece line, StringPiece directive) { + IfAST* ast = new IfAST(); + ast->set_loc(loc_); + ast->op = directive[2] == 'n' ? CondOp::IFNEQ : CondOp::IFEQ; + + if (!ParseIfEqCond(line, ast)) { + Error("*** invalid syntax in conditional."); + } + + out_asts_->push_back(ast); + EnterIf(ast); } void ParseElse(StringPiece line, StringPiece) { @@ -350,7 +404,7 @@ class Parser { return false; StringPiece rest = TrimRightSpace(RemoveComment(TrimLeftSpace( - line.substr(directive.size() + 1)))); + line.substr(directive.size())))); (this->*found->second)(rest, directive); return true; } @@ -223,9 +223,6 @@ static size_t SkipSpaces(StringPiece s, const char* terms) { return s.size(); } -static Value* ParseExprImpl(StringPiece s, const char* terms, bool is_command, - size_t* index_out); - Value* ParseFunc(Func* f, StringPiece s, size_t i, char* terms, size_t* index_out) { terms[1] = ','; @@ -332,8 +329,8 @@ Value* ParseDollar(StringPiece s, size_t* index_out) { } } -static Value* ParseExprImpl(StringPiece s, const char* terms, bool is_command, - size_t* index_out) { +Value* ParseExprImpl(StringPiece s, const char* terms, bool is_command, + size_t* index_out, bool trim_right_space) { // TODO: A faulty optimization. #if 0 char specials[] = "$(){}\\\n"; @@ -433,8 +430,13 @@ static Value* ParseExprImpl(StringPiece s, const char* terms, bool is_command, } } - if (i > b) - r->AddValue(new Literal(s.substr(b, i-b))); + if (i > b) { + StringPiece rest = s.substr(b, i-b); + if (trim_right_space) + rest = TrimRightSpace(rest); + if (!rest.empty()) + r->AddValue(new Literal(rest)); + } *index_out = i; return r->Compact(); } @@ -444,6 +446,11 @@ Value* ParseExpr(StringPiece s, bool is_command) { return ParseExprImpl(s, NULL, is_command, &n); } +Value* ParseExprUntilComma(StringPiece s, size_t* index_out) { + char terms[] = {',', '\0'}; + return ParseExprImpl(s, terms, false, index_out); +} + string JoinValues(const vector<Value*> vals, const char* sep) { vector<string> val_strs; for (Value* v : vals) { @@ -34,7 +34,9 @@ class Value : public Evaluable { virtual string DebugString_() const = 0; }; -Value* ParseExpr(StringPiece s, bool is_command); +Value* ParseExprImpl(StringPiece s, const char* terms, bool is_command, + size_t* index_out, bool trim_right_space = false); +Value* ParseExpr(StringPiece s, bool is_command = false); string JoinValues(const vector<Value*> vals, const char* sep); |