在 lexer/parser 中删除所需的引号
Drop the required surrounding quotes in the lexer/parser
我有几个项目 运行 在我的语法中产生了类似的效果。
我需要解析类似 Key="Value"
的内容
所以我创建了一个语法(为了显示效果我能做的最简单的):
grammar test;
KEY : [a-zA-Z0-9]+ ;
VALUE : DOUBLEQUOTE [ _a-zA-Z0-9.-]+ DOUBLEQUOTE ;
DOUBLEQUOTE : '"' ;
EQUALS : '=' ;
entry : key=KEY EQUALS value=VALUE;
我现在可以解析 thing="One Two Three"
并且在我的代码中收到
key
= thing
value
= "One Two Three"
在我所有的项目中,我最终都需要一个额外的步骤来从值中删除那些 "
。
通常是这样的(我用Java)
String value = ctx.value.getText();
value = value.substring(1, value.length()-1);
在我的实际语法中,我发现很难将周围 "
的检查移动到解析器中。
是否有一种干净的方法可以通过在 lexer/parser 中做一些事情来删除 "
?
基本上我想要 ctx.value.getText()
到 return One Two Three
而不是 "One Two Three"
.
更新:
我一直在研究 Bart Kiers 提供的出色答案,发现这个变体完全符合我的要求。
通过将 DOUBLEQUOTE 放在隐藏的通道上,它们被词法分析器使用并从解析器中隐藏。
TestLexer.g4
lexer grammar TestLexer;
KEY : [a-zA-Z0-9]+;
DOUBLEQUOTE : '"' -> channel(HIDDEN), pushMode(STRING_MODE);
EQUALS : '=';
mode STRING_MODE;
STRING_DOUBLEQUOTE
: '"' -> channel(HIDDEN), type(DOUBLEQUOTE), popMode
;
STRING
: [ _a-zA-Z0-9.-]+
;
和
TestParser.g4
parser grammar TestParser;
options { tokenVocab=TestLexer; }
entry : key=KEY EQUALS value=STRING ;
试试这个:
VALUE
: DOUBLEQUOTE [ _a-zA-Z0-9.-]+ DOUBLEQUOTE
{setText(getText().substring(1, getText().length()-1));}
;
不用说:这将您的语法与 Java 联系在一起,并且(取决于您拥有多少嵌入式 Java 代码)您的语法将很难移植到其他目标语言。
编辑
一旦创建了令牌,就没有 built-in 方法将其分开(除了在嵌入式操作中这样做,正如我所演示的那样)。您正在寻找的 可以 完成,但这意味着重写您的语法,以便字符串文字不会构造为单个标记。这可以通过使用 lexical modes 来完成,以便可以在解析器中构造字符串。
快速演示:
TestLexer.g4
lexer grammar TestLexer;
KEY : [a-zA-Z0-9]+;
DOUBLEQUOTE : '"' -> pushMode(STRING_MODE);
EQUALS : '=';
mode STRING_MODE;
STRING_DOUBLEQUOTE
: '"' -> type(DOUBLEQUOTE), popMode
;
STRING_ATOM
: [ _a-zA-Z0-9.-]
;
TestParser.g4
parser grammar TestParser;
options { tokenVocab=TestLexer; }
entry : key=KEY EQUALS value;
value : DOUBLEQUOTE string_atoms DOUBLEQUOTE;
string_atoms : STRING_ATOM*;
如果您现在 运行 Java 代码:
Lexer lexer = new TestLexer(CharStreams.fromString("Key=\"One Two Three\""));
TestParser parser = new TestParser(new CommonTokenStream(lexer));
TestParser.EntryContext entry = parser.entry();
System.out.println(entry.value().string_atoms().getText());
这将被打印:
One Two Three
我有几个项目 运行 在我的语法中产生了类似的效果。
我需要解析类似 Key="Value"
所以我创建了一个语法(为了显示效果我能做的最简单的):
grammar test;
KEY : [a-zA-Z0-9]+ ;
VALUE : DOUBLEQUOTE [ _a-zA-Z0-9.-]+ DOUBLEQUOTE ;
DOUBLEQUOTE : '"' ;
EQUALS : '=' ;
entry : key=KEY EQUALS value=VALUE;
我现在可以解析 thing="One Two Three"
并且在我的代码中收到
key
=thing
value
="One Two Three"
在我所有的项目中,我最终都需要一个额外的步骤来从值中删除那些 "
。
通常是这样的(我用Java)
String value = ctx.value.getText();
value = value.substring(1, value.length()-1);
在我的实际语法中,我发现很难将周围 "
的检查移动到解析器中。
是否有一种干净的方法可以通过在 lexer/parser 中做一些事情来删除 "
?
基本上我想要 ctx.value.getText()
到 return One Two Three
而不是 "One Two Three"
.
更新:
我一直在研究 Bart Kiers 提供的出色答案,发现这个变体完全符合我的要求。 通过将 DOUBLEQUOTE 放在隐藏的通道上,它们被词法分析器使用并从解析器中隐藏。
TestLexer.g4
lexer grammar TestLexer;
KEY : [a-zA-Z0-9]+;
DOUBLEQUOTE : '"' -> channel(HIDDEN), pushMode(STRING_MODE);
EQUALS : '=';
mode STRING_MODE;
STRING_DOUBLEQUOTE
: '"' -> channel(HIDDEN), type(DOUBLEQUOTE), popMode
;
STRING
: [ _a-zA-Z0-9.-]+
;
和
TestParser.g4
parser grammar TestParser;
options { tokenVocab=TestLexer; }
entry : key=KEY EQUALS value=STRING ;
试试这个:
VALUE
: DOUBLEQUOTE [ _a-zA-Z0-9.-]+ DOUBLEQUOTE
{setText(getText().substring(1, getText().length()-1));}
;
不用说:这将您的语法与 Java 联系在一起,并且(取决于您拥有多少嵌入式 Java 代码)您的语法将很难移植到其他目标语言。
编辑
一旦创建了令牌,就没有 built-in 方法将其分开(除了在嵌入式操作中这样做,正如我所演示的那样)。您正在寻找的 可以 完成,但这意味着重写您的语法,以便字符串文字不会构造为单个标记。这可以通过使用 lexical modes 来完成,以便可以在解析器中构造字符串。
快速演示:
TestLexer.g4
lexer grammar TestLexer;
KEY : [a-zA-Z0-9]+;
DOUBLEQUOTE : '"' -> pushMode(STRING_MODE);
EQUALS : '=';
mode STRING_MODE;
STRING_DOUBLEQUOTE
: '"' -> type(DOUBLEQUOTE), popMode
;
STRING_ATOM
: [ _a-zA-Z0-9.-]
;
TestParser.g4
parser grammar TestParser;
options { tokenVocab=TestLexer; }
entry : key=KEY EQUALS value;
value : DOUBLEQUOTE string_atoms DOUBLEQUOTE;
string_atoms : STRING_ATOM*;
如果您现在 运行 Java 代码:
Lexer lexer = new TestLexer(CharStreams.fromString("Key=\"One Two Three\""));
TestParser parser = new TestParser(new CommonTokenStream(lexer));
TestParser.EntryContext entry = parser.entry();
System.out.println(entry.value().string_atoms().getText());
这将被打印:
One Two Three