Я использую PLY для анализа команд для файла пользовательского определения.Команды определяются по одной в строке, и каждая из них должна начинаться с зарезервированного ключевого слова, за которым следует ряд строк.Мне успешно удалось написать лексер и парсер для грамматики, но у меня возникают проблемы с поднятием SyntaxError
из производственного процесса.
Согласно документации PLY , это возможно простовыбрасывая SyntaxError
из тела правила синтаксического анализатора:
При необходимости, производственное правило может вручную принудительно заставить анализатор ввести восстановление после ошибки.Это делается путем вызова исключения SyntaxError следующим образом:
def p_production(p):
'production : some production ...'
raise SyntaxError
Мой код вызывает SyntaxError
в производственном процессе, когда он сталкивается с недопустимым синтаксисом, но при запуске программы эта ошибка не возникает,Вот минимальный рабочий пример:
from ply import lex, yacc
class Parser(object):
# reserved keyword tokens
reserved = {
"r": "R"
}
# top level tokens
tokens = [
'CHUNK',
'NEWLINE'
]
# add reserved tokens
tokens += reserved.values()
# ignore spaces and tabs
t_ignore = ' \t'
def __init__(self):
# lexer and parser handlers
self.lexer = lex.lex(module=self)
self.parser = yacc.yacc(module=self)
def parse(self, text):
# pass text to yacc
self.parser.parse(text, lexer=self.lexer)
# detect new lines
def t_newline(self, t):
r'\n+'
# generate newline token
t.type = "NEWLINE"
return t
def t_CHUNK(self, t):
r'[a-zA-Z0-9_=.:]+'
# check if chunk is a keyword
t.type = self.reserved.get(t.value.lower(), 'CHUNK')
return t
def t_error(self, t):
raise SyntaxError("token error")
def p_instruction_list(self, p):
'''instruction_list : instruction
| instruction_list instruction'''
pass
# match instruction on their own lines
def p_instruction(self, p):
'''instruction : command NEWLINE
| NEWLINE'''
pass
def p_command(self, p):
'''command : R CHUNK CHUNK CHUNK CHUNK'''
# parse command
if p[2] not in ["a", "b"]:
raise SyntaxError("invalid thing")
def p_error(self, p):
raise SyntaxError("parsing error")
if __name__ == "__main__":
parser = Parser()
parser.parse("""
r a text text text
r c text text text
r b text text text
""")
Вышеприведенный пример работает без вывода чего-либо, что означает, что он успешно проанализировал текст, даже если синтаксическая ошибка должна быть вызвана в p_command
из-за строки r c text text text
(второй токен c
недействителен; допустимо только a
или b
).
Что я делаю не так?