001    package org.codehaus.groovy.antlr;
002    import java.awt.*;
003    import java.awt.event.*;
004    import java.io.*;
005    import java.lang.reflect.*;
006    import java.util.Hashtable;
007    
008    import javax.swing.*;
009    import javax.swing.border.Border;
010    import javax.swing.text.BadLocationException;
011    import org.codehaus.groovy.antlr.parser.*;
012    
013    import antlr.*;
014    
015    /**
016     * @author Santhosh Kumar T
017     * @version 1.0
018     */
019    
020    public class LexerFrame extends JFrame implements ActionListener{
021        JSplitPane jSplitPane1 = new JSplitPane();
022        JScrollPane jScrollPane1 = new JScrollPane();
023        JScrollPane jScrollPane2 = new JScrollPane();
024        JTextPane tokenPane = new HScrollableTextPane();
025        JButton jbutton = new JButton("open");
026        JPanel mainPanel = new JPanel(new BorderLayout());
027        JTextArea scriptPane = new JTextArea();
028        Border border1;
029        Border border2;
030    
031        Class lexerClass;
032    
033        public LexerFrame(Class lexerClass, Class tokenTypesClass){
034            super("Token Steam Viewer");
035            this.lexerClass = lexerClass;
036            try{
037                jbInit();
038                setSize(500, 500);
039                listTokens(tokenTypesClass);
040    
041                final JPopupMenu popup = new JPopupMenu();
042                popup.add(loadFileAction);
043    
044                jbutton.setSize(30,30);
045                jbutton.addMouseListener(new MouseAdapter(){
046                    public void mouseReleased(MouseEvent e) {
047                        //if(e.isPopupTrigger())
048                            popup.show(scriptPane, e.getX(), e.getY());
049                    }
050                });
051                setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
052            } catch(Exception e){
053                e.printStackTrace();
054            }
055        }
056    
057        Hashtable tokens = new Hashtable();
058    
059        private void listTokens(Class tokenTypes) throws Exception{
060            Field field[] = tokenTypes.getDeclaredFields();
061            for(int i = 0; i<field.length; i++)
062                tokens.put(field[i].get(null), field[i].getName());
063        }
064    
065        public void actionPerformed(ActionEvent ae){
066            Token token = (Token) ((JComponent) ae.getSource()).getClientProperty("token");
067            if(token.getType()==Token.EOF_TYPE){
068                scriptPane.select(0, 0);
069                return;
070            }
071            try{
072                int start = scriptPane.getLineStartOffset(token.getLine()-1)+token.getColumn()-1;
073                scriptPane.select(start, start+token.getText().length());
074                scriptPane.requestFocus();
075            } catch(BadLocationException ex){
076            }
077        }
078    
079        private Action loadFileAction = new AbstractAction("Open File..."){
080            public void actionPerformed(ActionEvent ae){
081                JFileChooser jfc = new JFileChooser();
082                int response = jfc.showOpenDialog(LexerFrame.this);
083                if(response!=JFileChooser.APPROVE_OPTION)
084                    return;
085                try{
086                    scanScript(jfc.getSelectedFile());
087                } catch(Exception ex){
088                    ex.printStackTrace();
089                }
090            }
091        };
092    
093        private void scanScript(File file) throws Exception{
094            scriptPane.read(new FileReader(file), null);
095    
096            // create lexer
097            Constructor constructor = lexerClass.getConstructor(new Class[]{InputStream.class});
098            CharScanner lexer = (CharScanner) constructor.newInstance(new Object[]{new FileInputStream(file)});
099    
100            tokenPane.setEditable(true);
101            tokenPane.setText("");
102    
103            int line = 1;
104            ButtonGroup bg = new ButtonGroup();
105            Token token = null;
106    
107            while(true){
108                token = lexer.nextToken();
109                JToggleButton tokenButton = new JToggleButton((String) tokens.get(new Integer(token.getType())));
110                bg.add(tokenButton);
111                tokenButton.addActionListener(this);
112                tokenButton.setToolTipText(token.getText());
113                tokenButton.putClientProperty("token", token);
114                tokenButton.setMargin(new Insets(0, 1, 0, 1));
115                tokenButton.setFocusPainted(false);
116                if(token.getLine()>line){
117                    tokenPane.getDocument().insertString(tokenPane.getDocument().getLength(), "\n", null);
118                    line = token.getLine();
119                }
120                insertComponent(tokenButton);
121                if(token.getType()==Token.EOF_TYPE)
122                    break;
123            }
124    
125            tokenPane.setEditable(false);
126            tokenPane.setCaretPosition(0);
127        }
128    
129        private void insertComponent(JComponent comp){
130            try{
131                tokenPane.getDocument().insertString(tokenPane.getDocument().getLength(), " ", null);
132            } catch(BadLocationException ex1){
133            }
134            try{
135                tokenPane.setCaretPosition(tokenPane.getDocument().getLength()-1);
136            } catch(Exception ex){
137                tokenPane.setCaretPosition(0);
138            }
139            tokenPane.insertComponent(comp);
140        }
141    
142        private void jbInit() throws Exception{
143            border1 = BorderFactory.createEmptyBorder();
144            border2 = BorderFactory.createEmptyBorder();
145            jSplitPane1.setOrientation(JSplitPane.VERTICAL_SPLIT);
146            tokenPane.setEditable(false);
147            tokenPane.setText("");
148            scriptPane.setFont(new java.awt.Font("DialogInput", 0, 12));
149            scriptPane.setEditable(false);
150            scriptPane.setMargin(new Insets(5, 5, 5, 5));
151            scriptPane.setText("");
152            jScrollPane1.setBorder(border1);
153            jScrollPane2.setBorder(border1);
154            jSplitPane1.setMinimumSize(new Dimension(800,600));
155            mainPanel.add(jSplitPane1, BorderLayout.CENTER);
156            mainPanel.add(jbutton,BorderLayout.NORTH);
157            this.getContentPane().add(mainPanel);
158            jSplitPane1.add(jScrollPane1, JSplitPane.LEFT);
159            jScrollPane1.getViewport().add(tokenPane, null);
160            jSplitPane1.add(jScrollPane2, JSplitPane.RIGHT);
161            jScrollPane2.getViewport().add(scriptPane, null);
162    
163            jScrollPane1.setColumnHeaderView(new JLabel(" Token Stream:"));
164            jScrollPane2.setColumnHeaderView(new JLabel(" Input Script:"));
165            jSplitPane1.setResizeWeight(0.5);
166        }
167    
168        public static void main(String[] args) throws Exception{
169            try{
170                UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
171            } catch(Exception ignore){
172            }
173            new LexerFrame(GroovyLexer.class, GroovyTokenTypes.class).setVisible(true);
174        }
175    }
176    
177    
178    class HScrollableTextPane extends JTextPane{
179        public boolean getScrollableTracksViewportWidth(){
180            return(getSize().width<getParent().getSize().width);
181        }
182    
183        public void setSize(Dimension d){
184            if(d.width<getParent().getSize().width){
185                d.width = getParent().getSize().width;
186            }
187            super.setSize(d);
188        }
189    }