自顶向下 逐步求精

将复杂的大问题分解为相对简单的小问题,找出每个问题的关键、重点所在,然后用精确的思维定性、定量地去 描述问题。其核心本质是”分解”。

自顶向下(top-down)的分析算法通过在最左推导中描述出各个步骤来分析记号串输入。之所以称这样的算法为自顶向下是由于分析树隐含的编号是一个前序编号,而且其顺序是由根到叶自顶向下的分析程序有两类:回溯分析程序(backtracking parser)和预测分析程序(predictive parser)。预测分析程序试图利用一个或多个先行记号来预测出输入串中的下一个构造,而回溯分析程序则试着分析其他可能的输入,当一种可能失败时就要求输入中备份任意数量的字符。虽然回溯分析程序比预测分析程序强大许多,但它们都非常慢,一般都在指数的数量级上,所以对于实际的编译器并不合适。

递归下降程序分析和LL(1)分析一般地都要求计算先行集合,它们分别称作First集合和Follow集合。由于无需显式地构造出这些集合就可以构造出简单的自顶向下的分析程序。

以下为用洗衣机的实例解决“自顶向下”方法:
这里写图片描述
如图,从设置模式,水量,到每一步的洗衣过程,都是自顶向下,逐步求解,十分具有条理。
正常洗衣:方法较为复杂,但清洗效果较好,时间也较长。
快速洗衣:方法简单,清洗效果不如正常洗衣,时间较短。

### 关于递归下降解析 `test` 语法规则的流程图 递归下降解析是一种自顶向下的语法分析方法,通常用于实现简单语言的解析器。它通过为文法中的每个非终结符编写一个递归过程来完成语法分析[^1]。对于 `test` 语法规则,假设其文法定义如下: ``` test → expr expr → term { ('+' | '-') term } term → factor { ('*' | '/') factor } factor → number | '(' expr ')' number → [0-9]+ ``` 根据上述文法,递归下降解析的流程可以分为以下几个部分: #### 1. 解析入口 从 `test` 规则开始,调用 `test()` 函数作为解析的入口。 #### 2. 解析 `expr` 规则 `expr` 规则由一个或多个 `term` 和操作符组成。解析过程如下: - 调用 `term()` 解析第一个 `term`。 - 检查当前符号是否为 `'+'` 或 `'-'`,如果是,则继续调用 `term()` 并重复此过程。 ```python def expr(): term() # 解析 term while peek_token() in ['+', '-']: match(peek_token()) # 匹配 '+' 或 '-' term() # 解析下一个 term ``` #### 3. 解析 `term` 规则 `term` 规则由一个或多个 `factor` 和操作符组成。解析过程如下: - 调用 `factor()` 解析第一个 `factor`。 - 检查当前符号是否为 `'*'` 或 `'/'`,如果是,则继续调用 `factor()` 并重复此过程。 ```python def term(): factor() # 解析 factor while peek_token() in ['*', '/']: match(peek_token()) # 匹配 '*' 或 '/' factor() # 解析下一个 factor ``` #### 4. 解析 `factor` 规则 `factor` 规则可以是一个数字或括号包围的表达式。解析过程如下: - 如果当前符号是数字,则匹配并返回。 - 如果当前符号是 `'('`,则递归调用 `expr()`,并确保后续符号为 `')'`。 ```python def factor(): if peek_token() == '(': match('(') # 匹配 '(' expr() # 解析 expr match(')') # 匹配 ')' elif is_number(peek_token()): match_number() # 匹配数字 else: error("Invalid factor") # 报错 ``` #### 5. 辅助函数 - `peek_token()`:查看当前未处理的符号。 - `match(token)`:匹配指定符号,并移动到下一个符号。 - `is_number(token)`:检查符号是否为数字。 ```python def match(expected_token): if peek_token() == expected_token: next_token() # 移动到下一个符号 else: error(f"Expected '{expected_token}', got '{peek_token()}'") def match_number(): if is_number(peek_token()): next_token() # 移动到下一个符号 else: error("Expected a number") ``` ### 流程图描述 以下是 `test` 语法规则的递归下降解析流程图的简要描述: 1. **起点**:从 `test()` 开始。 2. **调用 `expr()`**: - 调用 `term()`。 - 如果遇到 `'+'` 或 `'-'`,继续调用 `term()`。 3. **调用 `term()`**: - 调用 `factor()`。 - 如果遇到 `'*'` 或 `'/'`,继续调用 `factor()`。 4. **调用 `factor()`**: - 如果当前符号是数字,直接匹配。 - 如果当前符号是 `'('`,递归调用 `expr()`,并确保后续符号为 `')'`。 流程图可以用以下伪代码表示: ``` test() ├── expr() │ ├── term() │ │ ├── factor() │ │ │ ├── number │ │ │ └── '(' expr() ')' │ │ └── {'*' | '/'} factor() │ └── {'+' | '-'} term() └── EOF ``` ### 注意事项 在实际实现中,需要确保输入的词法单元序列正确无误,并处理可能的语法错误。此外,递归下降解析器对左递归不友好,因此文法必须经过适当的转换以避免无限递归[^1]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值