我一直在尝试调试这个错误,但我不知道原因是什么。从堆栈跟踪可以看出,它是在PopMode操作发生的时候发生的。当我开始在树上漫步时,就会发生异常。如果我删除了PopMode操作,就不会有异常,但是标记化没有正确完成。弹回默认模式时,我做错了什么?
词法分析器语法:
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];解析器语法:
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#代码:
var lexer = new BlockLexer(new AntlrInputStream(text));
var parser = new BlockParser(new CommonTokenStream(lexer));
var listener = new BlockListener();
new ParseTreeWalker().Walk(listener, parser.block());堆栈跟踪:
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发布于 2020-01-25 03:41:03
您不能弹出空栈,因此只有在使用过popMode的情况下才允许调用pushMode (并且频率与您推送的频率相同)。
在您的代码中,当您在缺省模式下看到换行符时调用popMode (当您处于块模式时不会调用,因此实际上永远不会离开块模式),这只会在堆栈为空时发生(因为您从不推送默认模式,所以只有在还没有推送任何东西的情况下才能处于缺省模式),所以在缺省模式中遇到换行符总是会导致异常,因为您弹出的是一个空栈。
https://stackoverflow.com/questions/59898091
复制相似问题