如何忽略 ply.yacc 中的标记
How to ignore tokens in ply.yacc
我正在用 PLY 编写一个 JSON 配置(即 JSON 格式的配置文件)解释器。
我想忽略大量配置文件。我想忽略的某些部分包含我无法在文件的其他部分忽略的标记。
比如我想忽略:
"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'''
但是我 运行 遇到的问题是我不能只是 "IGNORE_BLOCK" 因为块有一个 'name' 并且我的词法分析器中有一个标记 'name':
def t_NAME_KEY(t): r'name'; return t
非常感谢任何帮助。
当你定义一个正则表达式规则函数时,你可以选择是否return这个标记。根据 returned 的内容,令牌将被忽略或考虑。例如:
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
您可以按照这些思路稍微构建一个规则,然后根据您的重要特征是否存在来选择是否 return 令牌。
此外,指定要忽略的标记作为字符串的一般约定是将 t_IGNORE_
附加到名称。
基于 OP 的编辑。忘掉代币化过程中的消除吧。相反,您可以做的是,在使用语法解析 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 '''
和
data = []
def p_FEATURE(p):
'''FEATURE : BLOCK_START DATA BLOCK_END FEATURE
| BLOCK_START DATA BLOCK_END'''
def p_DATA(p):
'''DATA : KEY COLON VALUE COMMA DATA
| KEY COLON VALUE ''' # and so on (have another function for values)
你现在可以做的是检查 p[2]
看看它是否重要。如果是,请将其添加到您的 data
变量中。否则,请忽略。
这只是一个粗略的想法。您仍然需要准确地弄清楚语法规则(例如,VALUE
也可能会导致另一个状态),并向 data
添加正确的块以及如何添加。但这是可能的。
我正在用 PLY 编写一个 JSON 配置(即 JSON 格式的配置文件)解释器。
我想忽略大量配置文件。我想忽略的某些部分包含我无法在文件的其他部分忽略的标记。
比如我想忽略:
"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'''
但是我 运行 遇到的问题是我不能只是 "IGNORE_BLOCK" 因为块有一个 'name' 并且我的词法分析器中有一个标记 'name':
def t_NAME_KEY(t): r'name'; return t
非常感谢任何帮助。
当你定义一个正则表达式规则函数时,你可以选择是否return这个标记。根据 returned 的内容,令牌将被忽略或考虑。例如:
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
您可以按照这些思路稍微构建一个规则,然后根据您的重要特征是否存在来选择是否 return 令牌。
此外,指定要忽略的标记作为字符串的一般约定是将 t_IGNORE_
附加到名称。
基于 OP 的编辑。忘掉代币化过程中的消除吧。相反,您可以做的是,在使用语法解析 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 '''
和
data = []
def p_FEATURE(p):
'''FEATURE : BLOCK_START DATA BLOCK_END FEATURE
| BLOCK_START DATA BLOCK_END'''
def p_DATA(p):
'''DATA : KEY COLON VALUE COMMA DATA
| KEY COLON VALUE ''' # and so on (have another function for values)
你现在可以做的是检查 p[2]
看看它是否重要。如果是,请将其添加到您的 data
变量中。否则,请忽略。
这只是一个粗略的想法。您仍然需要准确地弄清楚语法规则(例如,VALUE
也可能会导致另一个状态),并向 data
添加正确的块以及如何添加。但这是可能的。