任何与'not'scala解析器组合相当的antlr4?

时间:2014-11-13 13:50:07

标签: comments antlr4 nested equivalent parser-combinators

我正在将一个语法从scala组合器移植到antlr4,原始语法使用'not(p:Parser)'解析器组合器,当封闭的解析器失败时会成功。

在我移植的解析器中,我使用'not'组合器来区分以

开头的特殊注释
'/*!' 

以标准评论开头

'/*'

同时在特殊注释中允许标准注释(多行或行尾),并允许嵌套在注释中的注释:

以下是原始的scala代码:

/* Annotation blocks with user defined contents. */
lazy val specialComment: PackratParser[Any] = specialCommentBegin ~> rep(  not( multilineCommentEnd ) ~ ( comment | specialCommentContents )  ) ~ multilineCommentEnd

/* The whitespace parser, swallows both true whitespace and non-special comments. */
lazy val whitespaceParser: PackratParser[Any] = rep( whiteSpace | comment )

/* Multiline comment start delimiter. */
lazy val multilineCommentStart: PackratParser[Any] = not(  specialCommentBegin  ) ~ multilineCommentBegin

/* Nested multiline comments. */
lazy val multilineComment: PackratParser[Any] =  multilineCommentStart ~ rep(  not( multilineCommentEnd ) ~ ( comment | any )  ) ~ multilineCommentEnd

/* End of line comments. */
lazy val endOfLineComment: PackratParser[Any] = endOfLineCommentBegin ~ rep ( anyButEOL ) ~ "\n"

/* Matches everything except end of line. */
lazy val anyButEOL: PackratParser[Any] = not ( "\n" ) ~ any

/* Any comment. */
lazy val comment = multilineComment | endOfLineComment

是否有任何等同于'not'(内置符号或设计模式)可以解决解析问题的问题:

/*  /*! this is an interpreted special comment */ that gets discarded because commented out */

/*! this is an interpreted special comment /* containing a comment */ */

   /*! a special comment // with end-of-line comments 
    * which spans several lines // and again
    * /*  and again
         over several lines
      */
    */

感谢您的帮助!

2 个答案:

答案 0 :(得分:0)

ANTLR的词法分析器规则也可以递归调用自己。所以你可以从这些特殊的评论中做出一个大的标记:

SPECIAL_COMMENT
 : '/*!' ( SPECIAL_COMMENT | SL_COMMENT | ML_COMMENT | . )*? '*/'
 ;

fragment SL_COMMENT
 : '//' ~[\r\n]*
 ;

fragment ML_COMMENT
 : '/*' .*? '*/'
 ;

答案 1 :(得分:0)

这是我的最终版本,它接受嵌套在注释内的注释,特殊注释中的注释,但拒绝特殊注释中的特殊注释。我使用了非急切的关闭' *?'使它按预期工作:

SPEC: (EOL_SPEC | C_SPEC ) -> channel(SPEC_CHANNEL) ;
fragment C_SPEC: '/*!' ( COMMENT | . )*? '*/' ;
fragment EOL_SPEC: '//@' .*? EOL;

COMMENT: ( EOL_COMMENT | C_COMMENT ) -> channel(COMMENT_CHANNEL);
fragment C_COMMENT: '/*' ( COMMENT |. )*? '*/' ;
fragment EOL_COMMENT: '//' .*? EOL;