如何将某些表达式抽象为 BNF?

发布于 2024-11-25 22:33:54 字数 464 浏览 1 评论 0原文

例如:

waldo:=fern+alpha/-beta^gamma;

上面的算术表达式可以通过这个BNF抽象出来(与标准BNF可能有一些差异,暂时忽略它):

AEXP = AS $AS ;

AS = .ID ':=' EX1 ';' ;

EX1 = EX2 $( '+' EX2 / '-' EX2 ) ;

EX2 = EX3 $( '*' EX3 / '/' EX3 ) ;

EX3 = EX4 $( '^' EX3 ) ;

EX4 = '+' EX5 / '-' EX5 / EX5 ;

EX5 = .ID / .NUMBER / '(' EX1 ')' ;

.END

但是EX1~EX5抽象对我来说不是那么直观。(我不太明白它们是如何制作的)

规范化此类表达式时有什么步骤要遵循吗?

For example :

waldo:=fern+alpha/-beta^gamma;

The above arithmetical expression may be abstracted by this BNF(there may be some difference from standard BNF,but lets ignore it for now):

AEXP = AS $AS ;

AS = .ID ':=' EX1 ';' ;

EX1 = EX2 $( '+' EX2 / '-' EX2 ) ;

EX2 = EX3 $( '*' EX3 / '/' EX3 ) ;

EX3 = EX4 $( '^' EX3 ) ;

EX4 = '+' EX5 / '-' EX5 / EX5 ;

EX5 = .ID / .NUMBER / '(' EX1 ')' ;

.END

But the EX1~EX5 abstraction is not so intuitive to me.(I don't quite understand how they are crafted in the first place)

Is there any steps to follow when normalizing such expressions?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

浊酒尽余欢 2024-12-02 22:33:54

您可以将此表示法直接翻译为 EBNF。

命名类别 EX1 到 EX5 并不是指定运算符优先级的常见方法。事实上,恕我直言,这是一个很好的选择,特别是在某些具有 15 个或更多优先级的语言中,例如 C 和 C++。 :)

您可以将它们重命名为表达式、术语、因子、主要等(或任何对您有意义的术语)。

附录

如果您需要将上述内容翻译成更传统的 EBNF,我会这样做:

AEXP => AS+
AS   => id ':=' EX1 ';'
EX1  => EX2 (('+' | '-') EX2)*
EX2  => EX3 (('*' | '/') EX3)*
EX3  => EX4 ('^' EX3)*
EX4  => ('+'|'-')? EX5
EX5  => id | number | '(' EX1 ')'

我使用“*”表示零个或多个,“+”表示一个或多个,使用“?”为可选。我认为这里处理运算符优先级的方式非常酷。

附录 2:

请注意:EX3 的规则似乎是错误的。现在的情况你可以得到像这样的解析树

                  EX3
                   |
     +---+----+----+----+---------+
     |   |    |    |    |    |    |
    EX4  ^   EX3   ^   EX3   ^   EX3
            / | \               / | \
         EX4  ^  EX3         EX4  ^  EX3

所以写 a^b^c^d^e^f 可能意味着 a^(b^c)^d^(e^ f)。但事实上还有其他方法可以制作这棵树。语法有歧义。

看来语法的设计者希望使 ^ 运算符具有右关联性。但要做到这一点,规则应该是

EX3 => EX4 ('^' EX3)?

现在语法不再含糊了。看看 a^b^c^d^e^f 的推导现在必须如何进行:

          EX3
         / | \
      EX4  ^  EX3
             / | \
          EX4  ^  EX3
                 / | \
              EX4  ^  EX3
                     / | \
                  EX4  ^  EX3
                         / | \
                      EX4  ^  EX3

现在 a^b^c^d^e^f 只能解析为a^(b^(c^(d^(e^f))))

另一种方法是将规则重写为 EX3 => EX4 ('^' EX4)* 并有一条辅助规则,表示“OBTW 插入符号是右关联的”。

You can translate this notation to EBNF directly.

Naming categories EX1 through EX5 is not an uncommon way of specifying operator precedence. In fact it is a good one, IMHO, especially in some languages that have 15 or more precedence levels, like C and C++ do. :)

You can rename them to expression, term, factor, primary, etc. (or whatever terms make sense to you).

ADDENDUM

If you need a translation of the above into more traditional EBNF, here is how I would do it:

AEXP => AS+
AS   => id ':=' EX1 ';'
EX1  => EX2 (('+' | '-') EX2)*
EX2  => EX3 (('*' | '/') EX3)*
EX3  => EX4 ('^' EX3)*
EX4  => ('+'|'-')? EX5
EX5  => id | number | '(' EX1 ')'

I use '*' for zero or more, '+' for one or more, and '?' for optional. It is pretty cool how operator precedence is handled here, I think.

ADDENDUM 2:

Please note: It appears that the rule for EX3 is wrong. The way it stands now you can get parse trees like this

                  EX3
                   |
     +---+----+----+----+---------+
     |   |    |    |    |    |    |
    EX4  ^   EX3   ^   EX3   ^   EX3
            / | \               / | \
         EX4  ^  EX3         EX4  ^  EX3

So writing a^b^c^d^e^f could mean a^(b^c)^d^(e^f). But in fact there are other ways to make this tree. The grammar is ambiguous.

It appears the designer of the grammar wanted to make the ^ operator right-associative. But to do so, the rule should have been

EX3 => EX4 ('^' EX3)?

Now the grammar is no longer ambiguous. Look how the derivation of a^b^c^d^e^f MUST now proceed:

          EX3
         / | \
      EX4  ^  EX3
             / | \
          EX4  ^  EX3
                 / | \
              EX4  ^  EX3
                     / | \
                  EX4  ^  EX3
                         / | \
                      EX4  ^  EX3

Now a^b^c^d^e^f can ONLY parse as a^(b^(c^(d^(e^f))))

An alternative is to rewrite the rule as EX3 => EX4 ('^' EX4)* and have a side rule saying "OBTW the caret is right associative."

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文