Синтаксическая ошибка в ',' в интерпретаторе, подобном PLY PascalPython

Программы на Python
Ответить
Anonymous
 Синтаксическая ошибка в ',' в интерпретаторе, подобном PLY Pascal

Сообщение Anonymous »

Я работаю над простым интерпретатором, подобным Паскалю, с использованием PLY, но во время синтаксического анализа обнаружил синтаксическую ошибку ','. Проблема возникает при попытке проанализировать исходный файл, содержащий запятые. Ниже приведен код кода 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 ")
sys.exit(1)
with open(sys.argv[1], 'r') as file:
source = file.read()
lexer.input(source)
parser.parse(source)
Пример исходного кода (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. Может ли кто-нибудь помочь мне понять, что происходит не так?

Подробнее здесь: https://stackoverflow.com/questions/793 ... nterpreter
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «Python»