Added unary plus/minus/not operators.

This commit is contained in:
yhirose 2015-06-03 22:50:00 -04:00
parent 650344c2c2
commit 36384e69a5
3 changed files with 43 additions and 3 deletions

View File

@ -18,6 +18,9 @@ struct Eval
case LogicalOr: return eval_logical_or(ast, env); case LogicalOr: return eval_logical_or(ast, env);
case LogicalAnd: return eval_logical_and(ast, env); case LogicalAnd: return eval_logical_and(ast, env);
case Condition: return eval_condition(ast, env); case Condition: return eval_condition(ast, env);
case UnaryPlus: return eval_unary_plus(ast, env);
case UnaryMinus: return eval_unary_minus(ast, env);
case UnaryNot: return eval_unary_not(ast, env);
case BinExpresion: return eval_bin_expression(ast, env); case BinExpresion: return eval_bin_expression(ast, env);
case Identifier: return eval_identifier(ast, env); case Identifier: return eval_identifier(ast, env);
case Number: return eval_number(ast, env); case Number: return eval_number(ast, env);
@ -173,6 +176,30 @@ private:
} }
} }
static Value eval_unary_plus(const Ast& ast, shared_ptr<Environment> env) {
if (ast.nodes.size() == 1) {
return eval(*ast.nodes[0], env);
} else {
return eval(*ast.nodes[1], env);
}
}
static Value eval_unary_minus(const Ast& ast, shared_ptr<Environment> env) {
if (ast.nodes.size() == 1) {
return eval(*ast.nodes[0], env);
} else {
return Value(eval(*ast.nodes[1], env).to_long() * -1);
}
}
static Value eval_unary_not(const Ast& ast, shared_ptr<Environment> env) {
if (ast.nodes.size() == 1) {
return eval(*ast.nodes[0], env);
} else {
return Value(!eval(*ast.nodes[1], env).to_bool());
}
}
static Value eval_bin_expression(const Ast& ast, shared_ptr<Environment> env) { static Value eval_bin_expression(const Ast& ast, shared_ptr<Environment> env) {
auto ret = eval(*ast.nodes[0], env).to_long(); auto ret = eval(*ast.nodes[0], env).to_long();
for (auto i = 1u; i < ast.nodes.size(); i += 2) { for (auto i = 1u; i < ast.nodes.size(); i += 2) {

View File

@ -22,14 +22,21 @@ static auto g_grammar = R"(
LOGICAL_OR <- LOGICAL_AND ('&&' _ LOGICAL_AND)* LOGICAL_OR <- LOGICAL_AND ('&&' _ LOGICAL_AND)*
LOGICAL_AND <- CONDITION (CONDITION_OPERATOR CONDITION)* LOGICAL_AND <- CONDITION (CONDITION_OPERATOR CONDITION)*
CONDITION <- TERM (TERM_OPERATOR TERM)* CONDITION <- TERM (TERM_OPERATOR TERM)*
TERM <- FACTOR (FACTOR_OPERATOR FACTOR)* TERM <- UNARY_PLUS_OPERATOR? UNARY_PLUS
UNARY_PLUS <- UNARY_MINUS_OPERATOR? UNARY_MINUS
UNARY_MINUS <- UNARY_NOT_OPERATOR? UNARY_NOT
UNARY_NOT <- FACTOR (FACTOR_OPERATOR FACTOR)*
FACTOR <- WHILE / IF / FUNCTION / FUNCTION_CALL / NUMBER / BOOLEAN / STRING / INTERPOLATED_STRING / IDENTIFIER / '(' _ EXPRESSION ')' _ FACTOR <- WHILE / IF / FUNCTION / FUNCTION_CALL / NUMBER / BOOLEAN / STRING / INTERPOLATED_STRING / IDENTIFIER / '(' _ EXPRESSION ')' _
BLOCK <- '{' _ STATEMENTS '}' _ BLOCK <- '{' _ STATEMENTS '}' _
CONDITION_OPERATOR <- < ('==' / '!=' / '<=' / '<' / '>=' / '>') > _ CONDITION_OPERATOR <- < ('==' / '!=' / '<=' / '<' / '>=' / '>') > _
TERM_OPERATOR <- < [-+] > _ TERM_OPERATOR <- < [-+] > _
UNARY_PLUS_OPERATOR <- < '+' > _
UNARY_MINUS_OPERATOR <- < '-' > _
UNARY_NOT_OPERATOR <- < '!' > _
FACTOR_OPERATOR <- < [*/%] > _ FACTOR_OPERATOR <- < [*/%] > _
IDENTIFIER <- < [a-zA-Z_][a-zA-Z0-9_]* > _ IDENTIFIER <- < [a-zA-Z_][a-zA-Z0-9_]* > _
NUMBER <- < [0-9]+ > _ NUMBER <- < [0-9]+ > _
@ -78,9 +85,15 @@ peg& get_parser()
{ peg::AstNodeType::Optimizable, "LOGICAL_OR", LogicalAnd }, { peg::AstNodeType::Optimizable, "LOGICAL_OR", LogicalAnd },
{ peg::AstNodeType::Optimizable, "LOGICAL_AND", Condition }, { peg::AstNodeType::Optimizable, "LOGICAL_AND", Condition },
{ peg::AstNodeType::Optimizable, "CONDITION", BinExpresion }, { peg::AstNodeType::Optimizable, "CONDITION", BinExpresion },
{ peg::AstNodeType::Optimizable, "TERM", BinExpresion }, { peg::AstNodeType::Optimizable, "TERM", UnaryPlus },
{ peg::AstNodeType::Optimizable, "UNARY_PLUS", UnaryMinus },
{ peg::AstNodeType::Optimizable, "UNARY_MINUS", UnaryNot },
{ peg::AstNodeType::Optimizable, "UNARY_NOT", BinExpresion },
{ peg::AstNodeType::Token, "CONDITION_OPERATOR", Undefined }, { peg::AstNodeType::Token, "CONDITION_OPERATOR", Undefined },
{ peg::AstNodeType::Token, "TERM_OPERATOR", Undefined }, { peg::AstNodeType::Token, "TERM_OPERATOR", Undefined },
{ peg::AstNodeType::Token, "UNARY_PLUS_OPERATOR", Undefined },
{ peg::AstNodeType::Token, "UNARY_MINUS_OPERATOR", Undefined },
{ peg::AstNodeType::Token, "UNARY_NOT_OPERATOR", Undefined },
{ peg::AstNodeType::Token, "FACTOR_OPERATOR", Undefined }, { peg::AstNodeType::Token, "FACTOR_OPERATOR", Undefined },
{ peg::AstNodeType::Token, "NUMBER", Number }, { peg::AstNodeType::Token, "NUMBER", Number },
{ peg::AstNodeType::Token, "BOOLEAN", Boolean }, { peg::AstNodeType::Token, "BOOLEAN", Boolean },

View File

@ -4,7 +4,7 @@ enum AstTag
{ {
Undefined, Undefined,
Statements, While, If, FunctionCall, Assignment, Statements, While, If, FunctionCall, Assignment,
LogicalOr, LogicalAnd, Condition, BinExpresion, LogicalOr, LogicalAnd, Condition, UnaryPlus, UnaryMinus, UnaryNot, BinExpresion,
Identifier, InterpolatedString, Identifier, InterpolatedString,
Number, Boolean, Function Number, Boolean, Function
}; };