python - 带有 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,但主要思想是使用您识别的保留字列表他们,只给我看那些被选中的人
解决方案
如果要丢弃不在“保留”列表中的令牌,请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'/'
可能也阻止了您的评论规则的应用。考虑在评论规则之后排序。
推荐阅读
- r - 找到到一组的最小距离
- excel - 在一封电子邮件中发送所有到期日期,并复制到期日期行数据
- macos - 代码签名失败;请手动重试。Electron 框架:bundle 格式不明确(可能是应用程序或框架)
- javascript - 未捕获的类型错误:没有名为“获取值”的方法 - 使用语义 ui 获取值以进行多选
- android - Flutter 中的 svg 操作(与用户交互)
- gradle - Gradle 脚本语法
- php - 从 php url $url 中删除空格
- amazon-web-services - 尝试使用 cloudformation 在 AWS greengrass 版本 2 中创建 iot 组件时出错
- android - Jetpack compose 停止观察数据
- python - 如何优雅地处理 Selenium 中的 NoSuchElementElement 异常?