diff options
author | Rico Tzschichholz <ricotz@ubuntu.com> | 2020-09-18 14:29:31 +0200 |
---|---|---|
committer | Rico Tzschichholz <ricotz@ubuntu.com> | 2020-09-18 14:34:03 +0200 |
commit | 55294d62876547189422ca4ec1fb41e63ee00857 (patch) | |
tree | 86f01d21462c66c2ce5be229871407ae3a6587a4 | |
parent | 69cc119d0db1b05e581647105e30875136948fa3 (diff) | |
download | vala-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.am | 1 | ||||
-rw-r--r-- | tests/parser/statement-keyword-as-identifier.vala | 85 | ||||
-rw-r--r-- | vala/valaparser.vala | 140 |
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 "); |