Python 如何忽略ply.yacc中的令牌
我正在用PLY编写一个JSON配置(即JSON格式的配置文件)解释器 我想忽略大量的配置文件。我想忽略的某些部分包含我在文件的其他部分不能忽略的标记 例如,我想忽略:Python 如何忽略ply.yacc中的令牌,python,json,yacc,lex,ply,Python,Json,Yacc,Lex,Ply,我正在用PLY编写一个JSON配置(即JSON格式的配置文件)解释器 我想忽略大量的配置文件。我想忽略的某些部分包含我在文件的其他部分不能忽略的标记 例如,我想忽略: "features" : [{ "name" : "someObscureFeature", "version": "1.2", "options": { "values" : ["a", "b", "c"] "allowWithoutContentLength": false,
"features" : [{
"name" : "someObscureFeature",
"version": "1.2",
"options": {
"values" : ["a", "b", "c"]
"allowWithoutContentLength": false,
"enabled": true
}
...
}]
"features" : [{
"name" : "importantFeature",
"version": "1.1",
"options": {
"value": {
"id": 587842,
"description": "ramy-single-hostmatch",
"products": [
"Fresca"
]
...
}]
但我不想忽视:
"features" : [{
"name" : "someObscureFeature",
"version": "1.2",
"options": {
"values" : ["a", "b", "c"]
"allowWithoutContentLength": false,
"enabled": true
}
...
}]
"features" : [{
"name" : "importantFeature",
"version": "1.1",
"options": {
"value": {
"id": 587842,
"description": "ramy-single-hostmatch",
"products": [
"Fresca"
]
...
}]
如果名称值不是“importantFeature”,那么在特性数组中还有许多其他标记我想忽略。例如,重要功能和模糊功能中都可能有一个值数组。我需要相应地忽略
还要注意,我需要提取values
字段的某些元素,我希望将values字段标记化,以便使用它。实际上,如果值字段位于importantMatch内部,我希望有条件地标记它
还要注意的是,importantFeature只是代表了最终将出现的十几个不同的特性,每个特性在各自的特性块中都有自己的语法
我遇到的问题是,很明显,每个特性都有一个名称。我想写一些大致的东西:
def p_FEATURES(p):
'''FEATURES : ARRAY_START FEATURE COMMA FEATURES ARRAY_END
| ARRAY_START FEATURE ARRAY_END'''
def p_FEATURE(p):
'''FEATURE : TESTABLE_FEATURE
| UNTESTABLE_FEATURE'''
def p_TESTABLE_FEATURE(p):
'''TESTABLE_FEATURE : BLOCK_START QUOTE NAME_KEY QUOTE COLON QUOTE CPCODE_FEATURE QUOTE COMMA IGNORE_KEY_VAL_PAIRS COMMA CPCODE_OPTIONS COMMA IGNORE_KEY_VAL_PAIRS'''
def p_UNTESTABLE_FEATURE(p):
'''UNTESTABLE_FEATURE : IGNORE_BLOCK '''
def p_IGNORE_BLOCK(p):
'''IGNORE_BLOCK : BLOCK_START LINES BLOCK_END'''
然而,我遇到的问题是,我不能只是“忽略_块”,因为具有的块有一个“name”,并且我的lexer中有一个名为“name”的标记:
def t_NAME_KEY(t): r'name'; return t
非常感谢您的帮助。定义正则表达式规则函数时,您可以选择是否返回令牌。根据返回的内容,将忽略或考虑令牌。例如:
def t_BLOCK(t):
r'\{[\s]*name[\s]*:[\s]*(importantFeature)|(obscureFeature)\}' # will match a full block with the 'name' key in it
if 'obscureFeature' not in t:
return t
else:
pass
您可以按照这些思路构建一个规则,然后根据您的重要功能是否存在来选择是否返回令牌
另外,将要忽略的标记指定为字符串的一般约定是将t\u ignore\u
附加到名称中
基于OP的编辑。忘记标记化过程中的消除。相反,您可以在使用语法解析json时手动重建json。比如说 替换
def p_FEATURE(p):
'''FEATURE : TESTABLE_FEATURE
| UNTESTABLE_FEATURE'''
def p_TESTABLE_FEATURE(p):
'''TESTABLE_FEATURE : BLOCK_START QUOTE NAME_KEY QUOTE COLON QUOTE CPCODE_FEATURE QUOTE COMMA IGNORE_KEY_VAL_PAIRS COMMA CPCODE_OPTIONS COMMA IGNORE_KEY_VAL_PAIRS'''
def p_UNTESTABLE_FEATURE(p):
'''UNTESTABLE_FEATURE : IGNORE_BLOCK '''
与
您现在可以做的是检查p[2]
,看看它是否重要。如果是,则将其添加到数据变量中。否则,请忽略
这只是一个粗略的想法。您仍然需要准确地找出语法规则(例如,VALUE
也可能导致另一种状态),并向数据添加正确的块以及如何添加。但这是可能的。解析值的正则表达式规则是什么?哪个值?对于“重要功能”?那就是:def t_IMPORTANT_FEATURE(t):r'importantFeature';返回t
,对于要忽略的不重要规则,您有单独的规则吗?或者你根本就没有规则?是的,有点。那就是:`t_STRING=r'[^:^[^]^\{^\}^,^\“^\']+“`我已经更新了我的问题,将关于块内多个标记的一点包括在内。感谢您的回答,但我认为这对我的情况不太合适。主要原因是,如果名称值为'importantFeature',我需要标记块。我想要做到这一点,我必须编写一个正则表达式,以便在整个块上与每个标记匹配。”功能块内部的块。这无疑给了我一些想法,但我不相信这完全回答了我的问题。@Ramy如果你能保证name
在你的字符串中,你可以始终使用*
来匹配字符串的其余部分。r'\{.*.name[\s]*:[\s]*(importantFeature)|(underfeature)\.}
现在这必须是一个多行匹配,因为您的字符串将包含换行符。在这之后,您将根据需要放弃或传递块。如果您可以在标记化过程中忽略块,您甚至不需要规则。让我详细说明我的问题,因为我认为这不起作用。@Ramy很高兴听到这个消息!希望它能起作用。我接受一个建议我对PLY很感兴趣,因为我已经深入研究了它,甚至用它编写了一次编译器(它有45条语法规则……不要让我开始标记化)。我也独自编写了文档,但它没有获得任何吸引力,哈哈。