From 8d34d3305544826972af57d2cf5246326201643d Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 20 Dec 2012 10:02:00 +0900 Subject: [PATCH] Implement "if not (foo)" syntax. It is syntactic sugar for if (!(foo)), but is useful for avoiding inconsistencies between such things as if (string) and if (!string), even though qcc can't parse if not (string). It also makes for easier to read code when the logic in the condition is complex. --- tools/qfcc/include/expr.h | 3 ++- tools/qfcc/source/expr.c | 11 ++++++++--- tools/qfcc/source/qc-lex.l | 1 + tools/qfcc/source/qc-parse.y | 17 +++++++++++------ tools/qfcc/source/qp-parse.y | 4 ++-- 5 files changed, 24 insertions(+), 12 deletions(-) diff --git a/tools/qfcc/include/expr.h b/tools/qfcc/include/expr.h index 713292fbf..a3348e9d7 100644 --- a/tools/qfcc/include/expr.h +++ b/tools/qfcc/include/expr.h @@ -598,7 +598,8 @@ expr_t *incop_expr (int op, expr_t *e, int postop); expr_t *array_expr (expr_t *array, expr_t *index); expr_t *pointer_expr (expr_t *pointer); expr_t *address_expr (expr_t *e1, expr_t *e2, struct type_s *t); -expr_t *build_if_statement (expr_t *test, expr_t *s1, expr_t *els, expr_t *s2); +expr_t *build_if_statement (int not, expr_t *test, expr_t *s1, expr_t *els, + expr_t *s2); expr_t *build_while_statement (expr_t *test, expr_t *statement, expr_t *break_label, expr_t *continue_label); expr_t *build_do_while_statement (expr_t *statement, expr_t *test, diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index 8f72240cf..109d0a51f 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -2284,7 +2284,7 @@ address_expr (expr_t *e1, expr_t *e2, type_t *t) } expr_t * -build_if_statement (expr_t *test, expr_t *s1, expr_t *els, expr_t *s2) +build_if_statement (int not, expr_t *test, expr_t *s1, expr_t *els, expr_t *s2) { int line = pr.source_line; string_t file = pr.source_file; @@ -2299,8 +2299,13 @@ build_if_statement (expr_t *test, expr_t *s1, expr_t *els, expr_t *s2) test = convert_bool (test, 1); if (test->type != ex_error) { - backpatch (test->e.bool.true_list, tl); - backpatch (test->e.bool.false_list, fl); + if (not) { + backpatch (test->e.bool.true_list, fl); + backpatch (test->e.bool.false_list, tl); + } else { + backpatch (test->e.bool.true_list, tl); + backpatch (test->e.bool.false_list, fl); + } append_expr (test->e.bool.e, tl); append_expr (if_expr, test); } diff --git a/tools/qfcc/source/qc-lex.l b/tools/qfcc/source/qc-lex.l index ff0f89e8a..7d190cb48 100644 --- a/tools/qfcc/source/qc-lex.l +++ b/tools/qfcc/source/qc-lex.l @@ -319,6 +319,7 @@ static keyword_t at_keywords[] = { {"static", STATIC }, {"sizeof", SIZEOF }, {"nosave", NOSAVE }, + {"not", NOT }, }; // These keywords require the QuakeForge VM to be of any use. ie, they cannot diff --git a/tools/qfcc/source/qc-parse.y b/tools/qfcc/source/qc-parse.y index ef7bd1cf6..7304f7f0e 100644 --- a/tools/qfcc/source/qc-parse.y +++ b/tools/qfcc/source/qc-parse.y @@ -145,7 +145,7 @@ int yylex (void); %token LOCAL RETURN WHILE DO IF ELSE FOR BREAK CONTINUE ELLIPSIS %token NIL IFBE IFB IFAE IFA SWITCH CASE DEFAULT ENUM TYPEDEF -%token ARGS EXTERN STATIC SYSTEM NOSAVE OVERLOAD +%token ARGS EXTERN STATIC SYSTEM NOSAVE OVERLOAD NOT %token STRUCT %token TYPE %token OBJECT TYPE_NAME @@ -205,7 +205,7 @@ int yylex (void); %type protocol_name %type methodprotolist methodprotolist2 %type ivar_decl_list -%type ci +%type ci not %{ @@ -1149,13 +1149,13 @@ statement switch_block = $5; break_label = $2; } - | IF '(' texpr ')' statement %prec IFX + | IF not '(' texpr ')' statement %prec IFX { - $$ = build_if_statement ($3, $5, 0, 0); + $$ = build_if_statement ($2, $4, $6, 0, 0); } - | IF '(' texpr ')' statement else statement + | IF not '(' texpr ')' statement else statement { - $$ = build_if_statement ($3, $5, $6, $7); + $$ = build_if_statement ($2, $4, $6, $7, $8); } | FOR break_label continue_label '(' opt_expr ';' opt_expr ';' opt_expr ')' statement @@ -1184,6 +1184,11 @@ statement } ; +not + : NOT { $$ = 1; } + | /* empty */ { $$ = 0; } + ; + else : ELSE { diff --git a/tools/qfcc/source/qp-parse.y b/tools/qfcc/source/qp-parse.y index f8c870ed4..a2b94acea 100644 --- a/tools/qfcc/source/qp-parse.y +++ b/tools/qfcc/source/qp-parse.y @@ -354,11 +354,11 @@ statement | compound_statement | IF expression THEN statement else statement { - $$ = build_if_statement ($2, $4, $5, $6); + $$ = build_if_statement (0, $2, $4, $5, $6); } | IF expression THEN statement %prec IFX { - $$ = build_if_statement ($2, $4, 0, 0); + $$ = build_if_statement (0, $2, $4, 0, 0); } | WHILE expression DO statement {