上周写了《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': ''
- }]
- }
源码:
<未完待续>
来源: http://www.cnblogs.com/windfic/p/6537042.html