]> git.rm.cloudns.org Git - xonotic/gmqcc.git/commitdiff
Parsing noref-pragma
authorWolfgang (Blub) Bumiller <blub@speed.at>
Mon, 3 Dec 2012 19:37:02 +0000 (20:37 +0100)
committerWolfgang (Blub) Bumiller <blub@speed.at>
Mon, 3 Dec 2012 19:37:02 +0000 (20:37 +0100)
lexer.c
parser.c

diff --git a/lexer.c b/lexer.c
index 4d283f464ddb2ff1bec50ec20dc294fb08f200e5..8e783e6988c449001e224336b12d7f022d460d46 100644 (file)
--- a/lexer.c
+++ b/lexer.c
@@ -492,6 +492,7 @@ unroll:
             vec_pop(command);
         }
         vec_free(command);
+        lex_ungetch(lex, ' ');
     }
     if (command) {
         vec_pop(command);
@@ -500,6 +501,7 @@ unroll:
             vec_pop(command);
         }
         vec_free(command);
+        lex_ungetch(lex, ' ');
     }
     if (pragma) {
         vec_pop(pragma);
index c3c4fa2c62c1fd275911daebb031aa6295a0124e..5f2f7dad20d16226552a9062805aad1bb20e0297 100644 (file)
--- a/parser.c
+++ b/parser.c
@@ -93,6 +93,9 @@ typedef struct {
      * we shall trigger -Wternary-precedence.
      */
     enum { POT_PAREN, POT_TERNARY1, POT_TERNARY2 } *pot;
+
+    /* pragma flags */
+    bool noref;
 } parser_t;
 
 static void parser_enterblock(parser_t *parser);
@@ -2398,6 +2401,75 @@ static bool parse_goto(parser_t *parser, ast_expression **out)
     return true;
 }
 
+static bool parse_skipwhite(parser_t *parser)
+{
+    do {
+        if (!parser_next(parser))
+            return false;
+    } while (parser->tok == TOKEN_WHITE && parser->tok < TOKEN_ERROR);
+    return parser->tok < TOKEN_ERROR;
+}
+
+static bool parse_eol(parser_t *parser)
+{
+    if (!parse_skipwhite(parser))
+        return false;
+    return parser->tok == TOKEN_EOL;
+}
+
+static bool parse_pragma_do(parser_t *parser)
+{
+    if (!parser_next(parser) ||
+        parser->tok != TOKEN_IDENT ||
+        strcmp(parser_tokval(parser), "pragma"))
+    {
+        parseerror(parser, "expected `pragma` keyword after `#`, got `%s`", parser_tokval(parser));
+        return false;
+    }
+    if (!parse_skipwhite(parser) || parser->tok != TOKEN_IDENT) {
+        parseerror(parser, "expected pragma, got `%s`", parser_tokval(parser));
+        return false;
+    }
+
+    if (!strcmp(parser_tokval(parser), "noref")) {
+        if (!parse_skipwhite(parser) || parser->tok != TOKEN_INTCONST) {
+            parseerror(parser, "`noref` pragma requires an argument: 0 or 1");
+            return false;
+        }
+        parser->noref = !!parser_token(parser)->constval.i;
+        if (!parse_eol(parser)) {
+            parseerror(parser, "parse error after `noref` pragma");
+            return false;
+        }
+    }
+    else
+    {
+        parseerror(parser, "unrecognized hash-keyword: `%s`", parser_tokval(parser));
+        return false;
+    }
+
+    return true;
+}
+
+static bool parse_pragma(parser_t *parser)
+{
+    bool rv;
+    parser->lex->flags.preprocessing = true;
+    parser->lex->flags.mergelines = true;
+    rv = parse_pragma_do(parser);
+    if (parser->tok != TOKEN_EOL) {
+        parseerror(parser, "junk after pragma");
+        rv = false;
+    }
+    parser->lex->flags.preprocessing = false;
+    parser->lex->flags.mergelines = false;
+    if (!parser_next(parser)) {
+        parseerror(parser, "parse error after pragma");
+        rv = false;
+    }
+    return rv;
+}
+
 static bool parse_statement(parser_t *parser, ast_block *block, ast_expression **out, bool allow_cases)
 {
     int cvq;
@@ -4266,6 +4338,10 @@ static bool parser_global_statement(parser_t *parser)
         parseerror(parser, "unrecognized keyword `%s`", parser_tokval(parser));
         return false;
     }
+    else if (parser->tok == '#')
+    {
+        return parse_pragma(parser);
+    }
     else if (parser->tok == '$')
     {
         if (!parser_next(parser)) {