ANTLR 中的字符串扩充和串联

问题描述 投票:0回答:1

我在使用 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 antlr4 lexer
1个回答
0
投票

您可以利用 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 }"
,您将得到以下结果:

© www.soinside.com 2019 - 2024. All rights reserved.