最新文章专题视频专题问答1问答10问答100问答1000问答2000关键字专题1关键字专题50关键字专题500关键字专题1500TAG最新视频文章推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37视频文章20视频文章30视频文章40视频文章50视频文章60 视频文章70视频文章80视频文章90视频文章100视频文章120视频文章140 视频2关键字专题关键字专题tag2tag3文章专题文章专题2文章索引1文章索引2文章索引3文章索引4文章索引5123456789101112131415文章专题3
当前位置: 首页 - 科技 - 知识百科 - 正文

解析转换器3:手写PHP转Python编译器的词法部分

来源:懂视网 责编:小采 时间:2020-11-27 14:25:42
文档

解析转换器3:手写PHP转Python编译器的词法部分

解析转换器3:手写PHP转Python编译器的词法部分:这篇文章解析转换器3:手写PHP转Python编译器的词法部分一时技痒,自然而然地想搞个大家伙,把整个PHP程序转成Python。不比模板,可以用正则匹配偷懒,这次非写一个Php编译器不可。上网搜了一下,发现大部分Python to xxx的transpile都是直接基于A
推荐度:
导读解析转换器3:手写PHP转Python编译器的词法部分:这篇文章解析转换器3:手写PHP转Python编译器的词法部分一时技痒,自然而然地想搞个大家伙,把整个PHP程序转成Python。不比模板,可以用正则匹配偷懒,这次非写一个Php编译器不可。上网搜了一下,发现大部分Python to xxx的transpile都是直接基于A

这篇文章解析转换器3:手写PHP转Python编译器的词法部分

一时技痒,自然而然地想搞个大家伙,把整个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'(
|
|
)', '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': ''}]}

文档

解析转换器3:手写PHP转Python编译器的词法部分

解析转换器3:手写PHP转Python编译器的词法部分:这篇文章解析转换器3:手写PHP转Python编译器的词法部分一时技痒,自然而然地想搞个大家伙,把整个PHP程序转成Python。不比模板,可以用正则匹配偷懒,这次非写一个Php编译器不可。上网搜了一下,发现大部分Python to xxx的transpile都是直接基于A
推荐度:
标签: php 部分 转换器
  • 热门焦点

最新推荐

猜你喜欢

热门推荐

专题
Top