【问题标题】:Algorithm to generate finite language from non-recursive context-free grammar从非递归上下文无关文法生成有限语言的算法
【发布时间】:2017-02-20 14:59:54
【问题描述】:

我正在搜索一种算法,以从非递归上下文无关文法生成完整的有限语言。该应用程序是为测试自动化生成一组可能的场景。

EBNF中的示例语法(S是开始规则):

S = Sender, Receiver;
Sender = Human | Machine;
Human = "user-type-1" | "user-type-2"
Machine = Access, Protocol;
Access = "internal" | "external";
Protocol = "soap" | "smtp";
Receiver = "local" | "remote";

应该产生一组句子,如:

user-type-1 local
internal soap local
external smtp remote

到目前为止,我发现的示例和文献涉及基于递归语法的示例随机生成。但我的问题更简单。 欢迎提供所有提示、名称或出版物链接。

谢谢,

S.

【问题讨论】:

  • 所以你基本上想要右手边集合的笛卡尔积? en.wikipedia.org/wiki/Cartesian_product
  • 你可以通过简单的递归方法生成所有句子。顺便说一句,你都试过什么?

标签: algorithm testing grammar


【解决方案1】:

一种方法是在编程语言中定义语法,然后编写代码来迭代所有可能性。您的语法是使用变量和三个结构指定的:lit(x) 表示像 "local"alt(a, b, c, ...) 之类的文字,表示选择 abc、...和seq(a, b, ..., z) 表示来自a 的一件事的序列,与来自b 的一件事连接等等。

这是你的语法格式。

Protocol = alt(lit("soap"), lit("smtp"))
Receiver = alt(lit("local"), lit("remote"))
Access = alt(lit("internal"), lit("external"))
Human = alt(lit("user-type-1"), lit("user-type-2"))
Machine = seq(Access, Protocol)
Sender = alt(Human, Machine)
S = seq(Sender, Receiver)

这里有一些完整的 (Python) 代码,这些代码使用精心挑选的 altseqlit 定义,使每个生产规则成为生成所有可能性的函数:

import itertools

def seq(*xs):
    def r():
        for f in itertools.product(*[x() for x in xs]):
            yield ' '.join(f)
    return r

def alt(*xs):
    def r():
        for x in xs:
            for f in x():
                yield f
    return r

def lit(x):
    def r():
        yield x
    return r

Protocol = alt(lit("soap"), lit("smtp"))
Receiver = alt(lit("local"), lit("remote"))
Access = alt(lit("internal"), lit("external"))
Human = alt(lit("user-type-1"), lit("user-type-2"))
Machine = seq(Access, Protocol)
Sender = alt(Human, Machine)
S = seq(Sender, Receiver)

for s in S():
    print s

【讨论】:

    【解决方案2】:

    您可以递归地生成一棵树,其分支将根据语法规则表示派生,其叶子将表示语法语言中的单词。恢复整个有限语言就像在生成叶子时保存叶子一样简单。

    将每个节点表示为符号(终结符或非终结符)的有序集合。对于每个非终结符,递归地下降到一组新的节点,在那里进行所有可能的替换。继续,直到您的列表仅包含终端符号,然后输出与您的节点对应的符号的有序连接。您的初始节点将始终为[S]。示例:

    S = Sender, Receiver;
    Sender = Human | Machine;
    Human = "user-type-1" | "user-type-2"
    Machine = Access, Protocol;
    Access = "internal" | "external";
    Protocol = "soap" | "smtp";
    Receiver = "local" | "remote";
    
    [S]
     [Sender, ",", Receiver]
      [Human, ",", Receiver]
       ["user-type-1", ",", Receiver]
        ["user-type-1", ",", "local"]   ***
        ["user-type-1", ",", "remote"]  ***
       ["user-type-2", ",", Receiver]
        ["user-type-2", ",", "local"]   ***
        ["user-type-2", ",", "remote"]  ***
      [Machine, ",", Receiver]
       [Access, ",", Protocol, ",", Receiver]
        ["internal", ",", Protocol, ",", Receiver]
         ["internal", ",", "soap", ",", Receiver]
          ["internal", ",", "soap", ",", "local"]   ***
          ["internal", ",", "soap", ",", "remote"]  ***
         ["internal", ",", "smtp", ",", Receiver]
          ["internal", ",", "smtp", ",", "local"]   ***
          ["internal", ",", "smtp", ",", "remote"]  ***
        ["external", ",", Protocol, ",", Receiver]
         ["external", ",", "soap", ",", Receiver]
          ["external", ",", "soap", ",", "local"]   ***
          ["external", ",", "soap", ",", "remote"]  ***
         ["external", ",", "smtp", ",", Receiver]
          ["external", ",", "smtp", ",", "local"]   ***
          ["external", ",", "smtp", ",", "remote"]  ***
    

    【讨论】:

      猜你喜欢
      • 2017-09-01
      • 1970-01-01
      • 2019-04-12
      • 2016-01-23
      • 2011-03-04
      • 1970-01-01
      • 2018-03-29
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多