使用 PLY 解析令牌
Parsing tokens with PLY
一段时间以来,我一直在尝试使用 PLY 解析一些给定的文本,但一直无法弄清楚。我定义了这些标记:
tokens = ['ID', 'INT', 'ASSIGNMENT']
并且我想将我找到的单词分类到这些标记中。例如,如果给定扫描仪:
var = 5
它应该打印这个:
ID : 'var'
ASSIGNMENT : '='
INT : 5
这很好用。问题是当程序给出以下文本时:
9var = 5
此输出为:
INT : 9
ID : 'var'
ASSIGNMENT : '='
INT : 5
这是错误的地方。它应该将 9var 作为 ID,根据 ID 正则表达式,这不是 ID 的有效名称。这些是我的正则表达式:
def t_ID(t):
r'[a-zA-Z_][a-zA-Z_0-9]*'
return t
def t_INT(t):
r'\d+'
t.value = int(t.value)
return t
t_ASSIGNMENT = r'\='
我该如何解决这个问题?
非常感谢您的帮助!
你说:"It should take 9var
as an ID"。但随后您指出 9var
与 ID 正则表达式模式不匹配。那为什么要9var
扫描成身份证呢?
如果您希望 9var
成为 ID,将正则表达式从 [a-zA-Z_][a-zA-Z_0-9]*
更改为 [a-zA-Z_0-9]+
就足够了。 (这也将匹配纯整数,因此您需要确保首先应用 INT 模式。或者,您可以使用 [a-zA-Z_0-9]*[a-zA-Z_][a-zA-Z_0-9]*
。)
我怀疑您真正想要的是 9var
被识别为词法错误而不是解析错误。但是如果无论如何都要被识别为错误,那么它是词法错误还是语法错误真的很重要吗?
值得一提的是,Python 词法分析器的工作方式与您的词法分析器完全相同:它将扫描 9var
作为两个标记,稍后会产生语法错误。
当然,在您的语言中,可能存在一些语法上正确的结构,其中 ID 可以直接跟在 INT 之后。或者,如果不是,关键字可以直接跟在 INT 之后,例如 Python 表达式 3 if x else 2
。 (同样,如果您将其写为 3if x else 2
,Python 不会抱怨。)
因此,如果您真的坚持为以数字开头并以非数字结尾的令牌标记扫描器错误,您可以插入另一个模式,例如 [0-9]+[a-zA-Z_][a-zA-Z_0-9]*
,并让它引发错误在行动中。
一段时间以来,我一直在尝试使用 PLY 解析一些给定的文本,但一直无法弄清楚。我定义了这些标记:
tokens = ['ID', 'INT', 'ASSIGNMENT']
并且我想将我找到的单词分类到这些标记中。例如,如果给定扫描仪:
var = 5
它应该打印这个:
ID : 'var'
ASSIGNMENT : '='
INT : 5
这很好用。问题是当程序给出以下文本时:
9var = 5
此输出为:
INT : 9
ID : 'var'
ASSIGNMENT : '='
INT : 5
这是错误的地方。它应该将 9var 作为 ID,根据 ID 正则表达式,这不是 ID 的有效名称。这些是我的正则表达式:
def t_ID(t):
r'[a-zA-Z_][a-zA-Z_0-9]*'
return t
def t_INT(t):
r'\d+'
t.value = int(t.value)
return t
t_ASSIGNMENT = r'\='
我该如何解决这个问题?
非常感谢您的帮助!
你说:"It should take 9var
as an ID"。但随后您指出 9var
与 ID 正则表达式模式不匹配。那为什么要9var
扫描成身份证呢?
如果您希望 9var
成为 ID,将正则表达式从 [a-zA-Z_][a-zA-Z_0-9]*
更改为 [a-zA-Z_0-9]+
就足够了。 (这也将匹配纯整数,因此您需要确保首先应用 INT 模式。或者,您可以使用 [a-zA-Z_0-9]*[a-zA-Z_][a-zA-Z_0-9]*
。)
我怀疑您真正想要的是 9var
被识别为词法错误而不是解析错误。但是如果无论如何都要被识别为错误,那么它是词法错误还是语法错误真的很重要吗?
值得一提的是,Python 词法分析器的工作方式与您的词法分析器完全相同:它将扫描 9var
作为两个标记,稍后会产生语法错误。
当然,在您的语言中,可能存在一些语法上正确的结构,其中 ID 可以直接跟在 INT 之后。或者,如果不是,关键字可以直接跟在 INT 之后,例如 Python 表达式 3 if x else 2
。 (同样,如果您将其写为 3if x else 2
,Python 不会抱怨。)
因此,如果您真的坚持为以数字开头并以非数字结尾的令牌标记扫描器错误,您可以插入另一个模式,例如 [0-9]+[a-zA-Z_][a-zA-Z_0-9]*
,并让它引发错误在行动中。