• 欢迎访问搞代码网站,推荐使用最新版火狐浏览器和Chrome浏览器访问本网站!
  • 如果您觉得本站非常有看点,那么赶紧使用Ctrl+D 收藏搞代码吧

如何用Yacc实现一个Python的编译器?

python 搞代码 4年前 (2022-01-09) 21次浏览 已收录 0个评论
文章目录[隐藏]

YACC for ansi C 的文法在很多地方都可以找到了。为什么没有Python的?如何把Python源代码中的grammar编译成yacc的?

回复内容:

理论上是可以的,关键点在于您要在Lexer和Parser之间要多加一层,用于分析哪些地方是进入缩进,哪些地方是退出缩进。然后匹配到缩进的时候插入INDENT和DEDENT这样的Token。

至于分析的方法,您可以先建一个Stack来存放每一层缩进块的Token,
然后根据Lexer送来的Token中的行号、列号等信息来和Stack栈顶的数据进行对比,
判断下来是该进入缩进的就push一个INDENT,并这个INDENT插入到输出的Token流中。
发现是Stack中旧的Token匹配的,就把之前的缩进块pop出来,并在输出的Token流中插入DEDENT。

然后在Paser层面处理语句块的时候可以这样处理(我只写大概意思的伪码,具体您自己看着办)
block ::= INDENT NLS statements NLS DEDENT
if ::= IF LPAREN expression RPAREN COLON block

1:python这种靠缩进的语言的文法其实是上下文有关的,EBNF是表达不出来的,我不知道yacc是不是有什么丧心病狂的扩展来给你做这个。

2:每一行前面的tab的数量你不要看成一堆tab,要把他的数量本身看成一个整体,也就是说再作语法分析的时候其实是:

<code class="language-python"><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="k">def</span> <span class="nf">fuck</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span><span class="k">if</span> <span class="n">true</span><span class="p">:</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span><span class="n">fuck</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span><span class="k">else</span><span class="p">:</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span><span class="n">shit</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="k">def</span> <span class="nf">shit</span><span class="o">..</span></code>

主要是缩进语法的问题吧,只要先在词法上把python的缩进改成类似大括号分界的语法即可,压力在lex这边
cpython源码的token分析是用C手撸的,超长,可以看看源码补充一下 @vczh ,因为是上下文有关的,所以Yacc是不行的,不过我通过 peg, ometa 解决什么问题,ometa-js怎么入门/正确理解和认知? 这个问题知道 PEG 适合进行。

pyPEG 这个项目的主页,底下就有对缩进的分析,可以参考一下。我用C语言实现过一个简化的python解释器,用yacc来分析python的思路如下:
1. 在源程序中插入两个虚拟的TOKEN:TOKEN_BEGIN和TOKEN_END
TOKEN_BEGIN标志语法块的开始,TOKEN_END标志语法块的结束。看一个例子:

<code class="language-python"><span class="k">while</span> <span class="n">i</span> <span class="o"><</span> <span class="mi">100</span><span class="p">:</span><p>本文来源gao!%daima.com搞$代*!码$网9</p>    <span class="k">print</span> <span class="n">i</span>    <span class="n">i</span> <span class="o">+=</span> <span class="mi">1</span>   </code>

还不如直接看python源码里的interpreter好了。COOL都日出来了,python算个DIAO啊,文法拿去,玩吧。写完了我们膜拜一下。
github.com/python-git/p


搞代码网(gaodaima.com)提供的所有资源部分来自互联网,如果有侵犯您的版权或其他权益,请说明详细缘由并提供版权或权益证明然后发送到邮箱[email protected],我们会在看到邮件的第一时间内为您处理,或直接联系QQ:872152909。本网站采用BY-NC-SA协议进行授权
转载请注明原文链接:如何用Yacc实现一个Python的编译器?

喜欢 (0)
[搞代码]
分享 (0)
发表我的评论
取消评论

表情 贴图 加粗 删除线 居中 斜体 签到

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址