ANTLR4:输入“stringname”时没有可行的替代方案

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

我正在通过使用antlr4制作一种编程语言来进行研究,并且我一整天都在努力解决删除空格后两个单词成为一个标记的问题。

这是我的 antlr 语法:

grammar Grammar;

start: (statement ';')*;

//needs expressions extension
statement
    : variable
    | //class
    | if
    | function
    | loop
    | functionCall
    | show
    ;

variable
    : TYPE ID ('=' VAR_TYPE)?
    | ...
    ;

array 
    : TYPE ID '[]' ('=' '[' VAR_TYPE (',' VAR_TYPE)* ']')?
    ;

//needs expressions extension
function
    : (ACCESS TYPE ID '(' ID* ')' '{' 
        (
            variable
            | if
            | loop
            | functionCall
        ) 'return' VAR_TYPE
      '}')
    | (ACCESS 'void' ID '(' ID* ')' '{' 
        (
            variable
            | if
            | loop
            | functionCall
        )
      '}')
    ;

//needs expressions extension
if: 'if' (ID | VAR_TYPE) COMPARISON (ID | VAR_TYPE) ':'
        (
            '\t' variable
            | '\t' if
            | '\t' loop
            | '\t' functionCall
            | '\t' show
        )*
    ('else if' (ID | VAR_TYPE) COMPARISON (ID | VAR_TYPE) ':'
        (
            '\t' variable
            | '\t' if
            | '\t' loop
            | '\t' functionCall
            | '\t' show
        )*
    )*
    ('else' ':'
        (
            '\t' variable
            | '\t' if
            | '\t' loop
            | '\t' functionCall
            | '\t' show
        )*
    )?
    ;

loop: 'foreach' ID 'in' ID ':'
    (
        '\t' variable
        | '\t' if
        | '\t' loop
        | '\t' functionCall
        | '\t' show
    )*
    ;

functionCall: (ID '.')? ID '()';

//needs expressions extension
show: 'show' '(' (ID | VAR_TYPE)? ('+' (ID | VAR_TYPE))* ')';

ACCESS: 'private' | 'public';
COMPARISON: '>' | '<' | '>=' | '<=' | '==';
TYPE: 'int' | 'float' | 'string';
VAR_TYPE: STRING | INT | BOOL | FLOAT | ID;
ID: [a-zA-Z_][a-zA-Z0-9_]* ;
STRING : '"' .*? '"' ;
INT : [0-9]+ ;
BOOL : 'true' | 'false' ;
FLOAT : [0-9]+ '.' [0-9]+ ;
WS : [ \t\r\n]+ -> skip;

这是制作树后控制台给出的内容:

line 1:7 no viable alternative at input 'stringname'
line 2:4 no viable alternative at input 'intage'

这里还有语法的 input.txt 文件:

string name;
int age;
bool sex;
string children[];

public string returnPerson() {
    return "Name " + name + "\nAge " + age + "\nSex " + sex + "\n";
}

public bool isMinor() {
    if age > 17:
        return false;
    else:
        return true;
}

public void showChildren() {
    int i = 0;
    foreach child in children:
        show("Children №" + (i + 1) + ": " + child + "\n");
}

我基本上只是不知道该怎么办,我已经整理好了空间,但它仍然认为这是一个令牌。另外,通过输出树,我发现它不会超过 input.txt 的前两行。

请帮我解决这个问题。

java antlr antlr4
1个回答
0
投票

你的词法分析器永远不会产生

ID
标记,因为:

VAR_TYPE: STRING | INT | BOOL | FLOAT | ID;
ID: [a-zA-Z_][a-zA-Z0-9_]* ;

因为

VAR_TYPE
也匹配
ID
。 ANTLR 的词法分析器是这样工作的:

  1. 尝试匹配尽可能多的字符的规则
  2. 如果 2 个(或更多)规则匹配相同数量的字符,则让第一个定义的规则“获胜”

由于规则 2,很明显

ID
永远不会匹配。

VAR_TYPE
似乎是解析器规则的更好候选者:

var_type : STRING | INT | BOOL | FLOAT | ID;

但是您发布的语法还有很多其他不正确的地方。如果您在语法中定义了

'()'
,则将不会匹配 dingle
'('
标记。当在解析器规则中创建文字标记时,ANTLR 会像这样为它们创建标记:

functionCall: (ID '.')? ID '()';
show: 'show' '(' expression ')';

T__0 : '.';
T__1 : '()';
T__2 : 'show';
T__3 : '(';
T__4 : ')';
...

如果您现在尝试解析输入:

public string returnPerson() {
    return "Name " + name + "\nAge " + age + "\nSex " + sex + "\n";
}

使用解析器规则:

function
 : ACCESS TYPE ID '(' ...
 ;

它会失败,因为

()
被标记为
T__1
标记,而不是
T__3
T__4
标记。

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