首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >ANTLR PopMode: InvalidOperationException

ANTLR PopMode: InvalidOperationException
EN

Stack Overflow用户
提问于 2020-01-24 22:08:16
回答 1查看 104关注 0票数 0

我一直在尝试调试这个错误,但我不知道原因是什么。从堆栈跟踪可以看出,它是在PopMode操作发生的时候发生的。当我开始在树上漫步时,就会发生异常。如果我删除了PopMode操作,就不会有异常,但是标记化没有正确完成。弹回默认模式时,我做错了什么?

词法分析器语法:

代码语言:javascript
复制
lexer grammar BlockLexer;

P_START                 : '!(:' -> pushMode(P_BLOCK);
LINE_START              : '!';
SEPARATOR               : ',' WS* | WS+;
WS                      : ' '   -> channel(HIDDEN);
NEWLINE                 : ((RETURN_CHAR? NEWLINE_CHAR) | RETURN_CHAR) -> popMode;

mode P_BLOCK;
P_CONTENTS              : (LETTER | DIGIT)+ SEPARATOR (LETTER | DIGIT)+ SEPARATOR;

fragment RETURN_CHAR    : '\\r' | '\r';
fragment NEWLINE_CHAR   : '\\n' | '\n';
fragment DIGIT          : [0-9];
fragment LETTER         : [a-zA-Z];

解析器语法:

代码语言:javascript
复制
grammar BlockParser;
options { tokenVocab = BlockLexer; }

block           : comment_line* unit_info_line? comment_line* date_line comment_line*;
p_line          : P_START P_CONTENTS NEWLINE;
comment_line    : LINE_START .*? NEWLINE;

下面是我用来进行解析的C#代码:

代码语言:javascript
复制
var lexer = new BlockLexer(new AntlrInputStream(text));
var parser = new BlockParser(new CommonTokenStream(lexer));
var listener = new BlockListener();
new ParseTreeWalker().Walk(listener, parser.block());

堆栈跟踪:

代码语言:javascript
复制
System.InvalidOperationException
    HResult=0x80131509
    Message=Operation is not valid due to the current state of the object.
    Source=Antlr4.Runtime
    StackTrace:
        at Antlr4.Runtime.Lexer.PopMode()
        at Antlr4.Runtime.Atn.LexerPopModeAction.Execute(Lexer lexer)
        at Antlr4.Runtime.Atn.LexerActionExecutor.Execute(Lexer lexer, ICharStream input, Int32 startIndex)
        at Antlr4.Runtime.Atn.LexerATNSimulator.Accept(ICharStream input, LexerActionExecutor lexerActionExecutor, Int32 startIndex, Int32 index, Int32 line, Int32 charPos)
        at Antlr4.Runtime.Atn.LexerATNSimulator.FailOrAccept(SimState prevAccept, ICharStream input, ATNConfigSet reach, Int32 t)
        at Antlr4.Runtime.Atn.LexerATNSimulator.ExecATN(ICharStream input, DFAState ds0)
        at Antlr4.Runtime.Atn.LexerATNSimulator.Match(ICharStream input, Int32 mode)
        at Antlr4.Runtime.Lexer.NextToken()
        at Antlr4.Runtime.BufferedTokenStream.Fetch(Int32 n)
        at Antlr4.Runtime.BufferedTokenStream.Sync(Int32 i)
        at Antlr4.Runtime.BufferedTokenStream.Consume()
        at Antlr4.Runtime.Atn.ParserATNSimulator.ExecATN(DFA dfa, ITokenStream input, Int32 startIndex, SimulatorState initialState)
        at Antlr4.Runtime.Atn.ParserATNSimulator.ExecDFA(DFA dfa, ITokenStream input, Int32 startIndex, SimulatorState state)
        at Antlr4.Runtime.Atn.ParserATNSimulator.AdaptivePredict(ITokenStream input, Int32 decision, ParserRuleContext outerContext, Boolean useContext)
        at Antlr4.Runtime.Atn.ParserATNSimulator.AdaptivePredict(ITokenStream input, Int32 decision, ParserRuleContext outerContext)
        at MyLibrary.Parser.BlockParser.block() in C:\Projects\mylibrary\MyLibrary.Parser\obj\Debug\BlockParser.cs:line 143
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-01-25 03:41:03

您不能弹出空栈,因此只有在使用过popMode的情况下才允许调用pushMode (并且频率与您推送的频率相同)。

在您的代码中,当您在缺省模式下看到换行符时调用popMode (当您处于块模式时不会调用,因此实际上永远不会离开块模式),这只会在堆栈为空时发生(因为您从不推送默认模式,所以只有在还没有推送任何东西的情况下才能处于缺省模式),所以在缺省模式中遇到换行符总是会导致异常,因为您弹出的是一个空栈。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/59898091

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档