Syntaxfehler bei „,“ im PLY Pascal-ähnlichen InterpreterPython

Python-Programme
Guest
 Syntaxfehler bei „,“ im PLY Pascal-ähnlichen Interpreter

Post by Guest »

Ich arbeite an einem einfachen Pascal-ähnlichen Interpreter mit PLY, aber beim Parsen tritt bei „,“ ein Syntaxfehler auf. Das Problem tritt auf, wenn versucht wird, eine Quelldatei zu analysieren, die Kommas enthält. Unten finden Sie den Code für den PLY-Code sowie ein Beispiel des Quellcodes, den ich verwende und der den Fehler verursacht.
Pascal.py

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)
Beispielquellcode (SumAndAverage.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

Code: Select all

python Pascal.py SumAndAverage.pas

Code: Select all

Num1 is 10
Num2 is 20
Num3 is 30
Sum 3 numbers is 60
Average is 2.0000000000000000E+001
Ich habe meine Token-Definitionen und meine Grammatik überprüft, kann aber nicht herausfinden, warum der Parser Probleme mit dem Komma in der WRITELN-Anweisung hat. Könnte mir jemand helfen herauszufinden, was falsch läuft?

Quick Reply

Change Text Case: 
   
  • Similar Topics
    Replies
    Views
    Last post