如何基于给定的正则表达式构造CFG

时间:2014-05-03 19:13:12

标签: regex algorithm context-free-grammar

我试图弄清楚如何基于给定的正则表达式构造CFG(无上下文语法)。 例如,a(ab)*(a | b) 我认为有一个算法可以通过,但它确实令人困惑。 这是我到目前为止所得到的:

    S->aAB; 
    A->aAb|empty;
    B->a|b;

这看起来不错吗? 任何帮助将不胜感激。

2 个答案:

答案 0 :(得分:3)

分为三个部分构建CFG,每个部分适用于a(ab)*(a|b)

对于(a|b),您的B -> a | b是正确的。

(ab)*表示abababababab等字符串。所以A -> abA | empty将是正确的制作。

因此,完整的语法变为:

S -> aAB
A -> abA | empty
B -> a | b

注意:A -> aAb | empty会派生出abaabbaaabbb等字符串,而不是regular language,并且不可能代表regular expression

答案 1 :(得分:3)

为给定的正则表达式构造无上下文语法的另一种方法是:

  1. 构造一个有限状态机,它接受与正则表达式相同的语言。
  2. 创建一个语法,其终端是正则表达式的字母表,其非终端是(或对应于1:1)状态机中的状态,并且具有{{1}形式的规则对于终端符号t上从状态X到状态Y的每个状态机转换。如果您的CFG表示法允许,则每个最终状态F都会获得X -> t Y形式的规则。如果您的CFG表示法不允许这样的规则,那么对于从终端t的状态X到最终状态F的每次转换,产生规则F -> epsilon(除了已经描述的规则X -> t之外)。结果是一个常规语法,一个无上下文的语法,遵循每个右侧最多有一个非终端的额外约束。
  3. 对于给出的示例,假设我们构造了以下FSA(许多接受与正则表达式相同的语言):

    FSA for language <code>a(ab)*(a|b)</code>

    由此可以直接推导出以下常规语法:

    X -> t F

    或者,如果我们不想要具有空右侧的规则,请删除该语法的最后三个规则并添加:

    S -> a A1
    A1 -> a A2
    A2 -> b B3
    B3 -> a A2
    B3 -> a A4
    B3 -> b B5
    A1 -> a A4
    A1 -> b B5
    A4 -> epsilon
    B5 -> epsilon
    epsilon -> 
    

    与其他方法相比,这种方法的缺点是结果语法比它需要的更冗长,并且推导可以完全机械化的优点,这意味着它更容易正确而不必刻意思考。