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

将Lexer中的所有文本匹配并标记为一个标记,直到ANTLR4中的某个字符串为止

薛博艺
2023-03-14
#integer12314#end
#freetextFoo bar#end
    null
tokenOf(#integer) Integer tokenOf(#end) tokenOf(#freetext) TEXT tokenOf(#end)

显然,我可以尝试在lexer语法中以以下方式解决这个问题:

TEXT : [\u0001-\u007f]+? '#end'

但它也将包含结束标记,解析器语法更难看。

(加分题:

  • 如何在文本中正确捕获空格,但可能需要使用lexer模式
  • 如何避免标识符:[a-za-z_[a-za-z0-9_$]*和其他lexer定义的干扰。)

共有1个答案

南门魁
2023-03-14

编辑了任何在lexer规则中添加+的尝试,例如

TEXT : (NOT_END1 ...)+ ;
fragment NOT_END1 : [\u0001-"$-\u007f] ;

消耗太多。

关于other:,请参阅Bart在这里的回答。;

#integer12314#end
#freetext x'010203' #end
#freetext##end
#freetext#e#end
#freetext#en e n d # en nd##end
#freetext#e x'040506' #en  #end
00000000  23 69 6e 74 65 67 65 72  31 32 33 31 34 23 65 6e  |#integer12314#en|
00000010  64 0a 23 66 72 65 65 74  65 78 74 01 02 03 23 65  |d.#freetext...#e|
00000020  6e 64 0a 23 66 72 65 65  74 65 78 74 23 23 65 6e  |nd.#freetext##en|
00000030  64 0a 23 66 72 65 65 74  65 78 74 23 65 23 65 6e  |d.#freetext#e#en|
00000040  64 0a 23 66 72 65 65 74  65 78 74 23 65 6e 20 65  |d.#freetext#en e|
00000050  20 6e 20 64 20 23 20 65  6e 20 6e 64 23 23 65 6e  | n d # en nd##en|
00000060  64 0a 23 66 72 65 65 74  65 78 74 23 65 20 04 05  |d.#freetext#e ..|
00000070  06 23 65 6e 20 20 23 65  6e 64 0a                 |.#en  #end.|
0000007b

文件question_any.g4:

grammar Question_any;

prog
@init {System.out.println("Question_any last update 0901");}
    :   ( line
            {System.out.println("Found line " + $line.source_line + " `" + $line.text + "`");}
        )+ EOF
    ;

line returns [int source_line]
@init {$source_line = getCurrentToken().getLine();}
    :   SHARP_INT INTEGER SHARP_END
    |   SHARP_FREE ANY+ SHARP_END
    ;

SHARP_INT  : '#integer' ;
SHARP_FREE : '#freetext' ;
SHARP_END  : '#end' ;
INTEGER    : [0-9]+ ;
NL         : [\r\n]+ -> skip ;
WS         : [ \t]+ -> channel(HIDDEN) ;

ANY        : [\u0001-\u007f] ; // must be after WS

执行:

$ grun Question_any prog -tokens input.txt 
[@0,0:7='#integer',<'#integer'>,1:0]
[@1,8:12='12314',<INTEGER>,1:8]
[@2,13:16='#end',<'#end'>,1:13]
[@3,18:26='#freetext',<'#freetext'>,2:0]
[@4,27:27='',<ANY>,2:9]
[@5,28:28='',<ANY>,2:10]
[@6,29:29='',<ANY>,2:11]
[@7,30:33='#end',<'#end'>,2:12]
...
[@35,98:106='#freetext',<'#freetext'>,6:0]
[@36,107:107='#',<ANY>,6:9]
[@37,108:108='e',<ANY>,6:10]
[@38,109:109=' ',<WS>,channel=1,6:11]
[@39,110:110='',<ANY>,6:12]
[@40,111:111='',<ANY>,6:13]
[@41,112:112='',<ANY>,6:14]
[@42,113:113='#',<ANY>,6:15]
[@43,114:114='e',<ANY>,6:16]
[@44,115:115='n',<ANY>,6:17]
[@45,116:117='  ',<WS>,channel=1,6:18]
[@46,118:121='#end',<'#end'>,6:20]
[@47,123:122='<EOF>',<EOF>,7:0]
Question_any last update 0901
Found line 1 `#integer12314#end`
Found line 2 `#freetext#end`
Found line 3 `#freetext##end`
Found line 4 `#freetext#e#end`
Found line 5 `#freetext#en e n d # en nd##end`
Found line 6 `#freetext#e #en  #end`

不打印特殊字符。

 类似资料:
  • 我试图用ANTLR创建一个lexer/parser,它可以解析中间分散有标记的纯文本。这些标记由打开({)和关闭(})括号表示,它们表示可以计算为字符串的Java对象,然后在原始输入中替换该字符串,以创建排序的动态模板。 这里有一个例子:{player:name}向你问好!{player:name}应该被玩家的名字替换,并导致输出,即Mark say hi!为了那个叫马克的玩家。 现在我可以很好地

  • 例如,如何在lexer 中找到上一个/左标记 等

  • 对于以下超文本标记语言: 我们可以将第一行与这个xpath匹配-- 我们无法将第2行与此xpath匹配-- BR标记正在运行。Selenium IDE的“Select”功能可以获取DIV标记xpath,但不能深入到它所包含的文本中。 有什么建议吗?

  • 现在生成的匹配器将'~'捕获为未知,但为输入'~~~'创建3'~'未知标记,而不是单个'~~~'标记。我应该做些什么来告诉lexer为未知的连续字符生成单词标记。我还尝试了“未知:.;”和“未知:.+;”没有结果。 编辑:在当前的antlr版本中。+?现在捕获剩余的单词,所以这个问题似乎得到了解决。

  • 问题内容: 在我的数据集中,我有一个字段,用于存储用HTML标记的文本。通用格式如下: 我可以尝试通过以下方法解决问题: 但是,这不是严格的规则,因为 某些条目违反了W3C标准, 并且不包含标签。更糟的是, 可能会缺少结束标记 。因此,我需要为每个可能存在的开始和结束标记包括函数。 我想知道是否有比使用多个嵌套函数更好的方法来完成此任务。不幸的是,我在这种环境中只能使用的语言是SQL和Visual

  • 问题内容: 嗨,我在下面的表格中记录了活动和分数 我需要从活动中返回所有记录 退货 然后我需要基于来自点表的用户ID对用户点求和 退货 一切都很好,但我需要将它们放在一起给用户,即 有指针吗? 问题答案: 使用外部联接: 或子查询: