如何识别数学运算符

时间:2017-02-02 08:13:38

标签: python compilation operators lexical-analysis cpython

简单的 2 ++ 2 如何在Python语言的幕后工作?

如果我们在 Python解释器中输入:

>>> 2+++--2
4
>>> 2+++*2
  File "<stdin>", line 1
    2++*2
       ^
SyntaxError: invalid syntax

在这里看语法错误,我注意到它是Python设计人员设计/实现Python的方式。

据说Python是开源代码,所以我开始更多地探索它。 我使用cpython阅读了很多关于Python实现的文章。

所以这里Python编译器很容易识别这些++*%-运算符。 因为它是用 C语言编写的。 C使用一些直接汇编代码编译器,然后转换为机器代码。

问题1: Python编译器如何识别运算符? (关于词汇和解析功能)

问题2 :我如何修改Python解释器的这种简单行为,它可以抛出语法错误,使多个运算符与多次运算符相同

>>> 2**2
4
>>> 2***2
  File "<stdin>", line 1
    2***2
       ^
SyntaxError: invalid syntax

我已阅读过cpython的这些文件:compile.c parser.creadline.c

但是我没有遇到任何关于语法错误的异常处理机制的文件。

更新:

我仍在搜索并等待Question-2的任何答案

1 个答案:

答案 0 :(得分:7)

你绊倒了二元和一元运算符之间的区别。在最简短的术语中,-2实际上是数字&#34;负数2&#34;。 --2是&#34;消极(负2)&#34;或更常规&#34;正2&#34;。 2+++--2被解析为&#34;两个加上正面正面负面消极两个&#34;,因此归结为2+2并为您提供4+2-2都是数字,但*2不是,所以这就是您的语法错误发生的原因。

请继续阅读,如果你想要可怕的细节,但第一段最能直接回答你的问题。

你问了详细信息,所以来了。编程语言(通常是......)由称为无上下文语法的东西定义。使用Bachus Naur Form描述Python的语法。从https://docs.python.org/2/reference/expressions.html#unary-arithmetic-and-bitwise-operations开始,我们有以下定义:

u_expr ::=  power | "-" u_expr | "+" u_expr | "~" u_expr

m_expr ::=  u_expr | m_expr "*" u_expr | m_expr "//" u_expr | m_expr "/" u_expr
            | m_expr "%" u_expr

a_expr ::=  m_expr | a_expr "+" m_expr | a_expr "-" m_expr

这定义了Python语言中的一元表达式,乘法表达式和算术表达式。在我尝试解释之前,我将把这两个都修改为与我们的问题直接相关的位:

u_expr ::=  "2" | "-" u_expr | "+" u_expr

m_expr ::=  u_expr | m_expr "*" u_expr

a_expr ::=  m_expr | a_expr "+" m_expr | a_expr "-" m_expr

因此,在这个语法中,u_expr要么是2,要么就是文字字符串+-,后跟任何其他u_expr所以以下所有内容都符合u_expr的定义:'2', '-2', '+2', '+-2', '++++---++2'

m_expr可以是u_expr,也可以是m_expr,然后是*,后跟u_expr22*22*+22*++-+2都符合此定义。

a_expr可以是m_expr,也可以是a_expr,后跟加号或减号,后跟m_expr22*22+22+2*22++2*-2等。

现在让我们开始查看您的第一个语法错误2+++*2。我们正在尝试将其转换为a_expr。它以2+开头,因此我们必须寻找a_expr "+" m_expr形式的内容。 2a_expr,我们已经得到了我们的文字+,因此对于我们来说语法错误,我们必须以某种方式将++*2转换为{{1} }}。我们可以看到每个m_expr必须以&#34; 2&#34;开头,但是现在解析失败了。

但是,

a_expr可以解析为2+++--2。具体来说,a_expr2,后跟文字a_expr,后跟+,即++--2

关于使m_expr有意义的第二个问题,我担心在Python中你必须重新定义它对程序有效Python的实际意义。查看我链接的文档,您可以看到每个运算符都是明确定义的,对于2***2我们有:

**

像Haskell这样的语言对power ::= primary ["**" u_expr] 之类的东西有着不同的理解,并且可以让你定义自己的任意运算符。在这种语言中,你可以定义一个2+2运算符,但是Python没有这样的功能而没有引发PEP并从根本上重写Python的部分内容。

如果你想要更多的细节,那么你将会沉迷于计算机科学而不是编程 - 是的,它们是不同的。通过查找常规语言,有限状态自动机,无上下文语言和Comsky层次结构等主题开始自己开始