以鶸ice为例,手撸一个解释器(一)明确目标

代码地址

# HelloWorld.ice
print("hello, world")

前言(废话)

其实从开始学习编译原理到现在已经有快半年的时间了,但是其间常常不能坚持看下去龙书(经常三天打鱼两天晒网,更何况每次打鱼不到半小时就累得不行又会放下书(笑)),截至到现在只勉强看完了前六章的部分,半年间其它事也没有做,其实想想上大学已经快两年了还是一事无成,知识也没有学到,不免觉得很羞愧。

暑假也要到了,这个学期马上也要结束了,临近大二结束之际,还是尝试着写一下以前想写的玩具吧,而本系列就是对这段过程的记录,也算是对龙书前六部分的一个小实践&总结(后面的部分可能看完了我也写不出什么东西来)。

其实再写这个解释器之前,我是拿lex + yacc + llvm照着tutorial试着拼过一个编译器,但是llvm对我来说可能有些太难了(苦笑)。残破不堪的代码在lyli分支上。

这个系列的教程(如果可以算作教程的话),其实主要还是实现了前端部分(一样有很多bug),而parser早就被研究透了,所以本教程基本上没有什么价值,可能唯一具有优势的地方就是我跟愿意看这几篇文章的读者大概是相同的入门(或者还未入门)的水平。

本教程分为四章

  1. 明确目标 & 设计语言
  2. 实现词法分析器
  3. 实现语法分析器
  4. 实现基础数据类型

且希望能达到在读者阅读完本系列后,能完成一个支持以下几项的解释器语言

  1. 整型、浮点型以及字符串类型
  2. 常见双目运算符
  3. 变量定义
  4. 函数定义及调用
  5. 基本控制流语句
  6. lambda表达式

适合读者

  1. 对编译原理感兴趣,但是还尚未正式的开始学习
  2. 尝试完成一个玩具解释器但不知道如何下手

正文

在正式手撸之前,我们要先确立我们要撸的是个什么玩意儿(你这不是废话吗摔)。毕竟在后期想要增加一些新的骚操作(新特性)的时候,若没有在一开始进行设计,难免会出现各种重构上令人烦躁的问题(虽然如果你按照本教程撸出来的解释器必然会带来重构上各种糟糕的问题,但是重构本身就是一件会带来各种糟糕的问题的事情(所以就不要介意了)),但是在正式写代码之前进行设计,总是一件应该做的事。

解释什么

从解释器角度来说,我们解释的是字符串,在验证字符串满足规则后进行解释,在解释完之后将其按照语义正确执行,而这个规则就是我们Ice的语法规则。

从词法分析器的角度来说,我们解释是字符串,只需要输入的字符串满足我们为词素指定的规则,然后根据输入的字符串返回token给语法分析器就可以了。

从语法分析的角度来说,我们解释的是token序列,且通过预测分析法依据token序列选择正确的产生式并返回抽象语法树(Abstract Syntax Tree)。

输入形式

只考虑交互式输入(即一行一行的输入)

如何解释

本项目中主要包含以下几个类:

  • Token:实例化的Token对象包含一个词素的类型以及词素值
  • LexicalAnalyzer:解析输入字符串,返回token序列
  • Node:实例化的Node及其派生类对象包含AST中一个节点所应具有的信息
  • SyntaxAnalyzer:根据token序列预测分析,返回AST(实质是一个Node或其派生类实例)
  • IceObject:包括自身类型信息,以及实现相关运算
  • Env:符号表,存储Ice运行时的对象信息
  • Interpreter:只提供run()接口供main函数调用,隐藏内部逻辑

好了,基本上结构就是这样,下面可以着手考虑Ice具备怎么样的语法了。

Ice 语法

整形、浮点型以及字符串类型
1
1.0
"hello, world"
常见双目运算符
1 + 1
(100 + 20) * 6 / 3
10 = 10
5 <= 3
变量定义
@a: 1
函数定义及调用
@add(a, b): a + b

@mul(a, b)
{
    return a * b
}

mul(mul(2, 3), add(2, 3))
基本控制流语句
@fib(n)
{
    if (n = 0) + (n = 1)
    {
        return 1
    }
    else
    {
        return fib(n-1) + fib(n-2)
    }
}

fib(10) # 89

@a: 3
while a
{
    print(a)
    @a: a - 1
}

@a: 0
do {
    @a: a + 1
    if a = 3
    {
        break
    }
    print(a)
} while a < 5

for 1 to 5
{
    @a: a + 1
    if a = 3
    {
        continue
    }
    print(a)
}
lambda表达式
@add(a, b): a + b
@mul: @(a, b){
    return a * b
}
@(a, b){ return a / b }(9, 3)

@quadraticSum: @(a, b){
    @sqrt: @(n){ return n * n }
    return @(a, b){ return a + b }(sqrt(a), sqrt(b))
}

基本上就是这样,那么如果你还继续打算看的话,下一章将会开始手撸Ice的词法分析器。

原文地址:https://www.cnblogs.com/Mu001999/p/8965745.html

时间: 2024-08-29 23:00:39

以鶸ice为例,手撸一个解释器(一)明确目标的相关文章

使用Java Socket手撸一个http服务器

原文连接:使用Java Socket手撸一个http服务器 作为一个java后端,提供http服务可以说是基本技能之一了,但是你真的了解http协议么?你知道知道如何手撸一个http服务器么?tomcat的底层是怎么支持http服务的呢?大名鼎鼎的Servlet又是什么东西呢,该怎么使用呢? 在初学java时,socket编程是逃不掉的一章:虽然在实际业务项目中,使用这个的可能性基本为0,本篇博文将主要介绍如何使用socket来实现一个简单的http服务器功能,提供常见的get/post请求支持

【手撸一个ORM】使用说明

传送门 [手撸一个ORM]第一步.约定和实体描述 [手撸一个ORM]第二步.封装实体描述和实体属性描述 [手撸一个ORM]第三步.SQL语句构造器和SqlParameter封装 [手撸一个ORM]第四步.Expression(表达式目录树)扩展 [手撸一个ORM]第五步.查询条件表达式目录树解析和插入.更新查询目录树解析 [手撸一个ORM]第六步.对象表达式解析和Select表达式解析 [手撸一个ORM]第七步.SqlDataReader转实体 [手撸一个ORM]第八步.实体查询和按需查询 [手

手撸一个SpringBoot的Starter,简单易上手

前言:今天介绍一SpringBoot的Starter,并手写一个自己的Starter,在SpringBoot项目中,有各种的Starter提供给开发者使用,Starter则提供各种API,这样使开发SpringBoot项目变得简单.实际上Starter简单来说就是Spring+SpringMVC开发的.话不多说开始撸代码 1.创建项目 首先在idea中创建SpringBoot项目,并首先创建一个BeautyProperties类,代码代码如下: package com.mystarter; im

来手撸一个小小小小小&quot;3D引擎&quot;

开始的唠叨 说是3D引擎确实有点过于博眼球了,其实就是实现了一个透视投影,当然也不是那么简单的. 此篇文章是纯粹给小白看的 高手请勿喷 .也称之为小向带你图形学入门基础 . 哇哈哈哈哈 一说到做一个3D画面的东东 一说总是到DirectX  OpenGL 这些玩意儿 我们这些菜鸟总是 想到哇擦擦 哇C++的   哇 计算机图形学好难.这玩意儿难度好大.其实就那么回事儿 ,DirectX OpenGL 只是工具 而已, 只要把原理搞懂了 你看我用low逼的GDI照样给你绘制一个3D物体 可以这样说

手撸一个Vue滚动加载自定义指令

用Vue在移动端做滚动加载,使用mint-ui框架, InfiniteScroll指令loadmore组件,在uc浏览器和qq浏览器都无法触发.无奈我只能自己写了. 决定用vue 的自定义指令 写滚动加载. 核心的api document.body.scrollTop 滚动条滚动的距离 (这个有兼容性问题,兼容性写法) let scrollTop = document.documentElement.scrollTop || window.pageYOffset || document.body

99%的程序员都在用Lombok,原理竟然这么简单?我也手撸了一个!|建议收藏!!!

罗曼罗兰说过:世界上只有一种英雄主义,就是看清生活的真相之后依然热爱生活. 对于 Lombok 我相信大部分人都不陌生,但对于它的实现原理以及缺点却鲜为人知,而本文将会从 Lombok 的原理出发,手撸一个简易版的 Lombok,让你理解这个热门技术背后的执行原理,以及它的优缺点分析. 简介 在讲原理之前,我们先来复习一下 Lombok (老司机可以直接跳过本段看原理部分的内容). Lombok 是一个非常热门的开源项目 (https://github.com/rzwitserloot/lomb

.NET手撸2048小游戏

.NET手撸2048小游戏 2048是一款益智小游戏,得益于其规则简单,又和2的倍数有关,因此广为人知,特别是广受程序员的喜爱. 本文将再次使用我自制的"准游戏引擎"FlysEngine,从空白窗口开始,演示如何"手撸"2048小游戏,并在编码过程中感受C#的魅力和.NET编程的快乐. 说明:FlysEngine是封装于Direct2D,重复本文示例,只需在.NET Core 3.0下安装NuGet包FlysEngine.Desktop即可. 并不一定非要做一层封装

编译原理 - 1 手撸状态机词法分析器

感谢vczh轮子叔的坑了的教程,我的编译原理第一次入了个门,词法分析写完了,今后可以看看书继续往下学了. http://www.cppblog.com/vczh/archive/2014/03/02/206014.html 词法分析,就是对于一段代码,把他们分割成一个个的token,同时记录他们的行列号,丢掉不必要的信息,这个词法分析器很简单,简单的状态机就能胜任,用正则就没有自己造轮子的快感了,所以要自己手撸状态机拆token出来. 模仿vczh的语言,我的语言包括了以下要素 标识符:大小写字

Haskell手撸Softmax回归实现MNIST手写识别

Haskell手撸Softmax回归实现MNIST手写识别 前言 初学Haskell,看的书是Learn You a Haskell for Great Good, 才刚看到Making Our Own Types and Typeclasses这一章. 为了加深对Haskell的理解,便动手写了个Softmax回归.纯粹造轮子,只用了base. 显示图片虽然用了OpenGL,但是本文不会提到关于OpenGL的内容.虽说是造轮子, 但是这轮子造得还是使我受益匪浅.Softmax回归方面的内容参考