Commit dc502042d5

Andrew Kelley <superjoe30@gmail.com>
2017-12-07 17:52:52
translate-c: refactor prefix and suffix op C macro parsing
1 parent 62c25af
src/c_tokenizer.cpp
@@ -121,6 +121,9 @@ static void begin_token(CTokenize *ctok, CTokId id) {
         case CTokIdRParen:
         case CTokIdEOF:
         case CTokIdDot:
+        case CTokIdAsterisk:
+        case CTokIdBang:
+        case CTokIdTilde:
             break;
     }
 }
@@ -228,10 +231,22 @@ void tokenize_c_macro(CTokenize *ctok, const uint8_t *c) {
                         begin_token(ctok, CTokIdRParen);
                         end_token(ctok);
                         break;
+                    case '*':
+                        begin_token(ctok, CTokIdAsterisk);
+                        end_token(ctok);
+                        break;
                     case '-':
                         begin_token(ctok, CTokIdMinus);
                         end_token(ctok);
                         break;
+                    case '!':
+                        begin_token(ctok, CTokIdBang);
+                        end_token(ctok);
+                        break;
+                    case '~':
+                        begin_token(ctok, CTokIdTilde);
+                        end_token(ctok);
+                        break;
                     default:
                         return mark_error(ctok);
                 }
src/c_tokenizer.hpp
@@ -22,6 +22,9 @@ enum CTokId {
     CTokIdRParen,
     CTokIdEOF,
     CTokIdDot,
+    CTokIdAsterisk,
+    CTokIdBang,
+    CTokIdTilde,
 };
 
 enum CNumLitSuffix {
src/translate_c.cpp
@@ -4000,6 +4000,10 @@ static void render_macros(Context *c) {
     }
 }
 
+static AstNode *parse_ctok_primary_expr(Context *c, CTokenize *ctok, size_t *tok_i);
+static AstNode *parse_ctok_expr(Context *c, CTokenize *ctok, size_t *tok_i);
+static AstNode *parse_ctok_prefix_op_expr(Context *c, CTokenize *ctok, size_t *tok_i);
+
 static AstNode *parse_ctok_num_lit(Context *c, CTokenize *ctok, size_t *tok_i, bool negate) {
     CTok *tok = &ctok->tokens.at(*tok_i);
     if (tok->id == CTokIdNumLitInt) {
@@ -4027,7 +4031,7 @@ static AstNode *parse_ctok_num_lit(Context *c, CTokenize *ctok, size_t *tok_i, b
     return nullptr;
 }
 
-static AstNode *parse_ctok(Context *c, CTokenize *ctok, size_t *tok_i) {
+static AstNode *parse_ctok_primary_expr(Context *c, CTokenize *ctok, size_t *tok_i) {
     CTok *tok = &ctok->tokens.at(*tok_i);
     switch (tok->id) {
         case CTokIdCharLit:
@@ -4044,38 +4048,17 @@ static AstNode *parse_ctok(Context *c, CTokenize *ctok, size_t *tok_i) {
             return parse_ctok_num_lit(c, ctok, tok_i, false);
         case CTokIdSymbol:
             {
-                bool need_symbol = false;
-                CTokId curr_id = CTokIdSymbol;
+                *tok_i += 1;
                 Buf *symbol_name = buf_create_from_buf(&tok->data.symbol);
-                AstNode *curr_node = trans_create_node_symbol(c, symbol_name);
-                AstNode *parent_node = curr_node;
-                do {
-                    *tok_i += 1;
-                    CTok* curr_tok = &ctok->tokens.at(*tok_i);
-                    if (need_symbol) {
-                        if (curr_tok->id == CTokIdSymbol) {
-                            symbol_name = buf_create_from_buf(&curr_tok->data.symbol);
-                            curr_node = trans_create_node_field_access(c, parent_node, buf_create_from_buf(symbol_name));
-                            parent_node = curr_node;
-                            need_symbol = false;
-                        } else {
-                            return nullptr;
-                        }
-                    } else {
-                        if (curr_tok->id == CTokIdDot) {
-                            need_symbol = true;
-                            continue;
-                        } else {
-                            break;
-                        }
-                    }
-                } while (curr_id != CTokIdEOF);
-                return curr_node;
+                return trans_create_node_symbol(c, symbol_name);
             }
         case CTokIdLParen:
             {
                 *tok_i += 1;
-                AstNode *inner_node = parse_ctok(c, ctok, tok_i);
+                AstNode *inner_node = parse_ctok_expr(c, ctok, tok_i);
+                if (inner_node == nullptr) {
+                    return nullptr;
+                }
 
                 CTok *next_tok = &ctok->tokens.at(*tok_i);
                 if (next_tok->id != CTokIdRParen) {
@@ -4087,12 +4070,69 @@ static AstNode *parse_ctok(Context *c, CTokenize *ctok, size_t *tok_i) {
         case CTokIdDot:
         case CTokIdEOF:
         case CTokIdRParen:
+        case CTokIdAsterisk:
+        case CTokIdBang:
+        case CTokIdTilde:
             // not able to make sense of this
             return nullptr;
     }
     zig_unreachable();
 }
 
+static AstNode *parse_ctok_expr(Context *c, CTokenize *ctok, size_t *tok_i) {
+    return parse_ctok_prefix_op_expr(c, ctok, tok_i);
+}
+
+static AstNode *parse_ctok_suffix_op_expr(Context *c, CTokenize *ctok, size_t *tok_i) {
+    AstNode *node = parse_ctok_primary_expr(c, ctok, tok_i);
+    if (node == nullptr)
+        return nullptr;
+
+    while (true) {
+        CTok *first_tok = &ctok->tokens.at(*tok_i);
+        if (first_tok->id == CTokIdDot) {
+            *tok_i += 1;
+
+            CTok *name_tok = &ctok->tokens.at(*tok_i);
+            if (name_tok->id != CTokIdSymbol) {
+                return nullptr;
+            }
+            *tok_i += 1;
+
+            node = trans_create_node_field_access(c, node, buf_create_from_buf(&name_tok->data.symbol));
+        } else if (first_tok->id == CTokIdAsterisk) {
+            *tok_i += 1;
+
+            node = trans_create_node_addr_of(c, false, false, node);
+        } else {
+            return node;
+        }
+    }
+}
+
+static PrefixOp ctok_to_prefix_op(CTok *token) {
+    switch (token->id) {
+        case CTokIdBang: return PrefixOpBoolNot;
+        case CTokIdMinus: return PrefixOpNegation;
+        case CTokIdTilde: return PrefixOpBinNot;
+        case CTokIdAsterisk: return PrefixOpDereference;
+        default: return PrefixOpInvalid;
+    }
+}
+static AstNode *parse_ctok_prefix_op_expr(Context *c, CTokenize *ctok, size_t *tok_i) {
+    CTok *op_tok = &ctok->tokens.at(*tok_i);
+    PrefixOp prefix_op = ctok_to_prefix_op(op_tok);
+    if (prefix_op == PrefixOpInvalid) {
+        return parse_ctok_suffix_op_expr(c, ctok, tok_i);
+    }
+    *tok_i += 1;
+
+    AstNode *prefix_op_expr = parse_ctok_prefix_op_expr(c, ctok, tok_i);
+    if (prefix_op_expr == nullptr)
+        return nullptr;
+    return trans_create_node_prefix_op(c, prefix_op, prefix_op_expr);
+}
+
 static void process_macro(Context *c, CTokenize *ctok, Buf *name, const char *char_ptr) {
     tokenize_c_macro(ctok, (const uint8_t *)char_ptr);
 
@@ -4105,7 +4145,7 @@ static void process_macro(Context *c, CTokenize *ctok, Buf *name, const char *ch
     assert(name_tok->id == CTokIdSymbol && buf_eql_buf(&name_tok->data.symbol, name));
     tok_i += 1;
 
-    AstNode *result_node = parse_ctok(c, ctok, &tok_i);
+    AstNode *result_node = parse_ctok_suffix_op_expr(c, ctok, &tok_i);
     if (result_node == nullptr) {
         return;
     }