pyparsing nestedExpr 和双结束字符
pyparsing nestedExpr and double closing characters
我正在尝试解析嵌套的列类型定义,例如
1 string
2 struct<col_1:string,col_2:int>
3 row(col_1 string,array(col_2 string),col_3 boolean)
4 array<struct<col_1:string,col_2:int>,col_3:boolean>
5 array<struct<col_1:string,col2:int>>
使用 nestedExpr 在情况 1-4 中按预期工作,但在情况 5 上会抛出解析错误。在双右括号之间添加 space,如“> >”似乎可行,并且可能由此解释引自作者。
By default, nestedExpr will look for space-delimited words of printables
https://sourceforge.net/p/pyparsing/bugs/107/
我主要是在寻找预处理和 post 处理输入字符串的替代方法
type_str = type_str.replace(">", "> ")
# parse string here
type_str = type_str.replace("> ", ">")
我试过使用 infix_notation 但我一直无法弄清楚在这种情况下如何使用它。我可能只是用错了方法...
代码片段
array_keyword = pp.Keyword('array')
row_keyword = pp.Keyword('row')
struct_keyword = pp.Keyword('struct')
nest_open = pp.Word('<([')
nest_close = pp.Word('>)]')
col_name = pp.Word(pp.alphanums + '_')
col_type = pp.Forward()
col_type_delimiter = pp.Word(':') | pp.White(' ')
column = col_name('name') + col_type_delimiter + col_type('type')
col_list = pp.delimitedList(pp.Group(column))
struct_type = pp.nestedExpr(
opener=struct_keyword + nest_open, closer=nest_close, content=col_list | col_type, ignoreExpr=None
)
row_type = pp.locatedExpr(pp.nestedExpr(
opener=row_keyword + nest_open, closer=nest_close, content=col_list | col_type, ignoreExpr=None
))
array_type = pp.nestedExpr(
opener=array_keyword + nest_open, closer=nest_close, content=col_type, ignoreExpr=None
)
col_type <<= struct_type('children') | array_type('children') | row_type('children') | scalar_type('type')
nestedExpr
和 infixNotation
不太适合这个项目。 nestedExpr
通常是您不想深入分析的内容的快捷表达式,您只想检测并跨过一些恰好在开始和结束标点符号中嵌套的文本块。 infixNotation
用于解析带有一元和二元运算符的表达式,通常是某种算术。您可能 能够将语法中的标点符号视为运算符,但这是一种延伸,并且肯定是用困难的方式来做事。
对于你的项目,你确实需要定义不同的元素,这将是一个递归语法(因为数组和结构类型本身将根据其他类型定义,也可以是数组或结构).
我尝试了一个 BNF,用于使用标量类型 int
、float
、boolean
和 string
以及复合类型的语法子集array
和 struct
,只有“<”和“>”嵌套标点符号。数组将采用单个类型参数,以定义数组中元素的类型。一个结构将采用一个或多个结构字段,其中每个字段是一对 identifier:type
。
scalar_type ::= 'int' | 'float' | 'string' | 'boolean'
array_type ::= 'array' '<' type_defn '>'
struct_type ::= 'struct' '<' struct_element (',' struct_element)... '>'
struct_element ::= identifier ':' type_defn
type_defn ::= scalar_type | array_type | struct_type
(如果您稍后还想添加行定义,请考虑该行应该是什么样子,以及它的元素将如何定义,然后将其添加到此 BNF。)
你看起来对 pyparsing 的基础知识很熟悉,所以我先从一些介绍开始,然后让你填写其余部分。
# define punctuation
LT, GT, COLON = map(pp.Suppress, "<>:")
ARRAY = pp.Keyword('array')
STRUCT = pp.Keyword('struct')
# create a Forward that will be used in other type expressions
type_defn = pp.Forward()
# here is the array type, you can fill in the other types following this model
# and the definitions in the BNF
array_type = pp.Group(ARRAY + LT + type_defn + GT)
...
# then finally define type_defn in terms of the other type expressions
type_defn <<= scalar_type | array_type | struct_type
完成后,进行一些测试:
type_defn.runTests("""\
string
struct<col_1:string,col_2:int>
array<struct<col_1:string,col2:int>>
""", fullDump=False)
你应该得到类似的东西:
string
['string']
struct<col_1:string,col_2:int>
['struct', [['col_1', 'string'], ['col_2', 'int']]]
array<struct<col_1:string,col2:int>>
['array', ['struct', [['col_1', 'string'], ['col2', 'int']]]]>
一旦你有了它,你就可以尝试将它扩展到其他类型,例如你的行类型,可能是联合,或者采用多种类型的数组(如果这是你发布的示例中的意图)。始终从更新 BNF 开始 - 然后您需要在代码中进行的更改通常会随之而来。
我正在尝试解析嵌套的列类型定义,例如
1 string
2 struct<col_1:string,col_2:int>
3 row(col_1 string,array(col_2 string),col_3 boolean)
4 array<struct<col_1:string,col_2:int>,col_3:boolean>
5 array<struct<col_1:string,col2:int>>
使用 nestedExpr 在情况 1-4 中按预期工作,但在情况 5 上会抛出解析错误。在双右括号之间添加 space,如“> >”似乎可行,并且可能由此解释引自作者。
By default, nestedExpr will look for space-delimited words of printables https://sourceforge.net/p/pyparsing/bugs/107/
我主要是在寻找预处理和 post 处理输入字符串的替代方法
type_str = type_str.replace(">", "> ")
# parse string here
type_str = type_str.replace("> ", ">")
我试过使用 infix_notation 但我一直无法弄清楚在这种情况下如何使用它。我可能只是用错了方法...
代码片段
array_keyword = pp.Keyword('array')
row_keyword = pp.Keyword('row')
struct_keyword = pp.Keyword('struct')
nest_open = pp.Word('<([')
nest_close = pp.Word('>)]')
col_name = pp.Word(pp.alphanums + '_')
col_type = pp.Forward()
col_type_delimiter = pp.Word(':') | pp.White(' ')
column = col_name('name') + col_type_delimiter + col_type('type')
col_list = pp.delimitedList(pp.Group(column))
struct_type = pp.nestedExpr(
opener=struct_keyword + nest_open, closer=nest_close, content=col_list | col_type, ignoreExpr=None
)
row_type = pp.locatedExpr(pp.nestedExpr(
opener=row_keyword + nest_open, closer=nest_close, content=col_list | col_type, ignoreExpr=None
))
array_type = pp.nestedExpr(
opener=array_keyword + nest_open, closer=nest_close, content=col_type, ignoreExpr=None
)
col_type <<= struct_type('children') | array_type('children') | row_type('children') | scalar_type('type')
nestedExpr
和 infixNotation
不太适合这个项目。 nestedExpr
通常是您不想深入分析的内容的快捷表达式,您只想检测并跨过一些恰好在开始和结束标点符号中嵌套的文本块。 infixNotation
用于解析带有一元和二元运算符的表达式,通常是某种算术。您可能 能够将语法中的标点符号视为运算符,但这是一种延伸,并且肯定是用困难的方式来做事。
对于你的项目,你确实需要定义不同的元素,这将是一个递归语法(因为数组和结构类型本身将根据其他类型定义,也可以是数组或结构).
我尝试了一个 BNF,用于使用标量类型 int
、float
、boolean
和 string
以及复合类型的语法子集array
和 struct
,只有“<”和“>”嵌套标点符号。数组将采用单个类型参数,以定义数组中元素的类型。一个结构将采用一个或多个结构字段,其中每个字段是一对 identifier:type
。
scalar_type ::= 'int' | 'float' | 'string' | 'boolean'
array_type ::= 'array' '<' type_defn '>'
struct_type ::= 'struct' '<' struct_element (',' struct_element)... '>'
struct_element ::= identifier ':' type_defn
type_defn ::= scalar_type | array_type | struct_type
(如果您稍后还想添加行定义,请考虑该行应该是什么样子,以及它的元素将如何定义,然后将其添加到此 BNF。)
你看起来对 pyparsing 的基础知识很熟悉,所以我先从一些介绍开始,然后让你填写其余部分。
# define punctuation
LT, GT, COLON = map(pp.Suppress, "<>:")
ARRAY = pp.Keyword('array')
STRUCT = pp.Keyword('struct')
# create a Forward that will be used in other type expressions
type_defn = pp.Forward()
# here is the array type, you can fill in the other types following this model
# and the definitions in the BNF
array_type = pp.Group(ARRAY + LT + type_defn + GT)
...
# then finally define type_defn in terms of the other type expressions
type_defn <<= scalar_type | array_type | struct_type
完成后,进行一些测试:
type_defn.runTests("""\
string
struct<col_1:string,col_2:int>
array<struct<col_1:string,col2:int>>
""", fullDump=False)
你应该得到类似的东西:
string
['string']
struct<col_1:string,col_2:int>
['struct', [['col_1', 'string'], ['col_2', 'int']]]
array<struct<col_1:string,col2:int>>
['array', ['struct', [['col_1', 'string'], ['col2', 'int']]]]>
一旦你有了它,你就可以尝试将它扩展到其他类型,例如你的行类型,可能是联合,或者采用多种类型的数组(如果这是你发布的示例中的意图)。始终从更新 BNF 开始 - 然后您需要在代码中进行的更改通常会随之而来。