Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Javascript能做解析器的那些事 #1

Open
jschyz opened this issue Nov 11, 2016 · 0 comments
Open

Javascript能做解析器的那些事 #1

jschyz opened this issue Nov 11, 2016 · 0 comments

Comments

@jschyz
Copy link
Owner

jschyz commented Nov 11, 2016

现如今,解析已经在Javascript中有很多运用场景,比如:

也可以这样不严谨归纳认为,将一种语言转换成另一种语言的形式,需要用到解析流程。

学习实现语言,最好是从最简单,最干净的语言开始,迅速写出一个可用的解释器。之后再逐步往里面添加特性,同时保持正确。这样你才能有条不紊地构造出复杂的解释器。

程序代码映射称为一颗语法树,而通过操纵语法树,我们能够精准的获得程序代码中的某个节点。例如声明语句,赋值语句,而这是用正则表达式所不能准确体现的地方。

什么是语法树

抽象语法树(Abstract Syntax Tree)也称为AST语法树,指的是源代码语法所对应的树状结构。也就是说,对于一种具体编程语言下的源代码,通过构建语法树的形式将源代码中的语句映射到树中的每一个节点上。

下面用一张图来描述解析过程Code → Token → AST

AST

那么,有什么用呢?

抽象语法树的作用非常的多,比如下面这些静态分析器

  • UglifyJS、eslint、JSHint

  • CoffeeScript 、Bable / Buble 转换 ES6

  • Postcss、Css Lint

    etc...

实际这背后就是在对抽象语法树进行操作。

那么,AST该如何生成呢?

解析器

在编译语言流程中,程序中的一段代码在执行之前会经过解析环节转换成有意义的结构,这个环节通常分为二个步骤实现

词法分析

词法分析也称为分词过程Tokenizing/Lexing),这个过程将有意义的字符组成的字符串分解成有意义的代码块,这些代码块被称为词法单元(token)

拿大家熟悉的Javascript程序来讲解,例如:var AST = "is Tree"; 。这段程序会被分解成下面这些词法单元: varAST=is Tree;

input: "var a = 2;"
output: [ 
  { type: 'Keyword', value: 'var' },
  { type: 'Identifier', value: 'AST' },
  { type: 'Punctuator', value: '=' },
  { type: 'String', value: 'is Tree' } ,
  //{ type: 'EOF', value: ';' }
]

分词逻辑也有难易之分。

通常将每个关键词用空格分开,比如,var a = 2; 这段程序会被分解成下面这些词法单元: vara=2;

事实上在浏览器引擎里解析HTML、CSS、JS是以单个字符(token)进行分词,然后在语法分析中使用类似递归的方式遍历这些token,组装成有意义的。比如,var a = 2; 这段程序会被分解成下面这些词法单元: vara=2 、`;

语法分析

(Parsing)是将词法单元流(数组)转换成一个由元素逐级嵌套所组成的代表了程序语法结构树。这个树被称为“抽象语法树”(Abstract Syntax Tree, AST)

input: [ 
  { type: 'Keyword', value: 'var' },
  { type: 'Identifier', value: 'AST' },
  { type: 'Punctuator', value: '=' },
  { type: 'String', value: 'is Tree' } 
]
output: {
  type: 'Program',
  body: [
    {
      type: 'VariableDeclaration',
      declarations: [
        {
          type: 'AssignmentExpression',
          operator: '=',
          left: {
            type: 'Identifier',
            name: 'a'
          },
          right: {
            type: 'StringLiteral',
            value: 2
          }
         }
       ]
     }
  ]
}

题外话:

artTemplate 模版引擎解析就少了完整的词法分析过程,故而无法准确确定错误源所在的位置,给调试者带来诸多不便

参考

Parsing wiki

how browsers work HTML解析

You-Dont-Know-JS Javascript 解析

how to be a compiler

building javascript tools

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant