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());
 }