Java 创建一个ANTLR语法规则,如果在函数声明上方找到doctype注释,该规则将函数名作为标记返回

Java 创建一个ANTLR语法规则,如果在函数声明上方找到doctype注释,该规则将函数名作为标记返回,java,coldfusion,antlr,coldfusion-10,Java,Coldfusion,Antlr,Coldfusion 10,这是我想要解析的代码示例。当我覆盖ANTLR创建的parserBaseListener.java文件中的函数时,我希望getSaveable PaymentMethodsSmartList()作为令牌 /** @suppress */ public any function getSaveablePaymentMethodsSmartList() { if(!structKeyExists(variables, "saveablePaymentMethodsSmartList"))

这是我想要解析的代码示例。当我覆盖ANTLR创建的parserBaseListener.java文件中的函数时,我希望
getSaveable PaymentMethodsSmartList()
作为令牌

 /** @suppress */
 public any function getSaveablePaymentMethodsSmartList() {
    if(!structKeyExists(variables, "saveablePaymentMethodsSmartList")) {
        variables.saveablePaymentMethodsSmartList = getService("paymentService").getPaymentMethodSmartList();
        variables.saveablePaymentMethodsSmartList.addFilter('activeFlag', 1);
        variables.saveablePaymentMethodsSmartList.addFilter('allowSaveFlag', 1);
        variables.saveablePaymentMethodsSmartList.addInFilter('paymentMethodType', 'creditCard,giftCard,external,termPayment');
        if(len(setting('accountEligiblePaymentMethods'))) {
            variables.saveablePaymentMethodsSmartList.addInFilter('paymentMethodID', setting('accountEligiblePaymentMethods'));
        }
    }
    return variables.saveablePaymentMethodsSmartList;
}
我已经有了解析函数声明的语法,但是我需要一个新规则,可以将doctype注释与函数声明关联起来,如果有doctype注释与函数声明关联,则将函数名称作为单独的标记

语法如下所示:

functionDeclaration
  : accessType? typeSpec? FUNCTION identifier 
    LEFTPAREN parameterList? RIGHTPAREN
    functionAttribute* body=compoundStatement

  ;
 functionDeclaration: documented_function | undocumented_function ;

 documented_function: docstring accessType? typeSpec? FUNCTION
       documented_function_identifier rest_of_function ;

 undocumented_function: accessType? typeSpec? FUNCTION
       identifier rest_of_function ;

 rest_of_function: // avoids duplication, not pretty 
       LEFTPAREN parameterList? RIGHTPAREN
       functionAttribute* body=compoundStatement ;

您希望语法规则:

  • 如果源中“远处”的某个对象是a,则返回X
  • 如果远处的某个对象是B(或…),则返回Y
通常,这是上下文依赖关系。上下文无关语法无法很好地处理它,这是ANTLR试图用其BNF规则来近似的。本质上,您认为您想要做的是对解析器很久以前看到的历史进行编码,以影响现在正在生成的内容。一般来说,这很难

对于这样的事情,通常的解决方法是根本不在语法中处理它。相反:

  • 让语法规则产生一个X,不管距离有多远
  • 在解析时构建一棵树(ANTLR为您做这件事);这不仅捕获了X,还捕获了有关已解析实体的所有信息,包括远处的标记
  • 在树上走一走,如果树中包含a(通常在树的远处),则将找到的X解释为Y
对于docstring影响函数名的特定情况,您可能不需要编码遥远的历史

你需要这样的语法规则:

functionDeclaration
  : accessType? typeSpec? FUNCTION identifier 
    LEFTPAREN parameterList? RIGHTPAREN
    functionAttribute* body=compoundStatement

  ;
 functionDeclaration: documented_function | undocumented_function ;

 documented_function: docstring accessType? typeSpec? FUNCTION
       documented_function_identifier rest_of_function ;

 undocumented_function: accessType? typeSpec? FUNCTION
       identifier rest_of_function ;

 rest_of_function: // avoids duplication, not pretty 
       LEFTPAREN parameterList? RIGHTPAREN
       functionAttribute* body=compoundStatement ;
您必须将docstring识别为解析器可以“看到”的显式标记,这意味着修改lexer,将docstring从注释(例如空格)转换为标记。[这是第一件丑陋的事情]。看到这样的docstring后,lexer必须切换到词法模式,该模式将拾取标识符(如文本)并生成文档化的功能\u标识符,然后切换回正常模式。[这是第二件丑陋的事情]。您所做的是实现一个上下文依赖关系

尽管我提到了上下文依赖性,但您仍然可以实现这一点的原因是A并不遥远;它在X的几个标记内


所以,你可以这样做。我不会这样做;您试图让解析器做的太多了。坚持“通常的解决方案”。(你会遇到不同的问题:你的A是注释/空白,可能不是由ANTLR存储在树中。你必须解决这个问题;我不是ANTLR专家。)

因为我想显示我正在解析的代码。你能帮我学语法吗?就Ira而言,
public any function
不是ColdFusion@JamesAMohler-这是一个CF函数(在cfscript中);-)。诚然,这个问题听起来确实是关于java语法的。谢谢你的回答。这是cfscript中的冷聚变。这只是我试图解析的cfc文件的一小部分。@JamesAMohler-尽管我可以发誓语法是在CF10中引入的。