语法树生成
得到了词素之后,接下来就是进行语法分析。不过由于 Lisp 类语言的程序即是语法树,所以语法分析可以直接跳过。
以下面的程序为例:
程序即语法树
;
(def x (if (> a 1) a 1))
; 换一个角度看的话:
(
def
x
(
if
(
>
a
1
)
a
1
)
)
更加直观的图片:

这使得抽象语法树(Abstract Syntax Tree)的构建变得极其简单(无需考虑操作符优先级等问题),我们使用 SExpression 类型定义 iScheme 的语法树(事实上S Expression也是Lisp表达式的名字)。
抽象语法树的定义
public class SExpression {
public String Value { get; private set; }
public List<SExpression> Children { get; private set; }
public SExpression Parent { get; private set; }
public SExpression(String value, SExpression parent) {
this.Value = value;
this.Children = new List<SExpression>();
this.Parent = parent;
}
public override String ToString() {
if (this.Value == "(") {
return "(" + " ".Join(Children) + ")";
} else {
return this.Value;
}
}
}
然后用下面的步骤构建语法树:
-
碰到左括号,创建一个新的节点到当前节点( current ),然后重设当前节点。
碰到右括号,回退到当前节点的父节点。
否则把为当前词素创建节点,添加到当前节点中。
抽象语法树的构建过程
public static SExpression ParseAsIScheme(this String code) {
SExpression program = new SExpression(value: "", parent: null);
SExpression current = program;
foreach (var lex in Tokenize(code)) {
if (lex == "(") {
SExpression newNode = new SExpression(value: "(", parent: current);
current.Children.Add(newNode);
current = newNode;
} else if (lex == ")") {
current = current.Parent;
} else {
current.Children.Add(new SExpression(value: lex, parent: current));
}
}
return program.Children[0];
}










