@@ -504,6 +504,57 @@ def test_soft_keywords_lookahead(self) -> None:
504504 """
505505 self .run_test (grammar_source , test_source )
506506
507+ def test_first_set_dispatch (self ) -> None :
508+ grammar = parse_string (
509+ """
510+ start: expr NEWLINE
511+ expr: NAME | NUMBER | '(' NAME ')'
512+ """ ,
513+ GrammarParser ,
514+ )
515+ parser_source = generate_c_parser_source (grammar )
516+ self .assertIn ("switch (_current_token_type)" , parser_source )
517+
518+ overlapping_grammar = parse_string (
519+ "start: expr NEWLINE $\n expr: NAME '+' NAME | NAME\n " ,
520+ GrammarParser ,
521+ )
522+ parser_source = generate_c_parser_source (overlapping_grammar )
523+ self .assertIn ("_first_set_mask" , parser_source )
524+ self .run_test (
525+ "start: expr NEWLINE $\n expr: NAME '+' NAME | NAME\n " ,
526+ 'self.check_input_strings_for_grammar(["a\\ n", "a + b\\ n"])' ,
527+ )
528+
529+ nullable_grammar = parse_string (
530+ "start: expr NEWLINE\n expr: ['+'] | NUMBER\n " ,
531+ GrammarParser ,
532+ )
533+ parser_source = generate_c_parser_source (nullable_grammar )
534+ self .assertNotIn ("switch (_current_token_type)" , parser_source )
535+
536+ def test_first_set_dispatch_soft_keywords (self ) -> None :
537+ grammar_source = 'start: ("foo" | "bar") NEWLINE $\n '
538+ grammar = parse_string (grammar_source , GrammarParser )
539+ parser_source = generate_c_parser_source (grammar )
540+ self .assertIn ("_first_set_mask" , parser_source )
541+ self .run_test (
542+ grammar_source ,
543+ 'self.check_input_strings_for_grammar(["foo\\ n", "bar\\ n"], ["baz\\ n"])' ,
544+ )
545+
546+ def test_first_set_dispatch_invalid_rules (self ) -> None :
547+ grammar_source = """
548+ start: value NEWLINE $
549+ value: NAME '+' NAME | invalid_value
550+ invalid_value: NAME { RAISE_SYNTAX_ERROR("expected an addition") }
551+ """
552+ test_source = """
553+ with self.assertRaisesRegex(SyntaxError, "expected an addition"):
554+ parse.parse_string("name\\ n", mode=0)
555+ """
556+ self .run_test (grammar_source , test_source )
557+
507558 def test_forced (self ) -> None :
508559 grammar_source = """
509560 start: NAME &&':' | NAME
0 commit comments