Skip to content

test: comprehensive grammar and logic tests#47

Merged
henrylee97 merged 18 commits into
masterfrom
feat/grammar-logic-tests
May 12, 2026
Merged

test: comprehensive grammar and logic tests#47
henrylee97 merged 18 commits into
masterfrom
feat/grammar-logic-tests

Conversation

@henrylee97
Copy link
Copy Markdown
Member

Summary

  • Add tests/test_grammar_logic.py with 23 tests (22 passing, 1 xfail) across 10 sections covering grammar patterns and parser logic not exercised by the existing test suite.
  • All existing tests remain green (60 passed, 1 xfailed total).

What's tested

Section Tests
Arithmetic calculator Single op, mixed precedence (* > +), left-assoc subtraction chain, integer division, parentheses override, mixed same-precedence chain — all verified by evaluating to actual integer values
Default S/R associativity Proves that with no explicit precedence, the default conflict resolution is reduce (left-associative), not shift — the existing test_shift_reduce_resolution_prefers_shift only tests the two-token case with no tree-shape assertion
Dangling else (xfail) if c1 then if c2 then s1 else s2: Plare binds else to the outer if due to the default reduce-wins behavior; most languages (C, Java) expect the inner if to absorb it
Three-level %prec PLUS(1) < STAR(2) < UMINUS(3) hierarchy; verifies + and * in the same grammar as unary minus with a prec_token override
Comma-separated list Empty, single-

henrylee97 and others added 10 commits May 12, 2026 15:22
6가지 테스트: 덧셈, 곱셈 우선순위(STAR>PLUS), 좌결합 뺄셈 체인,
정수 나눗셈, 괄호 우선순위 오버라이드, 동일 우선순위 혼합 체인.
eval_c()로 실제 정수 값을 계산하여 검증.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
precedence=0 토큰들이 S/R 충돌 시 symbol.associative=="left" (기본값)
조건이 True가 되어 reduce 우선 → 좌결합 트리 생성.
기존 test_shift_reduce_resolution_prefers_shift는 체인 케이스 없음.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
S/R 충돌에서 기본 reduce 동작으로 인해 else가 inner if가 아닌
outer if에 바인딩됨. C/Java 관례(inner if가 else를 가져야 함)와 다름.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
PLUS(1) < STAR(2) < UMINUS_UP(3) 우선순위 계층.
prec_token 오버라이드로 단항 마이너스가 곱셈보다 강하게 바인딩됨을 검증.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
빈 리스트, 단일 요소, 3개 요소 케이스를 right-recursive 문법으로 검증.
items 값 리스트를 직접 비교하여 파싱 정확성 확인.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
인수 없음/1개/3개 함수 호출 케이스.
ID_F, LPAREN_F, RPAREN_F, COMMA_F, NUM_F 토큰 사용.
기존 테스트에 없는 함수 호출 구문 문법을 처음으로 검증.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
100단계 중첩 괄호를 스택 오버플로 없이 파싱함을 검증.
LR 스택은 Python 리스트(명시적)라 재귀 한계 무관.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
줄바꿈을 포함한 소스에서 각 토큰의 lineno/offset 정확성 검증.
CALC_LEXER로 렉싱 후 파싱까지 통합 테스트.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
괄호 미닫힘 및 여분 토큰 시 ParsingError 발생 검증.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
program → stmts → stmt stmts | ε 두 단계 문법.
빈 입력, 1개, 3개 구문 케이스 및 순서 보존 검증.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@henrylee97 henrylee97 self-assigned this May 12, 2026
@henrylee97 henrylee97 added the test Tests for verifying expected behavior. label May 12, 2026
@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@github-actions
Copy link
Copy Markdown

Super-linter summary

Language Validation result
PYTHON_BLACK Fail ❌
PYTHON_ISORT Pass ✅
YAML Pass ✅

Super-linter detected linting errors

For more information, see the GitHub Actions workflow run

Powered by Super-linter

PYTHON_BLACK
--- /github/workspace/tests/test_grammar_logic.py	2026-05-12 15:36:47.010496+00:00
+++ /github/workspace/tests/test_grammar_logic.py	2026-05-12 15:36:54.850653+00:00
@@ -176,11 +176,13 @@
             MINUS_C("-", lineno=1, offset=4),
             _num(2, 5),
         ],
     )
     assert isinstance(result, SubC)
-    assert isinstance(result.l, SubC), "left-assoc: outer sub must have inner sub as left child"
+    assert isinstance(
+        result.l, SubC
+    ), "left-assoc: outer sub must have inner sub as left child"
     assert eval_c(result) == 5


 def test_calc_integer_division() -> None:
     """7 / 2 produces DivC and floor-divides to 3."""
@@ -282,11 +284,13 @@
             PLUS_SR("+", lineno=1, offset=3),
             NUM_SR("3", lineno=1, offset=4),
         ],
     )
     assert isinstance(result, AddSR)
-    assert isinstance(result.l, AddSR), "default S/R resolution must produce a left-leaning tree"
+    assert isinstance(
+        result.l, AddSR
+    ), "default S/R resolution must produce a left-leaning tree"
     assert isinstance(result.l.l, NumSR) and result.l.l.value == 1
     assert isinstance(result.l.r, NumSR) and result.l.r.value == 2
     assert isinstance(result.r, NumSR) and result.r.value == 3


@@ -355,11 +359,15 @@
     Actual parse: IfThenElseD(c1, IfThenD(c2, s1), s2).
     """
     p = Parser(
         {
             "stmt": [
-                ([IF_D, BASE_D, THEN_D, "stmt", ELSE_D, "stmt"], IfThenElseD, [1, 3, 5]),
+                (
+                    [IF_D, BASE_D, THEN_D, "stmt", ELSE_D, "stmt"],
+                    IfThenElseD,
+                    [1, 3, 5],
+                ),
                 ([IF_D, BASE_D, THEN_D, "stmt"], IfThenD, [1, 3]),
                 ([BASE_D], BaseStmtD, [0]),
             ]
         }
     )would reformat /github/workspace/tests/test_grammar_logic.py

Oh no! 💥 💔 💥
1 file would be reformatted, 16 files would be left unchanged.

@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@github-actions
Copy link
Copy Markdown

Super-linter summary

Language Validation result
PYTHON_BLACK Fail ❌
PYTHON_ISORT Pass ✅
YAML Pass ✅

Super-linter detected linting errors

For more information, see the GitHub Actions workflow run

Powered by Super-linter

PYTHON_BLACK
--- /github/workspace/tests/test_grammar_logic.py	2026-05-12 15:42:31.378632+00:00
+++ /github/workspace/tests/test_grammar_logic.py	2026-05-12 15:42:39.584279+00:00
@@ -176,11 +176,13 @@
             MINUS_C("-", lineno=1, offset=4),
             _num(2, 5),
         ],
     )
     assert isinstance(result, SubC)
-    assert isinstance(result.l, SubC), "left-assoc: outer sub must have inner sub as left child"
+    assert isinstance(
+        result.l, SubC
+    ), "left-assoc: outer sub must have inner sub as left child"
     assert eval_c(result) == 5


 def test_calc_integer_division() -> None:
     """7 / 2 produces DivC and floor-divides to 3."""
@@ -282,11 +284,13 @@
             PLUS_SR("+", lineno=1, offset=3),
             NUM_SR("3", lineno=1, offset=4),
         ],
     )
     assert isinstance(result, AddSR)
-    assert isinstance(result.l, AddSR), "default S/R resolution must produce a left-leaning tree"
+    assert isinstance(
+        result.l, AddSR
+    ), "default S/R resolution must produce a left-leaning tree"
     assert isinstance(result.l.l, NumSR) and result.l.l.value == 1
     assert isinstance(result.l.r, NumSR) and result.l.r.value == 2
     assert isinstance(result.r, NumSR) and result.r.value == 3


@@ -355,11 +359,15 @@
     Actual parse: IfThenElseD(c1, IfThenD(c2, s1), s2).
     """
     p = Parser(
         {
             "stmt": [
-                ([IF_D, BASE_D, THEN_D, "stmt", ELSE_D, "stmt"], IfThenElseD, [1, 3, 5]),
+                (
+                    [IF_D, BASE_D, THEN_D, "stmt", ELSE_D, "stmt"],
+                    IfThenElseD,
+                    [1, 3, 5],
+                ),
                 ([IF_D, BASE_D, THEN_D, "stmt"], IfThenD, [1, 3]),
                 ([BASE_D], BaseStmtD, [0]),
             ]
         }
     )would reformat /github/workspace/tests/test_grammar_logic.py

Oh no! 💥 💔 💥
1 file would be reformatted, 16 files would be left unchanged.

@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@github-actions
Copy link
Copy Markdown

Super-linter summary

Language Validation result
PYTHON_BLACK Fail ❌
PYTHON_ISORT Pass ✅
YAML Pass ✅

Super-linter detected linting errors

For more information, see the GitHub Actions workflow run

Powered by Super-linter

PYTHON_BLACK
--- /github/workspace/tests/test_grammar_logic.py	2026-05-12 15:45:57.543538+00:00
+++ /github/workspace/tests/test_grammar_logic.py	2026-05-12 15:46:05.529741+00:00
@@ -176,11 +176,13 @@
             MINUS_C("-", lineno=1, offset=4),
             _num(2, 5),
         ],
     )
     assert isinstance(result, SubC)
-    assert isinstance(result.l, SubC), "left-assoc: outer sub must have inner sub as left child"
+    assert isinstance(
+        result.l, SubC
+    ), "left-assoc: outer sub must have inner sub as left child"
     assert eval_c(result) == 5


 def test_calc_integer_division() -> None:
     """7 / 2 produces DivC and floor-divides to 3."""
@@ -282,11 +284,13 @@
             PLUS_SR("+", lineno=1, offset=3),
             NUM_SR("3", lineno=1, offset=4),
         ],
     )
     assert isinstance(result, AddSR)
-    assert isinstance(result.l, AddSR), "default S/R resolution must produce a left-leaning tree"
+    assert isinstance(
+        result.l, AddSR
+    ), "default S/R resolution must produce a left-leaning tree"
     assert isinstance(result.l.l, NumSR) and result.l.l.value == 1
     assert isinstance(result.l.r, NumSR) and result.l.r.value == 2
     assert isinstance(result.r, NumSR) and result.r.value == 3


@@ -355,11 +359,15 @@
     Actual parse: IfThenElseD(c1, IfThenD(c2, s1), s2).
     """
     p = Parser(
         {
             "stmt": [
-                ([IF_D, BASE_D, THEN_D, "stmt", ELSE_D, "stmt"], IfThenElseD, [1, 3, 5]),
+                (
+                    [IF_D, BASE_D, THEN_D, "stmt", ELSE_D, "stmt"],
+                    IfThenElseD,
+                    [1, 3, 5],
+                ),
                 ([IF_D, BASE_D, THEN_D, "stmt"], IfThenD, [1, 3]),
                 ([BASE_D], BaseStmtD, [0]),
             ]
         }
     )would reformat /github/workspace/tests/test_grammar_logic.py

Oh no! 💥 💔 💥
1 file would be reformatted, 16 files would be left unchanged.

@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@github-actions
Copy link
Copy Markdown

Super-linter summary

Language Validation result
PYTHON_BLACK Fail ❌
PYTHON_ISORT Pass ✅
YAML Pass ✅

Super-linter detected linting errors

For more information, see the GitHub Actions workflow run

Powered by Super-linter

PYTHON_BLACK
--- /github/workspace/tests/test_grammar_logic.py	2026-05-12 15:48:26.595248+00:00
+++ /github/workspace/tests/test_grammar_logic.py	2026-05-12 15:48:34.859566+00:00
@@ -176,11 +176,13 @@
             MINUS_C("-", lineno=1, offset=4),
             num(2, 5),
         ],
     )
     assert isinstance(result, SubC)
-    assert isinstance(result.l, SubC), "left-assoc: outer sub must have inner sub as left child"
+    assert isinstance(
+        result.l, SubC
+    ), "left-assoc: outer sub must have inner sub as left child"
     assert eval_c(result) == 5


 def test_calc_integer_division() -> None:
     """7 / 2 produces DivC and floor-divides to 3."""
@@ -282,11 +284,13 @@
             PLUS_SR("+", lineno=1, offset=3),
             NUM_SR("3", lineno=1, offset=4),
         ],
     )
     assert isinstance(result, AddSR)
-    assert isinstance(result.l, AddSR), "default S/R resolution must produce a left-leaning tree"
+    assert isinstance(
+        result.l, AddSR
+    ), "default S/R resolution must produce a left-leaning tree"
     assert isinstance(result.l.l, NumSR) and result.l.l.value == 1
     assert isinstance(result.l.r, NumSR) and result.l.r.value == 2
     assert isinstance(result.r, NumSR) and result.r.value == 3


@@ -355,11 +359,15 @@
     Actual parse: IfThenElseD(c1, IfThenD(c2, s1), s2).
     """
     p = Parser(
         {
             "stmt": [
-                ([IF_D, BASE_D, THEN_D, "stmt", ELSE_D, "stmt"], IfThenElseD, [1, 3, 5]),
+                (
+                    [IF_D, BASE_D, THEN_D, "stmt", ELSE_D, "stmt"],
+                    IfThenElseD,
+                    [1, 3, 5],
+                ),
                 ([IF_D, BASE_D, THEN_D, "stmt"], IfThenD, [1, 3]),
                 ([BASE_D], BaseStmtD, [0]),
             ]
         }
     )would reformat /github/workspace/tests/test_grammar_logic.py

Oh no! 💥 💔 💥
1 file would be reformatted, 16 files would be left unchanged.

- Use Sequence (covariant) instead of list (invariant) for the RHS
  symbol sequence in Parser.__init__ grammar parameter type, resolving
  list variance errors when passing subclass token lists
- Add GrammarDict[T] type alias and annotate grammar dicts with concrete
  AST node types so Parser[T] is inferred correctly
- Add isinstance(result, ExprC) narrowing before eval_c() calls where
  parse() return type is ExprC | Token

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@henrylee97 henrylee97 enabled auto-merge (squash) May 12, 2026 16:28
@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@github-actions
Copy link
Copy Markdown

Super-linter summary

Language Validation result
PYTHON_BLACK Pass ✅
PYTHON_ISORT Pass ✅
YAML Pass ✅

All files and directories linted successfully

For more information, see the GitHub Actions workflow run

Powered by Super-linter

- Change grammar parameter type from dict to Mapping (covariant in
  value), fixing invariance errors when existing Grammar/GrammarRules
  type aliases (using list) are passed from other test files
- Add Sequence wrapper around the productions list for the same reason
- Convert right (now Sequence) to list() internally to preserve the
  list[Symbol] contract expected by Rule and Item

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@github-actions
Copy link
Copy Markdown

Super-linter summary

Language Validation result
PYTHON_BLACK Pass ✅
PYTHON_ISORT Pass ✅
YAML Pass ✅

All files and directories linted successfully

For more information, see the GitHub Actions workflow run

Powered by Super-linter

@github-actions
Copy link
Copy Markdown

Pytest Report

Test Results

  • Tests: 61
  • Errors: 0
  • Failures: 0
  • Skipped: 1

Comment by ✨sambyeol/publish-pytest-action

@github-actions
Copy link
Copy Markdown

Pytest Report

Test Results

  • Tests: 61
  • Errors: 0
  • Failures: 0
  • Skipped: 1

Comment by ✨sambyeol/publish-pytest-action

@github-actions
Copy link
Copy Markdown

Super-linter summary

Language Validation result
PYTHON_BLACK Pass ✅
PYTHON_ISORT Pass ✅
YAML Pass ✅

All files and directories linted successfully

For more information, see the GitHub Actions workflow run

Powered by Super-linter

@henrylee97 henrylee97 merged commit cb76cfb into master May 12, 2026
8 checks passed
@henrylee97 henrylee97 deleted the feat/grammar-logic-tests branch May 12, 2026 16:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

test Tests for verifying expected behavior.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant