如何在ply.yacc

时间:2017-06-21 19:21:49

标签: python json yacc lex ply

我正在用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字段的某些元素,并且我希望将值字段标记化,以便我可以使用它。实际上,如果它位于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

非常感谢任何帮助。

1 个答案:

答案 0 :(得分:2)

定义正则表达式规则函数时,可以选择是否返回令牌。根据返回的内容,将忽略或考虑令牌。例如:

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_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以及如何。但这是有可能的。