亚洲中字慕日产2020,大陆极品少妇内射AAAAAA,无码av大香线蕉伊人久久,久久精品国产亚洲av麻豆网站

資訊專欄INFORMATION COLUMN

用PHP寫一個(gè)最簡(jiǎn)單的解釋器Part4(寫一個(gè)最簡(jiǎn)單的腳本語(yǔ)言)

happen / 1530人閱讀

摘要:大家對(duì)解釋器的吸引,絕對(duì)沒有自己動(dòng)手寫一個(gè)腳本語(yǔ)言更有吸引力。前幾篇文章已經(jīng)實(shí)現(xiàn)一個(gè)簡(jiǎn)易的加減法計(jì)算器,想必看了文章之后可以很快的寫出來(lái)一個(gè)乘除法計(jì)算器。

好吧!我承認(rèn)我想標(biāo)題黨了。大家對(duì)解釋器的吸引,絕對(duì)沒有自己動(dòng)手寫一個(gè)腳本語(yǔ)言更有吸引力。不過(guò)如果看到標(biāo)題過(guò)來(lái)的,可能也是

我承認(rèn),之前收藏的減肥視頻,我都是這樣對(duì)待他們的。

不過(guò)我還是相信很多程序猿or程序媛不僅僅希望可以做出一個(gè)牛逼的產(chǎn)品,更想做出來(lái)一個(gè)牛逼閃閃的編程語(yǔ)言。而這里就是朝著開發(fā)一個(gè)腳本語(yǔ)言的方向去努力

恩!我就是xxoo語(yǔ)言之父。

前幾篇文章已經(jīng)實(shí)現(xiàn)一個(gè)簡(jiǎn)易的加減法計(jì)算器,想必看了文章之后可以很快的寫出來(lái)一個(gè)乘除法計(jì)算器。那么如果加減乘除混合運(yùn)算呢?

這節(jié)將實(shí)現(xiàn)類似6-1*2+4/2這樣的運(yùn)算方式,大家看到這個(gè)式子之后應(yīng)該已經(jīng)了解難點(diǎn)在哪里了。好了下面開始,首先展示完整的代碼。

type=$type;
        $this->value=$value;
    }
    
    /**
    通過(guò)該方法來(lái)獲取類的私有屬性
    */
    public function __get($name)
    {
        return $this->{$name};
    }
    /**
    用于調(diào)試
    */
    public function __toString()
    {
        return "type:".$this->type." value:".$this->value;
    }
}

class Lexer{
    private $current_char ;
    private $current_token ;
    private $text;
    private $pos=0;
    /***
    $text 需要進(jìn)行解釋的字符串
    */
    public function __construct($text){
        //去除前后可能存在的空格 這些空格是無(wú)效的
        $this->text=trim($text);
        //初始化 獲取第一個(gè)字符
        $this->current_char = $this->text[$this->pos];
    }
    
    public function error()
    {
        throw new Exception("Lexer eroor");
    }
    
    /*
    步進(jìn)方法,每操作一個(gè)字符后前進(jìn)一位
    */
    public function advance()
    {
        $this->pos++;
        if ($this->pos>strlen($this->text)-1){
            $this->current_char=null;
        }else{
            $this->current_char=$this->text[$this->pos];
        }
    }
    
    /*
    去除空格
    */
    public function skip_whitespace()
    {
        if ($this->current_char!=null&&$this->current_char==WHITESPACE){
            $this->advance();
        }
    }
    
    /*
    如果要支持多位的整數(shù),則需要將每位數(shù)字存儲(chǔ)起來(lái)
    */
    public function integers()
    {
        $result="";//用于存儲(chǔ)數(shù)字
        while($this->current_char!=null&&is_numeric($this->current_char)){//只要當(dāng)前字符是數(shù)字就一直循環(huán)并將數(shù)字存儲(chǔ)于$result
            $result.=$this->current_char;
            $this->advance();//步進(jìn)方法,每操作一個(gè)字符后前進(jìn)一位
        }
        return intval($result);//將數(shù)字字符串轉(zhuǎn)成整數(shù)
    }
    
    //獲取當(dāng)前字符的Token  
    public function get_next_token()
    {
        while($this->current_char!=null){
            if ($this->current_char==WHITESPACE){
                $this->skip_whitespace();
                continue;
            }
            if (is_numeric($this->current_char)){
                return new Token(ISINTEGER,$this->integers());
            }
            
            if ($this->current_char=="+"){
                $this->advance();
                return new Token(PLUS,"+");
            }
            
            if ($this->current_char=="-"){
                $this->advance();
                return new Token(MINUS,"-");
            }
            
            if ($this->current_char=="*"){
                $this->advance();
                return new Token(MUL,"*");
            }
            
            if ($this->current_char=="/"){
                $this->advance();
                return new Token(DIV,"/");
            }
            return new Token("EOF", null);
        }
    }
}

//解釋器
class Interpreter{
    private $current_token ;
    private $lexer ;
    
    public function __construct($lexer){
        //去除前后可能存在的空格 這些空格是無(wú)效的
        $this->lexer=$lexer;
        //初始化 獲取第一個(gè)字符
        $this->current_token=$this->lexer->get_next_token();
    }
    
    //如果字符類型和判斷的類型一致,則繼續(xù),否則輸入錯(cuò)誤
    public function eat($token_type)
    {
        if ($this->current_token->type==$token_type){
            $this->current_token=$this->lexer->get_next_token();
        }else{
            $this->error();
        }
    }
    
    public function error()
    {
        throw new Exception("eroor");
    }
    public function factor()
    {
        $token=$this->current_token;
        $this->eat(ISINTEGER);
        return $token->value;
    }
    
    public function term()
    {
        $result=$this->factor();
        while(in_array($this->current_token->type,[MUL,DIV])){
            $token=$this->current_token;
            if ($token->type==MUL){
                $this->eat(MUL);
                $result=$result*$this->factor();
            }
            else if ($token->type==DIV){
                $this->eat(DIV);
                $result=$result/$this->factor();
            }
        }
        
        return $result;
        
    }
    
    //解釋方法
    public function expr()
    {
        $result=$this->term();
        while(in_array($this->current_token->type,[PLUS,MINUS])){
            $token=$this->current_token;
            if ($token->type==PLUS){
                $this->eat(PLUS);
                $result=$result+$this->term();
            }
            else if ($token->type==MINUS){
                $this->eat(MINUS);
                $result=$result-$this->term();
            }
            
        }
        return $result;
    }
}

do{
    fwrite(STDOUT,"xav>");;
    $input=fgets(STDIN);
    $Interpreter=new Interpreter(new Lexer($input));
    echo $Interpreter->expr();
    unset($Interpreter);
    
}while(true);


看過(guò)前面幾篇文章的已經(jīng)了解過(guò),這里的代碼結(jié)構(gòu)發(fā)生了變化。

首先,分離出來(lái)詞法分析類,該類的作用:將字符串進(jìn)行類似分詞處理,并將每個(gè)詞的含義返回

class Lexer{
    private $current_char ;
    private $current_token ;
    private $text;
    private $pos=0;
    /***
    $text 需要進(jìn)行解釋的字符串
    */
    public function __construct($text){
        //去除前后可能存在的空格 這些空格是無(wú)效的
        $this->text=trim($text);
        //初始化 獲取第一個(gè)字符
        $this->current_char = $this->text[$this->pos];
    }
    
    public function error()
    {
        throw new Exception("Lexer eroor");
    }
    
    /*
    步進(jìn)方法,每操作一個(gè)字符后前進(jìn)一位
    */
    public function advance()
    {
        $this->pos++;
        if ($this->pos>strlen($this->text)-1){
            $this->current_char=null;
        }else{
            $this->current_char=$this->text[$this->pos];
        }
    }
    
    /*
    去除空格
    */
    public function skip_whitespace()
    {
        if ($this->current_char!=null&&$this->current_char==WHITESPACE){
            $this->advance();
        }
    }
    
    /*
    如果要支持多位的整數(shù),則需要將每位數(shù)字存儲(chǔ)起來(lái)
    */
    public function integers()
    {
        $result="";//用于存儲(chǔ)數(shù)字
        while($this->current_char!=null&&is_numeric($this->current_char)){//只要當(dāng)前字符是數(shù)字就一直循環(huán)并將數(shù)字存儲(chǔ)于$result
            $result.=$this->current_char;
            $this->advance();//步進(jìn)方法,每操作一個(gè)字符后前進(jìn)一位
        }
        return intval($result);//將數(shù)字字符串轉(zhuǎn)成整數(shù)
    }
    
    //獲取當(dāng)前字符的Token  
    public function get_next_token()
    {
        while($this->current_char!=null){
            if ($this->current_char==WHITESPACE){
                $this->skip_whitespace();
                continue;
            }
            if (is_numeric($this->current_char)){
                return new Token(ISINTEGER,$this->integers());
            }
            
            if ($this->current_char=="+"){
                $this->advance();
                return new Token(PLUS,"+");
            }
            
            if ($this->current_char=="-"){
                $this->advance();
                return new Token(MINUS,"-");
            }
            
            if ($this->current_char=="*"){
                $this->advance();
                return new Token(MUL,"*");
            }
            
            if ($this->current_char=="/"){
                $this->advance();
                return new Token(DIV,"/");
            }
            return new Token("EOF", null);
        }
    }
}

其實(shí)四則運(yùn)算最為復(fù)雜的部分就是如果解決先乘除后加減。這里將其分成了兩個(gè)部分。term函數(shù)就是在進(jìn)行乘除法部分,expr則進(jìn)行加法

public function term()
    {
        $result=$this->factor();
        while(in_array($this->current_token->type,[MUL,DIV])){
            $token=$this->current_token;
            if ($token->type==MUL){
                $this->eat(MUL);
                $result=$result*$this->factor();
            }
            else if ($token->type==DIV){
                $this->eat(DIV);
                $result=$result/$this->factor();
            }
        }
        
        return $result;
        
    }
    
    //解釋方法
    public function expr()
    {
        $result=$this->term();
        while(in_array($this->current_token->type,[PLUS,MINUS])){
            $token=$this->current_token;
            if ($token->type==PLUS){
                $this->eat(PLUS);
                $result=$result+$this->term();
            }
            else if ($token->type==MINUS){
                $this->eat(MINUS);
                $result=$result-$this->term();
            }
            
        }
        return $result;
    }

圖很丑,不過(guò)還是希望你可以看懂,也就是4-2*3-1 ,expr中乘除都是一個(gè)整體,其會(huì)被在term中進(jìn)行運(yùn)算返回,這樣這個(gè)式子就分成了,4-積-1.而積是在term中進(jìn)行運(yùn)算的。

文中很多描述存在很多不當(dāng),我也在積極的學(xué)習(xí)如何將知識(shí)講的通俗易懂。如果您有好的辦法,可以一同探討

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/29037.html

相關(guān)文章

  • PHP一個(gè)簡(jiǎn)單釋器Part5(計(jì)算器后一節(jié),下節(jié)開始如何個(gè)腳本語(yǔ)言

    摘要:經(jīng)過(guò)幾天的努力,用已經(jīng)實(shí)現(xiàn)了一個(gè)完整的基礎(chǔ)計(jì)算器,如下圖上代碼定義整數(shù)類型描述定義操作符號(hào)類型描述加法定義操作符號(hào)類型描述減法定義操作符號(hào)類型描述乘法定義操作符號(hào)類型描述除法定義操作符號(hào)類型描述定義操作符號(hào)類型描述定義空格用來(lái)存儲(chǔ)輸入字符的 showImg(https://segmentfault.com/img/bVbdNO5?w=900&h=377); 經(jīng)過(guò)幾天的努力,用PHP已經(jīng)...

    yanest 評(píng)論0 收藏0
  • PHP一個(gè)簡(jiǎn)單釋器Part1

    摘要:偶然間在朋友圈發(fā)現(xiàn)有人在看一本兩周自制腳本語(yǔ)言,覺得寫個(gè)腳本語(yǔ)言挺不錯(cuò)的,方便自己對(duì)語(yǔ)言本身進(jìn)一步了解。,不過(guò)同樣,該教程采用的也不是。在這里寫出代碼方便自己查找,同時(shí)也希望一些對(duì)解釋器感興趣的朋友一同學(xué)習(xí)。 偶然間在朋友圈發(fā)現(xiàn)有人在看一本《兩周自制腳本語(yǔ)言》,覺得寫個(gè)腳本語(yǔ)言挺不錯(cuò)的,方便自己對(duì)語(yǔ)言本身進(jìn)一步了解。于是乎,買了下來(lái)看了看,寫的挺通俗易懂,但是不便的是,采用的語(yǔ)言是Ja...

    molyzzx 評(píng)論0 收藏0
  • SegmentFault 技術(shù)周刊 Vol.40 - 2018,來(lái)學(xué)習(xí)一門新編程語(yǔ)言吧!

    摘要:入門,第一個(gè)這是一門很新的語(yǔ)言,年前后正式公布,算起來(lái)是比較年輕的編程語(yǔ)言了,更重要的是它是面向程序員的函數(shù)式編程語(yǔ)言,它的代碼運(yùn)行在之上。它通過(guò)編輯類工具,帶來(lái)了先進(jìn)的編輯體驗(yàn),增強(qiáng)了語(yǔ)言服務(wù)。 showImg(https://segmentfault.com/img/bV1xdq?w=900&h=385); 新的一年不知不覺已經(jīng)到來(lái)了,總結(jié)過(guò)去的 2017,相信小伙們一定有很多收獲...

    caspar 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

閱讀需要支付1元查看
<