@@ -533,6 +533,57 @@ def test_soft_keywords_lookahead(self) -> None:
533533 """
534534 self .run_test (grammar_source , test_source )
535535
536+ def test_first_set_dispatch (self ) -> None :
537+ grammar = parse_string (
538+ """
539+ start: expr NEWLINE
540+ expr: NAME | NUMBER | '(' NAME ')'
541+ """ ,
542+ GrammarParser ,
543+ )
544+ parser_source = generate_c_parser_source (grammar )
545+ self .assertIn ("switch (_current_token_type)" , parser_source )
546+
547+ overlapping_grammar = parse_string (
548+ "start: expr NEWLINE $\n expr: NAME '+' NAME | NAME\n " ,
549+ GrammarParser ,
550+ )
551+ parser_source = generate_c_parser_source (overlapping_grammar )
552+ self .assertIn ("_first_set_mask" , parser_source )
553+ self .run_test (
554+ "start: expr NEWLINE $\n expr: NAME '+' NAME | NAME\n " ,
555+ 'self.check_input_strings_for_grammar(["a\\ n", "a + b\\ n"])' ,
556+ )
557+
558+ nullable_grammar = parse_string (
559+ "start: expr NEWLINE\n expr: ['+'] | NUMBER\n " ,
560+ GrammarParser ,
561+ )
562+ parser_source = generate_c_parser_source (nullable_grammar )
563+ self .assertNotIn ("switch (_current_token_type)" , parser_source )
564+
565+ def test_first_set_dispatch_soft_keywords (self ) -> None :
566+ grammar_source = 'start: ("foo" | "bar") NEWLINE $\n '
567+ grammar = parse_string (grammar_source , GrammarParser )
568+ parser_source = generate_c_parser_source (grammar )
569+ self .assertIn ("_first_set_mask" , parser_source )
570+ self .run_test (
571+ grammar_source ,
572+ 'self.check_input_strings_for_grammar(["foo\\ n", "bar\\ n"], ["baz\\ n"])' ,
573+ )
574+
575+ def test_first_set_dispatch_invalid_rules (self ) -> None :
576+ grammar_source = """
577+ start: value NEWLINE $
578+ value: NAME '+' NAME | invalid_value
579+ invalid_value: NAME { RAISE_SYNTAX_ERROR("expected an addition") }
580+ """
581+ test_source = """
582+ with self.assertRaisesRegex(SyntaxError, "expected an addition"):
583+ parse.parse_string("name\\ n", mode=0)
584+ """
585+ self .run_test (grammar_source , test_source )
586+
536587 def test_forced (self ) -> None :
537588 grammar_source = """
538589 start: NAME &&':' | NAME
0 commit comments