有没有不适合使用flex/lex作为词法分析器的语言?(摘自知乎)

本问题及解答摘自本人知乎 http://www.zhihu.com/people/chaos-xie   http://www.zhihu.com/question/29922657

感谢知乎网友的回答!现将问题及可能的解答记录如下:

 

有没有不适合使用flex/lex作为词法分析器的语言?

O‘REILLY 《flex和bison(中文版)》第24面问题5。求指点!我个人认为词法分析既然是把输入流分割成为一个个有意义的记号(参见龙书),而只要是程序设计语言肯定就能分割成为有意义的记号(不然人类就无法理解了),那就一定可以用词法分析器生成器如flex生成,可是书上既然提出了这个问题那一定是有道理的!望指点!
 
Zete   的回答:
Javascript

Javascript 正则表达式字面量和除法操作符的二义性, 很难用 lex 解决, 一般只用 lex 做很少很少的事情, 然后把真正含义的辨清延迟到 parse 阶段.

有一个用 lex 中判断 / 含义的方案, 主要是通过保存前一个 token 状态来做判断, 你感受一下它的复杂度:

`//` 总是辨认为行注释开始

如果符号是 `/` 或者 `/=`, 并且前一个 token 是下列 token 之一, 那它就是除法运算符:
]
Identifier   Number   RegularExpression   String
class   false   null   private   protected   public   super   this   true
get   include   set

如果前一个 token 是下列 token 之一, 那它就是正则表达式的开始:
!   !=   !==   #   %   %=   &   &&   &&=   &=   (   *   *=   +   +=   ,   -   -=   ->
.   ..   ...   /   /=   :   ::   ;   <   <<   <<=   <=   =   ==   ===   >   >=   >>   >>=   >>>   >>>=
?   @   [   ^   ^=   ^^   ^^=   {   |   |=   ||   ||=   ~
abstract   break   case   catch   const   continue   debugger   default   delete   do   else   enum
export   extends   final   finally   for   function   goto   if   implements   import   in   instanceof
interface   is   namespace   native   new   package  return   static   switch   synchronized
throw   throws   transient   try   typeof   use   var   volatile   while   with

但是它依然判断不了 前一个 token 是 ) } 的情况...
if (true) /a/g ---> 正则表达式
(x+y)/2        ---> 除法
{}/a/g         ---> 正则表达式
+{}/a/g        ---> 除法

所以得添加一个状态栈来判断右括号是控制结构 if / for / while 的括号还是表达式的括号.
再加一个状态栈来判断右大括号是 block 结束还是 object literal 的结束.

但是它依然判断不了前一个 token 是 ++ 或 -- 的情况
a++/a/g  ---> 除法

RegExp.prototype.foo = 3
++/a/g.foo ---> 正则表达式

所以还得判断前面的 ++ 到底是后缀运算符, 还是前缀运算符...

至此你的 lexer 充满了一堆非常复杂的状态... 你会思考人生的价值, 怀疑 lex 到底有啥意义, 为什么不直接用一个 scannerless 的 parser 解决这个变态的语言?

参见 JavaScript 2.0 Syntax Rationale
 
vczh 的回答:
 

eta的答案所提到的问题还是相对比较简单的,只要你把bison当lex用就可以轻松解决,所有的那些状态都embed在你的文法里面了。主要标准就是,当你需要一个表达式而此时你看到的是/的时候,如果他不是注释,那就肯定是正则表达式。


真正复杂的问题是bison搞不定的,譬如说C++需要语义分析和语法分析同时做,让语义分析的结果来指导语法分析到底要选择哪条grammar rule来resolve conflict。

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。