当前位置: 首页 > 知识库问答 >
问题:

Antlr4将文本作为字符串而不是单个字符从lexer传递回解析器

邢良才
2023-03-14

我有一个语法,需要在输入流的任何一点处理以‘{*开始,以*}结束’的注释。此外,它还需要处理以“{”开头,后接“$"或与标识符,最后以”}“结尾的模板标记,并将其他内容作为文本传递。

实现这一点的唯一方法似乎是将任何不是注释或标记的东西作为单个字符传递回解析器,并让解析器构建字符串。这是非常低效的,因为解析器必须为它接收到的每个字符构建一个节点,然后我必须遍历这些节点,从这些节点构建一个字符串。如果lexer可以将文本作为一个大字符串返回,我会简单得多,速度也快得多。

在一个I7上运行该程序作为一个32bit#C程序在一个90K的文本文件上,没有标记或注释,只有文本,它需要大约15分钟才能崩溃,并在内存异常中退出。

Parser:
text: ANY_CHAR+;

Lexer:

COMMENT: '{*' .*? '*}' -> skip;

... Token Definitions .....

ANY_CHAR: [ -~];

共有1个答案

高海阳
2023-03-14

是的,这是低效的,但也不是这样做的方式。html" target="_blank">解决方案完全在lexer中。

我明白你想检测评论,模板标记和文本。为此,您应该使用lexer模式。每次点击“{”进入某个lexer模式,比如MODE1,在这里只能检测到“*”或“$”,或者(因为我不明白'{‘后面跟着一个“$”或与标识符)其他东西,这取决于你点击了什么,进入MODE2或MODE3。之后(MODE2或MODE3)等待“}”并切换回默认模式。当然,还有可能在两者之间设置更多模式,这取决于你想要做什么,但对于我刚刚写的内容来说:

  • mode1将在其中确定您现在正在检测注释或模板标记的区域。在此模式中只有两个令牌''和其他所有东西。如果是''转到MODE2,如果有其他内容,转到mode3
  • mode2这里只需要一个标记,那就是COMMENT,但是您还需要检测'*}‘或’}‘(取决于您想要如何处理它)
  • mode3与MODE2类似-检测您需要什么,并拥有一个令牌,该令牌将切换回默认模式。
 类似资料:
  • null null 以下是我的(不完整和不成功的)尝试: 如果不能在lexer中解决这个问题,我可以使用标记、、、、、和自行编写解析器规则。

  • 我正在使用antlr4语法存储库中的JSON语法为编辑器插件解析JSON文件。它可以工作,但逐个报告无效字符。以下片段导致18个lexer错误: 我想通过将相同类型的连续的、无效的单字符令牌作为一个更大的无效令牌来处理,将其缩减为1-2。 对于一个类似的问题,有人建议使用一个自定义的lexer将“未知”元素粘附到较大的令牌上:在antlr4 lexer中,如何有一个规则来捕获所有剩余的“单词”作为

  • 如果在antlr4 lexer中有一个ONELINE_STRING片段规则标识一行上的一个简单引号字符串,那么如何在lexer中创建一个更通用的字符串规则,该规则将相邻的ONELINE_STRING连接起来(即,只要它们都在不同的行上开始,仅用空格和/或注释分隔)? 即, 将被解析为两个字符串标记,“foo”后跟“bar” 同时: 示例1: Sample3(注意,'output'是该语言中的关键字

  • 我有一个具有完整语言名称的字符串,我想将该语言名称的前两个字符设置为文本视图。就像我有一个语言名称南非荷兰语,我只想在我的文本视图上设置AF。我怎么能这么做

  • 问题内容: 我有一个将存储Number对象的列表。该列表将通过分析字符串列表来填充,其中每个字符串都可以表示Number的任何子类。 如何将字符串解析为通用数字,而不是特定的整数或浮点数? 问题答案: 数字不能实例化,因为它是抽象类。我建议传入数字,但是如果您设置为字符串,则可以使用任何子类来解析它们, 要么 @请参阅NumberFormat