我很难弄清楚从哪个问题开始。问题是为字母{ ‘a’, ‘b’, ‘c’, ‘d’, ‘|’, ‘*’, ‘(‘, ‘)’ }
的正则表达式语言创建语法。假设输入1行(单个字符串)且没有空格。空字符串无效,它应该正确捕获运算符的优先级,从最低到最高的是union('|'),concatenation和kleene('*
')。开始为此编写语法的最佳方法是什么?任何意见都将不胜感激。
不寻找答案,只是不确定如何开始。到目前为止,我有类似的东西:
S -> S'('S')'S
| A
A -> AA
| A'*'
| T
T -> T'|'T
| X
X -> 'a'
| 'b'
| 'c'
| 'd'
但我不确定我是否走在正确的轨道上。
编辑:做了一些工作后,这是我达成的结论:START -> EXPRESSION
EXPRESSION -> EXPRESSION'|'EXPRESSION
EXPRESSION -> PARENTHETICAL'*'
EXPRESSION -> PARENTHETICAL
EXPRESSION -> EXPRESSION PARENTHETICAL
EXPRESSION -> PARENTHETICAL EXPRESSION
EXPRESSION -> EXPRESSION PARENTHETICAL EXPRESSION
EXPRESSION -> REPEAT
PARENTHETICAL -> PARENTHETICAL'*'
PARENTHETICAL -> '('EXPRESSION')'
REPEAT -> REPEAT REPEAT
REPEAT -> TERMINAL'*'
REPEAT -> TERMINAL
TERMINAL -> TERMINAL'*'
TERMINAL -> 'a'
TERMINAL -> 'b'
TERMINAL -> 'c'
TERMINAL -> 'd'
这也可以写成:
S -> E
E -> E'|'E
E -> P'*'
E -> P
E -> E P
E -> P E
E -> E P E
E -> R
P -> P'*'
P -> '('E')'
R -> R R
R -> T'*'
R -> T
T -> T'*'
T -> 'a'
T -> 'b'
T -> 'c'
T -> 'd'
我很确定这是对的,我用一堆不同的测试输入对它进行了双重检查。任何确认将不胜感激。
答案 0 :(得分:2)
这只是一个迭代问题。我总是喜欢从Start-> NonTerminal
这个规则开始,只是为了给自己一个普通语法的机会。我认为嵌套括号将减少我们的上下文无关语法,但这没关系。我发现它使这一步更容易。然后,您必须从LOWEST precendence运算符开始。在你的情况下,括号和联盟。所以,最初:
Start -> Expression
Expression -> Expression|Expression
Expression -> (Expression)
请注意,我已经避开了正常的'|'符号,因为它是您的字母表中的符号之一。这避免了混淆。然后,我们可以添加下一个运算符,连接,以及一组生成重复的规则。
Start -> Expression
Expression -> Expression|Expression
Expression -> (Expression)
Expression -> Repeat
Repeat -> RepeatRepeat
Repeat -> Terminal
Terminal -> a
Terminal -> b
Terminal -> c
Terminal -> d
然后,剩下的就是将Kleene Star添加为最低优先级运算符:
Start -> Expression
Expression -> Expression|Expression
Expression -> (Expression)
Expression -> Repeat
Repeat -> RepeatRepeat
Repeat -> Terminal
Terminal -> a
Terminal -> b
Terminal -> c
Terminal -> d
Repeat -> Terminal*
Expression -> (Expression)*
我们有一个语法,可以从所需的字母表中生成所有非空正则表达式。在更传统的变量表示法中,它可能如下所示:
S -> E
E -> E|E
E -> (E)
E -> (E)*
E -> R
R -> RR
R -> T*
R -> T
T -> a
T -> b
T -> c
T -> d
有一种语法,我很确定。希望有人会检查我的工作,因为我写了一个正式的语法已经有几年了。
编辑:
由于所述的双重检查,有人指出连接表达式和括号表达式不起作用。但是,我们可以补充一点。第一步是添加新规则Expression -> Parenthetical
并将Expression -> (Expression)
和Expression -> (Expression)*
更改为Parenthetical -> (Expression)
和Parenthetical -> (Expression)*
然后,一些快速连接规则导致规则集:
Start -> Expression
Expression -> Expression|Expression
Expression -> Parenthetical
Parenthetical -> (Expression)
Parenthetical -> (Expression)*
Expression -> Expression Parenthetical
Expression -> Parenthetical Expression
Expression -> Expression Parenthetical Expression
Expression -> Repeat
Repeat -> Repeat Repeat
Repeat -> Terminal
Terminal -> a
Terminal -> b
Terminal -> c
Terminal -> d
Repeat -> Terminal*
答案 1 :(得分:-2)
编译器的新手很难理解,仅能够解析有效输入的语法 无用 。< / p>
好语法必须反映输入的层次结构,以便我们可以附加语义。
这完全取决于意义。
尽管如此,Grako有一个正则表达式到CFG的翻译器为its only sample project。