为了账号安全,请及时绑定邮箱和手机立即绑定

以 Go 为目标匹配 ANTLR4 中任何可打印的类字母字符

以 Go 为目标匹配 ANTLR4 中任何可打印的类字母字符

Go
偶然的你 2023-06-01 14:27:39
这把我吓坏了,我就是找不到解决办法。我有一个搜索查询的语法,并且想匹配由可打印字母组成的查询中的任何搜索词,特殊字符“(”,“)”除外。引号中的字符串被单独处理并起作用。问题是 searchterm 太受限制了。它应该匹配注释掉的 NOT_SPECIAL 中的任何字符,即,有效查询将是:Person Name=% Person Address=^%Street%%%$^&*@^但是每当我尝试以任何方式将 NOT_SPECIAL 放入 searchterm 的定义中时,它都不起作用。我也尝试过将它逐字地放入规则中(注释掉 NOT_SPECIAL)和许多其他东西,但它就是行不通。在我的大多数尝试中,语法只是抱怨“=”之后的无关输入,并表示它期待 EOF。但我也不能将 EOF 放入 NOT_SPECIAL。有什么方法可以简单地解析规则字段搜索中“=”之后的每个文本,直到出现空格或“)”、“(”?注意 STRING 规则工作正常,但用户不应该每次都使用引号,因为这是一个命令行工具,他们需要转义。目标语言是围棋。
查看完整描述

1 回答

?
catspeake

TA贡献1111条经验 获得超0个赞

您可以通过引入一个词法模式来解决这个问题,只要您匹配一个EQ记号,您就会进入该词法模式。一旦进入该词法模式,您要么匹配一个(,)要么匹配一个空格(在这种情况下您会跳出词法模式),或者继续匹配您的NOT_SPECIAL字符。

通过使用词法模式,您必须在自己的文件中定义词法分析器和解析器规则。请务必使用lexer grammar ...andparser grammar ...而不是grammar ...您在组合.g4文件中使用的。

快速演示:

lexer grammar MdbLexer;


STRING

 : '"' ~[\r\n"]* '"'

 ;


OPAR

 : '('

 ;


CPAR

 : ')'

 ;


AND

 : 'and'

 ;


OR

 : 'or'

 ;


NOT

 : 'not'

 ;


NO

 : 'no'

 ;


EVERY

 : 'every'

 ;


EQ

 : '=' -> pushMode(NOT_SPECIAL_MODE)

 ;


ID

 : VALID_ID_START VALID_ID_CHAR*

 ;


DIGIT

 : [0-9]

 ;


WS

 : [ \r\n\t]+ -> skip

 ;


fragment VALID_ID_START

 : [a-zA-Z_]

 ;


fragment VALID_ID_CHAR

 : [a-zA-Z_0-9]

 ;


mode NOT_SPECIAL_MODE;


  OPAR2

   : '(' -> type(OPAR), popMode

   ;


  CPAR2

   : ')' -> type(CPAR), popMode

   ;


  WS2

   : [ \t\r\n] -> skip, popMode

   ;


  NOT_SPECIAL

   : ~[ \t\r\n()]+

   ;

您的解析器语法将像这样开始:


parser grammar MdbParser;


options {

    tokenVocab=MdbLexer;

}


start

 : searchclause EOF

 ;


// your other parser rules

我的 Go 有点生疏,但是一个小的 Java 测试:


String source = "Person Address=^%Street%%%$^&*@^()";


MdbLexer lexer = new MdbLexer(CharStreams.fromString(source));


CommonTokenStream tokens = new CommonTokenStream(lexer);

tokens.fill();


for (Token t : tokens.getTokens()) {

  System.out.printf("%-15s %s\n", MdbLexer.VOCABULARY.getSymbolicName(t.getType()), t.getText());

}

打印以下内容:


ID              Person

ID              Address

EQ              =

NOT_SPECIAL     ^%Street%%%$^&*@^

OPAR            (

CPAR            )

EOF             <EOF>


查看完整回答
反对 回复 2023-06-01
  • 1 回答
  • 0 关注
  • 117 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信