首页 > 解决方案 > 带有 PLY 的文本文件中的特定单词

问题描述

我正在为 .txt 文件中的确定单词制作词法分析器,为此我声明保留的确定单词并尝试仅在屏幕上打印选定的单词,但我得到的结果是它包含了所有单词txt 文件并打印出来。我一直在关注http://www.dabeaz.com/ply/ply.html#ply_nn6中的教程和官方 Ply 文档,但我仍然没有实现我的目标。有人可以帮我解决这个问题吗?非常感谢。

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,但主要思想是使用您识别的保留字列表他们,只给我看那些被选中的人

标签: pythonpython-3.x

解决方案


如果要丢弃不在“保留”列表中的令牌,请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'/'可能也阻止了您的评论规则的应用。考虑在评论规则之后排序。


推荐阅读