当前位置: 首页 > 知识库问答 >
问题:

ANTLR4语法给出了额外的输入错误

卜盛
2023-03-14

我在过去(90年代中期)使用过ANTLR,并决定重新使用它,因为我想为赋值文件中的注释以及Unicode关键字和值提供支持。

我的简单测试文件再次证明,即使使用好的工具,编写正确的语法也是一个困难的问题。我正在使用VS2012的ANTLR语言支持插件,并用C#进行开发。所以,我对Eclipse/Java保留很满意,但是C#插件和ANTLR Nuget包(运行时和代码生成器)完全按照广告所说的那样工作。

我的语法文件是:

grammar AssignmentListFile;

/*
 * See: http://en.wikipedia.org/wiki/List_of_Unicode_characters
 * for list of Unicode Code Points
 */


/*
 * Lexer Rules: Must be in all UPPER case
 * Parser Rules: Must be in all lower case
 */

// Ignore All non-printable control characters except: CR, LF and SPACE
IGNORED_WHITESPACE : 
       (
         '\u0000' .. '\u0009'  // 7-bit control chars less than Line Feed
       | '\u000B'  | '\u000C'  // Vertical tab and Form feed
       | '\u000E' .. '\u001F'  // 7-bit control chars more than Carriage Return
       | '\u007F' .. '\u009F'  // 8-bit ASCII control characters and DEL
       )+
     -> channel(HIDDEN)
     ;

// Ignore Comments and any ending white spaces
JAVADOC_COMMENT  
  : '/**' .*? '*/' [ \r\n]*
  -> channel(HIDDEN)
  ;
CSTYLE_COMMENT  
  : '/*'  .*? '*/'  [ \r\n]*
  -> channel(HIDDEN)
  ;

/*
 * Manage the assignment delimiter and 
 * the 3 white space characters which have not been ignored: SPACE, CR, and LF
 */
fragment SINGLE_SPACE : ' ';
EQUALS : '=';
EOL : SINGLE_SPACE* [\r\n]+ SINGLE_SPACE* ;
ASSIGNMENT_OPERATOR :  SINGLE_SPACE* EQUALS SINGLE_SPACE* ;

// define the various forms of single and double quotes for the dumb, open, and close variants 
                     //   ASCII    Open/Left  Close/Right
CHAR_SINGLEQUOTE : ('\u0027' | '\u2018' | '\u2019') ;
CHAR_DOUBLEQUOTE : ('\u0022' | '\u201C' | '\u201D') ;

/*
 * create the character sets that can be part of an ID
 */
fragment IDCHAR_COMMON : 
         ( '\u0020'  | '\u0021'  // Space and bang (!)
         | '\u0023' .. '\u0026'  // # to & (skips ")
         | '\u0028' .. '\u003C'  // ( to < (skips ')
         | '\u003E' .. '\u007E'  // > to ~ (skips =)
         | '\u00A0' .. '\u2018'  // printable UNICODE code points below  Open Single Quote
         | '\u201A' .. '\u201B'  // printable UNICODE code points between Close Single Quote and Open Double Quote
         | '\u201E' .. '\uFFFF'  // printable UNICODE code points above Close Double Quote
         )
       ;


// define the characters that can be contained in each of the quoted identifier types
NON_QUOTED_VALUE : IDCHAR_COMMON+;
DOUBLE_QUOTED_VALUE : NON_QUOTED_VALUE 
          | (IDCHAR_COMMON |  CHAR_SINGLEQUOTE | EQUALS)+
          ;
SINGLE_QUOTED_VALUE : NON_QUOTED_VALUE 
          | (IDCHAR_COMMON |  CHAR_DOUBLEQUOTE | EQUALS)+
          ;

file : file_line* EOF ;

file_line 
  : assignment
  | EOL
  ;

assignment
  : identifier  ASSIGNMENT_OPERATOR  identifier 
  ;

identifier 
    : NON_QUOTED_VALUE 
    | CHAR_DOUBLEQUOTE DOUBLE_QUOTED_VALUE CHAR_DOUBLEQUOTE 
    | CHAR_SINGLEQUOTE SINGLE_QUOTED_VALUE CHAR_SINGLEQUOTE
    ;

我的输入文件是:

/*
 * This is a Multiline C-Style comment
 * with white space here:   
 */
/* this is a single line C-Style comment  */
/* this is a single line C-Style comment /w whitepace */
/*      

  */
/**/

/**
 * this is a Multiline JavaDoc comment
 * with white space here:    
 */
/** this is a single line JavaDoc comment */
/**     

  */

  /***/     

JOHN=WASHBURN
 JOHN = WASHBURN 
'JOHN'='WASHBURN'
"JOHN" = "WASHBURN"

调用lexer/parser的C#代码是:

  var input = new AntlrInputStream(textStream.ReadToEnd());
  var lexer = new AssignmentListFileLexer(input);
  var tokens = new CommonTokenStream(lexer);
  var parser = new AssignmentListFileParser(tokens);

  Console.WriteLine("\n");
  IParseTree tree = parser.file();
  Console.WriteLine(tree.ToStringTree(parser));
  Console.WriteLine("\n");

并且当您针对测试文件调用此C#时,NUnit的结果是:

line 23:0 extraneous input 'JOHN=WASHBURN' expecting {<EOF>, EOL, CHAR_SINGLEQUOTE, CHAR_DOUBLEQUOTE, NON_QUOTED_VALUE}
line 24:1 extraneous input 'JOHN = WASHBURN ' expecting {<EOF>, EOL, CHAR_SINGLEQUOTE, CHAR_DOUBLEQUOTE, NON_QUOTED_VALUE}
line 25:0 extraneous input ''JOHN'='WASHBURN'' expecting {<EOF>, EOL, CHAR_SINGLEQUOTE, CHAR_DOUBLEQUOTE, NON_QUOTED_VALUE}
line 26:0 extraneous input '"JOHN" = "WASHBURN"' expecting {<EOF>, EOL, CHAR_SINGLEQUOTE, CHAR_DOUBLEQUOTE, NON_QUOTED_VALUE}

(file JOHN=WASHBURN (file_line \r\n ) JOHN = WASHBURN  (file_line \r\n) 'JOHN'='WASHBURN' (file_line \r\n) "JOHN" = "WASHBURN" <EOF>)

我感到困惑的是,4个字符的短语JOHN(或短语WASHBURN)与NON_QUOTED_VALUE不匹配,或者'JOHN'与char_singlequote不匹配。或者“=”或“=”无法匹配赋值规则的原因。

我敢肯定这会是一个doh!!但我错过了什么?

共有1个答案

高功
2023-03-14

4个字符的短语JOHN不被识别为NON_QUOTED_VALUE令牌的原因是JOHN=washburn被识别为double_quoted_value。使用下面的跟踪来检测语法将显示这一点(对不起,是Java代码,但我确信您可以翻译)。

NON_QUOTED_VALUE : IDCHAR_COMMON+  {System.out.println("#A:"+getText());};
DOUBLE_QUOTED_VALUE : NON_QUOTED_VALUE 
          | (IDCHAR_COMMON |  CHAR_SINGLEQUOTE | EQUALS)+ {System.out.println("#B:"+getText());}
          ;
SINGLE_QUOTED_VALUE : NON_QUOTED_VALUE 
          | (IDCHAR_COMMON |  CHAR_DOUBLEQUOTE | EQUALS)+ {System.out.println("#C:"+getText());}
          ;

...产生以下输出...

#B:JOHN=WASHBURN
#B:JOHN = WASHBURN 
#B:'JOHN'='WASHBURN'
#C:"JOHN" = "WASHBURN"

这样做的原因是,识别最长匹配的lexer规则具有优先级。

CHAR_SINGLEQUOTE : ('\u0027' | '\u2018' | '\u2019') ;
CHAR_DOUBLEQUOTE : ('\u0022' | '\u201C' | '\u201D') ;
EQUALS : '=';
EOL : [\r\n]+ ;

IGNORED_WHITESPACE : 
       ( ' '
       | '\u0000' .. '\u0009'  // 7-bit control chars less than Line Feed
       | '\u000B'  | '\u000C'  // Vertical tab and Form feed
       | '\u000E' .. '\u001F'  // 7-bit control chars more than Carriage Return
       | '\u007F' .. '\u009F'  // 8-bit ASCII control characters and DEL
       )+
     -> channel(HIDDEN)
     ;

IDCHAR_COMMON : 
         ( '\u0020'  | '\u0021'  // Space and bang (!)
         | '\u0023' .. '\u0026'  // # to & (skips ")
         | '\u0028' .. '\u003C'  // ( to < (skips ')
         | '\u003E' .. '\u007E'  // > to ~ (skips =)
         | '\u00A0' .. '\u2018'  // printable UNICODE code points below  Open Single Quote
         | '\u201A' .. '\u201B'  // printable UNICODE code points between Close Single Quote and Open Double Quote
         | '\u201E' .. '\uFFFF'  // printable UNICODE code points above Close Double Quote
         )
       ;
NON_QUOTED_VALUE : IDCHAR_COMMON+  {System.out.println("#A:"+getText());};

JAVADOC_COMMENT  
  : '/**' .*? '*/' [ \r\n]*
  -> channel(HIDDEN)
  ;
CSTYLE_COMMENT  
  : '/*'  .*? '*/'  [ \r\n]*
  -> channel(HIDDEN)
  ;


file : file_line* EOF ;

file_line 
  : assignment
  | EOL
  ;

assignment
  : identifier  EQUALS  identifier 
  ;
identifier : NON_QUOTED_VALUE 
           | CHAR_DOUBLEQUOTE (NON_QUOTED_VALUE |  CHAR_SINGLEQUOTE | EQUALS)+ CHAR_DOUBLEQUOTE 
           | CHAR_SINGLEQUOTE (NON_QUOTED_VALUE |  CHAR_DOUBLEQUOTE | EQUALS)+ CHAR_SINGLEQUOTE ;
'JO"HN'='WASHBURN'
"JO='HN" = "WASHBURN"
 类似资料:
  • 我的ANTLR4有问题。我正在尝试从python 3代码打印AST,但有一些错误,我不知道如何修复它们。 我编写了简单的测试代码: 我运行了程序,但出现了以下错误: 我的主要班级: 我有这个网站的语法:https://github.com/antlr/grammars-v4/tree/master/python3

  • 例如,当我为num1输入2,为num2输入3时,我希望在输入第二个数字后立即获得8的输出。但是,程序希望我再输入一个整数,而我只输入一个随机数,如242,它仍然输出8,这意味着它不会影响结果。所以我的问题是为什么有第三个输入?感谢您的帮助!

  • 我正在尝试通过使用if else条件在我的代码中的textbox上添加验证 我在textbox上添加了focusListener,当我从textbox中删除焦点时,它将检查条件 我还在chekbox旁边创建了一个标签,它将根据条件显示文本 如果textbox中的文本不等于“Hi”,则应在textbox旁边的标签中打印“Hello 否则应打印“再见” 请帮忙

  • 我得到了的意外结束。代码对我来说很好,我错过了什么? 安慰:

  • 我需要antlr4来解析一些简单的HTML文件。我已经将语法分为解析器语法和lexer语法,这样我就可以对标记内部的东西( )使用孤岛语法,如“确定的ANTLR4引用”中所述。antlr4反复告诉我“令牌识别错误”。 解析器语法: 示例HTML文件: ANTLR4的输出:

  • 我在第5个小时,我想是时候寻求帮助了。我正在尝试使用Ajax+PHP将表单上的一个图像和一些文本数据上传到数据库。整个系统是: 一个包含表单php处理页面和javascript函数的输入页面,该函数将表单发布到php处理页面,并将结果返回给上的div 问题是javascript中的$.parsejson(data)命令会导致“Input end of Input”错误: 我以为我的javascri