资讯专栏INFORMATION COLUMN

用PHP写一个最简单的解释器Part3

Ajian / 486人阅读

摘要:总想成为一名写作技巧高超的作家,却一不小心成为了码农。虽然并未像一样发展起来,却给了很多想学习解释器的同学一个学习和实践的途径。言归正传,这节这个解释器已经可以完成计算器的很多功能,可以实现多位数连续加减运算。

总想成为一名写作技巧高超的作家,却一不小心成为了码农。

不知道,大家有没有看原文作者的一些看法(传送门)。我们为什么要学习新的知识,我们应该如何学习新的知识。看过很多书,却没有记住多少,有时候觉得自己就像鱼一样,真的只有七秒的记忆。

正如原作者所说的,学习知识最好的方法就是去实践。这样才可以将知识掌握。

之前,看过一篇新闻,PHPPHP,不知道有没有人记得这个项目,当时他出现时,我想很多人一样说,这个无聊的项目有什么用户,后来才逐渐发现了自己的无知。虽然PHPHP并未像pypy一样发展起来,却给了很多想学习解释器的同学一个学习和实践的途径。

言归正传,这节这个解释器已经可以完成计算器的很多功能,可以实现多位数连续加减运算。

Talk is cheap ,show me the code.

type=$type;
        $this->value=$value;
    }
    
    /**
    通过该方法来获取类的私有属性
    */
    public function __get($name)
    {
        return $this->{$name};
    }
    /**
    用于调试
    */
    public function __toString()
    {
        return "type:".$this->type." value:".$this->value;
    }
}

//解释器
class Interpreter{
    private $current_char ;
    private $current_token ;
    private $text;
    private $pos=0;
    /***
    $text 需要进行解释的字符串
    */
    public function __construct($text){
        //去除前后可能存在的空格 这些空格是无效的
        $this->text=trim($text);
        //初始化 获取第一个字符
        $this->current_char = $this->text[$this->pos];
    }
    
    public function error()
    {
        throw new Exception("Lexer eroor");
    }
    
    /*
    步进方法,每操作一个字符后前进一位
    */
    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();
        }
    }
    
    /*
    如果要支持多位的整数,则需要将每位数字存储起来
    */
    public function integers()
    {
        $result="";//用于存储数字
        while($this->current_char!=null&&is_numeric($this->current_char)){//只要当前字符是数字就一直循环并将数字存储于$result
            $result.=$this->current_char;
            $this->advance();//步进方法,每操作一个字符后前进一位
        }
        return intval($result);//将数字字符串转成整数
    }
    
    //获取当前字符的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,"-");
            }
            return new Token("EOF", null);
        }
    }
    
    //如果字符类型和判断的类型一致,则继续,否则输入错误
    public function eat($token_type)
    {
        if ($this->current_token->type==$token_type){
            $this->current_token=$this->get_next_token();
        }else{
            $this->error();
        }
    }
    
    public function term()
    {
        $token=$this->current_token;
        $this->eat(ISINTEGER);
        return $token->value;
    }
    
    //解释方法
    public function expr()
    {
        $this->current_token=$this->get_next_token();//获取字符串开头部分的数字
        $result=$this->term();
        while($this->current_token->type==PLUS||$this->current_token->type==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($input);
    echo $Interpreter->expr();
    unset($Interpreter);
    
}while(true);


文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/29019.html

相关文章

  • EOS入门指南——PART3 如何创建账户

    摘要:最后一步付款和比特币以及以太坊不一样的是,在创建账户是有成本的,这也就是为什么我们需要一个账户才能创建账户的原因找个人来买单。 之前我们学习了如何编译EOS程序,以及如何连接到EOS主网,接下来我们要谈一谈大家最关心的,如何创建自己的EOS账户。 摘要 这篇我们会学习如何创建钱包、秘钥对、主网账户,向大家介绍一些实用工具。最重要的是,我们会学习到在EOS里,公钥和账户到底有什么区别。 ...

    oliverhuang 评论0 收藏0
  • Part3JS一个Blog (node + vue + mongoDB)

    摘要:用写一个用写一个上一节我们把数据库连接成功了,这节我准备写关于文章的数据接口增删改查上次说到接口都在文件夹里面写,打开文件,首先引入文章的模型新增文章新增文章方法保存数据到数据库如果出现错误,直接把错误进的错误中枢处理储存成功后,返回给客户 【Part1】用JS写一个Blog (node + vue + mongoDB)【Part2】用JS写一个Blog (node + vue + m...

    wuyumin 评论0 收藏0
  • Part3JS一个Blog (node + vue + mongoDB)

    摘要:用写一个用写一个上一节我们把数据库连接成功了,这节我准备写关于文章的数据接口增删改查上次说到接口都在文件夹里面写,打开文件,首先引入文章的模型新增文章新增文章方法保存数据到数据库如果出现错误,直接把错误进的错误中枢处理储存成功后,返回给客户 【Part1】用JS写一个Blog (node + vue + mongoDB)【Part2】用JS写一个Blog (node + vue + m...

    CoorChice 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<