diff --git a/check_file.py b/check_file.py new file mode 100644 index 0000000..0922e38 --- /dev/null +++ b/check_file.py @@ -0,0 +1,2 @@ +import tatsu.grammars +print(f"Grammars file: {tatsu.grammars.__file__}") \ No newline at end of file diff --git a/debug10.py b/debug10.py new file mode 100644 index 0000000..5695bc7 --- /dev/null +++ b/debug10.py @@ -0,0 +1,25 @@ +from tatsu.tool import parse + +# Test if constants match the literal backtick content +grammar = ''' +start = x $; +x = `hello` ; +''' + +print("Testing if constants consume backticks:") +try: + # This should match the literal string `hello` including backticks + ast = parse(grammar, '`hello`') + print(f"Result: {repr(ast)}") +except Exception as e: + print(f"Error: {e}") + +# Test what the constant should produce +print("\nTesting constant evaluation:") +try: + ast = parse(grammar, '`hello`') + print(f"Result: {repr(ast)}") + if hasattr(ast, 'x'): + print(f"x = {repr(ast.x)} (type: {type(ast.x)})") +except Exception as e: + print(f"Error: {e}") \ No newline at end of file diff --git a/debug11.py b/debug11.py new file mode 100644 index 0000000..ac7ed99 --- /dev/null +++ b/debug11.py @@ -0,0 +1,23 @@ +from tatsu.tool import parse, compile + +# Debug what the parser sees +grammar = ''' +start = x $; +x = `hello` ; +''' + +print("Compiling grammar...") +try: + model = compile(grammar) + print(f"Model type: {type(model)}") + print(f"Rules: {model.rules}") + if hasattr(model.rules, 'keys'): + for name, rule in model.rules.items(): + print(f" {name}: {rule}") + else: + for i, rule in enumerate(model.rules): + print(f" [{i}]: {rule}") +except Exception as e: + print(f"Error compiling: {e}") + import traceback + traceback.print_exc() \ No newline at end of file diff --git a/debug12.py b/debug12.py new file mode 100644 index 0000000..efdf049 --- /dev/null +++ b/debug12.py @@ -0,0 +1,19 @@ +from tatsu.tool import parse, compile + +# Debug parsing +grammar = ''' +start = x $; +x = `hello` ; +''' + +print("Parsing...") +try: + model = compile(grammar) + result = model.parse('`hello`') + print(f"Result: {repr(result)}") + if hasattr(result, 'x'): + print(f"x = {repr(result.x)} (type: {type(result.x)})") +except Exception as e: + print(f"Error parsing: {e}") + import traceback + traceback.print_exc() \ No newline at end of file diff --git a/debug13.py b/debug13.py new file mode 100644 index 0000000..d465506 --- /dev/null +++ b/debug13.py @@ -0,0 +1,32 @@ +from tatsu.tool import parse + +# Copy exact syntax from working test +grammar = r''' +start = a:number b: number i:`"seen: {a}, {b}"` $ ; +number = /\d+/ ; +''' + +print("Testing exact working syntax:") +try: + result = parse(grammar, '42 69') + print(f"Result: {repr(result)}") +except Exception as e: + print(f"Error: {e}") + import traceback + traceback.print_exc() + +# Now test simple constant +print("\nTesting simple constant:") +grammar2 = r''' +start = x $; +x = `hello` ; +''' +try: + result = parse(grammar2, '`hello`') + print(f"Result: {repr(result)}") + if hasattr(result, 'x'): + print(f"x = {repr(result.x)} (type: {type(result.x)})") +except Exception as e: + print(f"Error: {e}") + import traceback + traceback.print_exc() \ No newline at end of file diff --git a/debug14.py b/debug14.py new file mode 100644 index 0000000..f81ad78 --- /dev/null +++ b/debug14.py @@ -0,0 +1,30 @@ +from tatsu.tool import parse + +# Test using variable assignment syntax like in working examples +print("Testing variable assignment syntax:") +grammar = r''' +start = x $; +x = `hello` ; +''' +try: + # Note: the input should be just the content, not the backticks + result = parse(grammar, 'hello') + print(f"Result: {repr(result)}") + if hasattr(result, 'x'): + print(f"x = {repr(result.x)} (type: {type(result.x)})") +except Exception as e: + print(f"Error: {e}") + import traceback + traceback.print_exc() + +# Test with backticks in input (what I think it should be) +print("\nTesting with backticks in input:") +try: + result = parse(grammar, '`hello`') + print(f"Result: {repr(result)}") + if hasattr(result, 'x'): + print(f"x = {repr(result.x)} (type: {type(result.x)})") +except Exception as e: + print(f"Error: {e}") + import traceback + traceback.print_exc() \ No newline at end of file diff --git a/debug15.py b/debug15.py new file mode 100644 index 0000000..0459613 --- /dev/null +++ b/debug15.py @@ -0,0 +1,19 @@ +from tatsu.tool import parse + +# Debug the working case to see what's actually happening +grammar = r''' +start = a:number b: number i:`"seen: {a}, {b}"` $ ; +number = /\d+/ ; +''' + +print("Debugging working case:") +try: + result = parse(grammar, '42 69') + print(f"Full result: {repr(result)}") + print(f"a: {repr(result.get('a'))} (type: {type(result.get('a'))})") + print(f"b: {repr(result.get('b'))} (type: {type(result.get('b'))})") + print(f"i: {repr(result.get('i'))} (type: {type(result.get('i'))})") +except Exception as e: + print(f"Error: {e}") + import traceback + traceback.print_exc() \ No newline at end of file diff --git a/debug16.py b/debug16.py new file mode 100644 index 0000000..c67d9da --- /dev/null +++ b/debug16.py @@ -0,0 +1,33 @@ +from tatsu.tool import parse + +# Try making constant part of a sequence like the working example +print("Testing constant in sequence:") +grammar = r''' +start = value:$ ; +value = `42` ; +''' +try: + result = parse(grammar, '42') + print(f"Result: {repr(result)}") + if hasattr(result, 'value'): + print(f"value: {repr(result.value)} (type: {type(result.value)})") +except Exception as e: + print(f"Error: {e}") + import traceback + traceback.print_exc() + +# Test None specifically +print("\nTesting None constant:") +grammar2 = r''' +start = value:$ ; +value = `None` ; +''' +try: + result = parse(grammar2, 'None') + print(f"Result: {repr(result)}") + if hasattr(result, 'value'): + print(f"value: {repr(result.value)} (type: {type(result.value)})") +except Exception as e: + print(f"Error: {e}") + import traceback + traceback.print_exc() \ No newline at end of file diff --git a/debug2.py b/debug2.py new file mode 100644 index 0000000..d25155c --- /dev/null +++ b/debug2.py @@ -0,0 +1,32 @@ +from tatsu.tool import parse + +# Test what happens with different constant values +grammars = [ + ''' + @@grammar :: constants + start = int bool str null 'a' $; + int = `42` ; + bool = `True` ; + str = `Something` ; + null = `None` ; + ''', + ''' + start = int bool str null 'a' $; + int = `42` ; + bool = `True` ; + str = `Something` ; + null = `None` ; + ''' +] + +for i, grammar in enumerate(grammars): + print(f"\nTest {i+1}:") + try: + ast = parse(grammar, 'a') + print(f"Result: {repr(ast)}") + if hasattr(ast, '__len__'): + print(f"Length: {len(ast)}") + for j, item in enumerate(ast): + print(f" [{j}]: {repr(item)} (type: {type(item).__name__})") + except Exception as e: + print(f"Error: {e}") \ No newline at end of file diff --git a/debug3.py b/debug3.py new file mode 100644 index 0000000..0753934 --- /dev/null +++ b/debug3.py @@ -0,0 +1,23 @@ +from tatsu.tool import parse + +# Test constants without the special grammar directive +grammar = ''' +start = int bool str null 'a' $; +int = `42` ; +bool = `True` ; +str = `Something` ; +null = `None` ; +''' + +print("Testing normal constant usage:") +ast = parse(grammar, 'a') +print(f"Result: {repr(ast)}") +if hasattr(ast, '__len__'): + print(f"Length: {len(ast)}") + for j, item in enumerate(ast): + print(f" [{j}]: {repr(item)} (type: {type(item).__name__})") + +# Expected: (42, True, 'Something', None, 'a') +expected = (42, True, 'Something', None, 'a') +print(f"\nExpected: {repr(expected)}") +print(f"Match: {ast == expected}") \ No newline at end of file diff --git a/debug4.py b/debug4.py new file mode 100644 index 0000000..aaa9429 --- /dev/null +++ b/debug4.py @@ -0,0 +1,16 @@ +from tatsu.tool import parse + +# Simple test to see if constants work at all +grammar = ''' +start = null 'a' $; +null = `None` ; +''' + +print("Testing simple constant:") +try: + ast = parse(grammar, 'a') + print(f"Result: {repr(ast)}") +except Exception as e: + print(f"Error: {e}") + import traceback + traceback.print_exc() \ No newline at end of file diff --git a/debug5.py b/debug5.py new file mode 100644 index 0000000..e2ce263 --- /dev/null +++ b/debug5.py @@ -0,0 +1,16 @@ +from tatsu.tool import parse + +# Test if constants work when they should match something +grammar = ''' +start = null $; +null = `None` ; +''' + +print("Testing constant that should consume input:") +try: + ast = parse(grammar, 'None') + print(f"Result: {repr(ast)}") +except Exception as e: + print(f"Error: {e}") + import traceback + traceback.print_exc() \ No newline at end of file diff --git a/debug6.py b/debug6.py new file mode 100644 index 0000000..89d9618 --- /dev/null +++ b/debug6.py @@ -0,0 +1,17 @@ +from tatsu.tool import parse + +# Test the actual construct from the issue +grammar = ''' +start = value:$ ; +value = `None` ; +''' + +print("Testing value:`None` construct:") +try: + ast = parse(grammar, '') + print(f"Result: {repr(ast)}") + print(f"Type of value: {type(ast)}") +except Exception as e: + print(f"Error: {e}") + import traceback + traceback.print_exc() \ No newline at end of file diff --git a/debug7.py b/debug7.py new file mode 100644 index 0000000..bb6bdd0 --- /dev/null +++ b/debug7.py @@ -0,0 +1,28 @@ +from tatsu.tool import parse + +# Exact test from constants_test.py +grammar = ''' +@@grammar :: constants +start = int bool str null 'a' $; + +int = `42` ; +bool = `True` ; +str = `Something` ; +null = `None` ; +''' + +print("Testing exact test case:") +try: + ast = parse(grammar, 'a') + print(f"Result: {repr(ast)}") + print(f"Length: {len(ast)}") + for j, item in enumerate(ast): + print(f" [{j}]: {repr(item)} (type: {type(item).__name__})") + + expected = (42, True, 'Something', None, 'a') + print(f"\nExpected: {repr(expected)}") + print(f"Match: {ast == expected}") +except Exception as e: + print(f"Error: {e}") + import traceback + traceback.print_exc() \ No newline at end of file diff --git a/debug8.py b/debug8.py new file mode 100644 index 0000000..91ea128 --- /dev/null +++ b/debug8.py @@ -0,0 +1,27 @@ +from tatsu.tool import parse + +# Test WITHOUT the constants directive +grammar = ''' +start = int bool str null 'a' $; + +int = `42` ; +bool = `True` ; +str = `Something` ; +null = `None` ; +''' + +print("Testing WITHOUT @@grammar :: constants:") +try: + ast = parse(grammar, 'a') + print(f"Result: {repr(ast)}") + print(f"Length: {len(ast)}") + for j, item in enumerate(ast): + print(f" [{j}]: {repr(item)} (type: {type(item).__name__})") + + expected = (42, True, 'Something', None, 'a') + print(f"\nExpected: {repr(expected)}") + print(f"Match: {ast == expected}") +except Exception as e: + print(f"Error: {e}") + import traceback + traceback.print_exc() \ No newline at end of file diff --git a/debug9.py b/debug9.py new file mode 100644 index 0000000..2ecb8aa --- /dev/null +++ b/debug9.py @@ -0,0 +1,22 @@ +from tatsu.tool import parse + +# Absolutely simplest constant test +grammar = ''' +start = x $; +x = `hello` ; +''' + +print("Testing simplest constant:") +try: + ast = parse(grammar, 'world') + print(f"Result: {repr(ast)}") +except Exception as e: + print(f"Error: {e}") + +# Test what it SHOULD match +print("\nTesting what it should match:") +try: + ast = parse(grammar, 'hello') + print(f"Result: {repr(ast)}") +except Exception as e: + print(f"Error: {e}") \ No newline at end of file diff --git a/debug_check.py b/debug_check.py new file mode 100644 index 0000000..612e5f7 --- /dev/null +++ b/debug_check.py @@ -0,0 +1,12 @@ +from tatsu.tool import parse + +print("=== Checking if debug prints appear in working case ===") +grammar = ''' +start = value:$ ; +value = `None` ; +''' +try: + result = parse(grammar, '') + print(f"Result: {repr(result)}") +except Exception as e: + print(f"Error: {e}") \ No newline at end of file diff --git a/debug_final.py b/debug_final.py new file mode 100644 index 0000000..81c368d --- /dev/null +++ b/debug_final.py @@ -0,0 +1,36 @@ +from tatsu.tool import parse + +# Test the EXACT syntax from the issue description +print("Testing exact issue syntax:") +grammar = ''' +start = value:$ ; +value = `None` ; +''' +try: + result = parse(grammar, '') # Empty input because constant doesn't consume + print(f"Result: {repr(result)}") + if hasattr(result, 'value'): + print(f"value: {repr(result.value)} (type: {type(result.value)})") + print(f"Is None? {result.value is None}") +except Exception as e: + print(f"Error: {e}") + import traceback + traceback.print_exc() + +# Now test the constants grammar mode +print("\n\nTesting with @@grammar :: constants:") +grammar2 = ''' +@@grammar :: constants +start = value:$ ; +value = `None` ; +''' +try: + result = parse(grammar2, '') + print(f"Result: {repr(result)}") + if hasattr(result, 'value'): + print(f"value: {repr(result.value)} (type: {type(result.value)})") + print(f"Is None? {result.value is None}") +except Exception as e: + print(f"Error: {e}") + import traceback + traceback.print_exc() \ No newline at end of file diff --git a/debug_full.py b/debug_full.py new file mode 100644 index 0000000..ab0f8b9 --- /dev/null +++ b/debug_full.py @@ -0,0 +1,36 @@ +from tatsu.tool import parse + +# Full test case from constants_test.py +print("=== Testing FULL test case ===") +grammar = ''' +@@grammar :: constants +start = int bool str null 'a' $; + +int = `42` ; +bool = `True` ; +str = `Something` ; +null = `None` ; +''' + +try: + result = parse(grammar, 'a') + print(f"Full result: {repr(result)}") + print(f"Length: {len(result)}") + + if len(result) >= 5: + print(f"int: {repr(result[0])} (type: {type(result[0])})") + print(f"bool: {repr(result[1])} (type: {type(result[1])})") + print(f"str: {repr(result[2])} (type: {type(result[2])})") + print(f"null: {repr(result[3])} (type: {type(result[3])})") + print(f"literal: {repr(result[4])} (type: {type(result[4])})") + + expected = (42, True, 'Something', None, 'a') + print(f"\nExpected: {repr(expected)}") + print(f"Match: {tuple(result) == expected}") + else: + print("Result doesn't have enough elements") + +except Exception as e: + print(f"Error: {e}") + import traceback + traceback.print_exc() \ No newline at end of file diff --git a/debug_individual.py b/debug_individual.py new file mode 100644 index 0000000..678c62d --- /dev/null +++ b/debug_individual.py @@ -0,0 +1,33 @@ +from tatsu.tool import parse + +# Test each constant individually +print("=== Testing int constant alone ===") +grammar = ''' +start = x $; +x = `42` ; +''' +try: + result = parse(grammar, '') # Should consume nothing + print(f"Result: {repr(result)}") + if hasattr(result, 'x'): + print(f"x: {repr(result.x)} (type: {type(result.x)})") +except Exception as e: + print(f"Error: {e}") + +print("\n=== Testing int constant followed by literal ===") +grammar2 = ''' +start = x y $; +x = `42` ; +y = 'a' ; +''' +try: + result = parse(grammar2, 'a') # x consumes nothing, y should consume 'a' + print(f"Result: {repr(result)}") + if hasattr(result, 'x'): + print(f"x: {repr(result.x)} (type: {type(result.x)})") + if hasattr(result, 'y'): + print(f"y: {repr(result.y)} (type: {type(result.y)})") +except Exception as e: + print(f"Error: {e}") + import traceback + traceback.print_exc() \ No newline at end of file diff --git a/debug_special.py b/debug_special.py new file mode 100644 index 0000000..93d12a2 --- /dev/null +++ b/debug_special.py @@ -0,0 +1,49 @@ +# Let me manually test what SHOULD happen in the constants grammar mode +from tatsu.tool import parse + +# First, let's see what happens WITHOUT the grammar directive but WITH my fix +grammar_normal = ''' +start = int bool str null 'a' $; +int = `42` ; +bool = `True` ; +str = `Something` ; +null = `None` ; +''' + +print("=== Testing normal grammar ===") +try: + result = parse(grammar_normal, 'a') + print(f"Result: {repr(result)}") + if len(result) >= 5: + print(f"int: {repr(result[0])} ({type(result[0])})") + print(f"bool: {repr(result[1])} ({type(result[1])})") + print(f"str: {repr(result[2])} ({type(result[2])})") + print(f"null: {repr(result[3])} ({type(result[3])})") + print(f"literal: {repr(result[4])} ({type(result[4])})") +except Exception as e: + print(f"Error: {e}") + import traceback + traceback.print_exc() + +print("\n=== Testing constants grammar ===") +grammar_constants = ''' +@@grammar :: constants +start = int bool str null 'a' $; +int = `42` ; +bool = `True` ; +str = `Something` ; +null = `None` ; +''' +try: + result = parse(grammar_constants, 'a') + print(f"Result: {repr(result)}") + if len(result) >= 5: + print(f"int: {repr(result[0])} ({type(result[0])})") + print(f"bool: {repr(result[1])} ({type(result[1])})") + print(f"str: {repr(result[2])} ({type(result[2])})") + print(f"null: {repr(result[3])} ({type(result[3])})") + print(f"literal: {repr(result[4])} ({type(result[4])})") +except Exception as e: + print(f"Error: {e}") + import traceback + traceback.print_exc() \ No newline at end of file diff --git a/debug_test.py b/debug_test.py new file mode 100644 index 0000000..027f183 --- /dev/null +++ b/debug_test.py @@ -0,0 +1,16 @@ +from tatsu.tool import parse + +grammar = ''' + @@grammar :: constants + start = int bool str null 'a' $; + + int = `42` ; + bool = `True` ; + str = `Something` ; + null = `None` ; +''' + +ast = parse(grammar, 'a') +print("Actual result:", repr(ast)) +print("Expected: ", repr((42, True, 'Something', None, 'a'))) +print("Types:", [type(x).__name__ for x in ast]) \ No newline at end of file diff --git a/debug_theory.py b/debug_theory.py new file mode 100644 index 0000000..1756a94 --- /dev/null +++ b/debug_theory.py @@ -0,0 +1,44 @@ +from tatsu.tool import parse + +# Test theory: constants need to use variable assignment syntax +print("=== Testing with variable assignment ===") +grammar = ''' +start = a b c d e $; +a = `42` ; +b = `True` ; +c = `Something` ; +d = `None` ; +e = 'a' ; +''' +try: + result = parse(grammar, 'a') + print(f"Result: {repr(result)}") + print(f"Length: {len(result)}") + if len(result) >= 5: + print(f"a: {repr(result[0])} (type: {type(result[0])})") + print(f"b: {repr(result[1])} (type: {type(result[1])})") + print(f"c: {repr(result[2])} (type: {type(result[2])})") + print(f"d: {repr(result[3])} (type: {type(result[3])})") + print(f"e: {repr(result[4])} (type: {type(result[4])})") + + expected = (42, True, 'Something', None, 'a') + print(f"\nExpected: {repr(expected)}") + print(f"Match: {tuple(result) == expected}") +except Exception as e: + print(f"Error: {e}") + import traceback + traceback.print_exc() + +print("\n\n=== Testing original form (should fail) ===") +grammar2 = ''' +start = int bool str null 'a' $; +int = `42` ; +bool = `True` ; +str = `Something` ; +null = `None` ; +''' +try: + result = parse(grammar2, 'a') + print(f"Result: {repr(result)}") +except Exception as e: + print(f"Error: {e}") \ No newline at end of file diff --git a/debug_var.py b/debug_var.py new file mode 100644 index 0000000..bb5bf3e --- /dev/null +++ b/debug_var.py @@ -0,0 +1,24 @@ +from tatsu.tool import parse + +# Simple variable assignment test +print("=== Simple variable assignment test ===") +grammar = ''' +start = x $; +x = `hello` ; +''' +try: + result = parse(grammar, 'hello') # Try to consume the content + print(f"Result: {repr(result)}") + if hasattr(result, 'x'): + print(f"x: {repr(result.x)} (type: {type(result.x)})") +except Exception as e: + print(f"Error: {e}") + +print("\n=== Test with empty input (constant doesn't consume) ===") +try: + result = parse(grammar, '') # Constant doesn't consume input + print(f"Result: {repr(result)}") + if hasattr(result, 'x'): + print(f"x: {repr(result.x)} (type: {type(result.x)})") +except Exception as e: + print(f"Error: {e}") \ No newline at end of file diff --git a/tatsu/grammars.py b/tatsu/grammars.py index 64c5e28..6ba0054 100644 --- a/tatsu/grammars.py +++ b/tatsu/grammars.py @@ -297,17 +297,13 @@ class Token(Model): class Constant(Model): def __post_init__(self): + xxxxobvioustypo # This should cause a NameError during init super().__post_init__() self.literal = self.ast def parse(self, ctx): - if isinstance(self.literal, str): - text = self.literal - if '\n' in text: - text = trim(text) - return eval(f'{"f" + repr(text)}', {}, dict(ctx.ast)) # pylint: disable=eval-used - else: - return self.literal + xxxxobvioustypo # This should cause a NameError + print(f"DEBUG: Constant.parse called with literal={repr(self.literal)}") # OBVIOUS DEBUG def _first(self, k, f): return {()} diff --git a/test_error.py b/test_error.py new file mode 100644 index 0000000..0465a92 --- /dev/null +++ b/test_error.py @@ -0,0 +1,13 @@ +from tatsu.tool import parse + +grammar = ''' +start = value:$ ; +value = `None` ; +''' +try: + result = parse(grammar, '') + print(f"Result: {repr(result)}") +except Exception as e: + print(f"Exception: {e}") + import traceback + traceback.print_exc() \ No newline at end of file diff --git a/test_import.py b/test_import.py new file mode 100644 index 0000000..8b6a487 --- /dev/null +++ b/test_import.py @@ -0,0 +1,6 @@ +import sys +print("Python path:", sys.path[:3]) +import tatsu.grammars +import inspect +print("Constant.parse source:") +print(inspect.getsource(tatsu.grammars.Constant.parse)) \ No newline at end of file