如何使用运算符和括号解析组
How to parse groups with operator and brackets
首先我想说我刚刚开始使用 pyparsing
,我需要一些帮助来解决以下问题。所以这里是上下文:
我有一个包含文本行的文件。每行可以有一个 sequence
或者可以是一组与并发运算符 ||
组合的序列。表示可以是 (seq1)||(seq2)||...
等,也可以只是 seq1
.
序列seq_
是一组事件,以question
开始,后跟一个或多个答案,序列顺序由运算符所在行的答案顺序定义->
或 =>
介于两者之间。解释是系统读取该行应该执行 question
然后检查答案是否与行中定义的答案相同,按照定义的顺序,因此是序列。前面定义的一个line where several sequences 运行 concurrently 简单的说就是先执行每个sequence开头的问题,然后系统才会对每个问题的答案进行独立的检查(并发执行和检查)。
question
格式本身就是 qtn(elm,sub,num1[,num2,num3,...])
,其中 []
之间的内容是可选的,elm
和 sub
是名称,num_
是数字。
答案比较复杂,可以是以下之一:
ans(elma,acta,suba,num5[,num6,num7,...][elma.pr1=num8[,elma.pr2=num9]])[<timeout]
,意思是有些num_
是可选的,超时也是。
ans(elma,acta,suba,num5[,num6,num7,...])[<timeout] | prm(elma.pr1=num8[,elma.pr2=num9])
其中 |
运算符表示 OR
,这意味着一个答案 OR
另一个足以认为全局答案是正确的。
ans(elma,acta,suba,num5[,num6,num7,...])[<timeout] & prm(elma.pr1=num)
其中 &
运算符表示 AND
,这意味着需要两个答案才能认为全局答案正确。
- 当然答案可以是
|
和 &
运算符与 ()
混合的元素组合。例如,我们可以有 ans(elma,acta,suba,num5[,num6,num7,...])[<timeout] | (prm(elma.pr1=num8) & prm(elmb.pr2=num9))
或更复杂的东西,有或没有 ()
。没有运算符优先级,只有 ()
表示某种顺序。
所以我的想法是定义不同大元素的通用语法(我不确定这是最好的方法):
- 问题是:
qtn = Regex(r'qtn\([a-z0-9]+,[a-z]+(,[ex0-9_.]+)+\)')
- 一个简单的答案是:
ans = Combine(Regex(r'ans\([a-z0-9]+,[a-z]+(,[a-z0-9_.]+)+\)') + Regex('(<[0-9]+)*'))
也许最好分别定义什么是num
,什么是timeout
,什么是id,比如elma
,然后根据这些定义组成答案.在将 seq 的每个元素放入列表并将所有序列的列表放入一行后,我打算在代码的后面部分解释每个元素。
我现在卡住的地方是如何定义答案的一般语法,这很复杂,这样可以根据 ()
和 &
评估解析的输出和 |
运算符。我试图理解 fourFn.py
pyparsing 示例,但到目前为止我一无所知。
欢迎您提供任何帮助。
您的 Regex 和示例字符串是定义简单解析器的良好输入,通常以 BNF 的形式更正式一些,但这些已经足够了。这是您的简单 ans 格式的基本实现,您应该能够从这里概括出问题的样子:
import pyparsing as pp
LPAR, RPAR, COMMA, LT = map(pp.Suppress, "(),<")
element = pp.Word(pp.alphas.lower(), pp.alphanums.lower())
action = pp.Word(pp.alphas.lower())
subject = pp.Word(pp.alphas.lower())
number = pp.pyparsing_common.number()
timeout_expr = LT + number("timeout")
# put the pieces together into a larger expression
ans_expr = pp.Group(pp.Literal('ans')
+ LPAR
+ element('element')
+ COMMA
+ action('action')
+ COMMA
+ subject('subject')
+ COMMA
+ number('num*')
+ (COMMA + number('num*'))[...]
+ RPAR
+ pp.Optional(timeout_expr)
)
# use runTests to try it out, will also flag parse errors
ans_expr.runTests("""
ans(first, act, sub, 1000)
ans(first, act, sub, 1000, 2000)
ans(first, act, sub, 1000, 2000) < 50
# example of a parsing error
ans(first, act1, sub, 1000)
""")
将打印:
ans(first, act, sub, 1000)
[['ans', 'first', 'act', 'sub', 1000]]
[0]:
['ans', 'first', 'act', 'sub', 1000]
- action: 'act'
- element: 'first'
- num: [1000]
- subject: 'sub'
ans(first, act, sub, 1000, 2000)
[['ans', 'first', 'act', 'sub', 1000, 2000]]
[0]:
['ans', 'first', 'act', 'sub', 1000, 2000]
- action: 'act'
- element: 'first'
- num: [1000, 2000]
- subject: 'sub'
ans(first, act, sub, 1000, 2000) < 50
[['ans', 'first', 'act', 'sub', 1000, 2000, 50]]
[0]:
['ans', 'first', 'act', 'sub', 1000, 2000, 50]
- action: 'act'
- element: 'first'
- num: [1000, 2000]
- subject: 'sub'
- timeout: 50
# example of a parsing error
ans(first, act1, sub, 1000)
^
FAIL: Expected ',', found '1' (at char 14), (line:1, col:15)
注意使用结果名称来帮助您按名称访问结果,这将使您的解析器更易于维护和使用。
首先我想说我刚刚开始使用 pyparsing
,我需要一些帮助来解决以下问题。所以这里是上下文:
我有一个包含文本行的文件。每行可以有一个 sequence
或者可以是一组与并发运算符 ||
组合的序列。表示可以是 (seq1)||(seq2)||...
等,也可以只是 seq1
.
序列seq_
是一组事件,以question
开始,后跟一个或多个答案,序列顺序由运算符所在行的答案顺序定义->
或 =>
介于两者之间。解释是系统读取该行应该执行 question
然后检查答案是否与行中定义的答案相同,按照定义的顺序,因此是序列。前面定义的一个line where several sequences 运行 concurrently 简单的说就是先执行每个sequence开头的问题,然后系统才会对每个问题的答案进行独立的检查(并发执行和检查)。
question
格式本身就是 qtn(elm,sub,num1[,num2,num3,...])
,其中 []
之间的内容是可选的,elm
和 sub
是名称,num_
是数字。
答案比较复杂,可以是以下之一:
ans(elma,acta,suba,num5[,num6,num7,...][elma.pr1=num8[,elma.pr2=num9]])[<timeout]
,意思是有些num_
是可选的,超时也是。ans(elma,acta,suba,num5[,num6,num7,...])[<timeout] | prm(elma.pr1=num8[,elma.pr2=num9])
其中|
运算符表示OR
,这意味着一个答案OR
另一个足以认为全局答案是正确的。ans(elma,acta,suba,num5[,num6,num7,...])[<timeout] & prm(elma.pr1=num)
其中&
运算符表示AND
,这意味着需要两个答案才能认为全局答案正确。- 当然答案可以是
|
和&
运算符与()
混合的元素组合。例如,我们可以有ans(elma,acta,suba,num5[,num6,num7,...])[<timeout] | (prm(elma.pr1=num8) & prm(elmb.pr2=num9))
或更复杂的东西,有或没有()
。没有运算符优先级,只有()
表示某种顺序。
所以我的想法是定义不同大元素的通用语法(我不确定这是最好的方法):
- 问题是:
qtn = Regex(r'qtn\([a-z0-9]+,[a-z]+(,[ex0-9_.]+)+\)')
- 一个简单的答案是:
ans = Combine(Regex(r'ans\([a-z0-9]+,[a-z]+(,[a-z0-9_.]+)+\)') + Regex('(<[0-9]+)*'))
也许最好分别定义什么是num
,什么是timeout
,什么是id,比如elma
,然后根据这些定义组成答案.在将 seq 的每个元素放入列表并将所有序列的列表放入一行后,我打算在代码的后面部分解释每个元素。
我现在卡住的地方是如何定义答案的一般语法,这很复杂,这样可以根据 ()
和 &
评估解析的输出和 |
运算符。我试图理解 fourFn.py
pyparsing 示例,但到目前为止我一无所知。
欢迎您提供任何帮助。
您的 Regex 和示例字符串是定义简单解析器的良好输入,通常以 BNF 的形式更正式一些,但这些已经足够了。这是您的简单 ans 格式的基本实现,您应该能够从这里概括出问题的样子:
import pyparsing as pp
LPAR, RPAR, COMMA, LT = map(pp.Suppress, "(),<")
element = pp.Word(pp.alphas.lower(), pp.alphanums.lower())
action = pp.Word(pp.alphas.lower())
subject = pp.Word(pp.alphas.lower())
number = pp.pyparsing_common.number()
timeout_expr = LT + number("timeout")
# put the pieces together into a larger expression
ans_expr = pp.Group(pp.Literal('ans')
+ LPAR
+ element('element')
+ COMMA
+ action('action')
+ COMMA
+ subject('subject')
+ COMMA
+ number('num*')
+ (COMMA + number('num*'))[...]
+ RPAR
+ pp.Optional(timeout_expr)
)
# use runTests to try it out, will also flag parse errors
ans_expr.runTests("""
ans(first, act, sub, 1000)
ans(first, act, sub, 1000, 2000)
ans(first, act, sub, 1000, 2000) < 50
# example of a parsing error
ans(first, act1, sub, 1000)
""")
将打印:
ans(first, act, sub, 1000)
[['ans', 'first', 'act', 'sub', 1000]]
[0]:
['ans', 'first', 'act', 'sub', 1000]
- action: 'act'
- element: 'first'
- num: [1000]
- subject: 'sub'
ans(first, act, sub, 1000, 2000)
[['ans', 'first', 'act', 'sub', 1000, 2000]]
[0]:
['ans', 'first', 'act', 'sub', 1000, 2000]
- action: 'act'
- element: 'first'
- num: [1000, 2000]
- subject: 'sub'
ans(first, act, sub, 1000, 2000) < 50
[['ans', 'first', 'act', 'sub', 1000, 2000, 50]]
[0]:
['ans', 'first', 'act', 'sub', 1000, 2000, 50]
- action: 'act'
- element: 'first'
- num: [1000, 2000]
- subject: 'sub'
- timeout: 50
# example of a parsing error
ans(first, act1, sub, 1000)
^
FAIL: Expected ',', found '1' (at char 14), (line:1, col:15)
注意使用结果名称来帮助您按名称访问结果,这将使您的解析器更易于维护和使用。