Я использую PLY для анализа программы на C только с помощью конструкции for.Проблема, с которой я столкнулся, заключается в том, что моя программа, похоже, принимает только определенные формы / случаи цикла for, что приводит к синтаксической ошибке для других, хотя я написал деривации для тех, на которых программа, похоже, не работает.
Код:
import ply.lex as lex
import ply.yacc as yacc
tokens = ['HASH','HEADER_FILE','FLOW_OPEN','FLOW_CLOSE','SEMI_COLON',
'TYPE','SMALL_OPEN','SMALL_CLOSE','IDENTIFIER','COLON',
'ASSIGNMENT_OP','UNARY_OP','BINARY_OP','LITERAL','LOGICAL_OP']
reserved = {'include' : 'INCLUDE', 'main': 'MAIN','int':'INT','void':'VOID','for':'FOR','switch':'SWITCH','case':'CASE','default':'DEFAULT','break':'BREAK'}
tokens += reserved.values()
t_HASH = r'\#'
#t_INCLUDE = r'include'
t_HEADER_FILE = r'<stdio.h>'
#t_MAIN = r'main'
t_FLOW_OPEN = r'{'
t_FLOW_CLOSE = r'}'
t_SMALL_OPEN = r'\('
t_SMALL_CLOSE = r'\)'
t_SEMI_COLON = r';'
t_ASSIGNMENT_OP = r'\='
#t_IDENTIFIER = r'[a-zA-Z][a-zA-Z]*'
t_UNARY_OP = r'\++|\--'
#t_BINARY_OP = r'[\+\-\*\/]'
t_LITERAL = r'[0-9][0-9]*'
t_LOGICAL_OP = r'\<|\>'
t_COLON: r':'
def t_check_reserved(t):
r'[a-zA-Z][a-zA-Z]*'
if t.value in reserved:
t.type = reserved[t.value]
else:
t.type = 'IDENTIFIER'
return t
def t_error(token):
print(f'Illegal character: {token.value}')
def t_whitespace(t):
r'\s+'
pass
def t_COMMENT(t):
r'(\/\/\/.*)|(\/\/\!.*)|(\/\/.*)|(\/\*[.\n]*.*\*\/)'
pass
def t_newline(t):
r'\n+'
t.lexer.lineno += len(t.value)
lexer = lex.lex()
#Building the parser
def p_expression_start(p):
'expression : header body'
print('Derivation complete!')
def p_header(p):
'header : HASH INCLUDE HEADER_FILE'
print('Deriving rule header')
def p_body(p):
'body : main rest'
print('Deriving rule body')
def p_main(p):
'main : type MAIN SMALL_OPEN SMALL_CLOSE'
print('Deriving rule main')
def p_type(p):
'''type : INT
| VOID
'''
def p_rest(p):
'rest : FLOW_OPEN st FLOW_CLOSE'
print('Deriving rule rest')
def p_st(p):
'''
st : IDENTIFIER SEMI_COLON st
| type IDENTIFIER SEMI_COLON st
| for
| end
'''
print('Deriving rule st')
def p_for(p):
'''
for : FOR SMALL_OPEN declarative SEMI_COLON num_expression SEMI_COLON update_expression SMALL_CLOSE FLOW_OPEN st FLOW_CLOSE
'''
print('Deriving rule for')
def p_declarative(p):
'''
declarative : IDENTIFIER ASSIGNMENT_OP IDENTIFIER
| IDENTIFIER ASSIGNMENT_OP LITERAL
'''
def p_num_expression(p):
'''
num_expression : LITERAL
| IDENTIFIER
| conditional_expression
'''
def p_conditional_expression(p):
'''
conditional_expression : IDENTIFIER LOGICAL_OP LITERAL
| IDENTIFIER LOGICAL_OP IDENTIFIER
| empty
'''
def p_update_expression(p):
'''
update_expression : IDENTIFIER UNARY_OP
| empty
'''
def p_end(p): #Empty production
'''end :'''
print('Deriving rule end')
def p_error(p):
if p == None:
token = "end of file"
else:
token = f"{p.type}({p.value}) on line {p.lineno}"
print(f"Syntax error: Unexpected {token}")
parser = yacc.yacc(method='LALR',debug=True)
with open(r'forparsing.txt','r') as file:
'''while True:
try:
line = next(file)
print('Parsing')
parser.parse(line)
except:
print('Finished')
break
'''
content = file.read()
parser.parse(content)
Некоторые из случаев, когда эта программа дает сбой: 1. когда я даю идентификатор или литерал в части num_exp цикла for (то есть в for (init_exp; num_exp;update_exp)), хотя я явно упомянул эти случаи в правиле грамматики:
def p_num_expression(p):
'''
num_expression : LITERAL
| IDENTIFIER
| conditional_expression
'''
Более того, программа на C работает, только когда часть conditional_expression имеет форму> 10 (IDENTIFER LOGICAL_OP IDENTIFIER), даже еслиГрамматическое правило для этого нетерминала:
def p_conditional_expression(p):
'''
conditional_expression : IDENTIFIER LOGICAL_OP LITERAL
| IDENTIFIER LOGICAL_OP IDENTIFIER
| empty
'''
Таким образом, это только первый из 3 возможных дериваций, которые будут приняты.Использование одной из двух других форм дает мне синтаксическую ошибку.
Редактировать: Это один из входов, для которого я получаю синтаксическую ошибку:
# include <stdio.h>
void main()
{
for(a=15;1;a++)
{
}
}
Это не должно быть ошибкой, так какодин из моих выводов для нетерминального выражения num_expression - это num_expression -> LITERAL.Однако, если я заменю одно условное выражение чем-то вроде> 10, тогда деривация завершится.
Есть ли что-то принципиально неправильное в написанной мной грамматике, из-за которой синтаксический анализатор, по-видимому, не учитываетнекоторые из правил?