好!我承认我很怀念头条党。大家对解释器的吸引力肯定不如自己写一门脚本语言有吸引力。但是如果你看到这个标题,可能是我承认我之前收集的减肥视频都是这样对待他们的。但是我还是相信,很多程序员或者编程人员不仅希望做出一个伟大的产品,更希望做出一个伟大的编程语言。而这里就是朝着开发脚本语言的方向努力!我是xxoo语言之父。前面的文章已经实现了一个简单的加减法计算器。想必看完文章后,很快就能写出一个乘除法计算器了。那么加减乘除的混合运算呢?本节将实现类似6-1*2+4/2的计算方式。看到这个公式后,你应该已经明白难点在哪里了。好了,开始吧,先展示完整的代码。type=$type;$this->value=$value;}/**使用这个方法获取类的私有属性*/publicfunction__get($name){return$this->{$name};}/**用于调试*/publicfunction__toString(){return'type:'.$this->type.'值:'.$this->value;}}classLexer{private$current_char;私人$current_token;私人$文本;私人$pos=0;/***$text需要解释的字符串*/publicfunction__construct($text){//去除前后可能的空格这些空格无效$this->text=trim($text);//初始化获取第一个字符$this->current_char=$this->text[$this->pos];}publicfunctionerror(){thrownew\Exception('Lexereroor');}/*步进法,每次操作后前进一位*/publicfunctionadvance(){$this->pos++;如果($this->pos>strlen($this->text)-1){$this->current_char=null;}else{$this->current_char=$this->text[$this->pos];}}/*删除空格*/publicfunctionskip_whitespace(){if($this->current_char!=null&&$this->current_char==WHITESPACE){$this->advance();}}/*如果要支持多位整数,则需要存储每个数字*/publicfunctionintegers(){$result='';//用来存储数字while($this->current_char!=null&&is_numeric($this->current_char)){//只要当前字符是数字,就一直循环,把数字存入$result$result。=$this->current_char;$this->advance();//步骤方法,每一个操作一个在字符后前进一位}returnintval($result);//将数字串转为整数}//获取当前字符的Tokenpublicfunctionget_next_token(){while($this->current_char!=null){如果($this->current_char==WHITESPACE){$this->skip_whitespace();继续;}if(is_numeric($this->current_char)){returnnewToken(ISINTEGER,$this->integers());}if($this->current_char=="+"){$this->advance();返回新令牌(加号,'+');}if($this->current_char=="-"){$this->advance();返回新令牌(负号,'-');}if($this->current_char=="*"){$this->advance();返回新令牌(MUL,'*');}if($this->current_char=="/"){$th是->前进();返回新令牌(DIV,'/');}returnnewToken('EOF',null);}}}//解释器类解释器{private$current_token;私人$词法分析器;publicfunction__construct($lexer){//去掉这些空格前后可能存在的空格$this->lexer=$lexer;//初始化获取第一个字符$this->current_token=$this->lexer->get_next_token();}//如果字符类型与判断的类型一致,则继续,否则输入错误publicfunctioneat($token_type){if($this->current_token->type==$token_type){$this->current_token=$this->词法分析器->get_next_token();}else{$this->error();}}publicfunctionerror(){thrownew\Exception('eroor');}publicfunctionfactor(){$token=$this->current_token;$this->eat(ISINTEGER);返回$令牌->值;}publicfunctionterm(){$result=$this->factor();while(in_array($this->current_token->type,[MUL,DIV])){$token=$this->current_token;如果($token->type==MUL){$this->eat(MUL);$result=$result*$this->factor();}elseif($token->type==DIV){$this->eat(DIV);$result=$result/$this->factor();}}返回$结果;}//解释方法publicfunctionexpr(){$result=$this->term();while(in_array($this->current_token->type,[PLUS,MINUS])){$token=$this->current_token;如果($token->type==PLUS){$this->eat(PLUS);$result=$result+$this->term();}elseif($token->type==MINUS){$this->eat(MINUS);$result=$result-$this->term();}}返回$结果;}}do{fwrite(STDOUT,'xav>');;$输入=fgets(标准输入);$Interpreter=newInterpreter(newLexer($input));echo$Interpreter->expr();取消设置($解释器);}而(真);看过前面几篇文章的已经明白,这里的代码结构发生了变化首先,分离出词法分析类。该类的作用是对字符串进行类似分词的处理,将每个词的含义返回给classLexer{private$current_char;私人$current_token;私人$文本;私人$pos=0;/***$text需要解释的字符串*/publicfunction__construct($text){//去掉前后可能存在的空格。这些空格是无效的$this->text=trim($text);//初始化获取第一个字符$this->current_char=$this->text[$this->pos];}publicfunctionerror(){thrownew\Exception('Lexererosion');}/*step方法,每操作一个字符后Advance一位*/publicfunctionadvance(){$this->pos++;如果($this->pos>strlen($this->text)-1){$this->current_char=null;}else{$this->current_char=$this->text[$this->pos];}}/*删除空格*/publicfunctionskip_whitespace(){if($this->current_char!=null&&$this->current_char==WHITESPACE){$this->advance();}}/*如果你想支持多位整数,需要存储每个数字*/publicfunctionintegers(){$result='';//用来存储数字while($this->current_char!=null&&is_numeric($this->current_char)){//循环只要当前字符是一个数字,并将数字存储在$result$result.=$this->current_char;$this->advance();//步骤方法,每次操作后前进一位}returnintval($result);//将数字串转为整数}//获取当前字符的Tokenpublicfunctionget_next_token(){while($this->current_char!=null){如果($this->current_char==WHITESPACE){$this->skip_whitespace();继续;}if(is_numeric($this->current_char)){returnnewToken(ISINTEGER,$this->integers());}如果($this->current_char=="+"){$this->advance();返回新令牌(加号,'+');}if($this->current_char=="-"){$this->a提前();返回新令牌(负号,'-');}if($this->current_char=="*"){$this->advance();返回新令牌(MUL,'*');}if($this->current_char=="/"){$this->advance();返回新令牌(DIV,'/');}returnnewToken('EOF',null);}}}其实四运算中最复杂的部分就是先解乘除再解加减,这里分为两部分。term函数就是在执行乘除法部分,expr则执行加法publicfunctionterm(){$result=$this->factor();while(in_array($this->current_token->type,[MUL,DIV])){$token=$this->current_token;如果($token->type==MUL){$this->eat(MUL);$result=$result*$this->factor();}elseif($token->type==DIV){$this->eat(DIV);$result=$result/$this->factor();}}返回$结果;}//解释方法publicfunctionexpr(){$result=$this->term();while(in_array($this->current_token->type,[PLUS,MINUS])){$token=$this->current_token;如果($token->type==PLUS){$this->eat(PLUS);$result=$result+$this->term();}elseif($token->type==MINUS){$this->eat(MINUS);$r结果=$result-$this->term();}}返回$结果;}图丑了点,还是希望大家能看懂,就是4-2*3-1,expr里的乘除法都是一个整体,会在term里计算返回,所以这个公式可以分为4-product-1。产品是按术语计算的,文章中有很多不恰当的描述。我也在积极学习如何把知识解释得通俗易懂。大家有好的方法可以一起讨论
