Ant#4与C#的问题。消失的错误消息

时间:2017-04-03 18:26:53

标签: c# antlr4

我想使用Antlr4构建一个GraphQL解析器。目标语言是C#。这是我第一次尝试使用Antlr。

我找到了GraphQL语法here。将其加载到AntlrWorks2并尝试使用以下输入文件运行它:

query queryName($foo: ComplexType, $site: Site = MOBILE) {
  whoever123is: node(id: [123, 456]) {
    id ,
    ... on User @defer {
      field2 {
        id ,
        alias: field1(first:10, after:$foo,) @include(if: $foo) {
          id,
          ...frag
        }
      }
    }
    ... @skip(unless: $foo) {
      id
    }
    ... {
      id
    }
  }
}

Error is not reported Here. Parser just stops

mutation likeStory {
  like(story: 123) @defer {
    story {
      id
    }
  }
}

正如预期的那样,我在“错误”一词时收到错误:

line 29:26 token recognition error at: '. '
[@0,295:299='query',<17>,8:0]
[@1,301:309='queryName',<29>,8:6]
[@2,310:310='(',<6>,8:15]
[@3,311:311='$',<14>,8:16]
[@4,312:314='foo',<29>,8:17]
[@5,315:315=':',<5>,8:20]
[@6,317:327='ComplexType',<29>,8:22]
[@7,330:330='$',<14>,8:35]
[@8,331:334='site',<29>,8:36]
[@9,335:335=':',<5>,8:40]
[@10,337:340='Site',<29>,8:42]
[@11,342:342='=',<8>,8:47]
[@12,344:349='MOBILE',<29>,8:49]
[@13,350:350=')',<3>,8:55]
[@14,352:352='{',<10>,8:57]
[@15,357:368='whoever123is',<29>,9:2]
[@16,369:369=':',<5>,9:14]
[@17,371:374='node',<29>,9:16]
[@18,375:375='(',<6>,9:20]
[@19,376:377='id',<29>,9:21]
[@20,378:378=':',<5>,9:23]
[@21,380:380='[',<4>,9:25]
[@22,381:383='123',<30>,9:26]
[@23,386:388='456',<30>,9:31]
[@24,389:389=']',<1>,9:34]
[@25,390:390=')',<3>,9:35]
[@26,392:392='{',<10>,9:37]
[@27,399:400='id',<29>,10:4]
[@28,409:411='...',<9>,11:4]
[@29,413:414='on',<2>,11:8]
[@30,416:419='User',<29>,11:11]
[@31,421:421='@',<7>,11:16]
[@32,422:426='defer',<29>,11:17]
[@33,428:428='{',<10>,11:23]
[@34,437:442='field2',<29>,12:6]
[@35,444:444='{',<10>,12:13]
[@36,455:456='id',<29>,13:8]
[@37,469:473='alias',<29>,14:8]
[@38,474:474=':',<5>,14:13]
[@39,476:481='field1',<29>,14:15]
[@40,482:482='(',<6>,14:21]
[@41,483:487='first',<29>,14:22]
[@42,488:488=':',<5>,14:27]
[@43,489:490='10',<30>,14:28]
[@44,493:497='after',<29>,14:32]
[@45,498:498=':',<5>,14:37]
[@46,499:499='$',<14>,14:38]
[@47,500:502='foo',<29>,14:39]
[@48,504:504=')',<3>,14:43]
[@49,506:506='@',<7>,14:45]
[@50,507:513='include',<29>,14:46]
[@51,514:514='(',<6>,14:53]
[@52,515:516='if',<29>,14:54]
[@53,517:517=':',<5>,14:56]
[@54,519:519='$',<14>,14:58]
[@55,520:522='foo',<29>,14:59]
[@56,523:523=')',<3>,14:62]
[@57,525:525='{',<10>,14:64]
[@58,538:539='id',<29>,15:10]
[@59,553:555='...',<9>,16:10]
[@60,556:559='frag',<29>,16:13]
[@61,570:570='}',<11>,17:8]
[@62,579:579='}',<11>,18:6]
[@63,586:586='}',<11>,19:4]
[@64,593:595='...',<9>,20:4]
[@65,597:597='@',<7>,20:8]
[@66,598:601='skip',<29>,20:9]
[@67,602:602='(',<6>,20:13]
[@68,603:608='unless',<29>,20:14]
[@69,609:609=':',<5>,20:20]
[@70,611:611='$',<14>,20:22]
[@71,612:614='foo',<29>,20:23]
[@72,615:615=')',<3>,20:26]
[@73,617:617='{',<10>,20:28]
[@74,626:627='id',<29>,21:6]
[@75,634:634='}',<11>,22:4]
[@76,641:643='...',<9>,23:4]
[@77,645:645='{',<10>,23:8]
[@78,654:655='id',<29>,24:6]
[@79,662:662='}',<11>,25:4]
[@80,667:667='}',<11>,26:2]
[@81,670:670='}',<11>,27:0]
[@82,675:679='Error',<29>,29:0]
[@83,681:682='is',<29>,29:6]
[@84,684:686='not',<29>,29:9]
[@85,688:695='reported',<29>,29:13]
[@86,697:700='Here',<29>,29:22]
[@87,703:708='Parser',<29>,29:28]
[@88,710:713='just',<29>,29:35]
[@89,715:719='stops',<29>,29:40]
[@90,724:731='mutation',<18>,31:0]
[@91,733:741='likeStory',<29>,31:9]
[@92,743:743='{',<10>,31:19]
[@93,748:751='like',<29>,32:2]
[@94,752:752='(',<6>,32:6]
[@95,753:757='story',<29>,32:7]
[@96,758:758=':',<5>,32:12]
[@97,760:762='123',<30>,32:14]
[@98,763:763=')',<3>,32:17]
[@99,765:765='@',<7>,32:19]
[@100,766:770='defer',<29>,32:20]
[@101,772:772='{',<10>,32:26]
[@102,779:783='story',<29>,33:4]
[@103,785:785='{',<10>,33:10]
[@104,794:795='id',<29>,34:6]
[@105,802:802='}',<11>,35:4]
[@106,807:807='}',<11>,36:2]
[@107,810:810='}',<11>,37:0]
[@108,813:812='<EOF>',<-1>,38:0]
line 29:0 extraneous input 'Error' expecting {<EOF>, '{', 'fragment', 'query', 'mutation', 'schema', 'scalar', 'type', 'interface', 'enum', 'union', 'input', 'extend', 'directive'}
(document (definition (operationDefinition (operationType query) (name queryName) (variableDefinitions ((variableDefinition (variable $ (name foo)) : (type (typeName (name ComplexType)))) (variableDefinition (variable $ (name site)) : (type (typeName (name Site))) (defaultValue = (value (enumValue (name MOBILE))))) )) (selectionSet { (selection (field (alias (name whoever123is) :) (name node) (arguments ((argument (name id) : (valueWithVariable (arrayValueWithVariable[(valueWithVariable 123) (valueWithVariable 456) ]))) )) (selectionSet { (selection (field (name id))) (selection (inlineFragment... (typeCondition on (typeName (name User))) (directives (directive @ (name defer))) (selectionSet { (selection (field (name field2) (selectionSet { (selection (field (name id))) (selection (field (alias (name alias) :) (name field1) (arguments ((argument (name first) : (valueWithVariable 10)) (argument (name after) : (valueWithVariable (variable $ (name foo)))) )) (directives (directive @ (name include) (arguments ((argument (name if) : (valueWithVariable (variable $ (name foo)))) )))) (selectionSet { (selection (field (name id))) (selection (fragmentSpread... (fragmentName (name frag)))) }))) }))) }))) (selection (inlineFragment... (directives (directive @ (name skip) (arguments ((argument (name unless) : (valueWithVariable (variable $ (name foo)))) )))) (selectionSet { (selection (field (name id))) }))) (selection (inlineFragment... (selectionSet { (selection (field (name id))) }))) }))) }))) Error is not reported Here Parser just stops(definition (operationDefinition (operationType mutation) (name likeStory) (selectionSet { (selection(field(name like)(arguments((argument(name story) : (valueWithVariable 123))))(directives(directive @ (name defer))) (selectionSet { (selection(field(name story)(selectionSet { (selection(field(name id))) }))) }))) }))))

所以,我用这个语法来生成源代码(CSharp目标)。

问题: 如果输入不包含任何错误,我的解析器工作正常。但是如果输入看起来像上面的例子 - 它会默默地停止而不显示/抛出任何错误。结果树只包含一个元素(在输入错误之前解析的所有内容)

我尝试创建不同的错误侦听器,更改恢复策略等。没有任何更改此行为。

任何帮助都非常适合。

1 个答案:

答案 0 :(得分:0)

您需要实现一个BailErrorStrategy,它将覆盖ANTLR4从错误中恢复的能力。

1)加载严格的词法分析器

    AntlrInputStream inputStream = new AntlrInputStream(stream);
    BailLexer lexer = new BailLexer(inputStream);

2)加载严格的解析器:

    parser.RemoveErrorListeners();
    parser.ErrorHandler = new StrictErrorStrategy();

3)创建一个停止词汇错误的BailLexer类(随意调用它):

    public override void Recover(LexerNoViableAltException e)
    {
        throw new ParseCanceledException(BasicEnvironment.SyntaxError);
    }

4)创建一个严格的解析器类,它继承自几个类之一(我使用DefaultErrorStrategy)并覆盖如下所示的三个方法:

public class StrictErrorStrategy : DefaultErrorStrategy
{
    public override void Recover(Parser recognizer, RecognitionException e)
    {
        throw new Exception(message, e);
    }


    public override IToken RecoverInline(Parser recognizer)
    {
        throw new Exception(message, new InputMismatchException(recognizer));
    }


    public override void Sync(Parser recognizer) { }
}

请注意,空的Sync方法会使ANTLR4无法同步输入。