使用PLY开发类Pascal解释器时,逗号处出现Syntax error的问题求助
使用PLY开发类Pascal解释器时,逗号处出现Syntax error的问题求助
我正在用PLY开发一个简单的类Pascal解释器,但解析时遇到了逗号处的语法错误。当尝试解析包含逗号的源文件时就会出现这个问题。下面是PLY代码以及导致错误的示例源代码。
Pascal.py
import ply.lex as lex import ply.yacc as yacc # Lexical Analysis tokens = ( 'PROGRAM', 'VAR', 'BEGIN', 'END', 'INTEGER', 'REAL', 'ASSIGN', 'SEMICOLON', 'COLON', 'COMMA', 'PLUS', 'DIVIDE', 'LPAREN', 'RPAREN', 'WRITELN', 'STRING', 'ID', 'NUMBER', 'DOT' ) # Reserved words reserved = { 'PROGRAM': 'PROGRAM', 'VAR': 'VAR', 'BEGIN': 'BEGIN', 'END': 'END', 'integer': 'INTEGER', 'real': 'REAL', 'WRITELN': 'WRITELN' } # Token definitions t_ASSIGN = r':=' t_SEMICOLON = r';' t_COLON = r':' t_COMMA = r',' t_PLUS = r'\+' t_DIVIDE = r'/' t_LPAREN = r'\(' t_RPAREN = r'\)' t_DOT = r'\.' t_ignore = ' \t' # Ignore spaces and tabs def t_STRING(t): r"'[^']*'" t.value = t.value[1:-1] # Remove surrounding quotes return t def t_ID(t): r'[a-zA-Z_][a-zA-Z_0-9]*' t.type = reserved.get(t.value, 'ID') # Check if it's a reserved word return t def t_NUMBER(t): r'\d+(\.\d+)?' t.value = float(t.value) if '.' in t.value else int(t.value) return t def t_newline(t): r'\n+' t.lexer.lineno += len(t.value) def t_error(t): print(f"Illegal character '{t.value[0]}'") t.lexer.skip(1) lexer = lex.lex() # Syntax Analysis precedence = ( ('left', 'PLUS', 'DIVIDE'), ) def p_program(p): 'program : PROGRAM ID SEMICOLON declarations BEGIN statements END DOT' interpret(p[5]) # Pass the parsed statements to the interpreter def p_declarations(p): '''declarations : VAR var_declaration | empty''' def p_var_declaration(p): '''var_declaration : ID COLON type SEMICOLON var_declaration | ID COLON type SEMICOLON''' def p_type(p): '''type : INTEGER | REAL''' def p_statements(p): '''statements : statements statement SEMICOLON | statement SEMICOLON''' if len(p) == 4: p[0] = p[1] + [p[2]] else: p[0] = [p[1]] def p_statement(p): '''statement : ID ASSIGN expression | WRITELN LPAREN writeln_args RPAREN''' if p[1] == 'WRITELN': p[0] = ('WRITELN', p[3]) else: p[0] = ('ASSIGN', p[1], p[3]) def p_writeln_args(p): '''writeln_args : writeln_args COMMA writeln_arg | writeln_arg''' if len(p) == 4: p[0] = p[1] + [p[3]] else: p[0] = [p[1]] def p_writeln_arg(p): '''writeln_arg : STRING | expression''' p[0] = p[1] def p_expression(p): '''expression : expression PLUS term | expression DIVIDE term | term''' if len(p) == 4: p[0] = (p[2], p[1], p[3]) else: p[0] = p[1] def p_term(p): '''term : ID | NUMBER''' p[0] = p[1] def p_empty(p): 'empty :' p[0] = [] def p_error(p): print(f"Syntax error at '{p.value}'" if p else "Syntax error at EOF") parser = yacc.yacc() # Interpreter variables = {} def evaluate(tree): if isinstance(tree, (int, float)): return tree if isinstance(tree, str): return variables.get(tree, 0) if tree[0] == '+': return evaluate(tree[1]) + evaluate(tree[2]) if tree[0] == '/': return evaluate(tree[1]) / evaluate(tree[2]) return 0 def interpret(statements): for stmt in statements: if stmt[0] == 'ASSIGN': variables[stmt[1]] = evaluate(stmt[2]) elif stmt[0] == 'WRITELN': print(" ".join(str(evaluate(arg)) if not isinstance(arg, str) else arg for arg in stmt[1])) # Run the Program if __name__ == '__main__': import sys if len(sys.argv) < 2: print("Usage: python Pascal.py <file>") sys.exit(1) with open(sys.argv[1], 'r') as file: source = file.read() lexer.input(source) parser.parse(source)
Sample Source Code (SumAndAverage.pas)
PROGRAM SUMANDAVERAGE; VAR num1,num2,num3: integer; sum:integer; avg:real; BEGIN num1:=10; num2:=20; num3:=30; sum:=num1+num2+num3; avg:=sum/3; WRITELN('Num1 is ',num1); WRITELN('Num2 is ',num2); WRITELN('Num3 is ',num3); WRITELN('Sum 3 numbers is ',sum); WRITELN('Average is ',avg) END.
输入和预期输出
输入命令:
python Pascal.py SumAndAverage.pas
预期输出:
Num1 is 10 Num2 is 20 Num3 is 30 Sum 3 numbers is 60 Average is 2.0000000000000000E+001
我检查过令牌定义和语法规则,但搞不懂为什么解析器在处理WRITELN语句中的逗号时会出问题。有人能帮我找出问题所在吗?
备注:内容来源于stack exchange,提问作者Juju
相关产品推荐
相关产品推荐

