【问题标题】:How to implement simple parser tree?如何实现简单的解析器树?
【发布时间】:2011-09-03 19:09:44
【问题描述】:

我已经发布了类似的问题here,但由于我没有正确解释自己,它被关闭了。 我会再次尝试解释我的问题。

我设法编写了 LexicalAnalyzer,它将以下内容标记为“public”、“class”、“A”、“{”、...、“if”、“(”、...、}”

string seq = "public class A " +
             "{ " +
                  "public A() " +
                  "{ " +
                       "if(1==2) " +
                       "{ " +
                       "} " +
                       "else " +
                       "{ " +
                       "} " +
                 "} " +
             "} "

现在,我需要将其解析为树。正如我所读到的,最好以采用规则的方式构造解析器。同时我需要为“if”语句编写规则,这些规则将传递给解析器,最后一个将构建解析树。将来,我将添加“类”等规则。

解析我的意思是最终我会得到类似的树like here in the right

我的问题是如何实现规则和解析器?你能指导我或举个简单的例子吗?

我已经阅读了一些帖子,但我没有找到可以帮助我做我需要的事情。

附:如果还是不清楚,请不要关闭帖子,但告诉我,我会改变它。

谢谢

【问题讨论】:

标签: c# parsing syntax lexical-analysis


【解决方案1】:

从什么时候开始 RTFM 成为答案?无论如何。您尝试做的事情一点也不简单,因为 Java 是上下文无关的(类型 2)。尝试为初学者编写类型 3 语言的语法分析器 (Chomsky Hierarchy)。但我会尽力向你解释无论如何你需要做什么。

您必须为 Java 定义如下所示的规则(在我的示例中,我将在 java 类中定义一个函数,其中小写字母是终端,大写字母是非终端)。终结符不能被进一步推导,而非终结符可以。

X -> Y 表示 X 派生于 Y。 X -> Y | Z 表示 X 派生于 Y 或 Z。

f 是任何名称。 t 是一个类型,如果我想一路走下去,这将不是一个终端,但是由于我将类型定义为不可声明以使我的生活不那么痛苦,所以它是一个终端。 '(', ')', '{', '}', ',' 和 ' ' 是终结符。 Eps 是 Epsilon,没有任何意义。

S -> K t f(T) { N }
T -> t f | t f , T
F -> F, f | f
K -> k K | k
N -> L N | L
L -> f(F);

有了这个我可以解析

final boolean equals(Object obj) {
    compare(this, obj);
    compare(obj, this);
}

这会导致:

S -> K t f(T) { N } 
     with K -> k
  -> k t f(T) { N }
     with T -> t f
  -> k t f(t f) { N }
     with N -> L N
  -> k t f(t f) { L N }
     with L -> f(F);
  -> k t f(t f) { f(F); N }
     with F -> f, F
  -> k t f(t f) { f(f, F); N }
     with F -> f
  -> k t f(t f) { f(f, f); N }
     with N -> L
  -> k t f(t f) { f(f, f); L }
     with L -> f(F)
  -> k t f(t f) { f(f, f); f(F) }
     ...
  -> k t f(t f) { f(f, f); f(f, f); }

  -> k (=final) t(=boolean) f(=equals) (t(=Object) f(=obj)) { ... }

这证明了 S 定义了我的简单化 java(好吧它没有,但至少我举了一个例子)。所以接下来我们要做的就是弄清楚如何从这些规则中得到一个语法树。

谢天谢地,这是最简单的部分,因为您所要做的就是将线条更改为一棵树。所以 S 有孩子 K t f(T) { N }。 K 有孩子 K 和 k... 大写表示节点有孩子,小写表示没有。

最后一个问题,你不是从 S 开始,而是从已经编写的代码开始。剩下的就是

K t f(T) { N } -> S
t f            -> T
t f , T        -> T
F, f           -> F
f              -> F
k K            -> K
k              -> K
L N            -> N
N              -> L
f(F);          -> L

反向解析如下:

final boolean equals(Object obj) {
   compare(this, obj);
   compare(obj, this);
}
final   -> k
boolean -> t
equals  -> f
Object  -> t
obj     -> f
compare -> f
this    -> f

k t f(t f) { f(f, f); f(f,f); }
with k -> K
K t f(t f) ...
with t f -> T
K t f(T) ...
...

这将从下方构建树。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-03-16
    • 2014-01-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-25
    • 2012-11-09
    • 2012-09-06
    相关资源
    最近更新 更多