From 36384e69a5010ffc2d334a7fc4271f8c8cecad9f Mon Sep 17 00:00:00 2001 From: yhirose Date: Wed, 3 Jun 2015 22:50:00 -0400 Subject: [PATCH] Added unary plus/minus/not operators. --- language/interpreter.cc | 27 +++++++++++++++++++++++++++ language/parser.cc | 17 +++++++++++++++-- language/parser.hpp | 2 +- 3 files changed, 43 insertions(+), 3 deletions(-) diff --git a/language/interpreter.cc b/language/interpreter.cc index 9f5e36e..05fda22 100644 --- a/language/interpreter.cc +++ b/language/interpreter.cc @@ -18,6 +18,9 @@ struct Eval case LogicalOr: return eval_logical_or(ast, env); case LogicalAnd: return eval_logical_and(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 Identifier: return eval_identifier(ast, env); case Number: return eval_number(ast, env); @@ -173,6 +176,30 @@ private: } } + static Value eval_unary_plus(const Ast& ast, shared_ptr 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 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 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 env) { auto ret = eval(*ast.nodes[0], env).to_long(); for (auto i = 1u; i < ast.nodes.size(); i += 2) { diff --git a/language/parser.cc b/language/parser.cc index b8ad7a7..ce8ae4c 100644 --- a/language/parser.cc +++ b/language/parser.cc @@ -22,14 +22,21 @@ static auto g_grammar = R"( LOGICAL_OR <- LOGICAL_AND ('&&' _ LOGICAL_AND)* LOGICAL_AND <- CONDITION (CONDITION_OPERATOR CONDITION)* 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 ')' _ BLOCK <- '{' _ STATEMENTS '}' _ CONDITION_OPERATOR <- < ('==' / '!=' / '<=' / '<' / '>=' / '>') > _ TERM_OPERATOR <- < [-+] > _ + UNARY_PLUS_OPERATOR <- < '+' > _ + UNARY_MINUS_OPERATOR <- < '-' > _ + UNARY_NOT_OPERATOR <- < '!' > _ FACTOR_OPERATOR <- < [*/%] > _ + IDENTIFIER <- < [a-zA-Z_][a-zA-Z0-9_]* > _ NUMBER <- < [0-9]+ > _ @@ -78,9 +85,15 @@ peg& get_parser() { peg::AstNodeType::Optimizable, "LOGICAL_OR", LogicalAnd }, { peg::AstNodeType::Optimizable, "LOGICAL_AND", Condition }, { 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, "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, "NUMBER", Number }, { peg::AstNodeType::Token, "BOOLEAN", Boolean }, diff --git a/language/parser.hpp b/language/parser.hpp index 083e86e..8b9335a 100644 --- a/language/parser.hpp +++ b/language/parser.hpp @@ -4,7 +4,7 @@ enum AstTag { Undefined, Statements, While, If, FunctionCall, Assignment, - LogicalOr, LogicalAnd, Condition, BinExpresion, + LogicalOr, LogicalAnd, Condition, UnaryPlus, UnaryMinus, UnaryNot, BinExpresion, Identifier, InterpolatedString, Number, Boolean, Function };