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

本文介绍了一个使用PHP从零开始构建的简易计算器解释器。该解释器能够解析并执行基本的算术运算,如加法和减法,并支持多位数的连续计算。文章通过实例代码展示了如何定义和处理不同的Token,包括整数、加号和减号。

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

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

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

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

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

Talk is cheap ,show me the code.

<?php
define('ISINTEGER','ISINTEGER');//定义整数类型描述
define('PLUS','PLUS');//定义操作符号类型描述 加法
define('MINUS','MINUS');//定义操作符号类型描述 减法
define('WHITESPACE',' ');//定义空格
/**
Token  用来存储输入字符的类型
*/
class Token{
    private $type;
    private $value;
    /**
    $type ISINTEGER/PLUS/MINUS
    $value 对应的字符串
    */
    public function __construct($type,$value)
    {
        $this->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);


clipboard.png

要用 JavaScript 一个简单的语言解释器,我们可以简化任务并专注于最基础的功能。这里我们将创建一个极简化的解释器,它能理解和执行包含三步(123 步)命令的小脚本。为了清晰起见,我们假设每个步骤对应于对某个数字的操作。 ### 设计思路 #### 语法示例 ``` step 1 add 5; step 2 subtract 3; step 3 multiply 2; ``` 每一行代表一个指令,分别表示加法、减法和乘法操作。 ### 实现步骤 1. **词法分析**:将字符串分割成有意义的单词或符号; 2. **语法分析**:解析这些分隔出来的元素成为可以理解的数据结构; 3. **解释执行**:按照定义好的规则去逐一计算每一个语句的结果。 以下是具体的 JavaScript 代码实现: ```javascript // 解释器函数 function simpleInterpreter(input) { let value = 0; // 初始值设置为零 const lines = input.split(&#39;\n&#39;); // 按行拆分输入内容 for (let line of lines) { if (!line.trim()) continue; // 跳过空行 // 分割每一行的内容,并去除多余空白 const parts = line.split(/\s+/).map(part => part.trim()); switch(parts[1]) { // &#39;parts[1]&#39; 包含 step 后面的动作关键词 case "add": value += parseInt(parts[2]); break; case "subtract": value -= parseInt(parts[2]); break; case "multiply": value *= parseInt(parts[2]); break; default: console.log(`Unknown command ${parts[1]}`); } } return `Final result is ${value}`; } // 测试用例 const script = ` step 1 add 5; step 2 subtract 3; step 3 multiply 2; `; console.log(simpleInterpreter(script)); ``` 这段代码首先初始化了一个名为 `simpleInterpreter` 的函数接受一串文本作为输入。通过遍历该文本中的各行,依次对其执行相应的数学运算,最终返回累积起来的结果。 此例子展示了如何使用 JavaScript 创建一个非常初级的语言解释器,只涉及到了最基本的概念和技术要点。当然真实的编程语言远比这个复杂得多,涉及到更多方面的考量,包括但不限于错误处理机制以及更复杂的控制流等等。 希望这可以帮助您入门构建自己的简单解释器
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值