Pārlūkot izejas kodu

#121 initial working draft

Ranides Atterwim 2 gadi atpakaļ
vecāks
revīzija
8f531708dc

+ 11 - 6
assira.commons/src/main/java/net/ranides/assira/grammar/impl/ParserGenerated.java

@@ -30,7 +30,7 @@ import java.util.Map;
 import java.util.Set;
 import java.util.TreeMap;
 
-class ParserGenerated implements G4Parser {
+class G4ParserGenerated implements G4Parser {
 
     protected final IClass<? extends Lexer> lexer;
 
@@ -44,7 +44,7 @@ class ParserGenerated implements G4Parser {
 
     private final Set<String> branchValidator;
 
-    public ParserGenerated(IClass<? extends Lexer> lexer, IClass<? extends Parser> parser, G4ErrorHandler handler) {
+    public G4ParserGenerated(IClass<? extends Lexer> lexer, IClass<? extends Parser> parser, G4ErrorHandler handler) {
         this.lexer = lexer;
         this.parser = parser;
         this.handler = handler;
@@ -117,6 +117,11 @@ class ParserGenerated implements G4Parser {
         private final Map<String, BranchCoverage> branches;
 
         public MyCoverage() {
+            // @todo fix coverage
+            // false ALIAS detection: borderSizeComponent <= numberUnit
+            // this rule has few alternatives and only one of them links to "numberUnit"
+            // other alternatives link to TOKENS (not grammar rules)
+
             rules = new TreeMap<>();
             branches = new TreeMap<>();
 
@@ -210,19 +215,19 @@ class ParserGenerated implements G4Parser {
         private final NodeForRule tree;
 
         public MyRoot(String ruleName, String text) {
-            Lexer lexer = ParserGenerated.this.lexer.construct(CharStreams.fromString(text));
+            Lexer lexer = G4ParserGenerated.this.lexer.construct(CharStreams.fromString(text));
 
             lexer.removeErrorListeners();
 
             lexer.addErrorListener(new NodeSupport.DelegateListener(handler));
 
             CommonTokenStream tokens = new CommonTokenStream(lexer);
-            Parser interpreter = ParserGenerated.this.parser.construct(tokens);
+            Parser interpreter = G4ParserGenerated.this.parser.construct(tokens);
 
             interpreter.removeErrorListeners();
             interpreter.addErrorListener(new NodeSupport.DelegateListener(handler));
 
-            IMethod rule = ParserGenerated.this.parser
+            IMethod rule = G4ParserGenerated.this.parser
                 .method(ruleName)
                 .orElseThrow(() -> new IllegalArgumentException("Unknown rule: " + ruleName));
 
@@ -235,7 +240,7 @@ class ParserGenerated implements G4Parser {
 
         @Override
         public G4Parser parser() {
-            return ParserGenerated.this;
+            return G4ParserGenerated.this;
         }
 
         @Override

+ 1 - 2
assira.commons/src/main/java/net/ranides/assira/grammar/impl/ParserFactory.java

@@ -2,7 +2,6 @@ package net.ranides.assira.grammar.impl;
 
 import lombok.experimental.UtilityClass;
 import net.ranides.assira.grammar.G4ErrorHandler;
-import net.ranides.assira.grammar.G4Exception;
 import net.ranides.assira.grammar.G4Parser;
 import net.ranides.assira.reflection.IClass;
 import org.antlr.v4.runtime.Lexer;
@@ -12,7 +11,7 @@ import org.antlr.v4.runtime.Parser;
 public class ParserFactory {
 
     public static G4Parser newInstance(IClass<? extends Lexer> lexer, IClass<? extends Parser> parser, G4ErrorHandler handler) {
-        return new ParserGenerated(lexer, parser, handler);
+        return new G4ParserGenerated(lexer, parser, handler);
     }
 
     public static G4Parser newInstance(String grammar, String imports, G4ErrorHandler handler) {

+ 99 - 5
assira.g4interpreter/src/main/java/net/ranides/assira/grammar/impl/G4ParserInterpreter.java

@@ -1,16 +1,17 @@
 package net.ranides.assira.grammar.impl;
 
 import lombok.Data;
-import net.ranides.assira.collection.lists.ListUtils;
 import net.ranides.assira.collection.maps.CrossMap;
 import net.ranides.assira.collection.maps.OpenCrossMap;
 import net.ranides.assira.collection.sets.OpenSet;
+import net.ranides.assira.generic.Ref;
 import net.ranides.assira.grammar.G4ErrorHandler;
 import net.ranides.assira.grammar.G4Exception;
 import net.ranides.assira.grammar.G4Node;
 import net.ranides.assira.grammar.G4Parser;
-import net.ranides.assira.generic.Ref;
 import net.ranides.assira.grammar.G4ParserCoverage;
+import net.ranides.assira.grammar.impl.CoverageSupport.SimpleBranchCoverage;
+import net.ranides.assira.grammar.impl.CoverageSupport.SimpleRuleCoverage;
 import net.ranides.assira.text.StringUtils;
 import org.antlr.runtime.ANTLRStringStream;
 import org.antlr.runtime.RecognitionException;
@@ -38,10 +39,12 @@ import org.antlr.v4.tool.ast.AltAST;
 import org.antlr.v4.tool.ast.GrammarAST;
 import org.antlr.v4.tool.ast.GrammarRootAST;
 
+import java.util.Collection;
 import java.util.List;
 import java.util.Map;
 import java.util.NoSuchElementException;
 import java.util.Set;
+import java.util.TreeMap;
 
 public class G4ParserInterpreter implements G4Parser {
 
@@ -233,9 +236,7 @@ public class G4ParserInterpreter implements G4Parser {
 
     @Override
     public G4ParserCoverage rules() {
-        Vocabulary v = grammar.getVocabulary();
-        List<String> tokens = ListUtils.produce(v.getMaxTokenType() + 1, v::getSymbolicName);
-        throw new UnsupportedOperationException("TODO"); // @TODO implement that
+        return new MyCoverage();
     }
 
     private class MyRoot extends RootAbstract {
@@ -295,6 +296,99 @@ public class G4ParserInterpreter implements G4Parser {
         }
     }
 
+    private class MyCoverage extends G4ParserCoverage {
+
+        private final Map<String, RuleCoverage> rules;
+        private final Map<String, BranchCoverage> branches;
+        private final Map<String, String> aliases;
+
+        public MyCoverage() {
+            // @todo fix coverage: borderSize#borderSize2 <= borderSizeComponent
+            // this alternative links to only one grammar rule, granted, BUT:
+            // this rule is repeated, it is not "simple alias". we should ignore that.
+
+            rules = new TreeMap<>();
+            branches = new TreeMap<>();
+            aliases = new TreeMap<>();
+
+            Vocabulary v = grammar.getVocabulary();
+
+            for(int i=1, n = v.getMaxTokenType(); i<=n; i++) {
+                String token = v.getSymbolicName(i);
+                rules.put(token, new SimpleRuleCoverage(token, Ref.empty()));
+            }
+
+            for(Rule  rule : grammar.rules.values()) {
+                getRuleAliases(rule);
+                String ruleName = rule.name;
+                Ref<String> alias = Ref.ofNullable(aliases.get(ruleName));
+                rules.put(ruleName, new SimpleRuleCoverage(ruleName, alias));
+            }
+
+            for(String fqn : branchValidator) {
+                if(!fqn.startsWith(NodeSupport.QUALIFIER_NAME)) {
+                    String[] m = fqn.split(NodeSupport.QUALIFIER_NAME);
+                    String ruleName = m[0];
+                    String qualifier = NodeSupport.QUALIFIER_NAME + m[1];
+                    Ref<String> alias = Ref.ofNullable(aliases.get(ruleName + qualifier));
+                    branches.put(qualifier, new SimpleBranchCoverage(ruleName, qualifier, alias));
+                }
+            }
+
+            branches.values().forEach(branch -> {
+                rules.get(branch.rule()).branches().add(branch);
+            });
+        }
+
+        private void getRuleAliases(Rule rule) {
+            if(rule.alt != null) {
+                for (Alternative alt : rule.alt) {
+                    if (alt != null) {
+                        String alias = null;
+                        if(alt.ruleRefs.size() == 0 && alt.tokenRefs.size() == 1) {
+                            alias = alt.tokenRefs.keySet().iterator().next();
+                        }
+                        if(alt.ruleRefs.size() == 1 && alt.tokenRefs.size() == 0) {
+                            alias = alt.ruleRefs.keySet().iterator().next();
+                        }
+                        if(alias != null) {
+                            int ri = rule.index;
+                            int ai = alt.altNum;
+                            String altName = branchLabels.get(ri, ai);
+
+                            if(altName != null) {
+                                aliases.put(rule.name + NodeSupport.QUALIFIER_NAME+ altName, alias);
+                            }
+                            else if(rule.alt.length == 2) {
+                                aliases.put(rule.name, alias);
+                            }
+                        }
+                    }
+                }
+            }
+        }
+
+        @Override
+        public Collection<G4ParserCoverage.RuleCoverage> rules() {
+            return rules.values();
+        }
+
+        @Override
+        public Collection<BranchCoverage> branches() {
+            return branches.values();
+        }
+
+        @Override
+        public Ref<G4ParserCoverage.RuleCoverage> rule(String ruleName) {
+            return Ref.ofNullable(rules.get(ruleName));
+        }
+
+        @Override
+        public Ref<G4ParserCoverage.BranchCoverage> branch(String ruleName) {
+            return Ref.ofNullable(branches.get(ruleName));
+        }
+    }
+
     @Data
     private static final class ANTLRToolListenerAdapter implements ANTLRToolListener {
 

+ 15 - 21
assira.ui/src/test/java/net/ranides/assira/ui/primitives/CssParserTest.java

@@ -88,30 +88,24 @@ public class CssParserTest {
     @Ignore("manual")
     @Test
     public void grammarInterpretedCoverage() throws IOException {
-        G4Parser g4 = G4Parser
-            .builder()
-            .sourceFile(
-                "src\\main\\antlr4\\net\\ranides\\grammars\\generated\\CssGrammar.g4")
+        G4ParserCoverage info = G4Parser.builder()
+            .sourceFile("src\\main\\antlr4\\net\\ranides\\grammars\\generated\\CssGrammar.g4")
             .imports("src\\main\\antlr4\\imports")
             .handler((message, error) -> System.out.println(message))
-            .build();
+            .build()
+            .rules();
 
-        Color color = CssParser.COLOR.single(g4.parse("root_color", "#446600"));
-        assertEquals(new Color(68,102,0), color);
-
-//            .rules();
-//
-//        info.use(IGNORE);
-//
-//        info.use(CssParser.NUMBER);
-//        info.use(CssParser.SIZE_UNIT);
-//        info.use(CssParser.COLOR);
-//        info.use(CssParser.BORDER_STYLE);
-//        info.use(CssParser.BORDER_SIZE);
-//        info.use(CssParser.BORDER_SIZE_COMPONENT);
-//        info.use(CssParser.BORDER);
-//
-//        printCoverage(info);
+        info.use(IGNORE);
+
+        info.use(CssParser.NUMBER);
+        info.use(CssParser.SIZE_UNIT);
+        info.use(CssParser.COLOR);
+        info.use(CssParser.BORDER_STYLE);
+        info.use(CssParser.BORDER_SIZE);
+        info.use(CssParser.BORDER_SIZE_COMPONENT);
+        info.use(CssParser.BORDER);
+
+        printCoverage(info);
     }
 
     @Ignore("manual")