【问题标题】:antlr 4 lexer rule RULE: '<TAG>'; isn't recognized as token but if fragment rule then recognizedantlr 4 词法分析器规则规则:'<TAG>';不被识别为令牌,但如果片段规则则被识别
【发布时间】:2021-10-26 05:29:07
【问题描述】:

编辑: 有人问我是否可以提供完整的语法。我不能,原因如下:

我不能提供完整的语法代码,因为这是作业,我不能透露我的解决方案,如果我的问题因此无法回答,我会很遗憾地理解。我只是希望这是一件简单的事情,我只是无法从文档中理解,并且这足以让了解 antlr4 的人知道答案。

这已发布在原始答案中,但为了防止可能的帮助者感到沮丧,我现在将其提升到帖子的顶部。 免责声明:这是与作业相关的。

我正在尝试为家庭作业标记一段文本,几乎所有内容都按预期工作,除了以下内容:

TIME                    : '<time>';

这条规则曾经在我的语法中。在对一段文本进行标记时,我看不到 TIME 标记,而是看到一个 '&lt;time&gt;' 标记(我猜 Antlr 以某种方式为我创建了它)。但是当我将字符串本身移动到片段规则并让 TIME 规则指向它时,如下所示:

fragment TIME_TAG       : '<time>';
.
.
.
TIME                    : TIME_TAG;

然后我按预期看到了 TIME 令牌。我已经在互联网上搜索了几个小时,但找不到答案。

发生的另一件事是 ATHLETE 规则,它被定义为:

ATHLETE                 : WHITESPACE* '<athlete>' WHITESPACE*;

也被正确识别,我看到了 ATHLETE 标记,但在 我不允许在标记字符串前后使用WHITESPACE*

我不能提供完整的语法代码,因为这是家庭作业,我不能透露我的解决方案,如果我的问题因此无法回答,我会很遗憾地理解。我只是希望这是一件简单的事情,我只是无法从文档中理解,并且这足以让了解 antlr4 的人知道答案。

这是我的一段文字:

World Record World Record
[1] <time> 9.86 <athlete> "Carl Lewis" <country> "United
States" <date> 25 August 1991
[2] <time> 9.69 <athlete> "Tyson Gay" <country> "United
States" <date> 20 September 2009
[3] <time> 9.82 <athlete> "Donovan Baily" <country>
"Canada" <date> 27 July 1996
[4] <time> 9.58
 <athlete> "Usain Bolt"
 <country> "Jamaica" <date> 16 August 2009

[5] <time> 9.79 <athlete> "Maurice Greene" <country>
"United State" <date> 16 June 1999

我的任务只是标记它。我没有得到令牌的定义,我应该自己决定。我认为'&lt;sometag&gt;' 非常明显,'"' 包裹的字符串、数字、日期和方括号包围的枚举也是如此。

提前感谢任何帮助或任何有用的知识。

【问题讨论】:

  • 正如我在问题中明确指出的那样,不。这是一个家庭作业,我被禁止透露我的解决方案。对不起。
  • 所以我看到你的语法的一个问题与在 ATHLETE 规则中包含 WHITESPACE 的需要有关。你不应该那样做。词法分析器应该将空格分流到隐藏通道,因此WHITESPACE: [ \t\n\r]+ -&gt; channel(HIDDEN);。如果您根本不想将其视为 HIDDEN 令牌,请使用 skip 而不是 channel(HIDDEN)。问题陈述应明确说明如何处理空格。
  • “正如我在问题中明确指出的那样,不。这是家庭作业,我被禁止透露我的解决方案。”好的,然后包含尽可能多的内容,以便原始问题仍然存在。如果其他人无法重现您所描述的内容,则很难为您提供帮助。
  • @kaby76 是的,我不想在标签中添加空格,我也没有。这只是试图找出导致我无法识别标签的原因。我的解决方案是使用碎片,但我不明白为什么它解决了问题以及为什么问题首先存在。
  • @BartKiers 我不是在寻求你的帮助,我也没有说你不愿意。我理解这可能很难提供帮助,如果没有人能够提供帮助,我接受它。你拒绝相信我,但这真的是我可以发布的全部内容。整件事并没有比这更多,任何更多的披露都将是太多。因此,我再说一遍,如果无法帮助我,我接受。但是不,你实际上很不高兴,并认为我想出于某种奇怪的原因向你隐藏我的代码。不,我没有。我希望我可以发布更多。我确实意识到,如果问题不是微不足道的,这可能是至关重要的。我希望它是。

标签: antlr4 tokenize lexical-analysis


【解决方案1】:

(这将是一个挑战,不只是做你的功课,但也许一些 cmet 会让你上路)

TIME : '&lt;time&gt;'; 规则应该可以正常工作。 ANTLR 仅在解析器规则中为您创建标记。 (解析器规则以小写字母开头,而 Lexer 规则以大写字母开头,所以在这个确切的示例中不会出现这种情况(也许您的规则名称以小写字母开头?)

注意:如果您转储令牌,您将看到 TIME 令牌表示如下:

[@3,5:10='<time>',<'<time>'>,2:4]

这意味着 ANTLR 已将其识别为 TIME 令牌(我怀疑这可能是造成混淆的原因。这就是 ANTLR 打印出 TIME 令牌的方式。)

正如@kaby76 所提到的,我们通常会跳过空格或将其放入隐藏通道,因为我们不想在解析器规则中明确说明我们允许空格的任何地方。这些选项中的任何一个都会导致它们被解析器忽略。一个非常常见的空白规则是:

WS: [ \t\r\n]+;`.  

由于您只是进行标记化,因此您无需担心解析器规则。

添加此 Lexer 规则将为您将空格标记为单独的标记,因此您无需在 ATHLETE 等规则中考虑它。

您需要为您的内容制定 Lexer 规则,但这可能会帮助您继续前进。

【讨论】:

  • 谢谢!对我来说,这里有一些新东西。首先:我现在仔细检查了,我的语法中没有小写规则。我有一些片段规则(全大写)和一些全大写的词法分析器规则。我在顶部有“词法分析器语法”声明。我正在使用 q2.tokens 文件根据令牌类型(取自词法分析器)打印令牌。我的 TIME 规则是否有可能最终在此文件中有一个“
  • 另一个问题:我用这个模式来尝试跳过 WS: SKIPPED : [ \t\r\n] -> skip;现在,我知道 + 的作用,它表示前面的一个或多个。 \f 是什么?谷歌称它为表单提要,不知道那是什么。也许这打破了我的跳跃,从而打破了我的 TIME 令牌。我会试试这个。谢谢。另外,是`。到底是有意义的还是错字?
  • \f 字符毕竟是罪魁祸首。非常感谢你!你做了不可能的事,也许是不可能的事。
  • 如果您查看您的 q2.tokens 文件,您会发现您的号码有多个条目。在文件中,我在第一行得到了TIME=1,在文件的更下方得到了 `'
  • \f 是一个错字。我已经纠正了。这意味着形成,但你不太可能遇到它。我的意思是\n
【解决方案2】:

以下实现是一种拆分词法分析器/解析器语法,可“标记”您的输入文件。如果您愿意,可以将两者结合起来。由于 Antlr 词法分析器语法的限制,我通常会拆分我的语法,例如当您想要“超类”词法分析器时。

但是,如果没有明确的问题陈述,此实现可能无法按要求对输入进行标记。所有软件都必须从需求开始。如果作业中没有给出任何内容,那么我将准确说明识别的令牌类型。

在大多数语言中,空格不包含在解析器使用的标记类型集中。因此,我用“->skip”实现了它,它告诉词法分析器不要为识别的输入生成标记。

也不清楚诸如“[1]”之类的输入是作为一个标记还是单独标记。在以下实现中,我为“[”、“1”和“]”生成单独的标记。

可能没有必要使用“片段”规则,因此我不包括对该功能的任何使用。 “片段”规则本身不能用于生成标记,并且该符号不能用于解析器规则。它们对于重用通用 RHS 很有用。你可以阅读更多关于它的信息here

FooLexer.g4:

lexer grammar FooLexer;
Athlete : '<athlete>';
Date : '<date>';
Time : '<time>';
Country : '<country>';
StringLiteral : '"' .*? '"';
Stray : [a-zA-Z]+;
OB : '[';
CB : ']';
Number : [0-9.]+;
Ws : [ \t\r\n]+ -> skip;

FooParser.g4:

parser grammar FooParser;
options { tokenVocab = FooLexer; }
start: .* EOF;

代币:

$ trparse input.txt | trtokens
Time to parse: 00:00:00.0574154
# tokens per sec = 1219.1850966813781
[@0,0:4='World',<6>,1:0]
[@1,6:11='Record',<6>,1:6]
[@2,13:17='World',<6>,1:13]
[@3,19:24='Record',<6>,1:19]
[@4,27:27='[',<7>,2:0]
[@5,28:28='1',<9>,2:1]
[@6,29:29=']',<8>,2:2]
[@7,31:36='<time>',<3>,2:4]
[@8,38:41='9.86',<9>,2:11]
[@9,43:51='<athlete>',<1>,2:16]
[@10,53:64='"Carl Lewis"',<5>,2:26]
[@11,66:74='<country>',<4>,2:39]
[@12,76:91='"United\r\nStates"',<5>,2:49]
[@13,93:98='<date>',<2>,3:8]
[@14,100:101='25',<9>,3:15]
[@15,103:108='August',<6>,3:18]
[@16,110:113='1991',<9>,3:25]
[@17,116:116='[',<7>,4:0]
[@18,117:117='2',<9>,4:1]
[@19,118:118=']',<8>,4:2]
[@20,120:125='<time>',<3>,4:4]
[@21,127:130='9.69',<9>,4:11]
[@22,132:140='<athlete>',<1>,4:16]
[@23,142:152='"Tyson Gay"',<5>,4:26]
[@24,154:162='<country>',<4>,4:38]
[@25,164:179='"United\r\nStates"',<5>,4:48]
[@26,181:186='<date>',<2>,5:8]
[@27,188:189='20',<9>,5:15]
[@28,191:199='September',<6>,5:18]
[@29,201:204='2009',<9>,5:28]
[@30,207:207='[',<7>,6:0]
[@31,208:208='3',<9>,6:1]
[@32,209:209=']',<8>,6:2]
[@33,211:216='<time>',<3>,6:4]
[@34,218:221='9.82',<9>,6:11]
[@35,223:231='<athlete>',<1>,6:16]
[@36,233:247='"Donovan Baily"',<5>,6:26]
[@37,249:257='<country>',<4>,6:42]
[@38,260:267='"Canada"',<5>,7:0]
[@39,269:274='<date>',<2>,7:9]
[@40,276:277='27',<9>,7:16]
[@41,279:282='July',<6>,7:19]
[@42,284:287='1996',<9>,7:24]
[@43,290:290='[',<7>,8:0]
[@44,291:291='4',<9>,8:1]
[@45,292:292=']',<8>,8:2]
[@46,294:299='<time>',<3>,8:4]
[@47,301:304='9.58',<9>,8:11]
[@48,308:316='<athlete>',<1>,9:1]
[@49,318:329='"Usain Bolt"',<5>,9:11]
[@50,333:341='<country>',<4>,10:1]
[@51,343:351='"Jamaica"',<5>,10:11]
[@52,353:358='<date>',<2>,10:21]
[@53,360:361='16',<9>,10:28]
[@54,363:368='August',<6>,10:31]
[@55,370:373='2009',<9>,10:38]
[@56,378:378='[',<7>,12:0]
[@57,379:379='5',<9>,12:1]
[@58,380:380=']',<8>,12:2]
[@59,382:387='<time>',<3>,12:4]
[@60,389:392='9.79',<9>,12:11]
[@61,394:402='<athlete>',<1>,12:16]
[@62,404:419='"Maurice Greene"',<5>,12:26]
[@63,421:429='<country>',<4>,12:43]
[@64,432:445='"United State"',<5>,13:0]
[@65,447:452='<date>',<2>,13:15]
[@66,454:455='16',<9>,13:22]
[@67,457:460='June',<6>,13:25]
[@68,462:465='1999',<9>,13:30]
[@69,466:465='',<-1>,13:34]

【讨论】:

  • 谢谢。我希望我能支持你的答案。确实没有老板会在没有要求的情况下给出任务,但这是一门编译课程,所以我猜讲师希望我们体验必须实际设计语言的体验——从选择令牌开始。你提到了“超类化”词法分析器,我在哪里可以读到它?我正在寻找那个。
  • @יחזקאלהירשהורן github.com/antlr/antlr4/blob/master/doc/…grammar-v4中有很多Antlr的例子,里面包含了丰富的信息。词法分析器的一个示例超类是 here(未优化,即 Java 的慢版本)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-02-04
  • 1970-01-01
  • 1970-01-01
  • 2017-02-27
  • 2017-03-08
相关资源
最近更新 更多