首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

递归下降与生成的解析器 - 效率

递归下降与生成的解析器是编译器设计中的两种不同的解析方法。这两种方法都用于解析文法,并生成语法树。在这里,我们将讨论这两种方法的效率。

  1. 递归下降解析器

递归下降解析器是一种自顶向下的解析方法,它从文法的开始符号开始,递归地向下匹配。当遇到终结符号时,它会返回并继续匹配。递归下降解析器的效率通常较高,因为它可以在解析过程中立即消除歧义。然而,递归下降解析器的缺点是它不能处理左递归和无限左递归的文法。

  1. 生成的解析器

生成的解析器是一种自底向上的解析方法,它从文法的终结符号开始,逐步向上构建语法树。生成的解析器通常可以处理更复杂的文法,包括左递归和无限左递归。然而,生成的解析器的效率通常较低,因为它需要在解析过程中处理大量的冲突和回溯。

总之,递归下降与生成的解析器在效率上有所不同,但它们都可以用于解析文法并生成语法树。选择哪种方法取决于特定的应用场景和文法。

页面内容是否对你有帮助?
有帮助
没帮助

相关·内容

递归下降算法_递归下降分析程序得到经验

这里三层分离,越下层模型中所形成优先级就会越高。 我用递归下降算法写了个简单计算器,递归算法为我运算符号+ – * / 等基础运算符号形成优先级。...在使用过程中发现了递归下降算法很容易产生一个问题,左递归问题。接下来详细描述这个问题,以及解决方案。 什么叫左递归? 举个例子:1-2+1 正确答案应该是0,如果出现左递归答案将会是-2。...所谓递归其实就是算式在进行同等级运算符运算时候强行从右至左进行了运算解析,因为递归下降法中越是后生成运算符其优先级越高,在同等级运算中,就无法确保优先级了,在这里体现就是算式从右至左进行了解析...物理模型图对比: 左递归时候生成Node: 算式1-2+4,越是后面生成优先级就会高于前面生成,所以左递归,会先计算2+4。从而导致错误。...解决方案: 将运算符号抽象出来单独成立一层,将数值节点统统存入Vector,这样的话,在实际生成到内存中需要判断优先级只有+ – * / 四个了,因为递归下降算法,所以只要让 * /在+ –下一级子类中生成

29210

递归循环效率迷思

本文简单比较了一下相同逻辑下,递归实现和循环实现效率差异 已经不记得最初是从哪里获取信息了,自己总有一个印象是递归效率比循环差,因为递归有很大函数调用开销,再加上递归可能存在堆栈溢出问题...不过稍有递归经验朋友都会看出,上面的递归实现会做很多重复计算,更好方式就是缓存一下中间计算结果: // C# Dictionary s_buffer = new Dictionary...,似乎我们应该将之前递归代码改写为这种循环形式,但是 Profile 之后发现,其实循环版本还略慢于递归版本,原因就在于(模拟)调用栈引入抵消了(甚至超过了)函数调用开销....C++ 中实现循环版本还要显著慢于其递归版本....结论 一般而言,将递归代码改写为循环代码可以提高效率,但是一旦改写过程中引入了堆操作,那么结果往往是相反.

1.3K20

教你一招:用70 行 Python 代码编写一个递归下降解析器

我喜欢挑战,并且打算发一个有益帖子,所以我决定用通用递归下降解析器来写它。本着上次相同精神,我打算用尽可能少行数来干这件事,所以它充满了hacks和tricks。...这是个非常重要细节,我会向大家详细说明这一点。 LR版本使用了左递归模式。当LL解析器遇到递归时候,它会尝试去匹配规则。所以,当左递归发生是,解析器会进入无穷递归。...甚至连聪明LL解析器例如ANTLR也逃避不了这个问题,它会以友好错误提示代替无穷递归,而不像我们这个玩具解析器那样。 左递归可以很容易转变为右递归,我就这么做。...但是解析器并不是那么简单,它又会产生另一个问题:当左递归正确解析3-2-1为(3-2)-1,而右递归却错误解析为3-(2-1)。...只需用后处理代码相似的方式对树进行遍历(即DFS后序),并按照其中每条规则进行运算。对于运算器,因为我们使用了递归算法,所以每条规则必须只包含数字和操作符。代码如下: ?

1.2K100

​Python 之父解析器系列之三:生成一个 PEG 解析器

我已经在本系列第二篇文章中简述了解析器基础结构,并展示了一个简单手写解析器,根据承诺,我们将转向从语法中生成解析器。我还将展示如何使用@memoize装饰器,以实现packrat 解析。...参见第1篇、第2篇】 上篇文章我们以一个手写解析器结束。给语法加上一些限制的话,我们很容易从语法中自动生成这样解析器。(我们稍后会解除那些限制。)...我们需要两个东西:一个东西读取语法,并构造一个表现语法规则数据结构;还有一个东西则用该数据结构来生成解析器。我们还需要无聊胶水,我就不提啦。...,这是我们第一个元语法(语法语法),而我们解析器生成器将是一个元编译器(编译器是一个程序,将其它程序从一种语言转译为另一种语言;元编译器是一种编译器,其输入是一套语法,而输出是一个解析器)。...我仍然在抓头发中(译注:极度发愁),如何以最佳方式将协同工作标记生成器缓冲、解析器和记忆缓存作出可视化。或许我会设法生成动画 ASCII 作品,而不仅仅是跟踪日志输出。

72520

Python 之父解析器系列之五:左递归 PEG 语法

我曾几次提及左递归是一块绊脚石,是时候去解决它了。基本问题在于:使用递归下降解析器时,左递归会因堆栈溢出而导致程序终止。 【这是我 PEG 系列第 5 部分。...'+' term | term 如果我们天真地将它翻译成递归下降解析器片段,会得到如下内容: def expr(): if expr() and expect('+') and term(...(pgen 递归规则具有同样问题)。...原始递归语法已经表诉了所需关联性,因此,如果我们可以直接以该形式生成解析器,那将会很好。我们可以!一位粉丝向我指出了一个很好技巧,还附带了一个数学证明,很容易实现。我会试着在这里解释一下。...所以让我们坚持干,并展示一些真实代码。 首先,解析器生成器必须检测哪些规则是左递归。这是图论中一个已解决问题。

80930

不用递归生成无限层级

偶然间,在技术群里聊到生成无限层级树老话题,故此记录下,n年前一次生成无限层级树解决方案 业务场景 处理国家行政区域树,省市区,最小颗粒到医院,后端回包平铺数据大小1M多,前端处理数据后再渲染...,卡顿明显 后端返回数据结构 [ { "id": 1, "name": "中华人民共和国", "parentId": 0, }, {...{ "id": 4001, "name": "杭州市第一人民医院", "parentId": 3001, }, // 其他略 ] 第一版:递归处理树...常规处理方式 // 略,网上一抓一把 第二版:非递归处理树 改进版处理方式 const buildTree = (itemArray, { id = 'id', parentId = 'parentId...item[id]]; // 返回顶层数据 return String(item[parentId]) === topLevelId; }); }; 时间复杂度:O(2n) 最终版:非递归处理树

1K20

循环、递归魔术(四)——递归魔术逻辑初探欣赏

在前面的系列文章里,我们谈到了循环和递归数理逻辑和以及循环魔术艺术逻辑,今天我们进入最后一个议题——递归魔术逻辑。...相关历史文章请戳: 循环、递归魔术(三)——再谈循环魔术逻辑欣赏 循环、递归魔术(二)——循环魔术逻辑浅析欣赏 循环、递归魔术(一)——递归循环数理逻辑 递归魔术逻辑 递归在形态上表示为自相似...那么在魔术上,递归效果可以总结为一种特殊递进。...它和递归一般化归区别一样,递归是化为一个规模变小自己,可以不断进行下去,而化归完全化为另一个问题,是一次性智慧。 接下来我们来看相关魔术作品。...从最宏观角度看,整个作品就是一个递归结构:牌数量不断减少到不可能样子。

70120

循环、递归魔术(一)——递归循环数理逻辑

” 循环和递归本是程序设计中常见两种代码结构,其中循环对应数学描述为迭代,递归即为嵌套自身。而二者共同特性在于必须存在一种跳出机制:循环必有break,而递归必有对最简单情况直接求解返回。...不信你看下图: 图1/2/3 泰姬陵建筑上循环,递归对称 图4 分形之谢尔宾斯基(Sierpinski)三角形 我们大脑天然对这种有一定规律东西感到可以掌控和舒适。...我想,它用展开一列扑克牌来表达其意思应该再合适不过了: 图6 扑克牌序列循环 而递归其实是一种参数化简,形式不变一种化归思想。...所以代码建议中,都建议直接写循环而不是递归,但是,递归确是一种更高级逻辑,有时能够使得代码简洁漂亮。这就看如何把代码可维护调试和效率进行折中了。我们每个人懂得太少,都需要去依赖太多底层。...最后举一个例子,比如遍历一棵树,而树定义就是一种递归定义: 有一个根节点,若干节点有边相连或没有,其中每一个都是一棵树根节点。 这在结构上和一个包子有好几个包子馅或者没有是一样

1.3K21

循环、递归魔术(五)——再谈递归魔术逻辑欣赏

在前面的系列文章里,我们谈到了循环和递归数理逻辑和魔术艺术逻辑,今天我们就递归魔术逻辑,通过一个优雅魔术,来最后对整个系列做一个收尾。...如果不熟悉前面的文章,建议可以先回顾一下: 循环、递归魔术(四)——递归魔术逻辑初探欣赏 循环、递归魔术(三)——再谈循环魔术逻辑欣赏 循环、递归魔术(二)——循环魔术逻辑浅析欣赏...循环、递归魔术(一)——递归循环数理逻辑 在上一篇也提到了,递归逻辑其实是一种自相似的化归,可以无尽推导下去,有一个极限,而在魔术中,在观众期待下,去顺势而为地挑战这个极限,就变得很有意思了...递归简单来看就是递进,但那些递进次数至少三次,且每次递进都可以用同一类模式来建模这类方式叫做魔术递归逻辑。...在理性逻辑和感性艺术之间来回切换感受,我想这就是上帝送给人类最美好精神世界吧! 本系列作品到此结束,希望能对大家数学和魔术思维有所启发,我们下一个系列见!

57110

递归理解实现

本文将通过递归经典案例:求斐波那契数来讲解递归,通过画递归方式来讲解其时间复杂度和空间复杂度以及递归执行顺序,欢迎各位感兴趣开发者阅读本文。...最后一层结点总数,远远超过其他所有层总数。 时间复杂度取决于递归树中一共有多少节点。 所有递归时间复杂度都可以通过递归树来分析。...由于执行递归树中每一层时,都会有一个Call stack操作,将当前层变量(n)放进去,因此递归树中有多少个调用栈取决于递归层数,因此空间复杂度为O(n)。...空间复杂度节点总数关系不大,与其在Call stack里总共存了多少层直接相关。 所有递归空间复杂度都可以通过递归树来分析。...返回到F(3)时,第3步一样,获取其右子树值,然后重复第3至6步步骤,直至计算出F(3)和F(2)值,将其相加就得出了F(4)值,此时F(4)处值就是我们需要求斐波那契数,即图中第6~16

46720

技术分享 | 使用 TiDB SQL 解析器生成 SQL 指纹

---- 本文主要介绍如何借助 TiDB SQL 解析自定义生成 SQL 指纹,采用了一种有别于 pt-fingerprint(https://www.percona.com/doc/percona-toolkit...通过 TiDB SQL 解析器将 SQL 解析成语法树 解析出语法树大致如下,其中"..." 代表之前存在多级。 &ast.SelectStmt { Fields: ......修改语法树上节点对应值 TiDB 语法解析器代码实现了一套访问者设计模式,可以通过实现一个Visitor 来遍历语法树。...按照1中语法树结构,我们只需要在遍历到ast.ValueExpr对象时将他具体数值替换成?...} 总结 使用 TiDB SQL parser 可以快速准确实现 SQL 指纹,相比字符串解析降低了阅读复杂度; 额外你需要花时间了解 TiDB 语法树结构。 ----

1.6K20

递归之原理及汉罗塔递归递归实现

大家好,又见面了,我是你们朋友全栈君。 递归章节 一.什么是递归 递归:简单讲,就是定义一个过程或函数时出现调用本过程或本函数就称为递归。...(1) 从上例就可以看出,递归需要终止递归结束条件。...(2) 递归次数必须是有限次 (3) 可以将一个大问题转化为一个或多个原问题相似规模较小子问题,而这些小问题求解方法原问题相同。 三.可使用递归一些情况: 1....如 阶乘递归:以fun(5)为例 5阶乘分解和求解过程 递归模型一般步骤: (1) 首先,在大问题(第n个问题)假设合理小问题(第n-1个问题) (2) 确定nn-1之间关系,也就是确定递归体...z上 一般有以下三步: (1)Hanio(n-1,x,z,y) (2)mov(n,x,z) (3)Hanio(n-1,y,x,z) 若使用栈时:由于栈是后进先出这种特性; 所以在代码实现时递归实现

49030

c语言函数迭代与递归_递归迭代

递归子问题一定要有解。(即递归一定要有回归条件。)...递归有两个过程: 递推:层层推进,分解问题 回归:层层回归,返回较大问题递归函数缺陷: 1.对栈依赖性太高,需要耗费大量栈空间来实现递推过程 2.逻辑简单,好理解。...递归有两个过程: 递推 回归 2.什么是迭代 迭代是对递归一种优化,递归将递推过程交给了计算机,让计算机代替人去分析问题。而迭代将递推(归纳抽象解决方案)过程交给 了程序员。...进而减小了机器在递推过程中对栈消耗,大大提高了算法效率。...3.递归特点 1.解放了人 2.对栈消耗大 3.算法效率低下,不能过多层递归 4.迭代特点 1.需要人去分析迭代过程 2.减小对栈开销 3.算法效率高 5.什么时候使用递归 1.递归层次不多

1.1K10

按钮生成器!要就是效率

大家好,我是前端实验室大师兄! 按钮是我们页面开发中必不可少一部分。在平常开发中,我们常常一遍又一遍重复写着各种各样按钮样式。 这些简单,但机械重复工作是否影响到你工作效率了呢?...今天,大师兄就为大家推荐一个按钮生成网站。100+款按钮样式和响应方式供你挑选! 准备好了吗?一起来看下吧! 3D款 平面3D效果按钮。...,但就怕产品经理提这样需求。...阴影边框 按钮带点阴影边框,在大师兄项目中算是基本需求了。因为生硬边框总会缺乏点柔和美感。 拷贝个代码来看看。...各种hover状态 浮光掠影效果 镂空效果 滑动效果 增加其他显示 其他 按钮样式和交互功能,对大家来说都是很简单操作。但重复编写这些代码会浪费些许时间。

50120

3.3 栈递归实现

01 栈递归 1、栈还有一个重要应用是在程序设计语言中实现递归。一个直接调用自己或通过一系列调用语句间接调用自己函数,称做递归函数。...2、在高级语言编制程序中,调用函数和调用函数之间链接及信息交换需要通过栈来进行。...(2)为被调用函数局部变量分配存储区。 (3)将控制转移到被调函数入口。 2、从被调函数返回调用函数之前,系统也应该完成3件工作: (1)保存被调函数计算结果。 (2)释放被调函数数据区。...(3)依照被调函数保存返回地址将控制转移到调用函数。...3、一个递归函数运行过程类似于多个函数嵌套调用,只是调用函数和被调函数是同一个函数,因此,和每次调用相关一个重要概念是递归函数运行“层次”。

3863129

3.3 栈递归实现

01栈递归 1、栈还有一个重要应用是在程序设计语言中实现递归。一个直接调用自己或通过一系列调用语句间接调用自己函数,称做递归函数。...2、在高级语言编制程序中,调用函数和调用函数之间链接及信息交换需要通过栈来进行。...(2)为被调用函数局部变量分配存储区。 (3)将控制转移到被调函数入口。 2、从被调函数返回调用函数之前,系统也应该完成3件工作: (1)保存被调函数计算结果。 (2)释放被调函数数据区。...(3)依照被调函数保存返回地址将控制转移到调用函数。...3、一个递归函数运行过程类似于多个函数嵌套调用,只是调用函数和被调函数是同一个函数,因此,和每次调用相关一个重要概念是递归函数运行“层次”。

4952423

汉罗塔c++递归_栈递归区别

汉罗塔问题是一个非常经典算法,我们首先来研究一下修改汉罗塔(简化步骤),在后面我们将来讲述经典汉罗塔问题。...题目: 修改后汉罗塔规则:现在限制不能从最左侧塔直接移动到最右侧,必需要经过中间;同时从最右侧移动到最左测试,同样必需经过中间;要求移动N层塔时,打印最优移动 1、用递归函数实现(从最左移动到最右...层塔移动到右边,然后移动第N层塔到中间,再将1~N-1层塔移动到最左边,将N层塔由中间移动右边;这样,第N层塔就移好了 – 接下来重复上述步骤,将1~N-2层塔移到最右边,将第N-1层塔移到最中间……(利用递归函数实现...HanoiProblem1(2,"left","right"); } int main() { funtest(); getchar(); return 0; } 结果图 2.用栈模拟实现 分析: 我们上面用递归实现...,我们已经知道了基本走法,接下来我们用栈来模拟汉罗塔问题,将塔移动转换为入栈和出栈操作,但是,由题我们知道了参数入栈和出栈两个基本规则 小压大问题,即只有当要入栈参数小于栈顶元素,这时我们才能入栈

43010
领券