You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python实现Tiny语言解析器遇报错,请求技术协助排查

Fixing Issues in Your Tiny Language Parser's Expression Handling

Alright, let's dig into the problems with your parser code and fix them one by one. The core issues are in how you implemented the recursive expression rules (like simple_exp, term, exp) and some incomplete statement handling. Here's a breakdown of the fixes:

Key Problems in Your Current Code

  • Broken simple_exp logic: It only checks for leading +/- but doesn't properly handle the recursive combination of terms and add operations.
  • Incomplete term implementation: Ignores the recursive structure of factors and multiply operations.
  • Flawed exp validation: Fails to accept a single simple_exp (without a comparison operator).
  • Incomplete statements: repeat_stmt doesn't handle the UNTIL clause, and assign_stmt/write_stmt skip parsing expressions.
  • Incorrect string comparison: Using is instead of == for checking token values (unsafe in Python, as is compares object identity rather than string content).

Corrected Parser Code

import scanner3

def program(l):
    if len(l) < 1:
        print("Minimum number of expressions is not met")
        return False
    # Check if last token is a semicolon (invalid per grammar)
    if l[-1].value == ";":
        print("ERROR: Semicolon at last line")
        return False
    return stmt_seq(l)

def stmt_seq(l):
    if not stmt(l):
        return False
    # Handle optional semicolon + subsequent statements
    while l and l[0].value == ";":
        l.pop(0)
        if not stmt(l):
            return False
    return True

def stmt(l):
    if if_stmt(l):
        print("Parsed IF statement")
        return True
    elif repeat_stmt(l):
        print("Parsed REPEAT statement")
        return True
    elif assign_stmt(l):
        print("Parsed ASSIGN statement")
        return True
    elif read_stmt(l):
        print("Parsed READ statement")
        return True
    elif write_stmt(l):
        print("Parsed WRITE statement")
        return True
    else:
        if l:
            print(f"ERROR: Invalid statement at line {l[0].line_no}")
        return False

def if_stmt(l):
    if not l or l[0].value != "IF":
        return False
    l.pop(0)
    # Parse the condition expression
    if not exp(l):
        return False
    if not l or l[0].value != "THEN":
        print(f"ERROR: Expected THEN at line {l[0].line_no}")
        return False
    l.pop(0)
    # Parse THEN statement sequence
    if not stmt_seq(l):
        return False
    # Handle optional ELSE clause
    if l and l[0].value == "ELSE":
        l.pop(0)
        if not stmt_seq(l):
            return False
    # Check for END
    if not l or l[0].value != "END":
        print(f"ERROR: Expected END at line {l[0].line_no}")
        return False
    l.pop(0)
    return True

def repeat_stmt(l):
    if not l or l[0].value != "REPEAT":
        return False
    l.pop(0)
    # Parse the statement sequence inside REPEAT
    if not stmt_seq(l):
        return False
    if not l or l[0].value != "UNTIL":
        print(f"ERROR: Expected UNTIL at line {l[0].line_no}")
        return False
    l.pop(0)
    # Parse the UNTIL condition expression
    if not exp(l):
        return False
    return True

def assign_stmt(l):
    if not l or l[0].type != 'var' or len(l) < 2:
        return False
    if l[1].value != ":=":
        return False
    # Consume variable and assignment operator
    l.pop(0)
    l.pop(0)
    # Parse the right-hand side expression
    return exp(l)

def read_stmt(l):
    if not l or l[0].value != 'READ' or len(l) < 2:
        return False
    if l[1].type != "var":
        print(f"ERROR: Expected variable in READ at line {l[0].line_no}")
        return False
    l.pop(0)
    l.pop(0)
    return True

def write_stmt(l):
    if not l or l[0].value != "WRITE":
        return False
    l.pop(0)
    # Parse the expression to write
    return exp(l)

def exp(l):
    # Exp -> SimpleExp [ComparisonOp SimpleExp]
    if not simple_exp(l):
        return False
    # Optional comparison operator + second simple exp
    if l and (l[0].value in ("<", ">", "=")):
        comparison_op(l)
        if not simple_exp(l):
            return False
    return True

def comparison_op(l):
    if not l or l[0].value not in ("<", ">", "="):
        print(f"ERROR: Invalid comparison operator at line {l[0].line_no}")
        return False
    l.pop(0)
    return True

def simple_exp(l):
    # SimpleExp -> [AddOp] Term {AddOp Term}
    optional_op = False
    if l and l[0].value in ("+", "-"):
        add_op(l)
        optional_op = True
    # Must have at least one term
    if not term(l):
        return False
    # Handle repeated AddOp + Term
    while l and l[0].value in ("+", "-"):
        add_op(l)
        if not term(l):
            return False
    return True

def add_op(l):
    if not l or l[0].value not in ("+", "-"):
        print(f"ERROR: Invalid add operator at line {l[0].line_no}")
        return False
    l.pop(0)
    return True

def term(l):
    # Term -> Factor {MulOp Factor}
    if not factor(l):
        return False
    # Handle repeated MulOp + Factor
    while l and l[0].value in ("*", "/"):
        mul_op(l)
        if not factor(l):
            return False
    return True

def mul_op(l):
    if not l or l[0].value not in ("*", "/"):
        print(f"ERROR: Invalid multiply operator at line {l[0].line_no}")
        return False
    l.pop(0)
    return True

def factor(l):
    if not l:
        return False
    current_token = l[0]
    if current_token.value == "(":
        l.pop(0)
        if not exp(l):
            return False
        if not l or l[0].value != ")":
            print(f"ERROR: Expected closing parenthesis at line {current_token.line_no}")
            return False
        l.pop(0)
        return True
    elif current_token.type == "num":
        l.pop(0)
        return True
    elif current_token.type == "var":
        l.pop(0)
        return True
    else:
        print(f"ERROR: Invalid factor at line {current_token.line_no}")
        return False

# Main execution
tokens = scanner3.tagheez("res.txt").tokenz
print("Token list:")
for wa7da in tokens:
    print(f"{wa7da.value}, {wa7da.type} in line {wa7da.line_no}")
print("\nParser result:", program(tokens))

Key Fixes Explained

  1. simple_exp: Now correctly handles optional leading +/-, followed by a term, then any number of AddOp + Term combinations to match the grammar.
  2. term: Implements the recursive rule of Factor {MulOp Factor} to handle chains of multiplication/division operations.
  3. exp: Accepts a single simple_exp (without comparison) and properly handles the optional comparison operator + second expression.
  4. repeat_stmt: Completes the grammar rule by parsing the stmt_seq inside REPEAT and the required UNTIL expression.
  5. assign_stmt/write_stmt: Reinstates expression parsing for the right-hand side of assignments and the value to write, which was missing in your original code.
  6. String comparisons: Replaced all is checks with == for safe, correct string value comparison.
  7. stmt_seq: Now handles multiple statements separated by semicolons correctly using a loop, instead of a single recursive call.

内容的提问来源于stack exchange,提问作者Mariam Mohie Sleem

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 09:24:29