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



我正在创建自己的语法,到目前为止我只有基元类型。然而,现在我想通过引用添加一个新的类型,数组,其格式类似于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];
}

Lexer包含:

BOOL:                   'bool';
STRING:                 'string';
fragment DIGIT:         [0-9];
fragment LETTER:        [[a-zA-Zu0080-u00FF_];
fragment ESCAPE :          '\"' | '\\' ; // Escape 2-char sequences: " and \
LITERAL_INT:            DIGIT+;
LITERAL_STRING:         '"' (ESCAPE|.)*? '"' ;
OPEN_BRACKET:           '[';
CLOSE_BRACKET:          ']';
COLON:                  ':';
SEMICOLON:              ';';
ID:                     LETTER (LETTER|DIGIT)*;

我的Parser将是这个的扩展(有更多的规则和其他表达式,但我不认为这与这个场景有关系(:


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

我试过:

  • 在示例程序中的不同词素之间放置空格,以防lexer出现问题。(没有任何变化(
  • 在type_中创建一个名为arrayType的规则,在arrayType引用type_(由于左递归而失败:ANTLR显示以下错误The following sets of rules are mutually left-recursive [type_, arrayType]
  • 将基元类型和引用类型放入一个规则中
type_
: BOOL                              # TypeBool
| CHAR                              # TypeChar
| DOUBLE                            # TypeDouble
| INT                               # TypeInteger
| STRING                            # TypeString
| type_ '[' LITERAL_INT ']'         # TypeArray
;
  • 结果:·使用空格分隔数组(temp: string [5] ;(
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:这是在尝试生成我给出的示例时树的样子:分析树检查器

fragment LETTER:        [[a-zA-Zu0080-u00FF_];

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

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

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

对于那些希望灵活处理空白的语言来说,有一个规则是很常见的,比如

WS: [ trn]+ -> skip; // or channel(HIDDEN)

它应该能解决你的问题。

这会将空白区转移到一边,这样您就不必在解析器规则中关注它了。

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

相关内容

  • 没有找到相关文章

最新更新