Конкретные слова из текстового файла с помощью PLY

#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. Большое вам спасибо, я пытался разобраться в библиотеке и часами пытался решить проблему, вы всегда узнаете что-то новое. Еще раз большое вам спасибо =).