我在使用 ANTLR 增强字符串时遇到问题。 我的主要问题是,如果我希望augmentedStrings 被正确读取,我必须将字符串保留为解析器规则。 但这会导致字符串有引号、正文(如果有的话)、正文继续和结束引号。 这使得访问者的实现变得更加困难。 当我将字符串规则交换为
string: STRING; STRING: QUOTE ( ESCAPE_SEQUENCE | .)*? QUOTE;
它破坏了augmentedString,这已经是“hackish”了。
下面是语法。
任何的意见都将会有帮助。
使用的测试命令是:antlr4-parse strings.g4 root -gui grammar strings;
// Comments and white space
WS: [ \t\r\n]+ -> skip;
// key words
PLUS: '+';
// Symbols
QUESTION: '?';
LPAREN: '(';
RPAREN: ')';
LCURLY: '{';
RCURLY: '}';
SEMI: ';';
NEWLINE: '\n';
ASSIGN: '=';
QUOTE: '"';
DOLLAR: '$';
// Types
STRING_T: 'string';
type: STRING_T;
value:
| augmentedString
| concatanatedString
| string;
//this has to be changed to a lexer rule inorder to not have a child of every thing
string:
QUOTE ( ESCAPE_SEQUENCE | .)*? QUOTE;
augmentedString:
DOLLAR QUOTE (( ESCAPE_SEQUENCE | .)?( LCURLY expr RCURLY) | ( ESCAPE_SEQUENCE | .)( LCURLY expr RCURLY)? ) * QUOTE;
concatanatedString: (id | augmentedString | string ) (PLUS (id | augmentedString | string))*;
ESCAPE_SEQUENCE:
'\\' (('\\' | '\'' | '"' ) | UNICODE_ESCAPE);
fragment UNICODE_ESCAPE:
'u' HEX_DIGIT HEX_DIGIT HEX_DIGIT HEX_DIGIT;
fragment HEX_DIGIT: [0-9a-fA-F];
// Identifiers
ID: [a-zA-Z_][a-zA-Z_0-9]*;
id: ID;
argument: type id; //maybe replace all with the right hand side.
field: type? id ASSIGN expr SEMI;
// Expressions
expr:
id
|value;
// Statements
statementList: statement*;
statement:
field;
// Add a start rule for testing
root: (
field
)*;
我尝试将字符串规则更改为解析器规则,使用额外的步骤,以及一堆黑客解决方案,例如将字符串拆分为引号和字符串主体,并具有单独的结束主体。
您可以利用 ANTLR 的词法分析器模式。当您遇到
$"
时,您会切换到特殊字符串模式并创建特定于内插字符串的标记。在该模式下,当遇到 {
时,您将再次切换到“代码模式”。遇到 }
后,您会从此代码模式弹出;遇到 "
时,会再次弹出到默认模式。
要使用模式,您必须将词法分析器和解析器语法分开在单独的文件中。快速演示:
// File: ModeDemoLexer.g4
lexer grammar ModeDemoLexer;
PLUS : '+';
SIMPLE_STRING : '"' ~["\r\n]* '"';
STRING_START : '$"' -> pushMode(STRING_MODE);
SPACES : S+ -> skip;
fragment S : [ \t\r\n];
mode STRING_MODE;
STRING_END : '"' -> popMode;
CODE_START : '{' -> pushMode(CODE_MODE);
STRING_ATOM : ~["{];
mode CODE_MODE;
CODE_MODE_SKIP : S+ -> skip;
ID : [a-zA-Z_] [a-zA-Z_0-9]*;
CODE_END : '}' -> popMode;
和:
// File: ModeDemoParser.g4
parser grammar ModeDemoParser;
options {
tokenVocab=ModeDemoLexer;
}
parse
: expr EOF
;
expr
: expr PLUS expr
| string
| SIMPLE_STRING
;
string
: STRING_START string_atom* STRING_END
;
string_atom
: STRING_ATOM
| CODE_START code_expr CODE_END
;
code_expr
: ID
;
如果您现在解析
"normal string" + $"id: { id }"
,您将得到以下结果: