从3.2升级到3.5.2后,Antlr生成的代码无效

问题描述 投票:1回答:1

我是antlr的新手 由于迁移到java 8,我必须将antlrv3代码从3.2迁移到3.5.2。 我在antlr语法中没有任何改变,它与版本3.2和java 7(目标java 6)完美配合 随着版本3.5.2的antlr maven生成编译错误,如:

[ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.7.0:compile (default-compile) on project ccff-sql2xpath: Compilation failure: Compilation failure:
[ERROR] /C:/ProjectSVN/JSR170/ccff-sql2xpath/target/generated-sources/antlr3/sql2xpath/query/compiler/TParser.java:[262,73] cannot find symbol
[ERROR]   symbol:   variable props
[ERROR]   location: variable p of type org.antlr.runtime.ParserRuleReturnScope

我认为antlr v3.5.2生成代码的方式发生了变化,因为我有超过77600行的这一行和'仅'3181行与TParser.java生成的文件中的旧版本的antlr

你能帮助我吗 ?

这是解析器语法:

parser grammar TParser;

options {
        language  = Java;
        output    = AST;
        superClass = AbstractTParser;
        tokenVocab = TLexer;
}




@header {
    package sql2xpath.query.compiler;

    import sql2xpath.query.xpath.XPathException;
    import sql2xpath.query.xpath.constraint.TemporaryPathConstraint;
}

//=============================================================================

query
    : s=select (f=from)? (w=where)? (o=orderby)? EOF;

//=============================================================================

select
    : SELECT^ p=proplist { 
        for (String o: ((List<String>) p.props)) {
            composer.getColumnSpecifier().addProperty(o);
        }
    };

//=============================================================================

from returns[String res = "unknown"]
    : FROM^ n=ntlist {
        if (n.nodetypes.size() > 1)
            throw new XPathException("Unable to deal with joined tables in FROM clause");
        composer.getPathConstraint().setTypeName(toCompactStringTree(n.nodetypes.get(0)));
    };

//=============================================================================

where returns[String res = "unknown"]
    : WHERE^ o=orexpression[true] {
        if (o.res != null) {
            // System.out.println("add constraint: " + o.res);
            composer.getPropertyConstraint().addConstraint(o.res);
        }
        };

//=============================================================================

orderby returns[String res = "unknown"]
    : (ORDER BY)^ p=propname d=(DESC | ASC)? {
                if (d == null)
                    composer.getOrderingSpecifier().addProperty(p.res, null);
                else if (d.getType() == ASC)
                    composer.getOrderingSpecifier().addProperty(p.res, "ascending");
                else
                    composer.getOrderingSpecifier().addProperty(p.res, "descending");         
         } (COMA q=propname e=(DESC | ASC)? { 
                if (e == null)
                    composer.getOrderingSpecifier().addProperty(q.res, null);
                else if (e.getType() == ASC)
                    composer.getOrderingSpecifier().addProperty(q.res, "ascending");
                else
                    composer.getOrderingSpecifier().addProperty(q.res, "descending");         
         })* ;

//=============================================================================

proplist returns[Object props]
@init{
List<String> l = new ArrayList<String>();
}
    : a=propname { l.add(a.res); } (COMA b=propname { l.add(b.res); })* { $props = l; };

//=============================================================================

ntlist returns[List nodetypes]
    : c+=complexpropname (COMA c+=complexpropname)* { $nodetypes = $c; };

//============================================================================= 

orexpression[boolean b] returns[String res = null]
@init{
List<String> l = new ArrayList<String>();   
List<Object> p = new    ArrayList<Object>();
}
    : a=andexpression[b] { 
            p.addAll(((List<Object>)(((Object []) a.res)[1])));
            l.add((String)(((Object []) a.res)[0]));
        } (OR^ c=andexpression[b] { 
            p.addAll(((List<Object>)(((Object []) c.res)[1])));
            l.add((String)(((Object []) c.res)[0]));
        })* {

        StringBuffer sb = new StringBuffer();
        for (String s: l) 
            if (s!=null)
                sb.append(s + " or ");
        if (sb.length() > 0)
            $res = sb.substring(0,sb.length()-4);

        if (p.size() > 2)
            throw new XPathException("Unable to deal with more than two path constraints");
        else if (p.size() == 2) {
            if (!$b)
                throw new XPathException("Cannot deal with negated or clauses");
            TemporaryPathConstraint pc1 = (TemporaryPathConstraint) p.get(0);
            TemporaryPathConstraint pc2 = (TemporaryPathConstraint) p.get(1);

            //LOGGER.debug("Found or-ed constraints on jcr:path = " + pc1.path + " OR " + pc2.path);

            if (pc1.b && pc2.b) {
                composer.getPathConstraint().orConstraint(pc1.path, pc2.path);
            } else
                throw new XPathException("Only positive path constraints can be in the same or clause");

        }else if (p.size() == 1) {
            if (!$b)
                throw new XPathException("Cannot deal with single negated path constraint");

            TemporaryPathConstraint pc1 = (TemporaryPathConstraint) p.get(0);
            //LOGGER.debug("Found single constraint on jcr:path = " + pc1.path);

            if (pc1.b) {
                composer.getPathConstraint().singleConstraint(pc1.path);    
            } else {
                throw new XPathException("Cannot deal with negative single path constraints");
            }

        }
         };

//=============================================================================

andexpression[boolean b] returns[Object res = null]
@init{
List<String> l = new ArrayList<String>();
List<Object> p = new    ArrayList<Object>();
String k = null;
}
    : a=notexpression[b] { if (a.res instanceof TemporaryPathConstraint) p.add(a.res); else l.add((String)a.res); } (AND^ c=notexpression[b] { if (c.res instanceof TemporaryPathConstr
        StringBuffer sb = new StringBuffer();
        for (String s: l) 
            if (s!=null)
                sb.append(s + " and ");
        if (sb.length() > 0)
            k = sb.substring(0,sb.length()-5);
        if (p.size() > 2)
            throw new XPathException("Unable to deal with more than two path constraints");
        else if (p.size() == 2) {
            if (!$b)
                throw new XPathException("Cannot deal with negated and clauses");
            TemporaryPathConstraint pc1 = (TemporaryPathConstraint) p.get(0);
            TemporaryPathConstraint pc2 = (TemporaryPathConstraint) p.get(1);

            //LOGGER.debug("Found and-ed constraints on jcr:path = " + pc1.path + " AND " + pc2.path);

            if (pc1.b && !pc2.b) {
                composer.getPathConstraint().andNotConstraint(pc1.path, pc2.path);
            } else if (pc2.b && !pc1.b) {
                composer.getPathConstraint().andNotConstraint(pc2.path, pc1.path);
            } else
                throw new XPathException("Only one positive and one negative path constraint can be in the same and clause");    
            p.clear();
        }

        $res = new Object [] {k, p};    

         };

//=============================================================================

notexpression[boolean b] returns[Object res = null]
    : NOT^ d=containsexpression[false] { if (!$b) throw new XPathException("Impossible to parse nested NOT operators"); $res = d.res;}
    | c=containsexpression[b] {$res = c.res; };

//=============================================================================

containsexpression[boolean b] returns[Object res = null]
    : c=containsfun[b] { $res = c.res; }
    | v=value IN p=propname { $res = composer.getPropertyConstraint().getComparingConstraint(p.res, "=", v.res, b); }
    | o=operatorexpression[b] { $res = o.res; };

//=============================================================================

operatorexpression[boolean b] returns[Object res = null]
    : p=propname o=op v=value { 
        if ("jcr:path".equals(p.res)) 
            if (!"=".equals(o.res))
                throw new XPathException("Impossible to use other operator than \"=\" or \"LIKE\" with jcr:xpath property");
            else {
                TemporaryPathConstraint tpc = new TemporaryPathConstraint(TemporaryPathConstraint.EQUAL);
                tpc.path = v.res;
                tpc.b = $b;
                $res = tpc;
            }
                //composer.getPathConstraint().addConstraintAndProcess(v.res, b, false);
        else
            $res = composer.getPropertyConstraint().getComparingConstraint(p.res, o.res, v.res, b); 

    }
    | p=propname IS NULL { $res = composer.getPropertyConstraint().getIsNullConstraint(p.res, b); } 
    | p=propname IS NOT NULL { $res = composer.getPropertyConstraint().getIsNotNullConstraint(p.res, b); }
    | l=like[b] { $res = l.res; }
    | t=parentexpression[b] { $res = t.res; };

//=============================================================================

op returns[String res = "unknown"]
    : EQ { $res = "="; }
    | NEQ { $res = "!="; }
    | LEQ { $res = "<="; }
    | LES { $res = "<"; }
    | GEQ { $res = ">="; }
    | GRE { $res = ">"; };   

//=============================================================================

parentexpression[boolean b] returns[String res = "unknown"] 
    : LEFT_PAREN o=orexpression[b] RIGHT_PAREN { $res = "(" + o.res + ")"; }; 

//=============================================================================

propname returns[String res = "unknown"]
    : QUOT c=complexpropname QUOT { $res = $c.res; }
    | c=complexpropname { $res = $c.res; }; 

//=============================================================================

complexpropname returns[String res = "unknown"]
    : a=simplepropname (DOT b=simplepropname)? {$res = a.res; if (b != null) $res += "." + b.res;};

//=============================================================================

simplepropname returns[String res = "unknown"]
    : a=identifier (COLON b=identifier)? {$res = a.res; if (b != null) $res += ":" + b.res;};

//=============================================================================

identifier returns[String res = "unknown"]
        : nq=NonQuotedIdentifier { $res = $nq.getText(); }
        | q=QuotedIdentifier { $res = q.getText(); }
        | l=Letter { $res = l.getText(); }
        | STAR { $res = "*"; }; 

//=============================================================================

value returns[String res = "value"]
    : x=complexpropname { $res = x.res; } 
    | c=constant { $res = c.res; };  

//=============================================================================

like[boolean b] returns[Object res = null]
    : p=propname LIKE e=expression (c = escape)? { 
        if ("jcr:path".equals(p.res)) { 
            TemporaryPathConstraint tpc = new TemporaryPathConstraint(TemporaryPathConstraint.LIKE);
            tpc.path = e.res;
            tpc.b = $b;
            $res = tpc;
            // composer.getPathConstraint().addConstraintAndProcess(((c == null) ? e.res : e.res.replaceAll(c.res, "\\" + c.res)), $b, false);
        } else
            $res = composer.getPropertyConstraint().getLikeConstraint(p.res, ((c == null) ? e.res : e.res.replaceAll(c.res, "\\" + c.res)), $b);
};

//=============================================================================

escape returns[String res = "escape"]
    : ESCAPE e=expression { $res = e.res; };

//=============================================================================

expression returns[String res = "expression"]
    : (u=unaryOperator)? c=constant { $res = ((u!=null)?u.res:"") + c.res; };

//=============================================================================

unaryOperator returns[String res = "unaryOperator"]
    : MINUS { $res = "-"; };

//=============================================================================

constant returns[String res = "constant"]
    : Number { $res = $Number.getText(); } 
    | NULL { $res = $NULL.getText(); }
    | s=stringLiteral { $res = s.res; }
    | Currency { $res = $Currency.getText(); }
    | ODBCDateTime { $res = $ODBCDateTime.getText(); };

//=============================================================================

stringLiteral returns[String res = "stringLiteral"]
    : UnicodeStringLiteral { $res = $UnicodeStringLiteral.getText(); }
    | ASCIIStringLiteral { $res = $ASCIIStringLiteral.getText(); };

//=============================================================================

containsfun[boolean b] returns[String res = "containsfun"]
    : CONTAINS_FUN c=containscope COMA e=expression RIGHT_PAREN { 
            $res = composer.getPropertyConstraint().getContainsConstraint(c.res, e.res, b);
        };

//=============================================================================

containscope returns[String res = "containscope"]   
    : c=complexpropname { $res = c.res; } 
    | DOT { $res = "."; };  

这是方法的代码,其中是错误:

// $ANTLR start "select"
// be\\fgov\\minfin\\ccff\\jcr2\\sql2xpath\\query\\compiler\\TParser.g:27:4: select : SELECT ^p= proplist ;
public final TParser.select_return select() throws RecognitionException {
    TParser.select_return retval = new TParser.select_return();
    retval.start = input.LT(1);

    Object root_0 = null;

    Token SELECT2=null;
    ParserRuleReturnScope p =null;

    Object SELECT2_tree=null;

    try {
        // sql2xpath\\query\\compiler\\TParser.g:28:5: ( SELECT ^p= proplist )
        // sql2xpath\\query\\compiler\\TParser.g:28:7: SELECT ^p= proplist
        {
        root_0 = (Object)adaptor.nil();


        SELECT2=(Token)match(input,SELECT,FOLLOW_SELECT_in_select186); 
        SELECT2_tree = (Object)adaptor.create(SELECT2);
        root_0 = (Object)adaptor.becomeRoot(SELECT2_tree, root_0);

        pushFollow(FOLLOW_proplist_in_select191);
        p=proplist();
        state._fsp--;

        adaptor.addChild(root_0, p.getTree());


                for (String o: ((List<String>) p.props)) {   // <=====[ERROR]   
                    composer.getColumnSpecifier().addProperty(o);
                }

        }

        retval.stop = input.LT(-1);

        retval.tree = (Object)adaptor.rulePostProcessing(root_0);
        adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop);

    }
    catch (RecognitionException re) {
        reportError(re);
        recover(input,re);
        retval.tree = (Object)adaptor.errorNode(input, retval.start, input.LT(-1), re);
    }
    finally {
        // do for sure before leaving
    }
    return retval;
}
// $ANTLR end "select"
maven antlr antlr3
1个回答
0
投票

我想我理解编译错误:

ParserRuleReturnScope类型的p属性使用返回类型为proplist_return的类的方法进行初始化,并扩展类ParserRuleReturnScope。

ParserRuleReturnScope p =null;
...
p=proplist();  // (proplist_return extend ParserRuleReturnScope)
...  
for (String o: ((List<String>) p.props)) {   // <=====[COMPILATION ERROR] 

因为类prolist_return是ParserRuleReturnScope的子类,所以必须先搜索p,然后才能搜索子类中包含的属性,这里的props属性如下:

    proplist_return castP = (proplist_return) p;
    for (String o: ((List<String>) castP.props)) {

在3.2版本中,插件会生成无错误的代码。在版本3.5.2中,它会生成这些错误!

我理解编译错误的原因。

事实上,ANTLR的版本3.5.2更严格,在我的规则'select'的语法antlr的动作部分中,我忘记引用变量p并在之前添加$。这就是为什么生成器不会抛出我的类(参见上面的注释)错误的语法是:

select
    : SELECT^ p=proplist { 
        for (String o: ((List<String>)  p.props)) {
            composer.getColumnSpecifier().addProperty(o);
        }
    };

所以解决方案是:

   select
       : SELECT^ p=proplist { 
            for (String o: ((List<String>)  $p.props)) {
                composer.getColumnSpecifier().addProperty(o);
            }
         };
© www.soinside.com 2019 - 2024. All rights reserved.