You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@plc4x.apache.org by ld...@apache.org on 2020/09/01 16:17:51 UTC

[plc4x] 01/01: Tracing of cross parser calls.

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

ldywicki pushed a commit to branch feature/parser-tracing
in repository https://gitbox.apache.org/repos/asf/plc4x.git

commit 5715f9d1f04421314fee6af2450af778fed564c4
Author: Ɓukasz Dywicki <lu...@code-house.org>
AuthorDate: Tue Sep 1 18:12:51 2020 +0200

    Tracing of cross parser calls.
    
    Main intention of these changes is propagation of call stack from one parser to another. It also allows to track rules and their matching down the path while going over file.
---
 .../codegenerator/language/mspec/ParserStack.java  | 69 ++++++++++++++++++++++
 .../mspec/expression/ExpressionStringListener.java | 37 ++++++++++++
 .../mspec/expression/ExpressionStringParser.java   | 13 +++-
 .../mspec/parser/MessageFormatListener.java        | 40 ++++++++++++-
 .../language/mspec/parser/MessageFormatParser.java | 61 +++++++++++++++++--
 5 files changed, 213 insertions(+), 7 deletions(-)

diff --git a/build-utils/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/ParserStack.java b/build-utils/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/ParserStack.java
new file mode 100644
index 0000000..12a2bda
--- /dev/null
+++ b/build-utils/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/ParserStack.java
@@ -0,0 +1,69 @@
+/*
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements.  See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership.  The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License.  You may obtain a copy of the License at
+
+     http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied.  See the License for the
+ specific language governing permissions and limitations
+ under the License.
+ */
+package org.apache.plc4x.plugins.codegenerator.language.mspec;
+
+import java.util.Map;
+import java.util.Stack;
+
+/**
+ * Helper to hold information about parsing of rules.
+ */
+public class ParserStack {
+
+    private final Stack<ParserCall> lines = new Stack<>();
+
+    public void push(int line, int character, Map<String, Object> context) {
+        lines.push(new ParserCall(line, character, context));
+    }
+
+    public void pop() {
+        lines.pop();
+    }
+
+    public void clear() {
+        lines.clear();
+    }
+
+    @Override
+    public String toString() {
+        final StringBuilder sb = new StringBuilder("ParserStack:");
+        for (int index = 0, linesSize = lines.size(); index < linesSize; index++) {
+            ParserCall call = lines.get(index);
+            sb.append(index).append(". ").append(call).append("\n");
+        }
+        return sb.toString();
+    }
+
+    private class ParserCall {
+        private final int line;
+        private final int character;
+        private final Map<String, Object> context;
+
+        private ParserCall(int line, int character, Map<String, Object> context) {
+            this.line = line;
+            this.character = character;
+            this.context = context;
+        }
+
+        @Override
+        public String toString() {
+            return "line: " + line + ":" + character + (context.isEmpty() ? "" : ", context: " + context);
+        }
+    }
+}
diff --git a/build-utils/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/expression/ExpressionStringListener.java b/build-utils/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/expression/ExpressionStringListener.java
index d593c2d..d988ada 100644
--- a/build-utils/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/expression/ExpressionStringListener.java
+++ b/build-utils/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/expression/ExpressionStringListener.java
@@ -19,24 +19,61 @@
 
 package org.apache.plc4x.plugins.codegenerator.language.mspec.expression;
 
+import org.antlr.v4.runtime.ParserRuleContext;
+import org.antlr.v4.runtime.tree.ErrorNode;
+import org.apache.plc4x.plugins.codegenerator.language.mspec.ParserStack;
 import org.apache.plc4x.plugins.codegenerator.types.terms.*;
 
+import java.util.Arrays;
 import java.util.Collection;
+import java.util.HashMap;
 import java.util.LinkedList;
 import java.util.List;
+import java.util.Map;
 import java.util.Stack;
 
 public class ExpressionStringListener extends ExpressionBaseListener {
 
+    private final List<String> ruleNames;
+    private final ParserStack parserStack;
     private Stack<List<Term>> parserContexts;
 
     private Term root;
 
+    public ExpressionStringListener(ParserStack parserStack, String[] recognizer) {
+        this.parserStack = parserStack;
+        this.ruleNames = Arrays.asList(recognizer);
+    }
+
     public Term getRoot() {
         return root;
     }
 
     @Override
+    public void visitErrorNode(ErrorNode node) {
+        System.out.println("Error in expression " + parserStack.toString() + " " + node);
+    }
+
+    @Override
+    public void enterEveryRule(ParserRuleContext ctx) {
+        Map<String, Object> context = new HashMap<>();
+        context.put("kind", "expression");
+        context.put("source", ctx.getStart().getTokenSource().getSourceName());
+        context.put("line", ctx.getStart().getTokenSource().getLine());
+        context.put("callChain", ctx.getRuleContext().toString(ruleNames));
+        parserStack.push(
+            ctx.getStart().getLine(),
+            ctx.getStart().getCharPositionInLine(),
+            context
+        );
+    }
+
+    @Override
+    public void exitEveryRule(ParserRuleContext ctx) {
+        parserStack.pop();
+    }
+
+    @Override
     public void enterExpressionString(ExpressionParser.ExpressionStringContext ctx) {
         parserContexts = new Stack<>();
         parserContexts.push(new LinkedList<>());
diff --git a/build-utils/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/expression/ExpressionStringParser.java b/build-utils/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/expression/ExpressionStringParser.java
index 7b9f124..a4d0a04 100644
--- a/build-utils/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/expression/ExpressionStringParser.java
+++ b/build-utils/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/expression/ExpressionStringParser.java
@@ -22,6 +22,7 @@ package org.apache.plc4x.plugins.codegenerator.language.mspec.expression;
 import org.antlr.v4.runtime.CharStreams;
 import org.antlr.v4.runtime.CommonTokenStream;
 import org.antlr.v4.runtime.tree.ParseTreeWalker;
+import org.apache.plc4x.plugins.codegenerator.language.mspec.ParserStack;
 import org.apache.plc4x.plugins.codegenerator.types.terms.Term;
 
 import java.io.IOException;
@@ -29,6 +30,16 @@ import java.io.InputStream;
 
 public class ExpressionStringParser {
 
+    private final ParserStack parserStack;
+
+    public ExpressionStringParser() {
+        this(new ParserStack());
+    }
+
+    public ExpressionStringParser(ParserStack parserStack) {
+        this.parserStack = parserStack;
+    }
+
     public Term parse(InputStream source) {
         ExpressionLexer lexer;
         try {
@@ -36,7 +47,7 @@ public class ExpressionStringParser {
         } catch (IOException e) {
             throw new RuntimeException(e);
         }
-        ExpressionStringListener listener = new ExpressionStringListener();
+        ExpressionStringListener listener = new ExpressionStringListener(parserStack, ExpressionParser.ruleNames);
         new ParseTreeWalker().walk(listener, new ExpressionParser(new CommonTokenStream(lexer)).expressionString());
         return listener.getRoot();
     }
diff --git a/build-utils/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/parser/MessageFormatListener.java b/build-utils/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/parser/MessageFormatListener.java
index 554ce4c..b4e11d5 100644
--- a/build-utils/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/parser/MessageFormatListener.java
+++ b/build-utils/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/parser/MessageFormatListener.java
@@ -19,9 +19,12 @@
 
 package org.apache.plc4x.plugins.codegenerator.language.mspec.parser;
 
+import org.antlr.v4.runtime.ParserRuleContext;
+import org.antlr.v4.runtime.tree.ErrorNode;
 import org.apache.commons.io.IOUtils;
 import org.apache.plc4x.plugins.codegenerator.language.mspec.MSpecBaseListener;
 import org.apache.plc4x.plugins.codegenerator.language.mspec.MSpecParser;
+import org.apache.plc4x.plugins.codegenerator.language.mspec.ParserStack;
 import org.apache.plc4x.plugins.codegenerator.language.mspec.expression.ExpressionStringParser;
 import org.apache.plc4x.plugins.codegenerator.language.mspec.model.definitions.*;
 import org.apache.plc4x.plugins.codegenerator.language.mspec.model.fields.*;
@@ -45,12 +48,20 @@ import java.util.*;
 
 public class MessageFormatListener extends MSpecBaseListener {
 
+    private final ParserStack parserStack;
+    private final List<String> ruleNames;
+
     private Deque<List<Field>> parserContexts;
 
     private Deque<List<EnumValue>> enumContexts;
 
     private Map<String, TypeDefinition> types;
 
+    public MessageFormatListener(ParserStack parserStack, String[] ruleNames) {
+        this.parserStack = parserStack;
+        this.ruleNames = Arrays.asList(ruleNames);
+    }
+
     public Deque<List<Field>> getParserContexts() {
         return parserContexts;
     }
@@ -71,6 +82,31 @@ public class MessageFormatListener extends MSpecBaseListener {
     }
 
     @Override
+    public void enterEveryRule(ParserRuleContext ctx) {
+        Map<String, Object> context = new HashMap<>();
+        context.put("kind", "mspec");
+        context.put("source", ctx.getStart().getTokenSource().getSourceName());
+        context.put("line", ctx.getStart().getTokenSource().getLine());
+        context.put("text", ctx.getRuleContext().getText());
+        context.put("callChain", ctx.getRuleContext().toString(ruleNames));
+        parserStack.push(
+            ctx.getStart().getLine(),
+            ctx.getStart().getCharPositionInLine(),
+            context
+        );
+    }
+
+    @Override
+    public void exitEveryRule(ParserRuleContext ctx) {
+        parserStack.pop();
+    }
+
+    @Override
+    public void visitErrorNode(ErrorNode node) {
+        System.out.println("Error node " + parserStack.toString() + " " + node);
+    }
+
+    @Override
     public void enterComplexType(MSpecParser.ComplexTypeContext ctx) {
         if (ctx.enumValues != null) {
             List<EnumValue> enumContext = new LinkedList<>();
@@ -412,7 +448,7 @@ public class MessageFormatListener extends MSpecBaseListener {
 
     private Term getExpressionTerm(String expressionString) {
         InputStream inputStream = IOUtils.toInputStream(expressionString, Charset.defaultCharset());
-        ExpressionStringParser parser = new ExpressionStringParser();
+        ExpressionStringParser parser = new ExpressionStringParser(parserStack);
         try {
             return parser.parse(inputStream);
         } catch (Exception e) {
@@ -495,7 +531,7 @@ public class MessageFormatListener extends MSpecBaseListener {
 
     private Term parseExpression(String expressionString) {
         InputStream inputStream = IOUtils.toInputStream(expressionString, Charset.defaultCharset());
-        ExpressionStringParser parser = new ExpressionStringParser();
+        ExpressionStringParser parser = new ExpressionStringParser(parserStack);
         try {
             return parser.parse(inputStream);
         } catch (Exception e) {
diff --git a/build-utils/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/parser/MessageFormatParser.java b/build-utils/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/parser/MessageFormatParser.java
index cc6f9df..df649f1 100644
--- a/build-utils/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/parser/MessageFormatParser.java
+++ b/build-utils/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/parser/MessageFormatParser.java
@@ -19,27 +19,80 @@
 
 package org.apache.plc4x.plugins.codegenerator.language.mspec.parser;
 
+import org.antlr.v4.runtime.CharStream;
 import org.antlr.v4.runtime.CharStreams;
 import org.antlr.v4.runtime.CommonTokenStream;
 import org.antlr.v4.runtime.tree.ParseTreeWalker;
 import org.apache.plc4x.plugins.codegenerator.language.mspec.MSpecLexer;
 import org.apache.plc4x.plugins.codegenerator.language.mspec.MSpecParser;
+import org.apache.plc4x.plugins.codegenerator.language.mspec.ParserStack;
 import org.apache.plc4x.plugins.codegenerator.types.definitions.TypeDefinition;
 
+import java.io.File;
 import java.io.IOException;
 import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.nio.file.Path;
+import java.nio.file.Paths;
 import java.util.Map;
 
 public class MessageFormatParser {
 
+    private final ParserStack parserStack;
+
+    public MessageFormatParser() {
+        this(new ParserStack());
+    }
+
+    public MessageFormatParser(ParserStack stack) {
+        this.parserStack = stack;
+    }
+
     public Map<String, TypeDefinition> parse(InputStream source) {
-        MSpecLexer lexer;
         try {
-            lexer = new MSpecLexer(CharStreams.fromStream(source));
+            return parse(CharStreams.fromStream(source));
+        } catch (IOException e) {
+            throw new RuntimeException("Could not read source stream", e);
+        }
+    }
+
+    public Map<String, TypeDefinition> parse(InputStream source, String name) {
+        try {
+            return parse(CharStreams.fromReader(new InputStreamReader(source), name));
+        } catch (IOException e) {
+            throw new RuntimeException("Could not read source stream", e);
+        }
+    }
+
+    public Map<String, TypeDefinition> parse(Path source) {
+        try {
+            return parse(CharStreams.fromPath(source));
         } catch (IOException e) {
-            throw new RuntimeException(e);
+            throw new RuntimeException("Could not read source path", e);
         }
-        MessageFormatListener listener = new MessageFormatListener();
+    }
+
+    public Map<String, TypeDefinition> parse(URL source) {
+        try {
+            return parse(Paths.get(source.toURI()));
+        } catch (URISyntaxException e) {
+            throw new RuntimeException("Invalid source URI", e);
+        }
+    }
+
+    public Map<String, TypeDefinition> parse(File source) {
+        try {
+            return parse(CharStreams.fromFileName(source.getAbsolutePath()));
+        } catch (IOException e) {
+            throw new RuntimeException("Could not open file", e);
+        }
+    }
+
+    private Map<String, TypeDefinition> parse(CharStream input) {
+        MSpecLexer lexer = new MSpecLexer(input);
+        MessageFormatListener listener = new MessageFormatListener(parserStack, MSpecParser.ruleNames);
         new ParseTreeWalker().walk(listener, new MSpecParser(new CommonTokenStream(lexer)).file());
         return listener.getTypes();
     }