summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRico Tzschichholz <ricotz@ubuntu.com>2020-09-18 14:29:31 +0200
committerRico Tzschichholz <ricotz@ubuntu.com>2020-09-18 14:34:03 +0200
commit55294d62876547189422ca4ec1fb41e63ee00857 (patch)
tree86f01d21462c66c2ce5be229871407ae3a6587a4
parent69cc119d0db1b05e581647105e30875136948fa3 (diff)
downloadvala-wip/issue/1073.tar.gz
parser: Allow to begin expression with statement keywordwip/issue/1073
Fixes https://gitlab.gnome.org/GNOME/vala/issues/1073
-rw-r--r--tests/Makefile.am1
-rw-r--r--tests/parser/statement-keyword-as-identifier.vala85
-rw-r--r--vala/valaparser.vala140
3 files changed, 179 insertions, 47 deletions
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 0f636c50c..5d7cc13ab 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -760,6 +760,7 @@ TESTS = \
parser/qualified-symbol-access.vala \
parser/signal-no-class.test \
parser/signal-no-static.test \
+ parser/statement-keyword-as-identifier.vala \
parser/statement-outside-root.test \
parser/switch-statement.vala \
parser/template.vala \
diff --git a/tests/parser/statement-keyword-as-identifier.vala b/tests/parser/statement-keyword-as-identifier.vala
new file mode 100644
index 000000000..a88f11e46
--- /dev/null
+++ b/tests/parser/statement-keyword-as-identifier.vala
@@ -0,0 +1,85 @@
+void main () {
+ {
+ int if;
+ if = 1;
+ assert (if == 1);
+ }
+ {
+ int switch;
+ switch = 2;
+ assert (switch == 2);
+ }
+ {
+ int while;
+ while = 3;
+ assert (while == 3);
+ }
+ {
+ int do;
+ do = 4;
+ assert (do == 4);
+ }
+ {
+ int for;
+ for = 5;
+ assert (for == 5);
+ }
+ {
+ int foreach;
+ foreach = 6;
+ assert (foreach == 6);
+ }
+ {
+ //FIXME
+ //int break;
+ //break = 7;
+ //assert (break == 7);
+ }
+ {
+ //FIXME
+ //int continue;
+ //continue = 8;
+ //assert (continue == 8);
+ }
+ {
+ int return;
+ return = 9;
+ assert (return == 9);
+ }
+ {
+ //FIXME
+ //int yield;
+ //yield = 10;
+ //assert (yield == 10);
+ }
+ {
+ int throw;
+ throw = 11;
+ assert (throw == 11);
+ }
+ {
+ int try;
+ try = 12;
+ assert (try == 12);
+ }
+ {
+ int lock;
+ lock = 13;
+ assert (lock == 13);
+ }
+ {
+ int unlock;
+ unlock = 14;
+ assert (unlock == 14);
+ }
+ {
+ int delete;
+ delete = 15;
+ assert (delete == 15);
+ }
+ {
+ int with;
+ with = 16;
+ assert (with == 16);
+ }
+}
diff --git a/vala/valaparser.vala b/vala/valaparser.vala
index 216cd0a7d..74cf0f2f4 100644
--- a/vala/valaparser.vala
+++ b/vala/valaparser.vala
@@ -1584,6 +1584,81 @@ public class Vala.Parser : CodeVisitor {
return expr;
}
+ Statement? parse_statement (TokenType type) throws ParseError {
+ Statement? stmt = null;
+ var begin = get_location ();
+ try {
+ switch (type) {
+ case TokenType.IF:
+ stmt = parse_if_statement ();
+ break;
+ case TokenType.SWITCH:
+ stmt = parse_switch_statement ();
+ break;
+ case TokenType.WHILE:
+ stmt = parse_while_statement ();
+ break;
+ case TokenType.DO:
+ stmt = parse_do_statement ();
+ break;
+ case TokenType.FOR:
+ stmt = parse_for_statement ();
+ break;
+ case TokenType.FOREACH:
+ stmt = parse_foreach_statement ();
+ break;
+ case TokenType.BREAK:
+ stmt = parse_break_statement ();
+ break;
+ case TokenType.CONTINUE:
+ stmt = parse_continue_statement ();
+ break;
+ case TokenType.RETURN:
+ stmt = parse_return_statement ();
+ break;
+ case TokenType.YIELD:
+ stmt = parse_yield_statement ();
+ break;
+ case TokenType.THROW:
+ stmt = parse_throw_statement ();
+ break;
+ case TokenType.TRY:
+ stmt = parse_try_statement ();
+ break;
+ case TokenType.LOCK:
+ stmt = parse_lock_statement ();
+ break;
+ case TokenType.UNLOCK:
+ stmt = parse_unlock_statement ();
+ break;
+ case TokenType.DELETE:
+ stmt = parse_delete_statement ();
+ break;
+ case TokenType.WITH:
+ stmt = parse_with_statement ();
+ break;
+ default:
+ assert_not_reached ();
+ }
+ } catch (ParseError e) {
+ var e_begin = get_location ();
+ string token = ((EnumClass) typeof (TokenType).class_ref ()).get_value (type).value_nick;
+ try {
+ rollback (begin);
+ stmt = parse_expression_statement ();
+ Report.warning (get_src (begin), "`%s' is a syntax keyword, replace with `@%s'".printf (token, token));
+ } catch (ParseError e2) {
+ var e2_begin = get_location ();
+ rollback (e_begin);
+ next ();
+ Report.error (get_src (e_begin), "Possible `%s-statement' syntax error, %s".printf (token, e.message));
+ rollback (e2_begin);
+ throw e2;
+ }
+ }
+ return stmt;
+ }
+
void parse_statements (Block block) throws ParseError {
while (current () != TokenType.CLOSE_BRACE
&& current () != TokenType.CASE
@@ -1602,52 +1677,22 @@ public class Vala.Parser : CodeVisitor {
stmt = parse_empty_statement ();
break;
case TokenType.IF:
- stmt = parse_if_statement ();
- break;
case TokenType.SWITCH:
- stmt = parse_switch_statement ();
- break;
case TokenType.WHILE:
- stmt = parse_while_statement ();
- break;
case TokenType.DO:
- stmt = parse_do_statement ();
- break;
case TokenType.FOR:
- stmt = parse_for_statement ();
- break;
case TokenType.FOREACH:
- stmt = parse_foreach_statement ();
- break;
case TokenType.BREAK:
- stmt = parse_break_statement ();
- break;
case TokenType.CONTINUE:
- stmt = parse_continue_statement ();
- break;
case TokenType.RETURN:
- stmt = parse_return_statement ();
- break;
case TokenType.YIELD:
- stmt = parse_yield_statement ();
- break;
case TokenType.THROW:
- stmt = parse_throw_statement ();
- break;
case TokenType.TRY:
- stmt = parse_try_statement ();
- break;
case TokenType.LOCK:
- stmt = parse_lock_statement ();
- break;
case TokenType.UNLOCK:
- stmt = parse_unlock_statement ();
- break;
case TokenType.DELETE:
- stmt = parse_delete_statement ();
- break;
case TokenType.WITH:
- stmt = parse_with_statement ();
+ stmt = parse_statement (current ());
break;
case TokenType.VAR:
is_decl = true;
@@ -1821,22 +1866,23 @@ public class Vala.Parser : CodeVisitor {
Report.warning (get_current_src (), "%s-statement without body".printf (statement_name));
}
return parse_empty_statement ();
- case TokenType.IF: return parse_if_statement ();
- case TokenType.SWITCH: return parse_switch_statement ();
- case TokenType.WHILE: return parse_while_statement ();
- case TokenType.DO: return parse_do_statement ();
- case TokenType.FOR: return parse_for_statement ();
- case TokenType.FOREACH: return parse_foreach_statement ();
- case TokenType.BREAK: return parse_break_statement ();
- case TokenType.CONTINUE: return parse_continue_statement ();
- case TokenType.RETURN: return parse_return_statement ();
- case TokenType.YIELD: return parse_yield_statement ();
- case TokenType.THROW: return parse_throw_statement ();
- case TokenType.TRY: return parse_try_statement ();
- case TokenType.LOCK: return parse_lock_statement ();
- case TokenType.UNLOCK: return parse_unlock_statement ();
- case TokenType.DELETE: return parse_delete_statement ();
- case TokenType.WITH: return parse_with_statement ();
+ case TokenType.IF:
+ case TokenType.SWITCH:
+ case TokenType.WHILE:
+ case TokenType.DO:
+ case TokenType.FOR:
+ case TokenType.FOREACH:
+ case TokenType.BREAK:
+ case TokenType.CONTINUE:
+ case TokenType.RETURN:
+ case TokenType.YIELD:
+ case TokenType.THROW:
+ case TokenType.TRY:
+ case TokenType.LOCK:
+ case TokenType.UNLOCK:
+ case TokenType.DELETE:
+ case TokenType.WITH:
+ return parse_statement (current ());
case TokenType.VAR:
case TokenType.CONST:
throw new ParseError.SYNTAX ("embedded statement cannot be declaration ");