parsing the ternary
authorWolfgang (Blub) Bumiller <blub@speed.at>
Wed, 21 Nov 2012 19:36:42 +0000 (20:36 +0100)
committerWolfgang (Blub) Bumiller <blub@speed.at>
Wed, 21 Nov 2012 19:36:42 +0000 (20:36 +0100)
lexer.c
lexer.h
parser.c

diff --git a/lexer.c b/lexer.c
index c6e8552c063a89df6cf23a9ac411afe23653f9eb..5a1f23e43cb7ed56b3127dfb1aead63364080ff7 100644 (file)
--- a/lexer.c
+++ b/lexer.c
@@ -1021,6 +1021,7 @@ int lex_do(lex_file *lex)
     {
         case '[':
         case '(':
+        case ':':
             lex_tokench(lex, ch);
             lex_endtoken(lex);
             if (lex->flags.noops)
@@ -1029,7 +1030,6 @@ int lex_do(lex_file *lex)
                 return (lex->tok.ttype = TOKEN_OPERATOR);
         case ')':
         case ';':
-        case ':':
         case '{':
         case '}':
         case ']':
diff --git a/lexer.h b/lexer.h
index 137bfe9414ebdced2e2f45a4f18a982a3c3c6a1f..a6f910062ff962623c63107381ce8350be0a4bd6 100644 (file)
--- a/lexer.h
+++ b/lexer.h
@@ -207,6 +207,7 @@ static const oper_info c_operators[] = {
     { "||",  2, opid2('|','|'),     ASSOC_LEFT,  4,  0 },
 
     { "?",   3, opid2('?',':'),     ASSOC_RIGHT, 3,  0 },
+    { ":",   3, opid2(':','?'),     ASSOC_RIGHT, 3,  0 },
 
     { "=",   2, opid1('='),         ASSOC_RIGHT, 2,  0 },
     { "+=",  2, opid2('+','='),     ASSOC_RIGHT, 2,  0 },
@@ -262,9 +263,10 @@ static const oper_info qcc_operators[] = {
     { "&&",  2, opid2('&','&'),     ASSOC_LEFT,  5,  0 },
     { "||",  2, opid2('|','|'),     ASSOC_LEFT,  5,  0 },
 
-    { ",",   2, opid1(','),         ASSOC_LEFT,  2,  0 }
+    { ",",   2, opid1(','),         ASSOC_LEFT,  2,  0 },
 
     { "?",   3, opid2('?',':'),     ASSOC_RIGHT, 1,  0 },
+    { ":",   3, opid2(':','?'),     ASSOC_RIGHT, 1,  0 }
 };
 static const size_t qcc_operator_count = (sizeof(qcc_operators) / sizeof(qcc_operators[0]));
 
index 99b7eb7bace4f651eb2fbf37d221cd18a14444cb..65535098903a63adcb01d3bbe17491cbedec1318 100644 (file)
--- a/parser.c
+++ b/parser.c
@@ -1080,6 +1080,7 @@ static ast_expression* parse_expression_leave(parser_t *parser, bool stopatcomma
      * end of a condition is an unmatched closing paren
      */
     int parens = 0;
+    int ternaries = 0;
 
     sy.out = NULL;
     sy.ops = NULL;
@@ -1267,6 +1268,12 @@ static ast_expression* parse_expression_leave(parser_t *parser, bool stopatcomma
                 break;
             }
 
+            /* a colon without a pervious question mark cannot be a ternary */
+            if (op->id == opid2(':','?')) {
+                parser->tok = ':';
+                break;
+            }
+
             if (vec_size(sy.ops) && !vec_last(sy.ops).paren)
                 olast = &operators[vec_last(sy.ops).etype-1];
 
@@ -1323,6 +1330,15 @@ static ast_expression* parse_expression_leave(parser_t *parser, bool stopatcomma
                 vec_push(sy.ops, syop(parser_ctx(parser), op));
                 vec_push(sy.ops, syparen(parser_ctx(parser), SY_PAREN_INDEX, 0));
                 wantop = false;
+            } else if (op->id == opid2('?',':')) {
+                wantop = false;
+                vec_push(sy.ops, syop(parser_ctx(parser), op));
+                wantop = false;
+                --ternaries;
+            } else if (op->id == opid2(':','?')) {
+                /* we don't push this operator */
+                wantop = false;
+                ++ternaries;
             } else {
                 DEBUGSHUNTDO(con_out("push operator %s\n", op->op));
                 vec_push(sy.ops, syop(parser_ctx(parser), op));
@@ -1333,8 +1349,7 @@ static ast_expression* parse_expression_leave(parser_t *parser, bool stopatcomma
             goto onerr;
         }
         if (parser->tok == ';' ||
-            (!parens && parser->tok == ']') ||
-            parser->tok == ':')
+            (!parens && parser->tok == ']'))
         {
             break;
         }