- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我正在用 C++ 编写一个手工制作的词法分析器和一个解析器。我以这样的方式编写词法分析器,如果它找到例如 ;
,它会打印 "SEMICOLON",如果它找到 while
,它会打印"KEYWORD",如果它找到 hello
,它会打印 "IDENTIFIER" 等等。但是现在我需要将这些标记传递给解析器。例如,如何使用列表来做到这一点?而且我发现我需要存储 token 类型和 token 值
最佳答案
您显然没有使用经典方法,其中解析器调用扫描器来获取下一个标记。通常使用拉式解析器。意思是,解析器通过调用相应的函数从扫描器(Lexer)中提取标记。最常见的扫描器/解析器生成器 Lex/Yacc 或 Flex/Bison 使用这种方法。因此,解析器调用类似 getNextToken 的方法,然后扫描器从输入流中读取字节,直到找到标记。它不会在检测到 token (或错误)之前返回。
还有推送解析器。这里输入流由解析器或其他东西(例如套接字)读取,然后塞入扫描器,直到可以识别 token ,然后将其返回。这有点复杂,因为扫描器需要维护状态。最新的 Bison 版本支持此方法。
两者的共同点是使用类或结构 (POD)“ token ”。此类通常包含 token 类型和一个或多个属性,如值。还有许多经常重载的 setter 和 getter。这通常是解析器和扫描器之间的主要接口(interface)。
据我了解您的方法,您首先运行扫描器,使用整个输入并收集所有 token 。也有可能。然后,您会将所有标记(如上所述)存储在 std::vector(或其他 STL::container)中。然后解析器将访问该 vector 。
对于这种通信,您可以使用中介模式,或者您可以将容器嵌入“上下文”类中,并在扫描器和解析器之间交换它。
您还可以向扫描器类 (getToken) 添加一个成员函数,该函数返回 token 容器的一个元素。为此,您需要维护状态。您的扫描器的迭代器基本上会调用底层容器的迭代器,这也是一个很好的建议。有了它,您可以轻松地遍历您的标记并实现(可能)必要的操作,例如阅读前瞻符号或“取消”某些内容。
以上应该基本上回答了你的问题。
并且,对于简单的语法,这将起作用。但对于更复杂的语法,我会推荐经典方法。可能需要上下文相关扫描。例如。相同的关键字可能会产生不同的标记。这无法通过您的方法处理。
我建议阅读 Lex 和 Yacc,不是因为你应该使用它们,而是为了获得更深入的理解。或者,当然,阅读 Dragon 书或诸如“使用 C 编写编译器”之类的东西
您可能还想查看 2 个编译器示例 here
希望我能帮上一点忙。
关于c++ - 将标记从词法分析器传递到解析器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23583872/
Github:https://github.com/jjvang/PassIntentDemo 我一直在关注有关按 Intent 传递对象的教程:https://www.javacodegeeks.c
我有一个 View ,其中包含自动生成的 text 类型的 input 框。当我单击“通过电子邮件发送结果”按钮时,代码会将您带到 CalculatedResults Controller 中的 Em
我有一个基本的docker镜像,我将以此为基础构建自己的镜像。我没有基础镜像的Dockerfile。 基本上,基本镜像使用两个--env arg,一个接受其许可证,一个选择在容器中激活哪个框架。我可以
假设我想计算 2^n 的总和,n 范围从 0 到 100。我可以编写以下内容: seq { 0 .. 100 } |> Seq.sumBy ((**) 2I) 但是,这与 (*) 或其他运算符/函数不
我有这个网址: http://www.example.com/get_url.php?ID=100&Link=http://www.test.com/page.php?l=1&m=7 当我打印 $_G
我想将 window.URL.createObjectURL(file) 创建的地址传递给 dancer.js 但我得到 GET blob:http%3A//localhost/b847c5cd-aa
我想知道如何将 typedef 传递给函数。例如: typedef int box[3][3]; box empty, *board[3][3]; 我如何将 board 传递给函数?我
我正在将一些代码从我的 Controller 移动到核心数据应用程序中的模型。 我编写了一个方法,该方法为我定期发出的特定获取请求返回 NSManagedObjectID。 + (NSManagedO
为什么我不能将类型化数组传递到采用 any[] 的函数/构造函数中? typedArray = new MyType[ ... ]; items = new ko.observableArray(ty
我是一名新的 Web 开发人员,正在学习 html5 和 javascript。 我有一个带有“选项卡”的网页,可以使网页的某些部分消失并重新出现。 链接如下: HOME 和 JavaScript 函
我试图将对函数的引用作为参数传递 很难解释 我会写一些伪代码示例 (calling function) function(hello()); function(pass) { if this =
我在尝试调用我正在创建的 C# 项目中的函数时遇到以下错误: System.Runtime.InteropServices.COMException: Operation is not allowed
使用 ksh。尝试重用当前脚本而不修改它,基本上可以归结为如下内容: `expr 5 $1 $2` 如何将乘法命令 (*) 作为参数 $1 传递? 我首先尝试使用“*”,甚至是\*,但没有用。我尝试
我一直在研究“Play for Java”这本书,这本书非常棒。我对 Java 还是很陌生,但我一直在关注这些示例,我有点卡在第 3 章上了。可以在此处找到代码:Play for Java on Gi
我知道 Javascript 中的对象是通过引用复制/传递的。但是函数呢? 当我跳到一些令人困惑的地方时,我正在尝试这段代码。这是代码片段: x = function() { console.log(
我希望能够像这样传递参数: fn(a>=b) or fn(a!=b) 我在 DjangoORM 和 SQLAlchemy 中看到了这种行为,但我不知道如何实现它。 最佳答案 ORM 使用 specia
在我的 Angular 项目中,我最近将 rxjs 升级到版本 6。现在,来自 npm 的模块(在 node_modules 文件夹内)由于一些破坏性更改而失败(旧的进口不再有效)。我为我的代码调整了
这个问题在这里已经有了答案: The issue of * in Command line argument (6 个答案) 关闭 3 年前。 我正在编写一个关于反向波兰表示法的 C 程序,它通过命
$(document).ready(function() { function GetDeals() { alert($(this).attr("id")); } $('.filter
下面是一个例子: 复制代码 代码如下: use strict; #这里是两个数组 my @i =('1','2','3'); my @j =('a','b','c'); &n
我是一名优秀的程序员,十分优秀!