This is an automated email from the ASF dual-hosted git repository.

mariofusco pushed a commit to branch dev-new-parser
in repository https://gitbox.apache.org/repos/asf/incubator-kie-drools.git

commit 19cf539e663b328d33a4e2bb79a8f7d886b4da7d
Author: Toshiya Kobayashi <[email protected]>
AuthorDate: Fri Dec 16 17:48:34 2022 +0900

    [DROOLS-7253] Review and improve drools-lsp parser Visitor design (#16)
    
    * [DROOLS-7253] Review and improve drools-lsp parser Visitor design
    - Remove currentConstructStack. Utilize return object instead.
    
    * - Remove instance fields. Utilize return objects instead.
---
 .../java/org/drools/parser/DRLParserException.java |  12 +
 .../java/org/drools/parser/DRLParserHelper.java    |  29 +-
 .../java/org/drools/parser/DRLParserWrapper.java   |  10 +-
 .../java/org/drools/parser/DRLVisitorImpl.java     | 355 ++++++++++++---------
 4 files changed, 245 insertions(+), 161 deletions(-)

diff --git 
a/drools-drl/drools-drl10-parser/src/main/java/org/drools/parser/DRLParserException.java
 
b/drools-drl/drools-drl10-parser/src/main/java/org/drools/parser/DRLParserException.java
new file mode 100644
index 0000000000..6bc5812a78
--- /dev/null
+++ 
b/drools-drl/drools-drl10-parser/src/main/java/org/drools/parser/DRLParserException.java
@@ -0,0 +1,12 @@
+package org.drools.parser;
+
+public class DRLParserException extends RuntimeException {
+
+    public DRLParserException() {
+        super();
+    }
+
+    public DRLParserException(String message) {
+        super(message);
+    }
+}
diff --git 
a/drools-drl/drools-drl10-parser/src/main/java/org/drools/parser/DRLParserHelper.java
 
b/drools-drl/drools-drl10-parser/src/main/java/org/drools/parser/DRLParserHelper.java
index feabbe3920..9d42bf0964 100644
--- 
a/drools-drl/drools-drl10-parser/src/main/java/org/drools/parser/DRLParserHelper.java
+++ 
b/drools-drl/drools-drl10-parser/src/main/java/org/drools/parser/DRLParserHelper.java
@@ -3,7 +3,6 @@ package org.drools.parser;
 import org.antlr.v4.runtime.CharStream;
 import org.antlr.v4.runtime.CharStreams;
 import org.antlr.v4.runtime.CommonTokenStream;
-import org.antlr.v4.runtime.RuleContext;
 import org.antlr.v4.runtime.Token;
 import org.antlr.v4.runtime.tree.ErrorNode;
 import org.antlr.v4.runtime.tree.ParseTree;
@@ -12,11 +11,14 @@ import org.drools.drl.ast.descr.PackageDescr;
 
 public class DRLParserHelper {
 
+    private DRLParserHelper() {
+    }
+
     public static PackageDescr parse(String drl) {
-        return parseTree2PackageDescr(createParseTree(drl));
+        return compilationUnitContext2PackageDescr(createParseTree(drl));
     }
 
-    public static ParseTree createParseTree(String drl) {
+    public static DRLParser.CompilationUnitContext createParseTree(String drl) 
{
         return createDrlParser(drl).compilationUnit();
     }
 
@@ -24,28 +26,31 @@ public class DRLParserHelper {
         CharStream inputStream = CharStreams.fromString(drl);
         DRLLexer drlLexer = new DRLLexer(inputStream);
         CommonTokenStream commonTokenStream = new CommonTokenStream(drlLexer);
-        DRLParser drlParser = new DRLParser(commonTokenStream);
-        return drlParser;
+        return new DRLParser(commonTokenStream);
     }
 
-    public static PackageDescr parseTree2PackageDescr(ParseTree parseTree) {
+    public static PackageDescr 
compilationUnitContext2PackageDescr(DRLParser.CompilationUnitContext ctx) {
         DRLVisitorImpl visitor = new DRLVisitorImpl();
-        visitor.visit(parseTree);
-        return visitor.getPackageDescr();
+        Object descr = visitor.visit(ctx);
+        if (descr instanceof PackageDescr) {
+            return (PackageDescr) descr;
+        } else {
+            throw new DRLParserException("CompilationUnitContext should 
produce PackageDescr. descr = " + descr.getClass());
+        }
     }
 
-
     public static Integer computeTokenIndex(DRLParser parser, int row, int 
col) {
         for (int i = 0; i < parser.getInputStream().size(); i++) {
             Token token = parser.getInputStream().get(i);
             int start = token.getCharPositionInLine();
             int stop = token.getCharPositionInLine() + 
token.getText().length();
-            if (token.getLine() > row)
+            if (token.getLine() > row) {
                 return token.getTokenIndex() - 1;
-            else if (token.getLine() == row && start >= col)
+            } else if (token.getLine() == row && start >= col) {
                 return token.getTokenIndex() == 0 ? 0 : token.getTokenIndex() 
- 1;
-            else if (token.getLine() == row && start < col && stop >= col)
+            } else if (token.getLine() == row && start < col && stop >= col) {
                 return token.getTokenIndex();
+            }
         }
         return null;
     }
diff --git 
a/drools-drl/drools-drl10-parser/src/main/java/org/drools/parser/DRLParserWrapper.java
 
b/drools-drl/drools-drl10-parser/src/main/java/org/drools/parser/DRLParserWrapper.java
index 251c918190..7bfdcd8904 100644
--- 
a/drools-drl/drools-drl10-parser/src/main/java/org/drools/parser/DRLParserWrapper.java
+++ 
b/drools-drl/drools-drl10-parser/src/main/java/org/drools/parser/DRLParserWrapper.java
@@ -4,31 +4,29 @@ import java.util.ArrayList;
 import java.util.List;
 import java.util.stream.Collectors;
 
-import org.antlr.v4.runtime.tree.ParseTree;
 import org.drools.drl.ast.descr.PackageDescr;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import static 
org.drools.parser.DRLParserHelper.compilationUnitContext2PackageDescr;
+
 public class DRLParserWrapper {
 
     private static final Logger LOGGER = 
LoggerFactory.getLogger(DRLParserWrapper.class);
 
     private final List<DRLParserError> errors = new ArrayList<>();
 
-    public DRLParserWrapper() {
-    }
-
     public PackageDescr parse(String drl) {
         DRLParser drlParser = DRLParserHelper.createDrlParser(drl);
         DRLErrorListener errorListener = new DRLErrorListener();
         drlParser.addErrorListener(errorListener);
 
-        ParseTree parseTree = drlParser.compilationUnit();
+        DRLParser.CompilationUnitContext cxt = drlParser.compilationUnit();
 
         errors.addAll(errorListener.getErrors());
 
         try {
-            return DRLParserHelper.parseTree2PackageDescr(parseTree);
+            return compilationUnitContext2PackageDescr(cxt);
         } catch (Exception e) {
             LOGGER.error("Exception while creating PackageDescr", e);
             errors.add(new DRLParserError(e));
diff --git 
a/drools-drl/drools-drl10-parser/src/main/java/org/drools/parser/DRLVisitorImpl.java
 
b/drools-drl/drools-drl10-parser/src/main/java/org/drools/parser/DRLVisitorImpl.java
index e9585a9ab1..236478d7fb 100644
--- 
a/drools-drl/drools-drl10-parser/src/main/java/org/drools/parser/DRLVisitorImpl.java
+++ 
b/drools-drl/drools-drl10-parser/src/main/java/org/drools/parser/DRLVisitorImpl.java
@@ -1,19 +1,19 @@
 package org.drools.parser;
 
-import java.util.ArrayDeque;
-import java.util.Deque;
+import java.util.ArrayList;
 import java.util.List;
 import java.util.Objects;
+import java.util.Optional;
 import java.util.stream.Collectors;
 
 import org.antlr.v4.runtime.ParserRuleContext;
 import org.antlr.v4.runtime.tree.ParseTree;
+import org.antlr.v4.runtime.tree.RuleNode;
 import org.antlr.v4.runtime.tree.TerminalNode;
 import org.drools.drl.ast.descr.AndDescr;
 import org.drools.drl.ast.descr.AnnotationDescr;
 import org.drools.drl.ast.descr.AttributeDescr;
 import org.drools.drl.ast.descr.BaseDescr;
-import org.drools.drl.ast.descr.ConditionalElementDescr;
 import org.drools.drl.ast.descr.ExistsDescr;
 import org.drools.drl.ast.descr.ExprConstraintDescr;
 import org.drools.drl.ast.descr.FromDescr;
@@ -35,63 +35,74 @@ import static org.drools.util.StringUtils.unescapeJava;
 
 public class DRLVisitorImpl extends DRLParserBaseVisitor<Object> {
 
-    private final PackageDescr packageDescr = new PackageDescr();
-
-    private RuleDescr currentRule;
-    private PatternDescr currentPattern;
-
-    private final Deque<ConditionalElementDescr> currentConstructStack = new 
ArrayDeque<>(); // e.g. whole LHS (= AndDescr), NotDescr, ExistsDescr
-
     @Override
-    public Object visitCompilationUnit(DRLParser.CompilationUnitContext ctx) {
-        return super.visitCompilationUnit(ctx);
+    public PackageDescr visitCompilationUnit(DRLParser.CompilationUnitContext 
ctx) {
+        PackageDescr packageDescr = new PackageDescr();
+        if (ctx.packagedef() != null) {
+            
packageDescr.setName(getTextWithoutErrorNode(ctx.packagedef().name));
+        }
+        List<BaseDescr> descrList = visitDescrChildren(ctx);
+        applyChildrenDescrs(packageDescr, descrList);
+        return packageDescr;
     }
 
-    @Override
-    public Object visitPackagedef(DRLParser.PackagedefContext ctx) {
-        packageDescr.setName(getTextWithoutErrorNode(ctx.name));
-        return super.visitPackagedef(ctx);
+    private void applyChildrenDescrs(PackageDescr packageDescr, 
List<BaseDescr> descrList) {
+        descrList.forEach(descr -> {
+            if (descr instanceof UnitDescr) {
+                packageDescr.setUnit((UnitDescr) descr);
+            } else if (descr instanceof GlobalDescr) {
+                packageDescr.addGlobal((GlobalDescr) descr);
+            } else if (descr instanceof FunctionImportDescr) {
+                packageDescr.addFunctionImport((FunctionImportDescr) descr);
+            } else if (descr instanceof ImportDescr) {
+                packageDescr.addImport((ImportDescr) descr);
+            } else if (descr instanceof FunctionDescr) {
+                FunctionDescr functionDescr = (FunctionDescr) descr;
+                functionDescr.setNamespace(packageDescr.getNamespace());
+                AttributeDescr dialect = packageDescr.getAttribute("dialect");
+                if (dialect != null) {
+                    functionDescr.setDialect(dialect.getValue());
+                }
+                packageDescr.addFunction(functionDescr);
+            } else if (descr instanceof AttributeDescr) {
+                packageDescr.addAttribute((AttributeDescr) descr);
+            } else if (descr instanceof RuleDescr) {
+                packageDescr.addRule((RuleDescr) descr);
+            }
+        });
     }
 
     @Override
-    public Object visitUnitdef(DRLParser.UnitdefContext ctx) {
-        packageDescr.setUnit(new UnitDescr(ctx.name.getText()));
-        return super.visitUnitdef(ctx);
+    public UnitDescr visitUnitdef(DRLParser.UnitdefContext ctx) {
+        return new UnitDescr(ctx.name.getText());
     }
 
     @Override
-    public Object visitGlobaldef(DRLParser.GlobaldefContext ctx) {
+    public GlobalDescr visitGlobaldef(DRLParser.GlobaldefContext ctx) {
         GlobalDescr globalDescr = new 
GlobalDescr(ctx.drlIdentifier().getText(), ctx.type().getText());
         populateStartEnd(globalDescr, ctx);
-        packageDescr.addGlobal(globalDescr);
-        return super.visitGlobaldef(ctx);
+        return globalDescr;
     }
 
     @Override
-    public Object visitImportdef(DRLParser.ImportdefContext ctx) {
+    public ImportDescr visitImportdef(DRLParser.ImportdefContext ctx) {
         String target = ctx.drlQualifiedName().getText() + (ctx.MUL() != null 
? ".*" : "");
         if (ctx.DRL_FUNCTION() != null || ctx.STATIC() != null) {
             FunctionImportDescr functionImportDescr = new 
FunctionImportDescr();
             functionImportDescr.setTarget(target);
             populateStartEnd(functionImportDescr, ctx);
-            packageDescr.addFunctionImport(functionImportDescr);
+            return functionImportDescr;
         } else {
             ImportDescr importDescr = new ImportDescr();
             importDescr.setTarget(target);
             populateStartEnd(importDescr, ctx);
-            packageDescr.addImport(importDescr);
+            return importDescr;
         }
-        return super.visitImportdef(ctx);
     }
 
     @Override
-    public Object visitFunctiondef(DRLParser.FunctiondefContext ctx) {
+    public FunctionDescr visitFunctiondef(DRLParser.FunctiondefContext ctx) {
         FunctionDescr functionDescr = new FunctionDescr();
-        functionDescr.setNamespace(packageDescr.getNamespace());
-        AttributeDescr dialect = packageDescr.getAttribute("dialect");
-        if (dialect != null) {
-            functionDescr.setDialect(dialect.getValue());
-        }
         if (ctx.typeTypeOrVoid() != null) {
             functionDescr.setReturnType(ctx.typeTypeOrVoid().getText());
         } else {
@@ -102,87 +113,146 @@ public class DRLVisitorImpl extends 
DRLParserBaseVisitor<Object> {
         DRLParser.FormalParameterListContext formalParameterListContext = 
formalParametersContext.formalParameterList();
         if (formalParameterListContext != null) {
             List<DRLParser.FormalParameterContext> formalParameterContexts = 
formalParameterListContext.formalParameter();
-            formalParameterContexts.stream().forEach(formalParameterContext -> 
{
+            formalParameterContexts.forEach(formalParameterContext -> {
                 DRLParser.TypeTypeContext typeTypeContext = 
formalParameterContext.typeType();
                 DRLParser.VariableDeclaratorIdContext 
variableDeclaratorIdContext = formalParameterContext.variableDeclaratorId();
                 functionDescr.addParameter(typeTypeContext.getText(), 
variableDeclaratorIdContext.getText());
             });
         }
         
functionDescr.setBody(ParserStringUtils.getTextPreservingWhitespace(ctx.block()));
-        packageDescr.addFunction(functionDescr);
-        return super.visitFunctiondef(ctx);
+        return functionDescr;
+    }
+
+    @Override
+    public RuleDescr visitRuledef(DRLParser.RuledefContext ctx) {
+        RuleDescr ruleDescr = new 
RuleDescr(safeStripStringDelimiters(ctx.name.getText()));
+
+        
ctx.drlAnnotation().stream().map(this::visitDrlAnnotation).forEach(ruleDescr::addAnnotation);
+
+        if (ctx.attributes() != null) {
+            List<BaseDescr> descrList = visitDescrChildren(ctx.attributes());
+            descrList.stream()
+                    .filter(AttributeDescr.class::isInstance)
+                    .map(AttributeDescr.class::cast)
+                    .forEach(ruleDescr::addAttribute);
+        }
+
+        if (ctx.lhs() != null) {
+            List<BaseDescr> lhsDescrList = visitLhs(ctx.lhs());
+            lhsDescrList.forEach(descr -> ruleDescr.getLhs().addDescr(descr));
+            slimLhsRootDescr(ruleDescr.getLhs());
+        }
+
+        if (ctx.rhs() != null) {
+            ruleDescr.setConsequenceLocation(ctx.rhs().getStart().getLine(), 
ctx.rhs().getStart().getCharPositionInLine()); // location of "then"
+            
ruleDescr.setConsequence(ParserStringUtils.getTextPreservingWhitespace(ctx.rhs().consequence()));
+        }
+
+        return ruleDescr;
+    }
+
+    private void slimLhsRootDescr(AndDescr root) {
+        List<BaseDescr> descrList = new ArrayList<>(root.getDescrs());
+        root.getDescrs().clear();
+        descrList.forEach(root::addOrMerge); // This slims down nested AndDescr
     }
 
     @Override
-    public Object visitRuledef(DRLParser.RuledefContext ctx) {
-        currentRule = new 
RuleDescr(safeStripStringDelimiters(ctx.name.getText()));
-        packageDescr.addRule(currentRule);
+    public AnnotationDescr visitDrlAnnotation(DRLParser.DrlAnnotationContext 
ctx) {
+        AnnotationDescr annotationDescr = new 
AnnotationDescr(ctx.name.getText());
+        annotationDescr.setValue(ctx.drlArguments().drlArgument(0).getText());
+        return annotationDescr;
+    }
 
-        Object result = super.visitRuledef(ctx);
-        currentRule = null;
-        return result;
+    @Override
+    public AttributeDescr visitAttribute(DRLParser.AttributeContext ctx) {
+        AttributeDescr attributeDescr = new 
AttributeDescr(ctx.getChild(0).getText());
+        if (ctx.getChildCount() > 1) {
+            // TODO : will likely split visitAttribute methods using labels 
(e.g. #stringAttribute)
+            String value = 
unescapeJava(safeStripStringDelimiters(ctx.getChild(1).getText()));
+            attributeDescr.setValue(value);
+        }
+        return attributeDescr;
     }
 
     @Override
-    public Object visitLhs(DRLParser.LhsContext ctx) {
-        currentConstructStack.push(currentRule.getLhs());
-        try {
-            return super.visitLhs(ctx);
-        } finally {
-            currentConstructStack.pop();
+    public List<BaseDescr> visitLhs(DRLParser.LhsContext ctx) {
+        if (ctx.lhsExpression() != null) {
+            return visitLhsExpression(ctx.lhsExpression());
+        } else {
+            return new ArrayList<>();
         }
     }
 
     @Override
-    public Object visitLhsPatternBind(DRLParser.LhsPatternBindContext ctx) {
+    public List<BaseDescr> visitLhsExpression(DRLParser.LhsExpressionContext 
ctx) {
+        return visitDescrChildren(ctx);
+    }
+
+    @Override
+    public BaseDescr visitLhsPatternBind(DRLParser.LhsPatternBindContext ctx) {
         if (ctx.lhsPattern().size() == 1) {
-            Object result = super.visitLhsPatternBind(ctx);
-            ConditionalElementDescr parentDescr = currentConstructStack.peek();
-            PatternDescr patternDescr = (PatternDescr) 
parentDescr.getDescrs().get(parentDescr.getDescrs().size() - 1);
-            if (ctx.label() != null) {
-                patternDescr.setIdentifier(ctx.label().IDENTIFIER().getText());
-            }
-            return result;
+            return getSinglePatternDescr(ctx);
         } else if (ctx.lhsPattern().size() > 1) {
-            OrDescr orDescr = new OrDescr();
-            currentConstructStack.peek().addDescr(orDescr);
-            currentConstructStack.push(orDescr);
-            try {
-                Object result = super.visitLhsPatternBind(ctx);
-                List<? extends BaseDescr> descrs = orDescr.getDescrs();
-                for (BaseDescr descr : descrs) {
-                    PatternDescr patternDescr = (PatternDescr) descr;
-                    if (ctx.label() != null) {
-                        
patternDescr.setIdentifier(ctx.label().IDENTIFIER().getText());
-                    }
-                }
-                return result;
-            } finally {
-                currentConstructStack.pop();
-            }
+            return getOrDescrWithMultiplePatternDescr(ctx);
         } else {
             throw new IllegalStateException("ctx.lhsPattern().size() == 0 : " 
+ ctx.getText());
         }
     }
 
+    private PatternDescr getSinglePatternDescr(DRLParser.LhsPatternBindContext 
ctx) {
+        Optional<BaseDescr> optPatternDescr = visitFirstDescrChild(ctx);
+        PatternDescr patternDescr = 
optPatternDescr.filter(PatternDescr.class::isInstance)
+                .map(PatternDescr.class::cast)
+                .orElseThrow(() -> new IllegalStateException("lhsPatternBind 
must have at least one lhsPattern : " + ctx.getText()));
+        if (ctx.label() != null) {
+            patternDescr.setIdentifier(ctx.label().IDENTIFIER().getText());
+        }
+        return patternDescr;
+    }
+
+    private OrDescr 
getOrDescrWithMultiplePatternDescr(DRLParser.LhsPatternBindContext ctx) {
+        OrDescr orDescr = new OrDescr();
+        List<BaseDescr> descrList = visitDescrChildren(ctx);
+        descrList.stream()
+                .filter(PatternDescr.class::isInstance)
+                .map(PatternDescr.class::cast)
+                .forEach(patternDescr -> {
+                    if (ctx.label() != null) {
+                        
patternDescr.setIdentifier(ctx.label().IDENTIFIER().getText());
+                    }
+                    orDescr.addDescr(patternDescr);
+                });
+
+        return orDescr;
+    }
+
     @Override
-    public Object visitLhsPattern(DRLParser.LhsPatternContext ctx) {
-        currentPattern = new PatternDescr(ctx.objectType.getText());
+    public PatternDescr visitLhsPattern(DRLParser.LhsPatternContext ctx) {
+        PatternDescr patternDescr = new PatternDescr(ctx.objectType.getText());
         if (ctx.patternSource() != null) {
             String expression = ctx.patternSource().getText();
             FromDescr from = new FromDescr();
             from.setDataSource(new MVELExprDescr(expression));
-            from.setResource(currentPattern.getResource());
-            currentPattern.setSource(from);
+            from.setResource(patternDescr.getResource());
+            patternDescr.setSource(from);
         }
-        Object result = super.visitLhsPattern(ctx);
-        currentConstructStack.peek().addDescr(currentPattern);
-        currentPattern = null;
-        return result;
+        List<ExprConstraintDescr> constraintDescrList = 
visitConstraints(ctx.constraints());
+        constraintDescrList.forEach(patternDescr::addConstraint);
+        return patternDescr;
+    }
+
+    @Override
+    public List<ExprConstraintDescr> 
visitConstraints(DRLParser.ConstraintsContext ctx) {
+        List<BaseDescr> descrList = visitDescrChildren(ctx);
+        return descrList.stream()
+                .filter(ExprConstraintDescr.class::isInstance)
+                .map(ExprConstraintDescr.class::cast)
+                .collect(Collectors.toList());
     }
 
     @Override
-    public Object visitConstraint(DRLParser.ConstraintContext ctx) {
+    public ExprConstraintDescr visitConstraint(DRLParser.ConstraintContext 
ctx) {
         Object constraint = super.visitConstraint(ctx);
         if (constraint != null) {
             String constraintString = constraint.toString();
@@ -190,15 +260,15 @@ public class DRLVisitorImpl extends 
DRLParserBaseVisitor<Object> {
             if (label != null) {
                 constraintString = label.getText() + constraintString;
             }
-            ExprConstraintDescr constr = new 
ExprConstraintDescr(constraintString);
-            constr.setType(ExprConstraintDescr.Type.NAMED);
-            currentPattern.addConstraint(constr);
+            ExprConstraintDescr constraintDescr = new 
ExprConstraintDescr(constraintString);
+            constraintDescr.setType(ExprConstraintDescr.Type.NAMED);
+            return constraintDescr;
         }
         return null;
     }
 
     @Override
-    public Object visitDrlExpression(DRLParser.DrlExpressionContext ctx) {
+    public String visitDrlExpression(DRLParser.DrlExpressionContext ctx) {
         return ctx.children.stream()
                 .map(c -> c instanceof TerminalNode ? c : c.accept(this))
                 .filter(Objects::nonNull)
@@ -207,7 +277,7 @@ public class DRLVisitorImpl extends 
DRLParserBaseVisitor<Object> {
     }
 
     @Override
-    public Object visitDrlPrimary(DRLParser.DrlPrimaryContext ctx) {
+    public String visitDrlPrimary(DRLParser.DrlPrimaryContext ctx) {
         return ctx.children.stream()
                 .map(c -> c instanceof TerminalNode ? c : c.accept(this))
                 .filter(Objects::nonNull)
@@ -216,97 +286,69 @@ public class DRLVisitorImpl extends 
DRLParserBaseVisitor<Object> {
     }
 
     @Override
-    public Object visitDrlIdentifier(DRLParser.DrlIdentifierContext ctx) {
+    public String visitDrlIdentifier(DRLParser.DrlIdentifierContext ctx) {
         return ctx.getText();
     }
 
     @Override
-    public Object visitDrlLiteral(DRLParser.DrlLiteralContext ctx) {
+    public String visitDrlLiteral(DRLParser.DrlLiteralContext ctx) {
         ParseTree node = ctx;
         while (true) {
             if (node instanceof TerminalNode) {
                 return node.toString();
             }
             if (node.getChildCount() != 1) {
-                return super.visitDrlLiteral(ctx);
+                return super.visitDrlLiteral(ctx).toString();
             }
             node = node.getChild(0);
         }
     }
 
     @Override
-    public Object visitDrlAnnotation(DRLParser.DrlAnnotationContext ctx) {
-        AnnotationDescr annotationDescr = new 
AnnotationDescr(ctx.name.getText());
-        annotationDescr.setValue(ctx.drlArguments().drlArgument(0).getText());
-        currentRule.addAnnotation(annotationDescr);
-        return super.visitDrlAnnotation(ctx);
-    }
-
-    @Override
-    public Object visitAttribute(DRLParser.AttributeContext ctx) {
-        AttributeDescr attributeDescr = new 
AttributeDescr(ctx.getChild(0).getText());
-        if (ctx.getChildCount() > 1) {
-            // TODO : will likely split visitAttribute methods using labels 
(e.g. #stringAttribute)
-            String value = 
unescapeJava(safeStripStringDelimiters(ctx.getChild(1).getText()));
-            attributeDescr.setValue(value);
-        }
-        if (currentRule != null) {
-            currentRule.addAttribute(attributeDescr);
-        } else {
-            packageDescr.addAttribute(attributeDescr);
-        }
-        return super.visitAttribute(ctx);
-    }
-
-    @Override
-    public Object visitLhsExists(DRLParser.LhsExistsContext ctx) {
+    public ExistsDescr visitLhsExists(DRLParser.LhsExistsContext ctx) {
         ExistsDescr existsDescr = new ExistsDescr();
-        currentConstructStack.peek().addDescr(existsDescr);
-        currentConstructStack.push(existsDescr);
-        try {
-            return super.visitLhsExists(ctx);
-        } finally {
-            currentConstructStack.pop();
-        }
+        BaseDescr descr = visitLhsPatternBind(ctx.lhsPatternBind());
+        existsDescr.addDescr(descr);
+        return existsDescr;
     }
 
     @Override
-    public Object visitLhsNot(DRLParser.LhsNotContext ctx) {
+    public NotDescr visitLhsNot(DRLParser.LhsNotContext ctx) {
         NotDescr notDescr = new NotDescr();
-        currentConstructStack.peek().addDescr(notDescr);
-        currentConstructStack.push(notDescr);
-        try {
-            return super.visitLhsNot(ctx);
-        } finally {
-            currentConstructStack.pop();
-        }
+        BaseDescr descr = visitLhsPatternBind(ctx.lhsPatternBind());
+        notDescr.addDescr(descr);
+        return notDescr;
     }
 
     @Override
-    public Object visitLhsOr(DRLParser.LhsOrContext ctx) {
+    public BaseDescr visitLhsOr(DRLParser.LhsOrContext ctx) {
         if (!ctx.DRL_OR().isEmpty()) {
             OrDescr orDescr = new OrDescr();
-            currentConstructStack.peek().addDescr(orDescr);
-            currentConstructStack.push(orDescr);
-            try {
-                return super.visitLhsOr(ctx);
-            } finally {
-                currentConstructStack.pop();
-            }
+            List<BaseDescr> descrList = visitDescrChildren(ctx);
+            descrList.forEach(orDescr::addDescr);
+            return orDescr;
         } else {
-            return super.visitLhsOr(ctx);
+            // No DRL_OR means only one lhsAnd
+            return visitLhsAnd(ctx.lhsAnd().get(0));
         }
     }
 
     @Override
-    public Object visitRhs(DRLParser.RhsContext ctx) {
-        currentRule.setConsequenceLocation(ctx.getStart().getLine(), 
ctx.getStart().getCharPositionInLine()); // location of "then"
-        
currentRule.setConsequence(ParserStringUtils.getTextPreservingWhitespace(ctx.consequence()));
-        return super.visitChildren(ctx);
+    public BaseDescr visitLhsAnd(DRLParser.LhsAndContext ctx) {
+        if (!ctx.DRL_AND().isEmpty()) {
+            AndDescr andDescr = new AndDescr();
+            List<BaseDescr> descrList = visitDescrChildren(ctx);
+            descrList.forEach(andDescr::addDescr);
+            return andDescr;
+        } else {
+            // No DRL_AND means only one lhsUnary
+            return visitLhsUnary(ctx.lhsUnary().get(0));
+        }
     }
 
-    public PackageDescr getPackageDescr() {
-        return packageDescr;
+    @Override
+    public BaseDescr visitLhsUnary(DRLParser.LhsUnaryContext ctx) {
+        return (BaseDescr) visitChildren(ctx);
     }
 
     private void populateStartEnd(BaseDescr descr, ParserRuleContext ctx) {
@@ -315,4 +357,31 @@ public class DRLVisitorImpl extends 
DRLParserBaseVisitor<Object> {
         //       I will revisit if this is the right approach.
         descr.setEndCharacter(ctx.getStop().getStopIndex());
     }
+
+    private List<BaseDescr> visitDescrChildren(RuleNode node) {
+        List<BaseDescr> aggregator = new ArrayList<>();
+        int n = node.getChildCount();
+
+        for (int i = 0; i < n && this.shouldVisitNextChild(node, aggregator); 
++i) {
+            ParseTree c = node.getChild(i);
+            Object childResult = c.accept(this);
+            if (childResult instanceof BaseDescr) {
+                aggregator.add((BaseDescr) childResult);
+            }
+        }
+        return aggregator;
+    }
+
+    private Optional<BaseDescr> visitFirstDescrChild(RuleNode node) {
+        int n = node.getChildCount();
+
+        for (int i = 0; i < n && this.shouldVisitNextChild(node, null); ++i) {
+            ParseTree c = node.getChild(i);
+            Object childResult = c.accept(this);
+            if (childResult instanceof BaseDescr) {
+                return Optional.of((BaseDescr) childResult);
+            }
+        }
+        return Optional.empty();
+    }
 }


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to