blueloveTH 3 anos atrás
pai
commit
d9cf73a6d3
4 arquivos alterados com 22 adições e 4 exclusões
  1. 13 1
      src/compiler.h
  2. 1 1
      src/obj.h
  3. 2 1
      src/parser.h
  4. 6 1
      tests/basic.py

+ 13 - 1
src/compiler.h

@@ -87,6 +87,7 @@ public:
         rules[TK("@num")] =     { METHOD(exprLiteral),   NO_INFIX };
         rules[TK("@str")] =     { METHOD(exprLiteral),   NO_INFIX };
         rules[TK("@fstr")] =    { METHOD(exprFString),   NO_INFIX };
+        rules[TK("?")] =        { nullptr,               METHOD(exprTernary),        PREC_TERNARY };
         rules[TK("=")] =        { nullptr,               METHOD(exprAssign),         PREC_ASSIGNMENT };
         rules[TK("+=")] =       { nullptr,               METHOD(exprAssign),         PREC_ASSIGNMENT };
         rules[TK("-=")] =       { nullptr,               METHOD(exprAssign),         PREC_ASSIGNMENT };
@@ -102,7 +103,7 @@ public:
 #undef METHOD
 #undef NO_INFIX
 
-#define EXPR() parsePrecedence(PREC_LOGICAL_OR)             // no '=' and ',' just a simple expression
+#define EXPR() parsePrecedence(PREC_TERNARY)             // no '=' and ',' just a simple expression
 #define EXPR_TUPLE() parsePrecedence(PREC_COMMA)            // no '=', but ',' is allowed
 #define EXPR_ANY() parsePrecedence(PREC_ASSIGNMENT)
     }
@@ -195,6 +196,7 @@ public:
                 case '&': parser->setNextToken(TK("&")); return;
                 case '|': parser->setNextToken(TK("|")); return;
                 case '^': parser->setNextToken(TK("^")); return;
+                case '?': parser->setNextToken(TK("?")); return;
                 case '.': {
                     if(parser->matchChar('.')) {
                         if(parser->matchChar('.')) {
@@ -411,6 +413,16 @@ public:
         patchJump(patch);
     }
 
+    void exprTernary() {
+        int patch = emitCode(OP_POP_JUMP_IF_FALSE);
+        EXPR();         // if true
+        int patch2 = emitCode(OP_JUMP_ABSOLUTE);
+        consume(TK(":"));
+        patchJump(patch);
+        EXPR();         // if false
+        patchJump(patch2);
+    }
+
     void exprBinaryOp() {
         _TokenType op = parser->previous.type;
         parsePrecedence((Precedence)(rules[op].precedence + 1));

+ 1 - 1
src/obj.h

@@ -10,7 +10,7 @@ const _Int _Int_MAX_NEG = -9223372036854775807LL;
 const _Float _FLOAT_INF_POS = INFINITY;
 const _Float _FLOAT_INF_NEG = -INFINITY;
 
-#define PK_VERSION "0.3.0"
+#define PK_VERSION "0.3.1"
 
 class CodeObject;
 class BasePointer;

+ 2 - 1
src/parser.h

@@ -8,7 +8,7 @@ constexpr const char* __TOKENS[] = {
     "@error", "@eof", "@eol", "@sof",
     ".", ",", ":", ";", "#", "(", ")", "[", "]", "{", "}", "%",
     "+", "-", "*", "/", "//", "**", "=", ">", "<", "...", "->",
-    "<<", ">>", "&", "|", "^",
+    "<<", ">>", "&", "|", "^", "?",
     "==", "!=", ">=", "<=",
     "+=", "-=", "*=", "/=", "//=",
     /** KW_BEGIN **/
@@ -73,6 +73,7 @@ enum Precedence {
   PREC_NONE,
   PREC_ASSIGNMENT,    // =
   PREC_COMMA,         // ,
+  PREC_TERNARY,       // ?:
   PREC_LOGICAL_OR,    // or
   PREC_LOGICAL_AND,   // and
   PREC_EQUALITY,      // == !=

+ 6 - 1
tests/basic.py

@@ -89,4 +89,9 @@ assert [1, 2, 3] != [1, 2, 4]
 
 # test + *=
 assert [1, 2, 3] + [4, 5, 6] == [1, 2, 3, 4, 5, 6]          
-assert [1, 2, 3] * 3 == [1, 2, 3, 1, 2, 3, 1, 2, 3]
+assert [1, 2, 3] * 3 == [1, 2, 3, 1, 2, 3, 1, 2, 3]
+
+# test ?:
+a = 5
+assert ((a > 3) ? 1 : 0) == 1
+assert ((a < 3) ? 1 : 0) == 0