Heim >Backend-Entwicklung >Python-Tutorial >如何用Yacc实现一个Python的编译器?

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

WBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWB
WBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOriginal
2016-06-06 16:24:152100Durchsuche

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 class="mi">100</span><span class="p">:</span>
    <span class="k">print</span> <span class="n">i</span>
    <span class="n">i</span> <span class="o">+=</span> <span class="mi">1</span>   
</span></code>
还不如直接看python源码里的interpreter好了。 COOL都日出来了,python算个DIAO啊,文法拿去,玩吧。写完了我们膜拜一下。
github.com/python-git/p
Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn