]> git.xonotic.org Git - xonotic/gmqcc.git/blobdiff - parser.c
strictness sweep: (void)-ing all vec_ macros which don't evaluate to a sensible value
[xonotic/gmqcc.git] / parser.c
index 6c507d1aeb4a24a83ac50b5778cc55c727a93777..9912f564d8f6ee638b2caf515e85963b336e87c0 100644 (file)
--- a/parser.c
+++ b/parser.c
@@ -75,8 +75,8 @@ typedef struct {
     ht *typedefs;
 
     /* same as above but for the spelling corrector */
-    ht       *correct_variables;
-    size_t ***correct_variables_score;  /* vector of vector of size_t* */
+    correct_trie_t  **correct_variables;
+    size_t         ***correct_variables_score;  /* vector of vector of size_t* */
 
     /* not to be used directly, we use the hash table */
     ast_expression **_locals;
@@ -109,6 +109,7 @@ static const ast_expression *intrinsic_debug_typestring = (ast_expression*)0x10;
 static void parser_enterblock(parser_t *parser);
 static bool parser_leaveblock(parser_t *parser);
 static void parser_addlocal(parser_t *parser, const char *name, ast_expression *e);
+static void parser_addglobal(parser_t *parser, const char *name, ast_expression *e);
 static bool parse_typedef(parser_t *parser);
 static bool parse_variable(parser_t *parser, ast_block *localblock, bool nofields, int qualifier, ast_value *cached_typedef, bool noref, bool is_static, uint32_t qflags, char *vstring);
 static ast_block* parse_block(parser_t *parser);
@@ -928,14 +929,21 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy)
                     exprs[0], exprs[1]);
             break;
         case opid1('^'):
-            parseerror(parser, "TODO: bitxor");
+            compile_error(ast_ctx(exprs[0]), "Not Yet Implemented: bit-xor via ^");
             return false;
 
         case opid2('<','<'):
         case opid2('>','>'):
+            if (CanConstFold(exprs[0], exprs[1]) && ! NotSameType(TYPE_FLOAT)) {
+                if (op->id == opid2('<','<'))
+                    out = (ast_expression*)parser_const_float(parser, (double)((int)(ConstF(0)) << (int)(ConstF(1))));
+                else
+                    out = (ast_expression*)parser_const_float(parser, (double)((int)(ConstF(0)) >> (int)(ConstF(1))));
+                break;
+            }
         case opid3('<','<','='):
         case opid3('>','>','='):
-            parseerror(parser, "TODO: shifts");
+            compile_error(ast_ctx(exprs[0]), "Not Yet Implemented: bit-shifts");
             return false;
 
         case opid2('|','|'):
@@ -1642,22 +1650,28 @@ static ast_expression* parse_expression_leave(parser_t *parser, bool stopatcomma
                      * We should also consider adding correction tables for
                      * other things as well.
                      */
-                    for (i = 0; i < vec_size(parser->correct_variables); i++) {
-                        correct = correct_str(parser->correct_variables[i], parser_tokval(parser));
-                        if (strcmp(correct, parser_tokval(parser))) {
-                            break;
-                        } else if (correct) {
-                            mem_d(correct);
+                    if (OPTS_FLAG(ENHANCED_DIAGNOSTICS)) {
+                        correction_t corr;
+                        correct_init(&corr);
+
+                        for (i = 0; i < vec_size(parser->correct_variables); i++) {
+                            correct = correct_str(&corr, parser->correct_variables[i], parser_tokval(parser));
+                            if (strcmp(correct, parser_tokval(parser))) {
+                                break;
+                            } else if (correct) {
+                                mem_d(correct);
+                                correct = NULL;
+                            }
                         }
-                    }
+                        correct_free(&corr);
 
-                    if (correct) {
-                        parseerror(parser, "unexpected ident: %s (did you mean %s?)", parser_tokval(parser), correct);
-                        mem_d(correct);
-                    } else {
-                        parseerror(parser, "unexpected ident: %s", parser_tokval(parser));
+                        if (correct) {
+                            parseerror(parser, "unexpected ident: %s (did you mean %s?)", parser_tokval(parser), correct);
+                            mem_d(correct);
+                            goto onerr;
+                        }
                     }
-
+                    parseerror(parser, "unexpected ident: %s", parser_tokval(parser));
                     goto onerr;
                 }
             }
@@ -1943,7 +1957,7 @@ static ast_expression* parse_expression_leave(parser_t *parser, bool stopatcomma
             goto onerr;
         }
         if (parser->tok == ';' ||
-            (!parens && parser->tok == ']'))
+            (!parens && (parser->tok == ']' || parser->tok == ')')))
         {
             break;
         }
@@ -1982,8 +1996,13 @@ static ast_expression* parse_expression(parser_t *parser, bool stopatcomma, bool
     ast_expression *e = parse_expression_leave(parser, stopatcomma, false, with_labels);
     if (!e)
         return NULL;
+    if (parser->tok != ';') {
+        parseerror(parser, "semicolon expected after expression");
+        ast_unref(e);
+        return NULL;
+    }
     if (!parser_next(parser)) {
-        ast_delete(e);
+        ast_unref(e);
         return NULL;
     }
     return e;
@@ -1998,7 +2017,7 @@ static void parser_enterblock(parser_t *parser)
     vec_push(parser->_block_ctx, parser_ctx(parser));
 
     /* corrector */
-    vec_push(parser->correct_variables, util_htnew(PARSER_HT_SIZE));
+    vec_push(parser->correct_variables, correct_trie_new());
     vec_push(parser->correct_variables_score, NULL);
 }
 
@@ -2061,6 +2080,19 @@ static void parser_addlocal(parser_t *parser, const char *name, ast_expression *
     );
 }
 
+static void parser_addglobal(parser_t *parser, const char *name, ast_expression *e)
+{
+    vec_push(parser->globals, e);
+    util_htset(parser->htglobals, name, e);
+
+    /* corrector */
+    correct_add (
+         parser->correct_variables[0],
+        &parser->correct_variables_score[0],
+        name
+    );
+}
+
 static ast_expression* process_condition(parser_t *parser, ast_expression *cond, bool *_ifnot)
 {
     bool       ifnot = false;
@@ -2164,6 +2196,8 @@ static bool parse_if(parser_t *parser, ast_block *block, ast_expression **out)
         ast_delete(cond);
         return false;
     }
+    if (!ontrue)
+        ontrue = (ast_expression*)ast_block_new(parser_ctx(parser));
     /* check for an else */
     if (!strcmp(parser_tokval(parser), "else")) {
         /* parse into the 'else' branch */
@@ -2641,6 +2675,13 @@ static bool parse_break_continue(parser_t *parser, ast_block *block, ast_express
         return false;
     }
 
+    if (!vec_size(loops)) {
+        if (is_continue)
+            parseerror(parser, "`continue` can only be used inside loops");
+        else
+            parseerror(parser, "`break` can only be used inside loops or switches");
+    }
+
     if (parser->tok == TOKEN_IDENT) {
         if (!OPTS_FLAG(LOOP_LABELS))
             parseerror(parser, "labeled loops not activated, try using -floop-labels");
@@ -3591,8 +3632,7 @@ static bool parse_function_body(parser_t *parser, ast_value *var)
                 return false;
             }
 
-            vec_push(parser->globals, (ast_expression*)thinkfunc);
-            util_htset(parser->htglobals, thinkfunc->name, thinkfunc);
+            parser_addglobal(parser, thinkfunc->name, (ast_expression*)thinkfunc);
 
             nextthink = (ast_expression*)thinkfunc;
 
@@ -4809,12 +4849,10 @@ static bool parse_variable(parser_t *parser, ast_block *localblock, bool nofield
                     }
                 }
                 else {
-                    vec_push(parser->globals, (ast_expression*)var);
-                    util_htset(parser->htglobals, var->name, var);
+                    parser_addglobal(parser, var->name, (ast_expression*)var);
                     if (isvector) {
                         for (i = 0; i < 3; ++i) {
-                            vec_push(parser->globals, (ast_expression*)me[i]);
-                            util_htset(parser->htglobals, me[i]->name, me[i]);
+                            parser_addglobal(parser, me[i]->name, (ast_expression*)me[i]);
                         }
                     }
                 }
@@ -5308,6 +5346,10 @@ bool parser_init()
     vec_push(parser->typedefs, util_htnew(TYPEDEF_HT_SIZE));
     vec_push(parser->_blocktypedefs, 0);
 
+    /* corrector */
+    vec_push(parser->correct_variables, correct_trie_new());
+    vec_push(parser->correct_variables_score, NULL);
+
     empty_ctx.file = "<internal>";
     empty_ctx.line = 0;
     parser->nil = ast_value_new(empty_ctx, "nil", TYPE_NIL);
@@ -5413,9 +5455,6 @@ void parser_cleanup()
     for (i = 0; i < vec_size(parser->correct_variables); ++i) {
         correct_del(parser->correct_variables[i], parser->correct_variables_score[i]);
     }
-    for (i = 0; i < vec_size(parser->correct_variables_score); ++i) {
-        vec_free(parser->correct_variables_score[i]);
-    }
     vec_free(parser->correct_variables);
     vec_free(parser->correct_variables_score);