如何忽略 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 添加正确的块以及如何添加。但这是可能的。