diff --git a/tests/Makefile.am b/tests/Makefile.am index 413132a6f87f407724f0e7c77273f3c6fed9f008..d5ddb491767f69f97e7aa8df4a44e169ff9923ca 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -929,6 +929,7 @@ TESTS = \ parser/statement-keyword-as-identifier.vala \ parser/statement-outside-root.test \ parser/switch-statement.vala \ + parser/switch-section-outside-switch.test \ parser/template.vala \ parser/tuple.vala \ parser/unsupported-property-async.test \ diff --git a/tests/parser/switch-section-outside-switch.test b/tests/parser/switch-section-outside-switch.test new file mode 100644 index 0000000000000000000000000000000000000000..8a888d83c281064f6b246c60c7fe70b7cf378e99 --- /dev/null +++ b/tests/parser/switch-section-outside-switch.test @@ -0,0 +1,5 @@ +Invalid Code + +void main () { + case 23: +} diff --git a/vala/valaparser.vala b/vala/valaparser.vala index 93031cee1ac81be56c589ad7f73fa5212a900e46..76c2bc92eafeabccf5729b683cd0453a12ea11aa 100644 --- a/vala/valaparser.vala +++ b/vala/valaparser.vala @@ -1634,6 +1634,10 @@ public class Vala.Parser : CodeVisitor { case TokenType.SWITCH: stmt = parse_switch_statement (); break; + case TokenType.CASE: + case TokenType.DEFAULT: + stmt = parse_switch_section_statement (); + break; case TokenType.WHILE: stmt = parse_while_statement (); break; @@ -1700,8 +1704,6 @@ public class Vala.Parser : CodeVisitor { void parse_statements (Block block) throws ParseError { while (current () != TokenType.CLOSE_BRACE - && current () != TokenType.CASE - && current () != TokenType.DEFAULT && current () != TokenType.EOF) { try { Statement stmt = null; @@ -1733,6 +1735,15 @@ public class Vala.Parser : CodeVisitor { case TokenType.WITH: stmt = parse_statement (current ()); break; + case TokenType.CASE: + case TokenType.DEFAULT: + if (block is SwitchSection) { + // begin a new switch case + return; + } else { + stmt = parse_statement (current ()); + } + break; case TokenType.VAR: is_decl = true; parse_local_variable_declarations (block); @@ -2182,28 +2193,34 @@ public class Vala.Parser : CodeVisitor { var stmt = new SwitchStatement (condition, get_src (begin)); expect (TokenType.OPEN_BRACE); while (current () != TokenType.CLOSE_BRACE) { - begin = get_location (); - var section = new SwitchSection (get_src (begin)); - do { - if (accept (TokenType.CASE)) { - section.add_label (new SwitchLabel (parse_expression (), get_src (begin))); - while (current () == TokenType.COMMA) { - expect (TokenType.COMMA); - section.add_label (new SwitchLabel (parse_expression (), get_src (begin))); - } - } else { - expect (TokenType.DEFAULT); - section.add_label (new SwitchLabel.with_default (get_src (begin))); - } - expect (TokenType.COLON); - } while (current () == TokenType.CASE || current () == TokenType.DEFAULT); - parse_statements (section); - stmt.add_section (section); + stmt.add_section ((SwitchSection) parse_switch_section_statement ()); } expect (TokenType.CLOSE_BRACE); return stmt; } + Statement parse_switch_section_statement () throws ParseError { + var begin = get_location (); + var section = new SwitchSection (get_src (begin)); + do { + if (accept (TokenType.CASE)) { + section.add_label (new SwitchLabel (parse_expression (), get_src (begin))); + while (current () == TokenType.COMMA) { + expect (TokenType.COMMA); + section.add_label (new SwitchLabel (parse_expression (), get_src (begin))); + } + expect (TokenType.COLON); + } else if (accept (TokenType.DEFAULT)) { + section.add_label (new SwitchLabel.with_default (get_src (begin))); + expect (TokenType.COLON); + } else { + throw new ParseError.SYNTAX ("expected `case' or `default' switch label"); + } + } while (current () == TokenType.CASE || current () == TokenType.DEFAULT); + parse_statements (section); + return section; + } + Statement parse_while_statement () throws ParseError { var begin = get_location (); expect (TokenType.WHILE); diff --git a/vala/valaswitchsection.vala b/vala/valaswitchsection.vala index af5be68dc66ce246764ebdeef6162243cd7cdce4..a44256b85c658062f69ee0f2d8a6f6e5fb793dd8 100644 --- a/vala/valaswitchsection.vala +++ b/vala/valaswitchsection.vala @@ -88,6 +88,12 @@ public class Vala.SwitchSection : Block { return !error; } + if (!(parent_node is SwitchStatement)) { + Report.error (source_reference, "no enclosing switch statement found"); + error = true; + return false; + } + foreach (SwitchLabel label in get_labels ()) { label.check (context); }