我正在将一个语法从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
*/
*/
感谢您的帮助!
答案 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;