Python. Язык программирования
import ply.yacc as yacc
# Лексический анализатор
tokens = (
'NAME', 'NUMBER',
'PLUS', 'MINUS', 'TIMES', 'DIVIDE', 'EQUALS',
'LPAREN', 'RPAREN', 'PRINT',
'PLUS_EQUALS', 'MINUS_EQUALS', 'TIMES_EQUALS', 'DIVIDE_EQUALS',
'IF', 'ELIF', 'ELSE', 'COLON',
'GT', 'LT', 'EQ'
)
# Регулярные выражения для токенов
t_PLUS = r'\+'
t_MINUS = r'-'
t_TIMES = r'\*'
t_DIVIDE = r'/'
t_EQUALS = r'='
t_LPAREN = r'\('
t_RPAREN = r'\)'
t_NAME = r'[a-zA-Z_][a-zA-Z0-9_]*'
t_PLUS_EQUALS = r'\+='
t_MINUS_EQUALS = r'-='
t_TIMES_EQUALS = r'\*='
t_DIVIDE_EQUALS = r'/='
t_PRINT = r'p'
t_IF = r'if'
t_ELIF = r'elif'
t_ELSE = r'else'
t_COLON = r':'
t_GT = r'>'
t_LT = r'<'
t_EQ = r'=='
def t_NUMBER(t):
r'\d+'
t.value = int(t.value)
return t
# Пропуск пробелов, табуляций и символов новой строки
t_ignore = ' \t\n'
# Обработка ошибок
def t_error(t):
print(f"Недопустимый символ '{t.value[0]}'")
t.lexer.skip(1)
# Создание лексера
lexer = lex.lex()
# Синтаксический анализатор
precedence = (
('left', 'PLUS', 'MINUS'),
('left', 'TIMES', 'DIVIDE'),
('left', 'GT', 'LT', 'EQ'),
)
# Словарь для хранения переменных
variables = {}
def p_statements(p):
'''statements : statement
| statements statement'''
if len(p) == 2:
p[0] = [p[1]]
else:
p[0] = p[1] + [p[2]]
def p_statement_assign(p):
'statement : NAME EQUALS expression'
variables[p[1]] = p[3]
def p_plus_equals(p):
'statement : NAME PLUS_EQUALS expression'
if p[1] in variables:
variables[p[1]] += p[3]
else:
print(f"Переменная '{p[1]}' не определена")
def p_minus_equals(p):
'statement : NAME MINUS_EQUALS expression'
if p[1] in variables:
variables[p[1]] -= p[3]
else:
print(f"Переменная '{p[1]}' не определена")
def p_times_equals(p):
'statement : NAME TIMES_EQUALS expression'
if p[1] in variables:
variables[p[1]] *= p[3]
else:
print(f"Переменная '{p[1]}' не определена")
def p_divide_equals(p):
'statement : NAME DIVIDE_EQUALS expression'
if p[1] in variables:
variables[p[1]] /= p[3]
else:
print(f"Переменная '{p[1]}' не определена")
def p_statement_print(p):
'statement : PRINT LPAREN expression RPAREN'
print(p[3])
def p_statement_if(p):
'''statement : IF expression COLON statements
| IF expression COLON statements ELSE COLON statements
| IF expression COLON statements elif_clauses
| IF expression COLON statements elif_clauses ELSE COLON statements'''
if p[2]:
p[0] = p[4]
elif len(p) == 6:
p[0] = p[6]
elif len(p) == 8:
p[0] = p[6] + p[8]
else:
p[0] = []
def p_elif_clauses(p):
'''elif_clauses : ELIF expression COLON statements
| elif_clauses ELIF expression COLON statements'''
if p[2]:
p[0] = p[4]
else:
p[0] = []
def p_expression_binop(p):
'''expression : expression PLUS expression
| expression MINUS expression
| expression TIMES expression
| expression DIVIDE expression
| expression GT expression
| expression LT expression
| expression EQ expression'''
if p[2] == '+':
p[0] = p[1] + p[3]
elif p[2] == '-':
p[0] = p[1] - p[3]
elif p[2] == '*':
p[0] = p[1] * p[3]
elif p[2] == '/':
p[0] = p[1] / p[3]
elif p[2] == '>':
p[0] = p[1] > p[3]
elif p[2] == '<':
p[0] = p[1] < p[3]
elif p[2] == '==':
p[0] = p[1] == p[3]
def p_expression_number(p):
'expression : NUMBER'
p[0] = p[1]
def p_expression_name(p):
'expression : NAME'
try:
p[0] = variables[p[1]]
except LookupError:
print(f"Переменная '{p[1]}' не определена")
p[0] = 0
def p_error(p):
if p:
print(f"Синтаксическая ошибка в '{p.value}'")
else:
print("Синтаксическая ошибка: неожиданный конец файла")
# Создание парсера
parser = yacc.yacc()
# Функция для интерпретации кода
def interpret(code):
parser.parse(code)
# Пример использования
code = """
a = 5
b = 4
if a > b:
p(1)
elif a < b:
p(2)
p(2)
else:
p(3)
"""
interpret(code)
Суть кода: выполнить code. функция p это как print в python, условные операторы также работают как в python.
Почему вывод: Синтаксическая ошибка в 'a' ? Если ожидается: 1