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_ 中创建一个名为 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: 这就是尝试生成我给出的示例时树的样子:
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
中删除 [
。
作为一般提示,当遇到您不理解的解析错误时,您应该尝试查看正在生成的标记以及它们是否符合您的预期。
我正在创建自己的语法,到目前为止我只有原始类型。但是,现在我想通过引用添加一个新类型,数组,其格式类似于 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_ 中创建一个名为 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: 这就是尝试生成我给出的示例时树的样子: 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
中删除 [
。
作为一般提示,当遇到您不理解的解析错误时,您应该尝试查看正在生成的标记以及它们是否符合您的预期。