当我想到“编译”时,我想把C ++代码变成二进制代码。或者也许将C#转换成CLR字节码。但是“解析”可能类似于解析Python或Web模板语言,它不需要生成任何二进制文件,但可以立即执行代码,逐个语句或直接输出HTML。
在这两种情况下,你基本上都会做同样的任务吗?忽略语言语法,编译C ++与解析网站模板文件(Django,Smarty,无论如何)或Python一样困难吗?
我想提到的是,如果我学习“编译”或阅读一本关于“编译”的书,我是否一定会掌握解析非编译语言的技能?
答案 0 :(得分:25)
简短回答:解析是而不是编译的一个子集。
长答案:一般来说,将来源转换为其他格式需要3个步骤:
(对于非常简单的语言,您甚至可能不需要解析器,您可能可以直接编译令牌流,或者您的解析器可以直接输出本机代码。)
所以从这样的原始字符串开始:
let x = 0
while x < 10
print x
x := x + 1
词法分析器会将其转换为令牌流,可能是这样的:
[LET; String("x"); EQ; Int(0); NEWLINE; WHILE; String("x");
LT; VAL(10); ... ]
解析器会将流转换为更有意义的数据结构,即抽象语法树:
// AST definition
type expr =
| Block of expr list
| Assign of string * expr
| While of expr * expr
| Call of string * expr list
| Add of expr * expr
| Var of string
| Int of int
// AST instance created from token stream
Block
[
Assign("x", Int(10));
While
(
LessThan(Var("x"), Int(10)),
Block
[
Call("print", [Var("x")]);
Assign("x", Add(Var("x"), Int(1)));
]
);
]
一旦你有了AST,你可以随心所欲地做任何事情:
Var("x")
的所有实例,并将其替换为Var("y")
,类似于代码重构工具。)因此,虽然您通常在编译之前解析输入,但这与说解析是编译的子集不同。
答案 1 :(得分:5)
不,解析和编译可以完全独立。
大多数编译器包括解析步骤,但我认为它不一定是编译的“子集”,解析当然不必与编译有任何关系。
答案 2 :(得分:2)
...“我会学习解析非编译语言的技能吗?”是的,你会,但你可以自己学习解析。
然而,您会发现,编译(名称解析,类型推断,模式匹配,编译指令[pcode而不是机器代码],高性能执行,针对特殊情况进行优化)的大部分内容都非常有用。 em>处理非编译语言。因此,如果您打算做的不仅仅是字面上解析,那么无论如何您都需要学习编译器技术。
答案 3 :(得分:1)
编译实际上比解析更困难,因为它只是编译中的一个初步步骤。
解析后,生成一个符号表,从中生成实际的二进制代码。
在解释诸如Javascript之类的语言时,可以在解析每个语句时执行语句。