diff --git a/modcc/expression.cpp b/modcc/expression.cpp index a33e7a767b8cdd2d3e73fac171e0cfff78129b57..18e5a53178496952419036ef47a81314d47fdca7 100644 --- a/modcc/expression.cpp +++ b/modcc/expression.cpp @@ -1138,6 +1138,8 @@ expression_ptr binary_expression(Location loc, case tok::lte : case tok::gt : case tok::gte : + case tok::land : + case tok::lor : case tok::equality : return make_expression<ConditionalExpression>(loc, op, std::move(lhs), std::move(rhs)); default : diff --git a/modcc/lexer.cpp b/modcc/lexer.cpp index 1eb684ff9f03f4aeb5d2191cd2ce1551eda1b2a6..dc5851ecdbd3c39d6ce978c7c3086500f97570b6 100644 --- a/modcc/lexer.cpp +++ b/modcc/lexer.cpp @@ -195,6 +195,40 @@ Token Lexer::parse() { } return t; } + case '&': { + bool valid = false; + t.spelling += character(); + if (*current_ == '&') { + t.spelling += character(); + if (*current_ != '&') { + t.type = tok::land; + valid = true; + } + } + if (!valid) { + error_string_ = pprintf("& must be in pairs"); + status_ = lexerStatus::error; + t.type = tok::reserved; + } + return t; + } + case '|': { + bool valid = false; + t.spelling += character(); + if (*current_ == '|') { + t.spelling += character(); + if (*current_ != '|') { + t.type = tok::lor; + valid = true; + } + } + if (!valid) { + error_string_ = pprintf("| must be in pairs"); + status_ = lexerStatus::error; + t.type = tok::reserved; + } + return t; + } case '\'': t.type = tok::prime; t.spelling += character(); @@ -379,18 +413,20 @@ void Lexer::binop_prec_init() { // I have taken the operator precedence from C++ // Note that only infix operators require precidence. - binop_prec_[tok::eq] = 2; + binop_prec_[tok::eq] = 1; + binop_prec_[tok::land] = 2; + binop_prec_[tok::lor] = 3; binop_prec_[tok::equality] = 4; binop_prec_[tok::ne] = 4; binop_prec_[tok::lt] = 5; binop_prec_[tok::lte] = 5; binop_prec_[tok::gt] = 5; binop_prec_[tok::gte] = 5; - binop_prec_[tok::plus] = 10; - binop_prec_[tok::minus] = 10; - binop_prec_[tok::times] = 20; - binop_prec_[tok::divide] = 20; - binop_prec_[tok::pow] = 30; + binop_prec_[tok::plus] = 6; + binop_prec_[tok::minus] = 6; + binop_prec_[tok::times] = 7; + binop_prec_[tok::divide] = 7; + binop_prec_[tok::pow] = 8; } int Lexer::binop_precedence(tok tok) { diff --git a/modcc/printer/cexpr_emit.cpp b/modcc/printer/cexpr_emit.cpp index 62aecf2e5c465997ca286db24667d27883c0573a..a3be027494849905622f689e83c34b287061f619 100644 --- a/modcc/printer/cexpr_emit.cpp +++ b/modcc/printer/cexpr_emit.cpp @@ -96,6 +96,8 @@ void CExprEmitter::visit(BinaryExpression* e) { {tok::gt, ">"}, {tok::gte, ">="}, {tok::equality, "=="}, + {tok::land, "&&"}, + {tok::lor, "||"}, {tok::ne, "!="}, {tok::min, "min"}, {tok::max, "max"}, diff --git a/modcc/symdiff.cpp b/modcc/symdiff.cpp index f8573b6a52fd10378b00b602fcb6b7424e766022..27c2ff2bbba0c345d53ea570ce190683b650311f 100644 --- a/modcc/symdiff.cpp +++ b/modcc/symdiff.cpp @@ -529,7 +529,11 @@ public: return; case tok::gte: as_number(loc, lval>=rval); - return; + case tok::land: + as_number(loc, lval&&rval); + case tok::lor: + as_number(loc, lval||rval); + return; default: ; // unrecognized, fall through to non-numeric case below } diff --git a/modcc/token.cpp b/modcc/token.cpp index bd9a2957dcfe3af6d24679d33ce8cae53dd0c3b8..6900d91cf40ecf10755388c0ba0994e6557ab057 100644 --- a/modcc/token.cpp +++ b/modcc/token.cpp @@ -84,6 +84,8 @@ static TokenString token_strings[] = { {">=", tok::gte}, {"==", tok::equality}, {"!=", tok::ne}, + {"&&", tok::land}, + {"||", tok::lor}, {"<->", tok::arrow}, {"~", tok::tilde}, {",", tok::comma}, diff --git a/modcc/token.hpp b/modcc/token.hpp index 03d064104de766300f05ad4a640960acbce7b1d1..21467063dce1a2359f2a0f4a847b9426fd37c35f 100644 --- a/modcc/token.hpp +++ b/modcc/token.hpp @@ -16,7 +16,7 @@ enum class tok { // infix binary ops // = + - * / ^ - eq, plus, minus, times, divide, pow, + eq, plus, minus, times, divide, pow, land, lor, // comparison lnot, // ! named logical not, to avoid clash with C++ not keyword lt, // < diff --git a/test/unit-modcc/test_lexer.cpp b/test/unit-modcc/test_lexer.cpp index 4641ae3d377ca09318a1006cdedee46e46fb48bf..c6fb38b07a551a8bea8f9629c88e609e0446349c 100644 --- a/test/unit-modcc/test_lexer.cpp +++ b/test/unit-modcc/test_lexer.cpp @@ -212,7 +212,7 @@ TEST(Lexer, symbols) { } TEST(Lexer, comparison_operators) { - char string[] = "< <= > >= == != !"; + char string[] = "< <= > >= == != ! && ||"; VerboseLexer lexer(string, string+sizeof(string)); auto t1 = lexer.parse(); @@ -229,9 +229,12 @@ TEST(Lexer, comparison_operators) { EXPECT_EQ(t6.type, tok::ne); auto t7 = lexer.parse(); EXPECT_EQ(t7.type, tok::lnot); - auto t8 = lexer.parse(); - EXPECT_EQ(t8.type, tok::eof); + EXPECT_EQ(t8.type, tok::land); + auto t9 = lexer.parse(); + EXPECT_EQ(t9.type, tok::lor); + auto t10 = lexer.parse(); + EXPECT_EQ(t10.type, tok::eof); } // test braces @@ -340,4 +343,21 @@ TEST(Lexer, numbers) { lexer = VerboseLexer("1.2E4.3"); lexer.parse(); EXPECT_EQ(lexerStatus::error, lexer.status()); + + // single or triple & or | should give errors + lexer = VerboseLexer("&"); + lexer.parse(); + EXPECT_EQ(lexerStatus::error, lexer.status()); + + lexer = VerboseLexer("&&&"); + lexer.parse(); + EXPECT_EQ(lexerStatus::error, lexer.status()); + + lexer = VerboseLexer("|"); + lexer.parse(); + EXPECT_EQ(lexerStatus::error, lexer.status()); + + lexer = VerboseLexer("|||"); + lexer.parse(); + EXPECT_EQ(lexerStatus::error, lexer.status()); }