ANTLR解析MismatchedTokenException

| 我正在尝试为我正在编写的更简单的语言编写一个简单的解析器。它由后缀表达式组成。截至目前,解析器出现问题。在输入“ 0”上运行它时,我得到一个MismatchedTokenException。 另外,我将如何实现递归后缀解析器? 这是我的代码:
grammar star;

options {
    language=Python;
    output=AST;
    ASTLabelType=CommonTree;
}

tokens {DECL;}
//start
//  :   decl ;
//decl
//  :   type ID -> ^(DECL type ID)
//  ;

program
    :   (body)+
    ;

body    :   (nested WS)*
    |   (var WS)*
    |   (get WS)*
    ;

var
    :   nested ID \'>>\'
    ;

get
    :   ID \'<<\'
    ;

//expressions

term
    :   INT
    ;

expr
    :   term (term operator)*
    ;

nested
    :   expr (expr operator)*
    ;

operator 
    :   (\'*\' | \'+\' | \'/\' | \'%\' | \'-\')
    ;

ID
    :   (\'a\'..\'z\' | \'A\'..\'Z\') (\'a..z\' | \'0\'..\'9\' | \'A\'..\'Z\')*
    ;

INT
    :   \'0\'..\'9\'+
    ;

WS
    :   (\' \' | \'\\n\' | \'\\t\' | \'\\r\') {$channel=HIDDEN;}
    ;
    
已邀请:
        有几件事是不正确的: 1个 您已将
WS
令牌放在
HIDDEN
通道上,这使得解析器规则无法使用它们。因此,您的
body
规则中的所有
WS
令牌都不正确。 2 _(您的最新编辑删除了左递归问题,但我仍然要对此表示抱歉,您的其他问题具有左递归规则(
expr
),因此我将在此处保留此信息)_ ANTLR是LL解析器生成器,因此您可以创建左递归语法。以下是递归的:
expr
  :  term term operator
  ;

term
  :  INT
  |  ID
  |  expr
  ;
因为
expr
规则内的第一个
term
可能与
expr
规则本身匹配。像任何LL解析器一样,ANTLR生成的解析器无法应对左递归。 3 如果解决了
WS
问题,则
body
规则将产生以下错误消息: (1/7)决策可以使用多种选择匹配输入,例如\“ INT \” 这意味着解析器无法“查看”
INT
令牌所属的规则。这是由于您所有的
body
选项都可以重复零次或更多次,并且times6ѭ和
nested
也可以重复。他们都可以匹配
INT
,这是ANTLR抱怨的。如果这样删除remove18ѭ\:
body
    :   nested
    |   var
    |   get
    ;

// ...

expr
    :   term (term operator)
    ;

nested
    :   expr (expr operator)
    ;
错误会消失(尽管那仍然不会导致您的输入被正确解析!)。 我意识到这听起来似乎还很含糊,但是要解释(或理解您是否是这一切的初学者)并非易事。 4 为了正确地说明
expr
中的递归
expr
,您将需要避免左递归,如我在#2中所述。您可以这样做:
expr
  :  term (expr operator | term operator)*
  ;
仍然是模棱两可的,但这是在使用LL语法描述后缀表达式的情况下,不可避免的AFAIK。要解决此问题,您可以在语法的“ 23”部分中启用全局回溯:
options {
  language=Python;
  output=AST;
  backtrack=true;
}
演示版 关于如何解析递归表达式的一些演示如下所示:
grammar star;

options {
  language=Python;
  output=AST;
  backtrack=true;
}

parse
  :  expr EOF -> expr
  ;

expr
  :  (term -> term) ( expr2 operator -> ^(operator $expr expr2) 
                    | term operator  -> ^(operator term term)
                    )*
  ;

expr2 
  :  expr
  ;

term
  :  INT
  |  ID
  ;

operator 
  :  (\'*\' | \'+\' | \'/\' | \'%\' | \'-\')
  ;

ID
  :  (\'a\'..\'z\' | \'A\'..\'Z\') (\'a..z\' | \'0\'..\'9\' | \'A\'..\'Z\')*
  ;

INT
  :  \'0\'..\'9\'+
  ;

WS
  :  (\' \' | \'\\n\' | \'\\t\' | \'\\r\') {$channel=HIDDEN;}
  ;
测试脚本:
#!/usr/bin/env python
import antlr3
from antlr3 import *
from antlr3.tree import *
from starLexer import *
from starParser import *

def print_level_order(tree, indent):
  print \'{0}{1}\'.format(\'   \'*indent, tree.text)
  for child in tree.getChildren():
    print_level_order(child, indent+1)

input = \"5 1 2 + 4 * + 3 -\"
char_stream = antlr3.ANTLRStringStream(input)
lexer = starLexer(char_stream)
tokens = antlr3.CommonTokenStream(lexer)
parser = starParser(tokens)
tree = parser.parse().tree 
print_level_order(tree, 0)
产生以下输出: --    +       5       *          +             1个             2          4    3 对应于以下AST:     
        问题是您的身体规则永远不会终止,因为它不允许任何匹配。我没有启动ANTLR,我真的不喜欢弄乱它,而是改写了C ++中的语法(使用AX解析器生成器),添加了打印语句来跟踪匹配项,并通过解析ѭ27得到了以下结果:
parsed term: 2
parsed expr: 2
parsed nested: 2
parsed term: 2
parsed expr: 2
parsed nested: 2
parsed body: 2 2
parsed body:
parsed body: ... here goes your infinite loop
如果您有兴趣调试此测试用例,则显示以下AX语法,在打印时设置断点以逐步通过解析器:
using namespace axe;
typedef std::string::iterator It;

auto space = r_any(\" \\t\\n\\r\");
auto int_rule = r_numstr();
auto id = r_ident();
auto op = r_any(\"*+/%-\");
auto term = int_rule 
    >> e_ref([](It i1, It i2)
{ 
    std::cout << \"\\nparsed term: \" << std::string(i1, i2); 
});
auto expr = (term & *(term & op)) 
    >> e_ref([](It i1, It i2)
{ 
    std::cout << \"\\nparsed expr: \" << std::string(i1, i2); 
});
auto nested = (expr & *(expr & op))
    >> e_ref([](It i1, It i2)
{ 
    std::cout << \"\\nparsed nested: \" << std::string(i1, i2); 
});
auto get = (id & \"<<\")  
    >> e_ref([](It i1, It i2)
{ 
    std::cout << \"\\nparsed get: \" << std::string(i1, i2); 
});
auto var = (nested & id & \">>\")  
    >> e_ref([](It i1, It i2)
{ 
    std::cout << \"\\nparsed var: \" << std::string(i1, i2); 
});
auto body = (*(nested & space) | *(var & space) | *(get & space))
     >> e_ref([](It i1, It i2)
{ 
    std::cout << \"\\nparsed body: \" << std::string(i1, i2); 
});
auto program = +(body)
    | r_fail([](It i1, It i2) 
{
    std::cout << \"\\nparsing failed, parsed portion: \" 
        << std::string(i1, i2);
});
// test parser
std::ostringstream text;
text << \"2 2 * test >>\";
std::string str = text.str();
program(str.begin(), str.end());
    

要回复问题请先登录注册