内部如何使用Python语法?

tem*_*ame 16 python grammar language-design python-3.x

我正在努力深入了解Python的工作原理,我一直在查看http://docs.python.org/3.3/reference/grammar.html上显示的语法.

我注意到它说你也必须改变parsermodule.c,但说实话我只是不关注这里发生了什么.

我理解语法是如何阅读语言的规范,但是......我甚至不知道这是什么写的.它看起来几乎像Python,但事实并非如此.

我希望更好地理解这个规范以及Python如何在内部使用它来做.... 什么取决于它(答案是一切,但我的意思是"引擎"的哪个方面正在处理它),使用它的是什么,它如何配合编译/运行脚本?

很难相信整个语言都归结为两页规范......

小智 15

语法用于描述语言中所有可能的字符串.它在指定解析器应如何解析语言时也很有用.

在这个语法中,似乎他们使用自己的EBNF版本,其中非终端是任何小写字,终端全部是大写或用引号括起来.例如,NEWLINE是终端,arith_expr是非终端,"if"也是终端.任何非终端都可以被它的相应生产规则的冒号右边的任何东西替换.例如,如果您查看第一条规则:

single_input:NEWLINE | simple_stmt | compound_stmt NEWLINE

我们可以使用NEWLINE,simple_stmt或者compound_stmt之一替换single_input,后跟NEWLINE.假设我们用"compound_stmt NEWLINE"替换它,那么我们将查找compound_stmt的生产规则:

compound_stmt:if_stmt | while_stmt | for_stmt | try_stmt | with_stmt | funcdef | classdef | 装饰

并选择我们要使用的其中一个,并将其替换为"compound_stmt"(在其中保留NEWLINE)

假设我们想生成有效的python程序:

if 5 < 2 + 3 or not 1 == 5:
    raise
Run Code Online (Sandbox Code Playgroud)

我们可以使用以下派生:

  1. single_input
  2. compound_stmt NEWLINE
  3. if_stmt NEWLINE
  4. 'if'test':'套件NEWLINE
  5. 'if'or_test':'NEWLINE INDENT stmt stmt DEDENT NEWLINE
  6. 'if'and_test'或'and_test':'NEWLINE INDENT simple_stmt DEDENT NEWLINE
  7. 'if'not_test'或'not_test':'NEWLINE INDENT small_stmt DEDENT NEWLINE
  8. 'if'比较'或''不'not_test':'NEWLINE INDENT flow_stmt DEDENT NEWLINE
  9. 'if'expr comp_op expr'或''not'comparison':'NEWLINE INDENT raise_stmt DEDENT NEWLINE
  10. 'if'arith_expr'<'arith_expr'或''not'arith_expr comp_op arith_expr':'NEWLINE INDENT'cree'DEDENT NEWLINE
  11. 'if'term'<'term'+'term'或''not'arith_expr == arith_expr':'NEWLINE INDENT'cree'DedENT NEWLINE
  12. 'if'NUMBER'<'NUMBER'+'NUMBER'或''not'NUMBER == NUM​​BER':'NEWLINE INDENT'提高'DEDENT NEWLINE

这里有几点注意事项,首先,我们必须从一个被列为起始非终端的非终端开始.在该页面中,它们将它们列为single_input,file_input或eval_input.其次,一旦所有符号都是终点(因此名称),就完成推导.第三,更常见的是每行进行一次替换,为了简洁起见,我立刻做了所有可能的替换并开始跳过接近结束的步骤.

给定语言中的字符串,我们如何找到它的推导?这是解析器的工作.解析器反向设计生产序列,首先检查它确实是一个有效的字符串,以及如何从语法中导出它.值得注意的是,许多语法可以描述单一语言.但是,对于给定的字符串,它的推导当然对于每个语法都是不同的.所以从技术上讲,我们为语法而不是语言编写解析器.一些语法更容易解析,一些语法更容易阅读/理解.这个属于前者.

这也没有指定整个语言,只是它的外观.语法没有提到语义.

如果您对解析和语法更感兴趣,我推荐Grune,Jacobs - Parsing Techniques.它是免费的,有益于自学.


Ste*_*nes 8

python语法 - 与大多数其他语法一样 - 以BNFBackus-Naur形式给出.尝试阅读如何阅读它,但基本结构是:

<something> ::= (<something defined elsewhere> | [some fixed things]) [...]
Run Code Online (Sandbox Code Playgroud)

这被<something> 定义为被定义为 something else 多次重复的固定事物.

BNF基于近2000年的描述语言允许结构的格式,非常简洁,将描述给定语言中所有允许的结构,不一定是所有那些有意义的结构.

基本算术可以描述为:

<simple arithmetic expression> ::= <numeric expr>[ ]...(<operator>[ ]...<numeric expr>|<simple arithmetic expression>)
<numeric expr> ::= [<sign>]<digit>[...][.<digit>[...]]
<sign> ::= +|-
<operator> ::= [+-*/]
<digit> ::= [0123456789]
Run Code Online (Sandbox Code Playgroud)

其中说一个简单的算术运算是一个可选的带符号的数字,由一个或多个数字组成,可能带有一个小数点和一个或多个后续数字,后跟可选的空格,后跟恰好其中一个+-*/,可选后跟空格,后跟数字或其他简单的算术运算,即后跟的数字等.

几乎描述所有基本算术运算,并且可以扩展为包括函数等.请注意,它允许无效操作是有效语法,例如:22.34 / -0.0即使结果无效,语法也是有效的.

它有时会让您意识到您可能没有想到的操作,例如:56+-50是有效的操作,2*-102*/3不是.

请注意,SGMLXML/Schema都是相关的,但是用于描述任何语言结构的方法不同.YAML是另一种描述计算机特定语言中允许的结构的方法.

免责声明:我的BNF有点生疏,所以如果我在上述道歉中犯了重大错误,请纠正我.


Amb*_*ber 5

这基本上是EBNF(Extended Backus-Naur Form)规范.

  • 值得补充的是,Python有自己的语法到源语言翻译器,而不是(更常见的)使用bison,byacc或yacc来完成这个技巧. (2认同)