You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@groovy.apache.org by pa...@apache.org on 2019/09/30 03:26:45 UTC

[groovy] branch GROOVY_3_0_X updated: add antlr4-based version

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

paulk pushed a commit to branch GROOVY_3_0_X
in repository https://gitbox.apache.org/repos/asf/groovy.git


The following commit(s) were added to refs/heads/GROOVY_3_0_X by this push:
     new 552cd69  add antlr4-based version
552cd69 is described below

commit 552cd695b6fe53ef58608445452307912c8e7a50
Author: Paul King <pa...@asert.com.au>
AuthorDate: Mon Sep 30 13:26:29 2019 +1000

    add antlr4-based version
---
 .../java/org/apache/groovy/antlr/LexerFrame.java   | 310 +++++++++++++++++++++
 1 file changed, 310 insertions(+)

diff --git a/src/main/java/org/apache/groovy/antlr/LexerFrame.java b/src/main/java/org/apache/groovy/antlr/LexerFrame.java
new file mode 100644
index 0000000..d7cacd2
--- /dev/null
+++ b/src/main/java/org/apache/groovy/antlr/LexerFrame.java
@@ -0,0 +1,310 @@
+/*
+ *  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.groovy.antlr;
+
+import org.antlr.v4.runtime.Token;
+import org.apache.groovy.parser.antlr4.GroovyLangLexer;
+import org.apache.groovy.parser.antlr4.GroovyLexer;
+import org.codehaus.groovy.runtime.IOGroovyMethods;
+import org.codehaus.groovy.runtime.ResourceGroovyMethods;
+
+import javax.swing.AbstractAction;
+import javax.swing.Action;
+import javax.swing.BorderFactory;
+import javax.swing.ButtonGroup;
+import javax.swing.JButton;
+import javax.swing.JComponent;
+import javax.swing.JFileChooser;
+import javax.swing.JFrame;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JPopupMenu;
+import javax.swing.JScrollPane;
+import javax.swing.JSplitPane;
+import javax.swing.JTextArea;
+import javax.swing.JTextPane;
+import javax.swing.JToggleButton;
+import javax.swing.UIManager;
+import javax.swing.WindowConstants;
+import javax.swing.border.Border;
+import javax.swing.text.BadLocationException;
+import java.awt.BorderLayout;
+import java.awt.Dimension;
+import java.awt.Insets;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+import java.io.File;
+import java.io.FileReader;
+import java.io.Reader;
+import java.io.StringReader;
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Swing application to graphically display the tokens produced by the lexer.
+ */
+public class LexerFrame extends JFrame implements ActionListener {
+    private static final long serialVersionUID = 2715693043143492893L;
+    private final JSplitPane jSplitPane1 = new JSplitPane();
+    private final JScrollPane jScrollPane1 = new JScrollPane();
+    private final JScrollPane jScrollPane2 = new JScrollPane();
+    private final JTextPane tokenPane = new HScrollableTextPane();
+    private final JButton jbutton = new JButton("open");
+    private final JPanel mainPanel = new JPanel(new BorderLayout());
+    private final JTextArea scriptPane = new JTextArea();
+    private final Map<Integer, String> tokens = new HashMap<>();
+    private static final Class<GroovyLexer> TOKEN_TYPES_CLASS = GroovyLexer.class;
+
+    /**
+     * Constructor used when invoking as a standalone application
+     *
+     */
+    public LexerFrame() {
+        this(null);
+    }
+
+    /**
+     * Constructor used when invoking for a specific file
+     *
+     */
+    public LexerFrame(Reader reader) {
+        super("Token Stream Viewer");
+        try {
+            jbInit(reader);
+            setSize(500, 500);
+            listTokens(TOKEN_TYPES_CLASS);
+
+            if (reader == null) {
+                final JPopupMenu popup = new JPopupMenu();
+                popup.add(loadFileAction);
+                jbutton.setSize(30, 30);
+                jbutton.addMouseListener(new MouseAdapter() {
+                    public void mouseReleased(MouseEvent e) {
+                        //if(e.isPopupTrigger())
+                        popup.show(scriptPane, e.getX(), e.getY());
+                    }
+                });
+            } else {
+                safeScanScript(reader);
+            }
+
+            setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+
+    private void listTokens(Class tokenTypes) throws Exception {
+        for (Field field : tokenTypes.getDeclaredFields()) {
+            int modifiers = field.getModifiers();
+
+            if (!(Modifier.isPublic(modifiers) && Modifier.isStatic(modifiers) && Modifier.isFinal(modifiers))) {
+                continue;
+            }
+
+            Object fieldValue = field.get(null);
+            if (!(fieldValue instanceof Integer)) {
+                continue;
+            }
+
+            String fieldName = field.getName();
+            if (fieldName.endsWith("_MODE")) {
+                continue;
+            }
+
+            tokens.put((Integer) fieldValue, fieldName);
+        }
+
+        tokens.put(-1, "EOF");
+    }
+
+    public void actionPerformed(ActionEvent ae) {
+        Token token = (Token) ((JComponent) ae.getSource()).getClientProperty("token");
+        if (eof().equals(token.getType())) {
+            scriptPane.select(0, 0);
+            return;
+        }
+        try {
+            int start = scriptPane.getLineStartOffset(token.getLine() - 1) + getColumn(token);
+            String text = token.getText();
+            scriptPane.select(start, "".equals(text.trim()) ? start : start + text.length());
+            scriptPane.requestFocus();
+        } catch (BadLocationException ex) {
+            // IGNORE
+        }
+    }
+
+    private final Action loadFileAction = new AbstractAction("Open File...") {
+        private static final long serialVersionUID = 4541927184172762704L;
+
+        public void actionPerformed(ActionEvent ae) {
+            final JFileChooser jfc = new JFileChooser();
+            final int response = jfc.showOpenDialog(LexerFrame.this);
+            if (response != JFileChooser.APPROVE_OPTION) {
+                return;
+            }
+            safeScanScript(jfc.getSelectedFile());
+        }
+    };
+
+    private void safeScanScript(File file) {
+        try {
+            scanScript(new StringReader(ResourceGroovyMethods.getText(file)));
+        } catch (final Exception ex) {
+            ex.printStackTrace();
+        }
+    }
+
+    private void safeScanScript(Reader reader) {
+        try {
+            scanScript(reader instanceof StringReader ? (StringReader) reader : new StringReader(IOGroovyMethods.getText(reader)));
+        } catch (final Exception ex) {
+            ex.printStackTrace();
+        }
+    }
+
+    private void scanScript(final StringReader reader) throws Exception {
+        scriptPane.read(reader, null);
+        reader.reset();
+
+        // create lexer
+        final GroovyLangLexer lexer = new GroovyLangLexer(reader);
+
+        tokenPane.setEditable(true);
+        tokenPane.setText("");
+
+        int line = 1;
+        final ButtonGroup bg = new ButtonGroup();
+        Token token;
+
+        while (true) {
+            token = lexer.nextToken();
+            JToggleButton tokenButton = new JToggleButton(tokens.get(token.getType()));
+            bg.add(tokenButton);
+            tokenButton.addActionListener(this);
+            tokenButton.setToolTipText(token.getText());
+            tokenButton.putClientProperty("token", token);
+            tokenButton.setMargin(new Insets(0, 1, 0, 1));
+            tokenButton.setFocusPainted(false);
+            if (token.getLine() > line) {
+                tokenPane.getDocument().insertString(tokenPane.getDocument().getLength(), "\n", null);
+                line = token.getLine();
+            }
+            insertComponent(tokenButton);
+            if (eof().equals(token.getType())) {
+                break;
+            }
+        }
+
+        tokenPane.setEditable(false);
+        tokenPane.setCaretPosition(0);
+        reader.close();
+    }
+
+    private Integer eof() {
+        return GroovyLangLexer.EOF;
+    }
+
+    private Integer getColumn(Token token) {
+        return token.getCharPositionInLine();
+    }
+
+    private void insertComponent(JComponent comp) {
+        try {
+            tokenPane.getDocument().insertString(tokenPane.getDocument().getLength(), " ", null);
+        } catch (BadLocationException ex1) {
+            // Ignore
+        }
+        try {
+            tokenPane.setCaretPosition(tokenPane.getDocument().getLength() - 1);
+        } catch (Exception ex) {
+            tokenPane.setCaretPosition(0);
+        }
+        tokenPane.insertComponent(comp);
+    }
+
+    private void jbInit(Reader reader) throws Exception {
+        final Border border = BorderFactory.createEmptyBorder();
+        jSplitPane1.setOrientation(JSplitPane.VERTICAL_SPLIT);
+        tokenPane.setEditable(false);
+        tokenPane.setText("");
+        scriptPane.setFont(new java.awt.Font("DialogInput", 0, 12));
+        scriptPane.setEditable(false);
+        scriptPane.setMargin(new Insets(5, 5, 5, 5));
+        scriptPane.setText("");
+        jScrollPane1.setBorder(border);
+        jScrollPane2.setBorder(border);
+        jSplitPane1.setMinimumSize(new Dimension(800, 600));
+        mainPanel.add(jSplitPane1, BorderLayout.CENTER);
+        if (reader == null) {
+            mainPanel.add(jbutton, BorderLayout.NORTH);
+        }
+        this.getContentPane().add(mainPanel);
+        jSplitPane1.add(jScrollPane1, JSplitPane.LEFT);
+        jScrollPane1.getViewport().add(tokenPane, null);
+        jSplitPane1.add(jScrollPane2, JSplitPane.RIGHT);
+        jScrollPane2.getViewport().add(scriptPane, null);
+
+        jScrollPane1.setColumnHeaderView(new JLabel(" Token Stream:"));
+        jScrollPane2.setColumnHeaderView(new JLabel(" Input Script:"));
+        jSplitPane1.setResizeWeight(0.5);
+    }
+
+    public static void main(String[] args) throws Exception {
+        try {
+            UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
+        } catch (Exception ignore) {
+            // Ignore
+        }
+        LexerFrame lexerFrame = null;
+
+        if (args.length == 0) {
+            lexerFrame = new LexerFrame();
+        } else if (args.length > 1) {
+            System.err.println("usage: java LexerFrame [filename.ext]");
+            System.exit(1);
+        } else {
+            String filename = args[0];
+            FileReader fileReader = new FileReader(filename);
+            lexerFrame = new LexerFrame(fileReader);
+        }
+        lexerFrame.setVisible(true);
+    }
+
+    private static class HScrollableTextPane extends JTextPane {
+        private static final long serialVersionUID = -8582328309470654441L;
+
+        @Override
+        public boolean getScrollableTracksViewportWidth() {
+            return (getSize().width < getParent().getSize().width);
+        }
+
+        @Override
+        public void setSize(final Dimension d) {
+            if (d.width < getParent().getSize().width) {
+                d.width = getParent().getSize().width;
+            }
+            super.setSize(d);
+        }
+    }
+}