mirror of
				https://github.com/python/cpython.git
				synced 2025-11-03 23:21:29 +00:00 
			
		
		
		
	Fix lookahead of soft keywords in the PEG parser (GH-20436)
Automerge-Triggered-By: @gvanrossum
This commit is contained in:
		
							parent
							
								
									21fda91f8d
								
							
						
					
					
						commit
						404b23b85b
					
				
					 4 changed files with 31 additions and 2 deletions
				
			
		| 
						 | 
					@ -432,3 +432,15 @@ def test_soft_keywords_parse(self) -> None:
 | 
				
			||||||
        self.check_input_strings_for_grammar(valid_cases, invalid_cases)
 | 
					        self.check_input_strings_for_grammar(valid_cases, invalid_cases)
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        self.run_test(grammar_source, test_source)
 | 
					        self.run_test(grammar_source, test_source)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def test_soft_keywords_lookahead(self) -> None:
 | 
				
			||||||
 | 
					        grammar_source = """
 | 
				
			||||||
 | 
					        start: &"if" "if" expr '+' expr NEWLINE
 | 
				
			||||||
 | 
					        expr: NAME
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        test_source = """
 | 
				
			||||||
 | 
					        valid_cases = ["if if + if"]
 | 
				
			||||||
 | 
					        invalid_cases = ["if if"]
 | 
				
			||||||
 | 
					        self.check_input_strings_for_grammar(valid_cases, invalid_cases)
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        self.run_test(grammar_source, test_source)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -718,6 +718,15 @@ _PyPegen_lookahead_with_name(int positive, expr_ty (func)(Parser *), Parser *p)
 | 
				
			||||||
    return (res != NULL) == positive;
 | 
					    return (res != NULL) == positive;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int
 | 
				
			||||||
 | 
					_PyPegen_lookahead_with_string(int positive, expr_ty (func)(Parser *, const char*), Parser *p, const char* arg)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    int mark = p->mark;
 | 
				
			||||||
 | 
					    void *res = func(p, arg);
 | 
				
			||||||
 | 
					    p->mark = mark;
 | 
				
			||||||
 | 
					    return (res != NULL) == positive;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int
 | 
					int
 | 
				
			||||||
_PyPegen_lookahead_with_int(int positive, Token *(func)(Parser *, int), Parser *p, int arg)
 | 
					_PyPegen_lookahead_with_int(int positive, Token *(func)(Parser *, int), Parser *p, int arg)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -119,6 +119,7 @@ int _PyPegen_is_memoized(Parser *p, int type, void *pres);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int _PyPegen_lookahead_with_name(int, expr_ty (func)(Parser *), Parser *);
 | 
					int _PyPegen_lookahead_with_name(int, expr_ty (func)(Parser *), Parser *);
 | 
				
			||||||
int _PyPegen_lookahead_with_int(int, Token *(func)(Parser *, int), Parser *, int);
 | 
					int _PyPegen_lookahead_with_int(int, Token *(func)(Parser *, int), Parser *, int);
 | 
				
			||||||
 | 
					int _PyPegen_lookahead_with_string(int , expr_ty (func)(Parser *, const char*), Parser *, const char*);
 | 
				
			||||||
int _PyPegen_lookahead(int, void *(func)(Parser *), Parser *);
 | 
					int _PyPegen_lookahead(int, void *(func)(Parser *), Parser *);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Token *_PyPegen_expect_token(Parser *p, int type);
 | 
					Token *_PyPegen_expect_token(Parser *p, int type);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -58,7 +58,8 @@ class NodeTypes(Enum):
 | 
				
			||||||
    STRING_TOKEN = 2
 | 
					    STRING_TOKEN = 2
 | 
				
			||||||
    GENERIC_TOKEN = 3
 | 
					    GENERIC_TOKEN = 3
 | 
				
			||||||
    KEYWORD = 4
 | 
					    KEYWORD = 4
 | 
				
			||||||
    CUT_OPERATOR = 5
 | 
					    SOFT_KEYWORD = 5
 | 
				
			||||||
 | 
					    CUT_OPERATOR = 6
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
BASE_NODETYPES = {
 | 
					BASE_NODETYPES = {
 | 
				
			||||||
| 
						 | 
					@ -123,7 +124,7 @@ def soft_keyword_helper(self, value: str) -> FunctionCall:
 | 
				
			||||||
            function="_PyPegen_expect_soft_keyword",
 | 
					            function="_PyPegen_expect_soft_keyword",
 | 
				
			||||||
            arguments=["p", value],
 | 
					            arguments=["p", value],
 | 
				
			||||||
            return_type="expr_ty",
 | 
					            return_type="expr_ty",
 | 
				
			||||||
            nodetype=NodeTypes.NAME_TOKEN,
 | 
					            nodetype=NodeTypes.SOFT_KEYWORD,
 | 
				
			||||||
            comment=f"soft_keyword='{value}'",
 | 
					            comment=f"soft_keyword='{value}'",
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -217,6 +218,12 @@ def lookahead_call_helper(self, node: Lookahead, positive: int) -> FunctionCall:
 | 
				
			||||||
                arguments=[positive, call.function, *call.arguments],
 | 
					                arguments=[positive, call.function, *call.arguments],
 | 
				
			||||||
                return_type="int",
 | 
					                return_type="int",
 | 
				
			||||||
            )
 | 
					            )
 | 
				
			||||||
 | 
					        elif call.nodetype == NodeTypes.SOFT_KEYWORD:
 | 
				
			||||||
 | 
					            return FunctionCall(
 | 
				
			||||||
 | 
					                function=f"_PyPegen_lookahead_with_string",
 | 
				
			||||||
 | 
					                arguments=[positive, call.function, *call.arguments],
 | 
				
			||||||
 | 
					                return_type="int",
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
        elif call.nodetype in {NodeTypes.GENERIC_TOKEN, NodeTypes.KEYWORD}:
 | 
					        elif call.nodetype in {NodeTypes.GENERIC_TOKEN, NodeTypes.KEYWORD}:
 | 
				
			||||||
            return FunctionCall(
 | 
					            return FunctionCall(
 | 
				
			||||||
                function=f"_PyPegen_lookahead_with_int",
 | 
					                function=f"_PyPegen_lookahead_with_int",
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue