自制前端框架 Day.7 解析布尔值和null

先写个parse函数和parser类把现有代码包装一下

今天打算先把之前的代码整理一下,写一个parser类,包装一下Lexer,ASTBuilder,Compiler类。

function Parser(){
  var lexer = new Lexer();
  var astbilder = new ASTBuilder(lexer);
  this.compiler = new Compiler(astbilder);
}
Parser.prototype.parse = function(expression){
  return this.compiler.compile(expression);
}

function parse(expression){
  var parser = new Parser();
  return parser.parse(expression);
}

这样以后调用就方便了,写个测试案例试试:

describe('用parse函数编译',function(){
  it('编译整数',function() {
    var fn = parse('233')
    expect(fn()).toBe(233);
  })
})

思路

如果遇到的字符串不是数字也不是引号,而是一个字符,就进入解析identity流程,这个identity就是说在编程中我们遇到的一些已经定义好的值,比如true,false等等,这种值都是确定的,所以叫identify(确定).
先写一个函数判断是不是遇到了identify的值。

Lexer.prototype.isIdent=function(char){
  return ('a'<=char && char<='z')||('A'<=char&&char<='Z')||char==="_"||char==="$";
}

如果遇到这样的字符,就进入readIdent流程:

Lexer.prototype.lex=function(expression){
  this.tokens=[];
  this.text = expression;
  this.index = 0;
  while (this.index

readIdent流程和其他的没什么不同,区别就是生成的token不一样,ident这种token没有值,因为值是已经被JS定义好的,只有text属性:

Lexer.prototype.readIdent = function () {
  var ident="";
  while(this.index

现在虽然有了一个token,但是在构建语法树的时候还是不行,因为构建语法树现在的body是tokens[0].value。显然这个token是没有value的。所以可以完善一下构建语法树的部分了:program的body属性现在是直接调用constant方法,完善一下,program调用一个新方法,primary方法。这个方法的意图是,所有节点的主处理方法。就是说处理其他节点都会通过这个方法过一次。
代码写好:

ASTBuilder.constants={
  'true':true,
  'false':false,
  'null':null
}
ASTBuilder.prototype.ast=function(expression){
  this.tokens = this.lexer.lex(expression);
  return this.program();
}
ASTBuilder.prototype.program=function(){
  return {
    type:ASTBuilder.Program,
    body:this.primary()
  }
}
ASTBuilder.prototype.primary=function(){
  if(ASTBuilder.constants.hasOwnProperty(this.tokens[0].text)){
    return {type:ASTBuilder.Literal,value:ASTBuilder.constants[this.tokens[0].text]}
  }else{
    return this.constant();
  }
}

先写个测试案例跑一下试试:

  it('编译true',function() {
    var fn = parse('true')
    expect(fn()).toBe(true);
  })
  it('编译false',function() {
    var fn = parse('false')
    expect(fn()).toBe(false);
  })
it('编译null',function() {
    var fn = parse('null')
    expect(fn()).toBe(null);
  })
自制前端框架 Day.7 解析布尔值和null_第1张图片
编译null报错

编译null的时候出错了,跟一下看看怎么回事:

自制前端框架 Day.7 解析布尔值和null_第2张图片
因为null就是啥都没有
自制前端框架 Day.7 解析布尔值和null_第3张图片
image.png

这下明白了,因为现在生成的函数是这样:

function(){
  return ;
}
``
所以其实是什么都没返回,测试案例期待的null就不行。我应该让生成的函数是这样:

function(){
return null ;
}

这样只要修改一下escape方法就行了:

Compiler.prototype.escape=function(value){
if(webframe.isString(value)){
return "'"+
value.replace(this.stringEscapeReg,this.changeToUnicode)
+"'";
}else if (value===null) {
return 'null';
} else{
return value;
}
}

这就编译成功了:

![image.png](http://upload-images.jianshu.io/upload_images/839173-03ff761e4480264c.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

今天已经开始写了这个东西第七天了,感觉进度还行,稳扎稳打,之前定的七个月,没准六个月就能完成呢。哈哈。

你可能感兴趣的:(自制前端框架 Day.7 解析布尔值和null)