编译器:如何解析函数调用和函数定义

imk*_*dal 5 python compiler-construction frontend parsing interpreter

在前面,我正在用 Python 制作一个解释器,而不是一个编译成机器码的实际编译器。我最近浏览了很多编译器构建指南,我了解为解析器生成标记和构建语法树来评估算术表达式的基础知识,但我不太明白如何解析包含函数调用的表达式,像

图(一)

1 + pow(1, 1)
Run Code Online (Sandbox Code Playgroud)

或者当用户定义这样的函数时如何解析行

图(b)

function newFunction( someArgs ){
   ... some magic ...
}
Run Code Online (Sandbox Code Playgroud)

在图(a)中,我应该如何标记这个表达式?阅读保留字“pow”后,我是否应该将所有内容都抓取到右括号并将其传递给解析器?或者我应该包含“pow”、“(”、“1”、“1”和“)”作为单独的标记并将它们添加到我的分析树中?

在斐波那契。(b) 在编译函数定义时,我什至不知道从哪里开始。任何让我朝着正确方向前进的信息将不胜感激。

编辑:我正在使用 Backus-Naur 形式语法:

S ::= 表达式

表达式 ::= 术语 | 术语 ([+-] 术语)+

术语 ::= 因子 | 因子 ([*/] 因子)+

因子 ::= 数字 | ( 表达 )

数字 ::= [0-9]+

小智 1

希望这个问题会有一些好的答案,但我建议您首先做的事情是:

\n\n
    \n
  1. 限制你的语言范围和
  2. \n
  3. 定义你的语法。
  4. \n
\n\n

查看Backus\xe2\x80\x93Naur Form,了解如何定义您的语言将支持的语法。

\n\n

首先,考虑为一些数学函数编写一个简单的解析器,以帮助您理解它。

\n\n
<digit>   ::= "0"|"1"|...|"9"\n<integer> ::= <digit>*\n<expr>    ::= <integer> | <add> | <pow>\n<add>     ::= "add(" <expr> "," <expr> ")"\n<sub>     ::= "sub(" <expr> "," <expr> ")"\n<pow>     ::= "pow(" <expr> "," <expr> ")"\n
Run Code Online (Sandbox Code Playgroud)\n\n

从这样的正式语法中,您可以确定什么是或不是有效的表达式。

\n\n

例如:add(1,2)andpow(2,add(2,1))都有效,而 as 则无效add(1),因为add语法需要两个表达式。

\n

  • 在大多数语言中,函数本质上是指向语句/表达式的顺序列表的指针。如何管理这取决于您。最简单的方法可能是将函数名称作为指向此列表的指针存储在符号表中,当在源代码中找到具有该 id 的标记时,解释器知道要执行指令列表。 (2认同)