baixiaoji / blog

writting & thinking
3 stars 0 forks source link

4-解析-理论剖析 #11

Open baixiaoji opened 5 years ago

baixiaoji commented 5 years ago

4-解析-理论剖析

其实我们很明白「解析」到底做了什么,说白了就一句话咯:「将源代码转化机器码」。难道不好奇转化这一流程中到底涉及到什么环节吗?

首先,我们展上述的那句话——「将源代码转化机器码」。

在浏览器中,大多数解析是文档,整个过程就是努力将文档转化为代码可以理解和使用的结构,对应输出的结果是对应文档结构的节点树,我们通常叫它为解析树或语法树。

感觉理解上可能还会有点问题,我们举个例子,解析 2 + 3 -1 这个表达式,通过解析会输出这样的语法树:

2+3-1表达式的语法树

整个解析过程都是基于文档的语法规则去处理的,而每种可以解析的格式都有确定的语法,又由连续的单词和语法规则组成,这样的语法我们叫做 context free grammer,而人类语言不属于此类范畴(所以不不能用常规的解析技术)。这样看来对应的解析还是比较刻板的过程,只是匹配语法然后转化的过程。

那解析过程可以分几个阶段呢?

解析过程分为两个阶段 lexical analysissyntax analysis

lexical analysis 阶段:整个过程是将输入的文档,转化有效的 tokens。这里想将 tokens 理解为人类语言中单词。

syntax analysis阶段:该阶段就是将上阶段的产物应用语法规则,产出语法树。

上述的过程是基于对应的载体作用的分别是词法分析器(lexer)和解析器(parse)。

词法分析器:将输入文档转化为有效的标记,能识别和剔除无效的字符。

解析器:将有效的标记转化解析树。

词法-语法-树

整个解析过程是循环的,parse 会不断向 lexer 索要 token,然后尝试去寻找对应的语法规则去击中,如击中则将 token 对应的 node 节点添加到 parse tree 上;若没有击中,先保存到内部;然后继续索要 token 去击中语法,直到将所有的 token 全部与语法规则击中为止,如果没有就引发异常,这说明文档存在异常,因存在语法错误。

而解析为语法树并没有完成将源代码转化为机器码的步骤,还差最后一步就是翻译。而翻译过程也是同时解析过程进行,可以理解为下面的流程图:

parse-translate

详细讲一下开始的例子: 2 + 3 -1 表达式。该表达式包含整数、加号和减号。

而对应数学计算语法如下:

  1. 构成语言的语法单位是表达式、项和运算符。
  2. 我们用的语言可以包含任意数量的表达式。
  3. 表达式的定义是:一个「项」接一个「运算符」,然后再接一个「项」。
  4. 运算符是加号或减号。
  5. 项是一个整数或一个表达式。

那解析一下表达式咯:匹配语法规则的第一个子串是 2,而根据第 5 条语法规则,这是一个项。匹配语法规则的第二个子串是 2 + 3,而根据第 3 条规则(一个项接一个运算符,然后再接一个项),这是一个表达式。下一个匹配项已经到了输入的结束。2 + 3 - 1 是一个表达式,因为我们已经知道 2 + 3 是一个项,这样就符合「一个项接一个运算符,然后再接一个项」的规则。2 + + 不与任何规则匹配,因此是无效的输入。

而在计算机中对应词汇都是有正则表示,所以上述表达式的词汇用正则表达为:

INTEGER: 0|[1-9][0-9]*
PLUS: +
MINUS: -

因为大多数解析的语法符合 context free grammer ,所以采用 BNF (巴科斯范式)规则。BNF 是由约翰·巴科斯(John Backus)和彼得·诺尔(Peter Naur)首先引入的用来描述计算机语言语法的符号集。语法规则为

<符号> ::= <使用符号的表达式>

上述例子可定义为:

expression :=  term  operation  term
operation :=  PLUS | MINUS
term := INTEGER | expression

上述仅仅是解析的整个理论过程,而其载体便是解析器,那解析器有哪些种类呢?