ANTLR PopMode: InvalidOperationException - PullRequest
       8

ANTLR PopMode: InvalidOperationException

0 голосов
/ 24 января 2020

Я пытался отладить эту ошибку, но не знаю, в чем причина. Из того, что я могу сказать через трассировку стека, это происходит, когда происходит действие 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

1 Ответ

1 голос
/ 24 января 2020

Вы не можете вытолкнуть пустой стек, поэтому вы можете вызывать popMode, только если вы использовали pushMode ранее (и только так часто, как вы нажали).

В вашем коде вы вызываете popMode, когда видите новую строку в режиме по умолчанию (и никогда, когда вы находитесь в режиме блокировки, поэтому вы никогда не сможете выйти из режима блокировки), что может произойти только тогда, когда стек пуст (потому что вы никогда не пользуетесь режимом по умолчанию sh, поэтому вы можете находиться в режиме по умолчанию только в том случае, если еще ничего не было передано), поэтому встреча с новой строкой в ​​режиме по умолчанию всегда приведет к исключению, поскольку вы выталкиваете пустой стек .

...