Syntaxfehler bei ',' in Ply-Pascal-ähnlicher DolmetscherPython

Python-Programme
Anonymous
 Syntaxfehler bei ',' in Ply-Pascal-ähnlicher Dolmetscher

Post by Anonymous »

Ich arbeite an einem einfachen pascalähnlichen Dolmetscher mit PLY, aber ich begegne einen Syntaxfehler bei ',' während der Parsen. Das Problem tritt auf, wenn versucht wird, eine Quelldatei zu analysieren, die Kommas enthält. Unten ist der Code für den Ply -Code sowie ein Beispiel des Quellcode, den ich verwende, der den Fehler verursacht.

Code: Select all

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)
Beispielquellencode (Sumaaverwut.Pas)

Code: Select all

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.
Eingabe und die erwartete Ausgabe
python Pascal.py SumAndAverage.pas
< /code>
Num1 is 10
Num2 is 20
Num3 is 30
Sum 3 numbers is 60
Average is 2.0000000000000000E+001
< /code>
I've reviewed my token definitions and grammar, but I can't figure out why the parser is having trouble with the comma in the WRITELN statement. Could someone help me figure out what's going wrong?

Quick Reply

Change Text Case: 
   
  • Similar Topics
    Replies
    Views
    Last post