【问题标题】:Generate Expressions from Grammar从语法生成表达式
【发布时间】:2021-08-16 13:31:00
【问题描述】:

我正在创建一个简单的(无上下文的)语法,比如这个:

E -> E + E
E -> E * E
E -> 0
E -> 1

出于测试目的,我想从这个语法生成所有表达式,直到一定深度。例如:

# depth 0:
0
1
# depth 1:
0 + 0
0 + 1
1 + 0
1 + 1
0 * 0
0 * 1
1 * 0
1 * 1
# depth 2:
(0 + 0) + 0
...
1 * (1 + 1)
...
(1 + 1) * (1 + 1)
...

在 Python 中实现这一目标的最简单方法是什么?也许我可以使用现有的解析库(例如 ANTLR、PLY、Lark)来帮助解决这个问题?

我找到了this similar question,但它指的语法比我的更简单。

【问题讨论】:

  • 您是否尝试过将每个中间步骤的每个可能转换排队的简单方法?例如,从 (E) 的队列开始,然后入队 (E+E, E*E, 1, 0),然后出队 E+E,入队 (E+E+E, E*E+E, E+E*E, 1+E, 0+E, E+0, E+1),永远重复?
  • 最简单的方法就是使用库。我建议你这样做,特别是如果你打算稍后复杂化你的语法。
  • @Welbog 如果我找不到适合我的任务的库,这是个好主意,谢谢!
  • @Lenormju 我也是这么想的,但是我在任何解析库中都没有找到这个功能(也许我没有使用正确的搜索词)。

标签: python context-free-grammar


【解决方案1】:

您可以使用递归生成器函数:

import re, itertools as it
s = """
E -> E + E
E -> E * E
E -> 0
E -> 1
"""
g = [((k:=re.findall('\w+|[\*\+]', i))[0], k[1:]) for i in s.split('\n') if i]
o = {a for a, _ in g}
def get_expr(d, s = None):
   if not d:
      for a, b in g:
         if all(i not in o for i in b) and (s is None or a in s):
            yield ' '.join(b)
   else:
      for a, b in g:
         if s is None or a in s:
            r = [[i] if i not in o else get_expr(d-1, s=(s or [])+[i]) for i in b]           
            yield from it.product(*r)

for i in range(3):
   print(list(get_expr(i)))

输出:

['0', '1']
[('0', '+', '0'), ('0', '+', '1'), ('1', '+', '0'), ('1', '+', '1'), ('0', '*', '0'), ('0', '*', '1'), ('1', '*', '0'), ('1', '*', '1'), ('0',), ('1',)]
[(('0', '+', '0'), '+', ('0', '+', '0')), (('0', '+', '0'), '+', ('0', '+', '1')), (('0', '+', '0'), '+', ('1', '+', '0')), (('0', '+', '0'), '+', ('1', '+', '1')), (('0', '+', '0'), '+', ('0', '*', '0')), (('0', '+', '0'), '+', ('0', '*', '1')), (('0', '+', '0'), '+', ('1', '*', '0')), (('0', '+', '0'), '+', ('1', '*', '1')), (('0', '+', '0'), '+', ('0',)), (('0', '+', '0'), '+', ('1',)), (('0', '+', '1'), '+', ('0', '+', '0')), (('0', '+', '1'), '+', ('0', '+', '1')), (('0', '+', '1'), '+', ('1', '+', '0')), (('0', '+', '1'), '+', ('1', '+', '1')), (('0', '+', '1'), '+', ('0', '*', '0')), (('0', '+', '1'), '+', ('0', '*', '1')), (('0', '+', '1'), '+', ('1', '*', '0')), (('0', '+', '1'), '+', ('1', '*', '1')), (('0', '+', '1'), '+', ('0',)), (('0', '+', '1'), '+', ('1',)), (('1', '+', '0'), '+', ('0', '+', '0')), (('1', '+', '0'), '+', ('0', '+', '1')), (('1', '+', '0'), '+', ('1', '+', '0')), (('1', '+', '0'), '+', ('1', '+', '1')), (('1', '+', '0'), '+', ('0', '*', '0')), (('1', '+', '0'), '+', ('0', '*', '1')), (('1', '+', '0'), '+', ('1', '*', '0')), (('1', '+', '0'), '+', ('1', '*', '1')), (('1', '+', '0'), '+', ('0',)), (('1', '+', '0'), '+', ('1',)), (('1', '+', '1'), '+', ('0', '+', '0')), (('1', '+', '1'), '+', ('0', '+', '1')), (('1', '+', '1'), '+', ('1', '+', '0')), (('1', '+', '1'), '+', ('1', '+', '1')), (('1', '+', '1'), '+', ('0', '*', '0')), (('1', '+', '1'), '+', ('0', '*', '1')), (('1', '+', '1'), '+', ('1', '*', '0')), (('1', '+', '1'), '+', ('1', '*', '1')), (('1', '+', '1'), '+', ('0',)), (('1', '+', '1'), '+', ('1',)), (('0', '*', '0'), '+', ('0', '+', '0')), (('0', '*', '0'), '+', ('0', '+', '1')), (('0', '*', '0'), '+', ('1', '+', '0')), (('0', '*', '0'), '+', ('1', '+', '1')), (('0', '*', '0'), '+', ('0', '*', '0')), (('0', '*', '0'), '+', ('0', '*', '1')), (('0', '*', '0'), '+', ('1', '*', '0')), (('0', '*', '0'), '+', ('1', '*', '1')), (('0', '*', '0'), '+', ('0',)), (('0', '*', '0'), '+', ('1',)), (('0', '*', '1'), '+', ('0', '+', '0')), (('0', '*', '1'), '+', ('0', '+', '1')), (('0', '*', '1'), '+', ('1', '+', '0')), (('0', '*', '1'), '+', ('1', '+', '1')), (('0', '*', '1'), '+', ('0', '*', '0')), (('0', '*', '1'), '+', ('0', '*', '1')), (('0', '*', '1'), '+', ('1', '*', '0')), (('0', '*', '1'), '+', ('1', '*', '1')), (('0', '*', '1'), '+', ('0',)), (('0', '*', '1'), '+', ('1',)), (('1', '*', '0'), '+', ('0', '+', '0')), (('1', '*', '0'), '+', ('0', '+', '1')), (('1', '*', '0'), '+', ('1', '+', '0')), (('1', '*', '0'), '+', ('1', '+', '1')), (('1', '*', '0'), '+', ('0', '*', '0')), (('1', '*', '0'), '+', ('0', '*', '1')), (('1', '*', '0'), '+', ('1', '*', '0')), (('1', '*', '0'), '+', ('1', '*', '1')), (('1', '*', '0'), '+', ('0',)), (('1', '*', '0'), '+', ('1',)), (('1', '*', '1'), '+', ('0', '+', '0')), (('1', '*', '1'), '+', ('0', '+', '1')), (('1', '*', '1'), '+', ('1', '+', '0')), (('1', '*', '1'), '+', ('1', '+', '1')), (('1', '*', '1'), '+', ('0', '*', '0')), (('1', '*', '1'), '+', ('0', '*', '1')), (('1', '*', '1'), '+', ('1', '*', '0')), (('1', '*', '1'), '+', ('1', '*', '1')), (('1', '*', '1'), '+', ('0',)), (('1', '*', '1'), '+', ('1',)), (('0',), '+', ('0', '+', '0')), (('0',), '+', ('0', '+', '1')), (('0',), '+', ('1', '+', '0')), (('0',), '+', ('1', '+', '1')), (('0',), '+', ('0', '*', '0')), (('0',), '+', ('0', '*', '1')), (('0',), '+', ('1', '*', '0')), (('0',), '+', ('1', '*', '1')), (('0',), '+', ('0',)), (('0',), '+', ('1',)), (('1',), '+', ('0', '+', '0')), (('1',), '+', ('0', '+', '1')), (('1',), '+', ('1', '+', '0')), (('1',), '+', ('1', '+', '1')), (('1',), '+', ('0', '*', '0')), (('1',), '+', ('0', '*', '1')), (('1',), '+', ('1', '*', '0')), (('1',), '+', ('1', '*', '1')), (('1',), '+', ('0',)), (('1',), '+', ('1',)), (('0', '+', '0'), '*', ('0', '+', '0')), (('0', '+', '0'), '*', ('0', '+', '1')), (('0', '+', '0'), '*', ('1', '+', '0')), (('0', '+', '0'), '*', ('1', '+', '1')), (('0', '+', '0'), '*', ('0', '*', '0')), (('0', '+', '0'), '*', ('0', '*', '1')), (('0', '+', '0'), '*', ('1', '*', '0')), (('0', '+', '0'), '*', ('1', '*', '1')), (('0', '+', '0'), '*', ('0',)), (('0', '+', '0'), '*', ('1',)), (('0', '+', '1'), '*', ('0', '+', '0')), (('0', '+', '1'), '*', ('0', '+', '1')), (('0', '+', '1'), '*', ('1', '+', '0')), (('0', '+', '1'), '*', ('1', '+', '1')), (('0', '+', '1'), '*', ('0', '*', '0')), (('0', '+', '1'), '*', ('0', '*', '1')), (('0', '+', '1'), '*', ('1', '*', '0')), (('0', '+', '1'), '*', ('1', '*', '1')), (('0', '+', '1'), '*', ('0',)), (('0', '+', '1'), '*', ('1',)), (('1', '+', '0'), '*', ('0', '+', '0')), (('1', '+', '0'), '*', ('0', '+', '1')), (('1', '+', '0'), '*', ('1', '+', '0')), (('1', '+', '0'), '*', ('1', '+', '1')), (('1', '+', '0'), '*', ('0', '*', '0')), (('1', '+', '0'), '*', ('0', '*', '1')), (('1', '+', '0'), '*', ('1', '*', '0')), (('1', '+', '0'), '*', ('1', '*', '1')), (('1', '+', '0'), '*', ('0',)), (('1', '+', '0'), '*', ('1',)), (('1', '+', '1'), '*', ('0', '+', '0')), (('1', '+', '1'), '*', ('0', '+', '1')), (('1', '+', '1'), '*', ('1', '+', '0')), (('1', '+', '1'), '*', ('1', '+', '1')), (('1', '+', '1'), '*', ('0', '*', '0')), (('1', '+', '1'), '*', ('0', '*', '1')), (('1', '+', '1'), '*', ('1', '*', '0')), (('1', '+', '1'), '*', ('1', '*', '1')), (('1', '+', '1'), '*', ('0',)), (('1', '+', '1'), '*', ('1',)), (('0', '*', '0'), '*', ('0', '+', '0')), (('0', '*', '0'), '*', ('0', '+', '1')), (('0', '*', '0'), '*', ('1', '+', '0')), (('0', '*', '0'), '*', ('1', '+', '1')), (('0', '*', '0'), '*', ('0', '*', '0')), (('0', '*', '0'), '*', ('0', '*', '1')), (('0', '*', '0'), '*', ('1', '*', '0')), (('0', '*', '0'), '*', ('1', '*', '1')), (('0', '*', '0'), '*', ('0',)), (('0', '*', '0'), '*', ('1',)), (('0', '*', '1'), '*', ('0', '+', '0')), (('0', '*', '1'), '*', ('0', '+', '1')), (('0', '*', '1'), '*', ('1', '+', '0')), (('0', '*', '1'), '*', ('1', '+', '1')), (('0', '*', '1'), '*', ('0', '*', '0')), (('0', '*', '1'), '*', ('0', '*', '1')), (('0', '*', '1'), '*', ('1', '*', '0')), (('0', '*', '1'), '*', ('1', '*', '1')), (('0', '*', '1'), '*', ('0',)), (('0', '*', '1'), '*', ('1',)), (('1', '*', '0'), '*', ('0', '+', '0')), (('1', '*', '0'), '*', ('0', '+', '1')), (('1', '*', '0'), '*', ('1', '+', '0')), (('1', '*', '0'), '*', ('1', '+', '1')), (('1', '*', '0'), '*', ('0', '*', '0')), (('1', '*', '0'), '*', ('0', '*', '1')), (('1', '*', '0'), '*', ('1', '*', '0')), (('1', '*', '0'), '*', ('1', '*', '1')), (('1', '*', '0'), '*', ('0',)), (('1', '*', '0'), '*', ('1',)), (('1', '*', '1'), '*', ('0', '+', '0')), (('1', '*', '1'), '*', ('0', '+', '1')), (('1', '*', '1'), '*', ('1', '+', '0')), (('1', '*', '1'), '*', ('1', '+', '1')), (('1', '*', '1'), '*', ('0', '*', '0')), (('1', '*', '1'), '*', ('0', '*', '1')), (('1', '*', '1'), '*', ('1', '*', '0')), (('1', '*', '1'), '*', ('1', '*', '1')), (('1', '*', '1'), '*', ('0',)), (('1', '*', '1'), '*', ('1',)), (('0',), '*', ('0', '+', '0')), (('0',), '*', ('0', '+', '1')), (('0',), '*', ('1', '+', '0')), (('0',), '*', ('1', '+', '1')), (('0',), '*', ('0', '*', '0')), (('0',), '*', ('0', '*', '1')), (('0',), '*', ('1', '*', '0')), (('0',), '*', ('1', '*', '1')), (('0',), '*', ('0',)), (('0',), '*', ('1',)), (('1',), '*', ('0', '+', '0')), (('1',), '*', ('0', '+', '1')), (('1',), '*', ('1', '+', '0')), (('1',), '*', ('1', '+', '1')), (('1',), '*', ('0', '*', '0')), (('1',), '*', ('0', '*', '1')), (('1',), '*', ('1', '*', '0')), (('1',), '*', ('1', '*', '1')), (('1',), '*', ('0',)), (('1',), '*', ('1',)), ('0',), ('1',)]

【讨论】:

    猜你喜欢
    • 2019-07-15
    • 2021-01-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-12-24
    • 2014-10-19
    • 2022-01-14
    • 1970-01-01
    相关资源
    最近更新 更多