ANTLR4 - 定义数组类型的正确方法是什么?

ANTLR4 - What is the correct way to define an array type?

我正在创建自己的语法,到目前为止我只有原始类型。但是,现在我想通过引用添加一个新类型,数组,其格式类似于 Java 或 C#,但我 运行 遇到了我无法使其与 ANTLR 一起工作的问题.

我正在使用的代码示例与此类似:

VariableDefinition
{
    id1: string;
    anotherId: bool;
    arrayVariable: string[5];
    anotherArray: bool[6];
}

MyMethod()
{
    temp: string[3];
    temp2: string;
    temp2 = "Some text";
    temp[0] = temp2;
    temp2 = temp[0];
}

词法分析器包含:

BOOL:                   'bool';
STRING:                 'string';

fragment DIGIT:         [0-9];
fragment LETTER:        [[a-zA-Z\u0080-\u00FF_];
fragment ESCAPE :          '\"' | '\\' ; // Escape 2-char sequences: \" and \
LITERAL_INT:            DIGIT+;
LITERAL_STRING:         '"' (ESCAPE|.)*? '"' ;

OPEN_BRACKET:           '[';
CLOSE_BRACKET:          ']';
COLON:                  ':';
SEMICOLON:              ';';

ID:                     LETTER (LETTER|DIGIT)*;

而我的解析器将是这个的扩展(有更多的规则和其他表达式,但我不认为与这种情况有关系):


global_
    : GLOBAL '{' globalVariables+=variableDefinition* '}'
    ;

variableDefinition
    : name=ID ':' type=type_ ';'                                               
    ;

type_
    : referenceType                     # TypeReference
    | primitiveType                     # TypePrimitive
    ;

primitiveType
    : BOOL                              # TypeBool
    | CHAR                              # TypeChar
    | DOUBLE                            # TypeDouble
    | INT                               # TypeInteger
    | STRING                            # TypeString
    ;

referenceType
    : primitiveType '[' LITERAL_INT ']' # TypeArray
    ;

expression_
    : identifier=expression_ '[' position=expression_ ']'      # AccessArrayExpression
    | left=expression_ operator=( '*' | '/' | '%') right=expression_      # ArithmeticExpression
    | left=expression_ operator=( '+' | '-' ) right=expression_      # ArithmeticExpression
    | value=ID                              # LiteralID

我试过:

type_
    : BOOL                              # TypeBool
    | CHAR                              # TypeChar
    | DOUBLE                            # TypeDouble
    | INT                               # TypeInteger
    | STRING                            # TypeString
    | type_ '[' LITERAL_INT ']'         # TypeArray
    ;
line 23:25 missing ';' at '[5'
line 23:27 mismatched input ']' expecting {'[', ';'}

· 没有空格 (temp: string[5];).

line 23:18 mismatched input 'string[5' expecting {BOOL, 'char', 'double', INT, 'string'}
line 23:26 mismatched input ']' expecting ':'

编辑 1: 这就是尝试生成我给出的示例时树的样子: Parse tree Inspector

对于想要灵活使用空格的语言来说,有这样的规则是很常见的:

WS: [ \t\r\n]+ -> skip; // or channel(HIDDEN)

它应该可以解决您的问题。

这会将空白移到一边,因此您不必在解析器规则中关心它。

如果没有这种方法,您仍然需要定义一个空白规则(与上面相同的模式),但是,如果您不这样做 skip 它(或将其发送给 eat HIDDEN 通道),您必须通过插入 WS? 将它包括在您想要允许空格的任何地方。显然,这有可能变得非常乏味(并且会为您的语法和生成的解析树添加很多“噪音”)。

fragment LETTER:        [[a-zA-Z\u0080-\u00FF_];

您允许 [ 作为字母(因此作为标识符中的字符),因此在 string[5] 中,string[5 被解释为标识符,这使得解析器认为后面的]没有匹配的[。同样在string [5]中,[5被解释为一个标识符,这使得解析器看到两个连续的标识符,这也是不允许的。

要解决此问题,您应该从 LETTER 中删除 [

作为一般提示,当遇到您不理解的解析错误时,您应该尝试查看正在生成的标记以及它们是否符合您的预期。