Parsing 使用ANTLR4识别单行中的多行注释

Parsing 使用ANTLR4识别单行中的多行注释,parsing,antlr,language-design,antlr4,lexer,Parsing,Antlr,Language Design,Antlr4,Lexer,我想用ANTLR4解析PostScript代码。我完成了语法,但有一个特定的语言扩展(是别人介绍的)很难再确认 举个简单的例子: 1: % This is a line comment 2: % The next line just pushes the value 10 onto the stack 3: 10 4: 5: %?description This is the special line-comment in question 6: /procedure { 7: /var1

我想用ANTLR4解析PostScript代码。我完成了语法,但有一个特定的语言扩展(是别人介绍的)很难再确认

举个简单的例子:

1: % This is a line comment
2: % The next line just pushes the value 10 onto the stack
3: 10
4: 
5: %?description This is the special line-comment in question
6: /procedure {
7:   /var1 30 def %This just creates a variable
8:   /var2 10 def %?description A description associated with var2 %?default 20
9:   /var3 (a string value) def %?description I am even allowed to use % signs %?default (another value)
10: }
识别行注释(如第1、2和7行中的注释)可以使用Lexer规则完成

LINE_COMMENT: '%' .*? NEWLINE;
NEWLINE: '\r'? '\n';
只需在%之后匹配所有内容,直到行结束

我遇到的问题是那些特殊的行注释,它们以
%?description
%?default
开头,因为这些注释也应该被识别,但与行注释不同的是,可以将多个注释放在一行中(如第8行和第9行)。因此,第8行包含两个特殊注释
%?description与var2相关的说明
%和
%?默认值20

可以这样想(尽管这行不通):

现在是真正棘手的部分:应该允许您在
%?description
之后放置任意文本,包括
%
,同时仍然可以拆分单个注释

简言之,问题可以简化为拆分表单的一行

(%?<keyword> <content with % allowed in it>)+ NEWLINE
进入


任何想法,如何制定词法分析器或解析器规则来实现这一点?

鉴于这些规则,我认为您必须在词法分析器中使用谓词来检查输入流中是否出现
%?
。您还必须确保普通注释必须以
%
开头,但后面不能跟
(或换行字符)

考虑到语法:

grammar T;

@lexer::members {
  boolean ahead(String text) {
    for (int i = 0; i < text.length(); i++) {
      if (text.charAt(i) != _input.LA(i + 1)) {
        return false;
      }
    }
    return true;
  }
}

parse
 : token* EOF
 ;

token
 : t=SPECIAL_COMMENT {System.out.println("special : " + $t.getText());}
 | t=COMMENT         {System.out.println("normal  : " + $t.getText());}
 ;

SPECIAL_COMMENT
 : '%?' ( {!ahead("%?")}? ~[\r\n] )*
 ;

COMMENT
 : '%' ( ~[?\r\n] ~[\r\n]* )?
 ;

SPACES
 : [ \t\r\n]+ -> skip
 ;
并将打印以下内容:

normal:%normal注释
特殊:%?说明我甚至可以使用%符号
特殊:%?默认值(另一个值)
正常:%n另一个正常注释(不带换行符!)
部分
({!ahead(“%?”)}~[\r\n])*
可以如下读取:如果前面没有“%?”,则匹配除
\r
\n
之外的任何字符,并执行此操作零次或多次

%?description descr. with % in in %?default (my default value for 100%) %?rest more
1.) %?description descr. with % in in 
2.) %?default (my default value for 100%)
3.) %?rest more
grammar T;

@lexer::members {
  boolean ahead(String text) {
    for (int i = 0; i < text.length(); i++) {
      if (text.charAt(i) != _input.LA(i + 1)) {
        return false;
      }
    }
    return true;
  }
}

parse
 : token* EOF
 ;

token
 : t=SPECIAL_COMMENT {System.out.println("special : " + $t.getText());}
 | t=COMMENT         {System.out.println("normal  : " + $t.getText());}
 ;

SPECIAL_COMMENT
 : '%?' ( {!ahead("%?")}? ~[\r\n] )*
 ;

COMMENT
 : '%' ( ~[?\r\n] ~[\r\n]* )?
 ;

SPACES
 : [ \t\r\n]+ -> skip
 ;