上周写了《ThinkPhp模板转Flask、Django模板》

一时技痒,自然而然地想搞个大家伙,把整个PHP程序转成Python。不比模板,可以用正则匹配偷懒,这次非写一个Php编译器不可。

上网搜了一下,发现大部分Python to xxx的transpile都是直接基于AST,省略了最重要的Tokenizer,Parser。直接写个Visitor了事。要不然就是基于Antlr之类的生成器,搞一大堆代码,看得令人心烦。

既然大家都不想做这个苦力,我就来试试,手工写一个Php编译器。分Tokenizer,Parser,Visitor三个部分来实现。

翻出《龙书》《虎书》做参考,仔细学了一回PHP,不学不知道,原来PHP有那么多特性,做个编译器真心累人。

词法部分很简单,就是一个自动机。设计了一个结构存放自动机,然后简单粗暴地在自动机上编程,也顾不上什么性能了,就是个一锤子买卖。

写得还算快,调试不是很顺,不过我是不会说的,哈

自动机不复杂,发上来大家看看,敬请指正。

self.statemachine = {
'current': {
'state': 'default', 'content': '', 'line': 0},
'default': [
{'name': 'open', 'next': 'php', 'extra': 0, 'start': 0, 'end': 0, 'cache': '',
'token': r'<\?'},
{'name': 'open', 'next': 'php', 'extra': 0, 'start': 0, 'end': 0, 'cache': '',
'token': r'<\?php'}],
'php': [
{'name': 'close', 'next': 'default', 'extra': 0,
'token': r'\?>', 'start': 0, 'end': 0, 'cache': ''},
{'name': 'lnum', 'next': '', 'extra': 0, 'start': 0, 'end': 0, 'cache': '',
'token': r'[0-9]+'},
{'name': 'dnum', 'next': '', 'extra': 0, 'start': 0, 'end': 0, 'cache': '',
'token': r'([0-9]*\.[0-9]+)|([0-9]+\.[0-9]*)'},
{'name': 'exponent', 'next': '', 'extra': 0, 'start': 0, 'end': 0, 'cache': '',
'token': r'(([0-9]+|([0-9]*\.[0-9]+)|([0-9]+\.[0-9]*))[eE][+-]?[0-9]+)'},
{'name': 'hnum', 'next': '', 'extra': 0, 'start': 0, 'end': 0, 'cache': '',
'token': r'0x[0-9a-fA-F]+'},
{'name': 'bnum', 'next': '', 'extra': 0, 'start': 0, 'end': 0, 'cache': '',
'token': r'0b[01]+'},
{'name': 'label', 'next': '', 'extra': 0, 'start': 0, 'end': 0, 'cache': '',
'token': r'[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*'},
{'name': 'comment', 'next': 'commentline', 'extra': 1,
'token': r'//', 'start': 0, 'end': 0, 'cache': ''},
{'name': 'comment', 'next': 'commentline', 'extra': 1,
'token': r'#', 'start': 0, 'end': 0, 'cache': ''},
{'name': 'comment', 'next': 'comment', 'extra': 1,
'token': r'/\*', 'start': 0, 'end': 0, 'cache': ''},
{'name': 'string', 'next': 'string1', 'extra': 1,
'token': r'\'', 'start': 0, 'end': 0, 'cache': ''},
{'name': 'string', 'next': 'string2', 'extra': 1,
'token': r'"', 'start': 0, 'end': 0, 'cache': ''},
{'name': 'symbol', 'next': '', 'extra': 0, 'start': 0, 'end': 0, 'cache': '',
'token': r'[\\\{\};:,\.\[\]\(\)\|\^&\+-/\*=%!~$<>\?@]'}],
'string1': [
{'name': 'string', 'next': 'php', 'extra': 0,
'token': r'\'', 'start': 0, 'end': 0, 'cache': ''},
{'name': 'string', 'next': 'escape1', 'extra': 1,
'token': r'\\', 'start': 0, 'end': 0, 'cache': ''},
{'name': 'string', 'next': '', 'extra': 1,
'token': r'', 'start': 0, 'end': 0, 'cache': ''}],
'escape1': [
{'name': 'string', 'next': 'string1', 'extra': 1,
'token': r'.', 'start': 0, 'end': 0, 'cache': ''}],
'string2': [
{'name': 'string', 'next': 'php', 'extra': 0,
'token': r'\'', 'start': 0, 'end': 0, 'cache': ''},
{'name': 'string', 'next': 'escape2', 'extra': 1,
'token': r'\\', 'start': 0, 'end': 0, 'cache': ''},
{'name': 'string', 'next': '', 'extra': 1,
'token': r'', 'start': 0, 'end': 0, 'cache': ''}],
'escape2': [
{'name': 'string', 'next': 'string2', 'extra': 1,
'token': r'.', 'start': 0, 'end': 0, 'cache': ''}],
'commentline': [
{'name': 'comment', 'next': 'php', 'extra': 0,
'token': r'(\r|\n|\r\n)', 'start': 0, 'end': 0, 'cache': ''},
{'name': 'comment', 'next': 'php', 'extra': 0,
'token': r'', 'start': 0, 'end': 0, 'cache': ''}],
'comment': [
{'name': 'comment', 'next': 'php', 'extra': 0,
'token': r'\*/', 'start': 0, 'end': 0, 'cache': ''},
{'name': 'comment', 'next': '', 'extra': 1,
'token': r'', 'start': 0, 'end': 0, 'cache': ''}]}

源码:converterV0.3.zip

<未完待续>

转换器3:手写PHP转Python编译器,词法部分的更多相关文章

  1. 转换器4:手写PHP转Python编译器,语法解析部分

    写完词法部分,又有很多杂事,周末终于有空来实现伟大的语法解析部分了. 撸完代码之后发现,程序太短了,不算上状态机,才186行(含注释),关键代码不到100行.运行调试过后,发现还行.居然可以解析One ...

  2. 为sproto手写了一个python parser

    这是sproto系列文章的第三篇,可以参考前面的<为sproto添加python绑定>.<为python-sproto添加map支持>. sproto是云风设计的序列化协议,用 ...

  3. 手写 Vue2 系列 之 编译器

    前言 接下来就要正式进入手写 Vue2 系列了.这里不会从零开始,会基于 lyn-vue 直接进行升级,所以如果你没有阅读过 手写 Vue 系列 之 Vue1.x,请先从这篇文章开始,按照顺序进行学习 ...

  4. KNN手写实践:Python基于数据集整体计算以及排序

    1. 距离计算,不要通过遍历每个样本来计算和指定样本距离,而是通过对于指定样本进行广播(复制)成为一个shape和全局一致后,再进行整体计算,这里的广播 / 复制采用的是tile函数来实现的: 2. ...

  5. Python学习宝典,Python400集让你成为从零基础到手写神经网络的Python大神

    当您学完Python,你学到了什么? 开发网站! 或者, 基础语法要点.函数.面向对象编程.调试.IO编程.进程与线程.正则表达式... 当你学完Python,你可以干什么? 当程序员! 或者, 手写 ...

  6. TensorFlow下利用MNIST训练模型识别手写数字

    本文将参考TensorFlow中文社区官方文档使用mnist数据集训练一个多层卷积神经网络(LeNet5网络),并利用所训练的模型识别自己手写数字. 训练MNIST数据集,并保存训练模型 # Pyth ...

  7. 手写 Vue2 系列 之 初始渲染

    前言 上一篇文章 手写 Vue2 系列 之 编译器 中完成了从模版字符串到 render 函数的工作.当我们得到 render 函数之后,接下来就该进入到真正的挂载阶段了: 挂载 -> 实例化渲 ...

  8. 使用神经网络来识别手写数字【译】(三)- 用Python代码实现

    实现我们分类数字的网络 好,让我们使用随机梯度下降和 MNIST训练数据来写一个程序来学习怎样识别手写数字. 我们用Python (2.7) 来实现.只有 74 行代码!我们需要的第一个东西是 MNI ...

  9. 手写数字识别 ----在已经训练好的数据上根据28*28的图片获取识别概率(基于Tensorflow,Python)

    通过: 手写数字识别  ----卷积神经网络模型官方案例详解(基于Tensorflow,Python) 手写数字识别  ----Softmax回归模型官方案例详解(基于Tensorflow,Pytho ...

随机推荐

  1. jQuery 动画的执行

    jQuery 动画的执行 <%@ page language="java" import="java.util.*" pageEncoding=" ...

  2. quick-cocos2d-x添加到Pomelo的支持

    https://github.com/luoxinliang/pomelo_quick_x/tree/master/pomelo_quick_x

  3. ARC使用小结

    内存管理基本原则 内存管理的依循下面的基本原则 自己生成的对象,那么既是其持有者 不是自己生成的对象,也可成为其持有者(一个对象可以被多个人持有) 如果不想持有对象的时候,必须释放其所有权 不能释放已 ...

  4. web前端性能调优(二)

    项目经过第一波优化之后APP端已基本已经符合我们的要求了,但是TV端还是反应比较慢,页面加载和渲染都比较慢了一点,我觉的还是有必要在进行一些优化,经过前面的优化,我们的优化空间已经小了一部分,不过还是 ...

  5. 如何用CSS快速布局(一)—— 布局元素详细

    要快速进行网页排版布局,则必须对布局的元素有清晰的了解,才不会总是在细节处出错.这一篇先详解有关布局的因素作为布局基础:块级元素and内联元素.盒模型.准确定位.元素对齐.样式继承.下一篇则重点描述快 ...

  6. hessian原理解析一(客户端分析)

    hessian 是一款开源的二进制远程通讯协议,使用简单方法提供了RMI功能,主要用于面向对象的消息通信. 优点:跨平台.多语言支持.使用简单 缺点:传递复杂对象性能会下降,不适合安全性高的应用 一 ...

  7. CodeForces 429B

    Working out Time Limit:2000MS     Memory Limit:262144KB     64bit IO Format:%I64d & %I64u   Desc ...

  8. 自己开发轻量级ORM(三)

    上一篇中简单分享了下ORM的设计思路.现在开始讲如何用代码来实现上篇的设计模型. 我们建2个类库来分别抽象数据库表结构关系映射和SQL增删改查操作. 打开VS2010,新建2个类库.分别起名为Mode ...

  9. C++编程练习(17)----“二叉树非递归遍历的实现“

    二叉树的非递归遍历 最近看书上说道要掌握二叉树遍历的6种编写方式,之前只用递归方式编写过,这次就用非递归方式编写试一试. C++编程练习(8)----“二叉树的建立以及二叉树的三种遍历方式“(前序遍历 ...

  10. api接口json串换行

    1.问题描述:在后台输入框中明明回车换行了,但是返回到 app客户端显示出来的 确实带有 \n  这个时候无论怎么调试都不行: 2.铺垫:大家都知道 php输出字符串的时候  使用 单引号 比使用 双 ...