#python #python-3.x
#python #python-3.x
Вопрос:
Я создаю лексический анализатор для определенных слов, которые находятся в .txt-файле, для этого я объявляю определенные слова зарезервированными и пытаюсь напечатать только выбранные слова на экране, но в результате я получаю, что он берет все слова в txt-файле и печатает их. Я следил за учебным пособием и официальной документацией Ply в http://www.dabeaz.com/ply/ply.html#ply_nn6 но я все еще не достигаю своей цели. Может ли кто-нибудь помочь мне с этим? Большое вам спасибо.
import ply.lex as lex
import re
import os
import sys
reservadas = {
'if' : 'if',
'then' : 'then',
'else' : 'else',
'while' : 'while',
}
tokens = ['ID','NUMBER','PLUS','MINUS','TIMES','DIVIDE',
'ODD','ASSIGN','NE','LT','LTE','GT','GTE',
'LPARENT', 'RPARENT','COMMA','SEMMICOLOM',
'DOT','UPDATE'
] list(reservadas.values())
#tokens = tokens reservadas
# reservadas = {
# 'begin':'BEGIN',
# 'end':'END',
# 'if':'IF',
# 'then':'THEN',
# 'while':'WHILE',
# 'do':'DO',
# 'call':'CALL',
# 'const':'CONST',
# 'int':'VAR',
# 'procedure':'PROCEDURE',
# 'out':'OUT',
# 'in':'IN',
# 'else':'ELSE'
# }
#tokens = tokens list(reservadas.values())
t_ignore = 't '
t_ignore_PLUS = r' '
t_ignore_MINUS = r'-'
t_ignore_TIMES = r'*'
t_ignore_DIVIDE = r'/'
t_ignore_ODD = r'ODD'
t_ignore_ASSIGN = r'='
t_ignore_NE = r'<>'
t_ignore_LT = r'<'
t_ignore_LTE = r'<='
t_ignore_GT = r'>'
t_ignore_GTE = r'>='
t_ignore_LPARENT = r'('
t_ignore_RPARENT = r')'
t_ignore_COMMA = r','
t_ignore_SEMMICOLOM = r';'
t_ignore_DOT = r'.'
t_ignore_UPDATE = r':='
def t_ID(t):
r'[a-zA-Z_][a-zA-Z_0-9]*'
t.type = reservadas.get(t.value,'ID') # Check for reserved words
return t
def t_newline(t):
r'n '
t.lexer.lineno = len(t.value)
#dsfjksdlgjklsdgjsdgslxcvjlk-,.
def t_COMMENT(t):
r'//.*'
r'/*.*'
r'*/.*'
pass
def t_NUMBER(t):
r'd '
t.value = int(t.value)
pass
def t_error(t):
print ("----- '%s'" % t.value[0])
t.lexer.skip(1)
while True:
tok = analizador.token()
if not tok : break
print (tok)
результат, который я получаю с помощью приведенного выше кода:
LexToken(ID,'FSR',1,3)
LexToken(ID,'testing',1,7)
LexToken(ID,'sketch',1,15)
'---- '
'---- '
LexToken(ID,'Connect',3,28)
LexToken(ID,'one',3,36)
LexToken(ID,'end',3,40)
LexToken(ID,'of',3,44)
LexToken(ID,'FSR',3,47)
LexToken(ID,'to',3,51)
LexToken(ID,'V',3,55)
LexToken(ID,'the',3,58)
LexToken(ID,'other',3,62)
LexToken(ID,'end',3,68)
LexToken(ID,'to',3,72)
LexToken(ID,'Analog',3,75)
'---- '
.
.
.
.
LexToken(ID,'Serial',21,694)
LexToken(ID,'print',21,701)
----- '"'
LexToken(ID,'Analog',21,708)
LexToken(ID,'reading',21,715)
----- '"'
'---- '
LexToken(ID,'Serial',22,732)
LexToken(ID,'println',22,739)
LexToken(ID,'fsrReading',22,747)
'---- '
'---- '
LexToken(ID,'LEDbrightness',26,898)
LexToken(ID,'map',26,914)
LexToken(ID,'fsrReading',26,918)
'---- '
LexToken(ID,'analogWrite',28,996)
LexToken(ID,'LEDpin',28,1008)
LexToken(ID,'LEDbrightness',28,1016)
'---- '
LexToken(ID,'IF',29,1034)
'---- '
LexToken(if,'if',30,1038)
'---- '
LexToken(ID,'delay',31,1044)
'---- '
----- '}'
Press any key to continue . . .
мое ожидание выхода было бы таким:
LexToken(ID,'IF',29,1034)
'---- '
LexToken(if,'if',30,1038)
Я анализирую код arduino, и все эти слова являются комментариями, но мне нужно, чтобы вы искали только условные выражения if или IF или другие зарезервированные слова, такие как for , но основная идея заключается в том, что со списком зарезервированных слов вы идентифицируете их и показываете мне только те, которые выбраны
Комментарии:
1. Ваш заголовок должен быть на английском языке
2. Извините, моя ошибка, я уже решил ее
Ответ №1:
Если вы хотите отбросить токены, которых нет в вашем «зарезервированном» списке, настройте t_ID
функцию следующим образом:
def t_ID(t):
r'[a-zA-Z_][a-zA-Z_0-9]*'
reserved_type = reservadas.get(t.value, False)
if reserved_type:
t.type = reserved_type
return t # Return token with reserved type
return None # Discard non-reserved tokens
Кроме того, ваша функция токена комментария, вероятно, неправильно применяется здесь.
def t_COMMENT(t):
r'//.*'
r'/*.*'
r'*/.*'
pass
Вы не можете использовать несколько правил или распределять правило по нескольким строкам таким образом. Потому что строка документа (которая ply
используется для получения регулярного выражения) будет содержать только самую первую строку.
Во-вторых, я думаю, что регулярное выражение нуждается в корректировке для комментариев, предполагая, что вы обозначаете C или C-подобный язык. В частности, необходимо учитывать возможность того, что комментарии занимают несколько строк.
Чтобы исправить, примените следующее для работы с комментариями:
def t_block_comment(tok):
r'/*((.|n))*?*/'
tok.lexer.lineno = tok.value.count('n')
return None # Discard block comments "/* comment */"
t_ignore_comment = r'//.*' # ignore inline comments "// comment"
Вам также может потребоваться применить многострочный флаг регулярного выражения:
analizador = lex.lex(reflags=re.MULTILINE)
Наконец, t_ignore_DIVIDE = r'/'
возможно, вы также препятствуете применению ваших правил комментариев. Рассмотрите возможность упорядочения этого после правил комментариев.
Комментарии:
1. большое вам спасибо за ваш ответ, указанная вами модификация выдает мне ошибку, она сообщает мне, что имя ‘reserved_value’ не определено, его не хватает для сравнения reserved_value с чем-то?, извините, если я не очень хорошо понимаю эту строку кода.
2. @andbrs извиняется. Я только что исправил ошибку ввода в своем ответе. Этого не должно было быть
reserved_type
reserved_value
.3. Большое вам спасибо, я пытался разобраться в библиотеке и часами пытался решить проблему, вы всегда узнаете что-то новое. Еще раз большое вам спасибо =).