/* * Copyright (c) 2014 Sam Harwell, Tunnel Vision Laboratories LLC * All rights reserved. * * The source code of this document is proprietary work, and is not licensed for * distribution. For information about licensing, contact Sam Harwell at: * sam@tunnelvisionlabs.com */ package org.antlr.works.editor.grammar.debugger; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.util.ArrayList; import java.util.EnumSet; import java.util.List; import javax.swing.table.AbstractTableModel; import javax.swing.text.Document; import javax.swing.text.JTextComponent; import org.antlr.netbeans.editor.text.DocumentSnapshot; import org.antlr.netbeans.editor.text.VersionedDocumentUtilities; import org.antlr.netbeans.parsing.spi.ParserDataOptions; import org.antlr.netbeans.parsing.spi.ParserTaskManager; import org.antlr.v4.runtime.ParserRuleContext; import org.antlr.v4.runtime.atn.ATN; import org.antlr.v4.runtime.atn.ATNDeserializer; import org.antlr.v4.runtime.tree.ErrorNode; import org.antlr.v4.runtime.tree.ParseTreeListener; import org.antlr.v4.runtime.tree.ParseTreeWalker; import org.antlr.v4.runtime.tree.TerminalNode; import org.netbeans.api.editor.EditorRegistry; import org.netbeans.api.settings.ConvertAsProperties; import org.openide.awt.ActionID; import org.openide.awt.ActionReference; import org.openide.util.Lookup; import org.openide.util.NbBundle.Messages; import org.openide.util.WeakListeners; import org.openide.windows.TopComponent; /** * Top component which displays something. */ @ConvertAsProperties( dtd = "-//org.antlr.works.editor.grammar.debugger//ParserDebuggerController//EN", autostore = false ) @TopComponent.Description( preferredID = "ParserDebuggerControllerTopComponent", //iconBase="SET/PATH/TO/ICON/HERE", persistenceType = TopComponent.PERSISTENCE_ALWAYS ) @TopComponent.Registration(mode = "rightSlidingSide", openAtStartup = false) @ActionID(category = "Window", id = "org.antlr.works.editor.grammar.debugger.ParserDebuggerControllerTopComponent") @ActionReference(path = "Menu/Window" /*, position = 333 */) @TopComponent.OpenActionRegistration( displayName = "#CTL_ParserDebuggerControllerAction", preferredID = "ParserDebuggerControllerTopComponent" ) @Messages({ "CTL_ParserDebuggerControllerAction=Parser Debugger Controller", "CTL_ParserDebuggerControllerTopComponent=Parser", "HINT_ParserDebuggerControllerTopComponent=This is a parser debugger controller window" }) public final class ParserDebuggerControllerTopComponent extends TopComponent { private final PropertyChangeListener editorRegistryListener = new EditorRegistryListener(); public ParserDebuggerControllerTopComponent() { initComponents(); setName(Bundle.CTL_ParserDebuggerControllerTopComponent()); setToolTipText(Bundle.HINT_ParserDebuggerControllerTopComponent()); jSplitPane1.setDividerLocation(0.8); EditorRegistry.addPropertyChangeListener(WeakListeners.propertyChange(editorRegistryListener, EditorRegistry.class)); } /** * This method is called from within the constructor to initialize the form. * WARNING: Do NOT modify this code. The content of this method is always * regenerated by the Form Editor. */ // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents private void initComponents() { jSplitPane1 = new javax.swing.JSplitPane(); javax.swing.JTabbedPane jTabbedPane1 = new javax.swing.JTabbedPane(); javax.swing.JPanel jPanel2 = new javax.swing.JPanel(); javax.swing.JScrollPane jScrollPane1 = new javax.swing.JScrollPane(); tblRules = new javax.swing.JTable(); javax.swing.JPanel jPanel7 = new javax.swing.JPanel(); javax.swing.JScrollPane jScrollPane5 = new javax.swing.JScrollPane(); tblDecisions = new javax.swing.JTable(); javax.swing.JPanel jPanel3 = new javax.swing.JPanel(); javax.swing.JScrollPane jScrollPane2 = new javax.swing.JScrollPane(); tblLookahead = new javax.swing.JTable(); javax.swing.JPanel jPanel5 = new javax.swing.JPanel(); javax.swing.JScrollPane jScrollPane3 = new javax.swing.JScrollPane(); tblConflicts = new javax.swing.JTable(); javax.swing.JPanel jPanel4 = new javax.swing.JPanel(); javax.swing.JScrollPane jScrollPane6 = new javax.swing.JScrollPane(); tblStatistics = new javax.swing.JTable(); jPanel1 = new javax.swing.JPanel(); setLayout(new java.awt.GridLayout(1, 0)); jSplitPane1.setBorder(javax.swing.BorderFactory.createEmptyBorder(1, 1, 1, 1)); jSplitPane1.setDividerLocation(120); jSplitPane1.setOrientation(javax.swing.JSplitPane.VERTICAL_SPLIT); jSplitPane1.setResizeWeight(1.0); jSplitPane1.setContinuousLayout(true); tblRules.setAutoCreateRowSorter(true); tblRules.setModel(new javax.swing.table.DefaultTableModel( new Object [][] { {null, null}, {null, null}, {null, null}, {null, null} }, new String [] { "Rule", "Instances" } ) { boolean[] canEdit = new boolean [] { false, false }; public boolean isCellEditable(int rowIndex, int columnIndex) { return canEdit [columnIndex]; } }); jScrollPane1.setViewportView(tblRules); if (tblRules.getColumnModel().getColumnCount() > 0) { tblRules.getColumnModel().getColumn(0).setHeaderValue(org.openide.util.NbBundle.getMessage(ParserDebuggerControllerTopComponent.class, "ParserDebuggerControllerTopComponent.tblRules.columnModel.title0")); // NOI18N tblRules.getColumnModel().getColumn(1).setHeaderValue(org.openide.util.NbBundle.getMessage(ParserDebuggerControllerTopComponent.class, "ParserDebuggerControllerTopComponent.tblRules.columnModel.title1")); // NOI18N } javax.swing.GroupLayout jPanel2Layout = new javax.swing.GroupLayout(jPanel2); jPanel2.setLayout(jPanel2Layout); jPanel2Layout.setHorizontalGroup( jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(jPanel2Layout.createSequentialGroup() .addGap(0, 0, 0) .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 381, Short.MAX_VALUE) .addGap(0, 0, 0)) ); jPanel2Layout.setVerticalGroup( jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel2Layout.createSequentialGroup() .addGap(0, 0, 0) .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 107, Short.MAX_VALUE) .addGap(0, 0, 0)) ); jTabbedPane1.addTab(org.openide.util.NbBundle.getMessage(ParserDebuggerControllerTopComponent.class, "ParserDebuggerControllerTopComponent.jPanel2.TabConstraints.tabTitle"), jPanel2); // NOI18N tblDecisions.setAutoCreateRowSorter(true); tblDecisions.setModel(new javax.swing.table.DefaultTableModel( new Object [][] { {null, null, null}, {null, null, null}, {null, null, null}, {null, null, null} }, new String [] { "Decision", "Rule", "Count" } ) { boolean[] canEdit = new boolean [] { false, false, false }; public boolean isCellEditable(int rowIndex, int columnIndex) { return canEdit [columnIndex]; } }); jScrollPane5.setViewportView(tblDecisions); if (tblDecisions.getColumnModel().getColumnCount() > 0) { tblDecisions.getColumnModel().getColumn(0).setHeaderValue(org.openide.util.NbBundle.getMessage(ParserDebuggerControllerTopComponent.class, "ParserDebuggerControllerTopComponent.tblLookahead.columnModel.title0")); // NOI18N tblDecisions.getColumnModel().getColumn(1).setHeaderValue(org.openide.util.NbBundle.getMessage(ParserDebuggerControllerTopComponent.class, "ParserDebuggerControllerTopComponent.tblLookahead.columnModel.title1")); // NOI18N tblDecisions.getColumnModel().getColumn(2).setHeaderValue(org.openide.util.NbBundle.getMessage(ParserDebuggerControllerTopComponent.class, "ParserDebuggerControllerTopComponent.tblLookahead.columnModel.title3")); // NOI18N } javax.swing.GroupLayout jPanel7Layout = new javax.swing.GroupLayout(jPanel7); jPanel7.setLayout(jPanel7Layout); jPanel7Layout.setHorizontalGroup( jPanel7Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(jPanel7Layout.createSequentialGroup() .addGap(0, 0, 0) .addComponent(jScrollPane5, javax.swing.GroupLayout.DEFAULT_SIZE, 381, Short.MAX_VALUE) .addGap(0, 0, 0)) ); jPanel7Layout.setVerticalGroup( jPanel7Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(jPanel7Layout.createSequentialGroup() .addGap(0, 0, 0) .addComponent(jScrollPane5, javax.swing.GroupLayout.DEFAULT_SIZE, 107, Short.MAX_VALUE) .addGap(0, 0, 0)) ); jTabbedPane1.addTab(org.openide.util.NbBundle.getMessage(ParserDebuggerControllerTopComponent.class, "ParserDebuggerControllerTopComponent.jPanel7.TabConstraints.tabTitle"), jPanel7); // NOI18N tblLookahead.setAutoCreateRowSorter(true); tblLookahead.setModel(new javax.swing.table.DefaultTableModel( new Object [][] { {null, null, null, null, null, null}, {null, null, null, null, null, null}, {null, null, null, null, null, null}, {null, null, null, null, null, null} }, new String [] { "Decision", "Rule", "Avg k", "Min k", "Max k", "Cost" } ) { boolean[] canEdit = new boolean [] { false, false, false, false, false, false }; public boolean isCellEditable(int rowIndex, int columnIndex) { return canEdit [columnIndex]; } }); jScrollPane2.setViewportView(tblLookahead); if (tblLookahead.getColumnModel().getColumnCount() > 0) { tblLookahead.getColumnModel().getColumn(0).setHeaderValue(org.openide.util.NbBundle.getMessage(ParserDebuggerControllerTopComponent.class, "ParserDebuggerControllerTopComponent.tblLookahead.columnModel.title0")); // NOI18N tblLookahead.getColumnModel().getColumn(1).setHeaderValue(org.openide.util.NbBundle.getMessage(ParserDebuggerControllerTopComponent.class, "ParserDebuggerControllerTopComponent.tblLookahead.columnModel.title1")); // NOI18N tblLookahead.getColumnModel().getColumn(2).setHeaderValue(org.openide.util.NbBundle.getMessage(ParserDebuggerControllerTopComponent.class, "ParserDebuggerControllerTopComponent.tblLookahead.columnModel.title3")); // NOI18N tblLookahead.getColumnModel().getColumn(3).setHeaderValue(org.openide.util.NbBundle.getMessage(ParserDebuggerControllerTopComponent.class, "ParserDebuggerControllerTopComponent.tblLookahead.columnModel.title4")); // NOI18N tblLookahead.getColumnModel().getColumn(4).setHeaderValue(org.openide.util.NbBundle.getMessage(ParserDebuggerControllerTopComponent.class, "ParserDebuggerControllerTopComponent.tblLookahead.columnModel.title5")); // NOI18N } javax.swing.GroupLayout jPanel3Layout = new javax.swing.GroupLayout(jPanel3); jPanel3.setLayout(jPanel3Layout); jPanel3Layout.setHorizontalGroup( jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(jPanel3Layout.createSequentialGroup() .addGap(0, 0, 0) .addComponent(jScrollPane2, javax.swing.GroupLayout.DEFAULT_SIZE, 381, Short.MAX_VALUE) .addGap(0, 0, 0)) ); jPanel3Layout.setVerticalGroup( jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(jPanel3Layout.createSequentialGroup() .addGap(0, 0, 0) .addComponent(jScrollPane2, javax.swing.GroupLayout.DEFAULT_SIZE, 107, Short.MAX_VALUE) .addGap(0, 0, 0)) ); jTabbedPane1.addTab(org.openide.util.NbBundle.getMessage(ParserDebuggerControllerTopComponent.class, "ParserDebuggerControllerTopComponent.jPanel3.TabConstraints.tabTitle"), jPanel3); // NOI18N tblConflicts.setAutoCreateRowSorter(true); tblConflicts.setModel(new javax.swing.table.DefaultTableModel( new Object [][] { {null, null, null, null, null, null}, {null, null, null, null, null, null}, {null, null, null, null, null, null}, {null, null, null, null, null, null} }, new String [] { "Decision", "Rule", "Count", "SLL Conflict", "Ambiguities", "Context Sensitivities" } ) { boolean[] canEdit = new boolean [] { false, false, false, false, false, false }; public boolean isCellEditable(int rowIndex, int columnIndex) { return canEdit [columnIndex]; } }); jScrollPane3.setViewportView(tblConflicts); if (tblConflicts.getColumnModel().getColumnCount() > 0) { tblConflicts.getColumnModel().getColumn(0).setHeaderValue(org.openide.util.NbBundle.getMessage(ParserDebuggerControllerTopComponent.class, "ParserDebuggerControllerTopComponent.tblLookahead.columnModel.title0")); // NOI18N tblConflicts.getColumnModel().getColumn(1).setHeaderValue(org.openide.util.NbBundle.getMessage(ParserDebuggerControllerTopComponent.class, "ParserDebuggerControllerTopComponent.tblLookahead.columnModel.title1")); // NOI18N tblConflicts.getColumnModel().getColumn(2).setHeaderValue(org.openide.util.NbBundle.getMessage(ParserDebuggerControllerTopComponent.class, "ParserDebuggerControllerTopComponent.tblConflicts.columnModel.title2")); // NOI18N tblConflicts.getColumnModel().getColumn(3).setHeaderValue(org.openide.util.NbBundle.getMessage(ParserDebuggerControllerTopComponent.class, "ParserDebuggerControllerTopComponent.tblConflicts.columnModel.title6")); // NOI18N tblConflicts.getColumnModel().getColumn(4).setHeaderValue(org.openide.util.NbBundle.getMessage(ParserDebuggerControllerTopComponent.class, "ParserDebuggerControllerTopComponent.tblConflicts.columnModel.title3")); // NOI18N tblConflicts.getColumnModel().getColumn(5).setHeaderValue(org.openide.util.NbBundle.getMessage(ParserDebuggerControllerTopComponent.class, "ParserDebuggerControllerTopComponent.tblConflicts.columnModel.title8")); // NOI18N } javax.swing.GroupLayout jPanel5Layout = new javax.swing.GroupLayout(jPanel5); jPanel5.setLayout(jPanel5Layout); jPanel5Layout.setHorizontalGroup( jPanel5Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(jPanel5Layout.createSequentialGroup() .addGap(0, 0, 0) .addComponent(jScrollPane3, javax.swing.GroupLayout.DEFAULT_SIZE, 381, Short.MAX_VALUE) .addGap(0, 0, 0)) ); jPanel5Layout.setVerticalGroup( jPanel5Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(jPanel5Layout.createSequentialGroup() .addGap(0, 0, 0) .addComponent(jScrollPane3, javax.swing.GroupLayout.DEFAULT_SIZE, 107, Short.MAX_VALUE) .addGap(0, 0, 0)) ); jTabbedPane1.addTab(org.openide.util.NbBundle.getMessage(ParserDebuggerControllerTopComponent.class, "ParserDebuggerControllerTopComponent.jPanel5.TabConstraints.tabTitle"), jPanel5); // NOI18N tblStatistics.setAutoCreateRowSorter(true); tblStatistics.setModel(new javax.swing.table.DefaultTableModel( new Object [][] { {null, null}, {null, null}, {null, null}, {null, null} }, new String [] { "Statistic", "Value" } ) { boolean[] canEdit = new boolean [] { false, false }; public boolean isCellEditable(int rowIndex, int columnIndex) { return canEdit [columnIndex]; } }); jScrollPane6.setViewportView(tblStatistics); if (tblStatistics.getColumnModel().getColumnCount() > 0) { tblStatistics.getColumnModel().getColumn(0).setHeaderValue(org.openide.util.NbBundle.getMessage(ParserDebuggerControllerTopComponent.class, "ParserDebuggerControllerTopComponent.tblStatistics.columnModel.title0")); // NOI18N tblStatistics.getColumnModel().getColumn(1).setHeaderValue(org.openide.util.NbBundle.getMessage(ParserDebuggerControllerTopComponent.class, "ParserDebuggerControllerTopComponent.tblStatistics.columnModel.title1")); // NOI18N } javax.swing.GroupLayout jPanel4Layout = new javax.swing.GroupLayout(jPanel4); jPanel4.setLayout(jPanel4Layout); jPanel4Layout.setHorizontalGroup( jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel4Layout.createSequentialGroup() .addGap(0, 0, 0) .addComponent(jScrollPane6, javax.swing.GroupLayout.DEFAULT_SIZE, 381, Short.MAX_VALUE) .addGap(0, 0, 0)) ); jPanel4Layout.setVerticalGroup( jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel4Layout.createSequentialGroup() .addGap(0, 0, 0) .addComponent(jScrollPane6, javax.swing.GroupLayout.DEFAULT_SIZE, 107, Short.MAX_VALUE) .addGap(0, 0, 0)) ); jTabbedPane1.addTab(org.openide.util.NbBundle.getMessage(ParserDebuggerControllerTopComponent.class, "ParserDebuggerControllerTopComponent.jPanel4.TabConstraints.tabTitle"), jPanel4); // NOI18N jSplitPane1.setTopComponent(jTabbedPane1); javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1); jPanel1.setLayout(jPanel1Layout); jPanel1Layout.setHorizontalGroup( jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGap(0, 386, Short.MAX_VALUE) ); jPanel1Layout.setVerticalGroup( jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGap(0, 180, Short.MAX_VALUE) ); jSplitPane1.setRightComponent(jPanel1); add(jSplitPane1); }// </editor-fold>//GEN-END:initComponents // Variables declaration - do not modify//GEN-BEGIN:variables private javax.swing.JPanel jPanel1; private javax.swing.JSplitPane jSplitPane1; private javax.swing.JTable tblConflicts; private javax.swing.JTable tblDecisions; private javax.swing.JTable tblLookahead; private javax.swing.JTable tblRules; private javax.swing.JTable tblStatistics; // End of variables declaration//GEN-END:variables @Override public void componentOpened() { // TODO add custom code on component opening } @Override public void componentClosed() { // TODO add custom code on component closing } void writeProperties(java.util.Properties p) { // better to version settings since initial version as advocated at // http://wiki.apidesign.org/wiki/PropertyFiles p.setProperty("version", "1.0"); // TODO store your settings } void readProperties(java.util.Properties p) { String version = p.getProperty("version"); // TODO read your settings according to their version } private class EditorRegistryListener implements PropertyChangeListener { private JTextComponent currentComponent; @Override public void propertyChange(PropertyChangeEvent evt) { if (EditorRegistry.FOCUS_GAINED_PROPERTY.equals(evt.getPropertyName())) { JTextComponent component = EditorRegistry.focusedComponent(); if (component == currentComponent) { return; } Document document = component.getDocument(); ParserInterpreterData parserInterpreterData = (ParserInterpreterData)document.getProperty(ParserDebuggerEditorKit.PROP_PARSER_INTERP_DATA); if (parserInterpreterData == null) { return; } ATN atn = new ATNDeserializer().deserialize(parserInterpreterData.serializedAtn.toCharArray()); ParserTaskManager taskManager = Lookup.getDefault().lookup(ParserTaskManager.class); DocumentSnapshot snapshot = VersionedDocumentUtilities.getVersionedDocument(document).getCurrentSnapshot(); FileParseResult fileParseResult = ParserDebuggerParserDataDefinitions.tryGetData(taskManager, snapshot, ParserDebuggerParserDataDefinitions.FILE_PARSE_RESULT, EnumSet.of(ParserDataOptions.SYNCHRONOUS)); ParserRuleContext parseTree = ParserDebuggerParserDataDefinitions.tryGetData(taskManager, snapshot, ParserDebuggerParserDataDefinitions.REFERENCE_PARSE_TREE, EnumSet.of(ParserDataOptions.SYNCHRONOUS)); currentComponent = component; final List<RuleDetail> ruleDetails = new ArrayList<>(); if (parseTree != null) { final long[] ruleCounts = new long[parserInterpreterData.ruleNames.size()]; ParseTreeWalker.DEFAULT.walk(new ParseTreeListener() { @Override public void visitTerminal(TerminalNode node) { } @Override public void visitErrorNode(ErrorNode node) { } @Override public void enterEveryRule(ParserRuleContext ctx) { ruleCounts[ctx.getRuleIndex()]++; } @Override public void exitEveryRule(ParserRuleContext ctx) { } }, parseTree); for (int i = 0; i < ruleCounts.length; i++) { ruleDetails.add(new RuleDetail(parserInterpreterData.ruleNames.get(i), ruleCounts[i])); } } tblRules.setModel(new AbstractTableModel() { @Override public int getRowCount() { return ruleDetails.size(); } @Override public int getColumnCount() { return 2; } @Override public String getColumnName(int column) { switch (column) { case 0: return "Rule"; case 1: return "Instances"; default: throw new IllegalArgumentException("column"); } } @Override public Class<?> getColumnClass(int columnIndex) { switch (columnIndex) { case 0: return String.class; case 1: return Long.class; default: throw new IllegalArgumentException("columnIndex"); } } @Override public Object getValueAt(int rowIndex, int columnIndex) { switch (columnIndex) { case 0: return ruleDetails.get(rowIndex).getRuleName(); case 1: return ruleDetails.get(rowIndex).getInstances(); default: throw new IllegalArgumentException("columnIndex"); } } }); final List<DecisionStatistic> decisionStatistics = new ArrayList<>(); if (fileParseResult != null) { for (int i = 0; i < fileParseResult.decisionInvocations.length; i++) { int ruleIndex = atn.decisionToState.get(i).ruleIndex; String ruleName = parserInterpreterData.ruleNames.get(ruleIndex); decisionStatistics.add(new DecisionStatistic(i, ruleName, fileParseResult.decisionInvocations[i])); } } tblDecisions.setModel(new AbstractTableModel() { @Override public int getRowCount() { return decisionStatistics.size(); } @Override public int getColumnCount() { return 3; } @Override public String getColumnName(int column) { switch (column) { case 0: return "Decision"; case 1: return "Rule"; case 2: return "Count"; default: throw new IllegalArgumentException("column"); } } @Override public Class<?> getColumnClass(int columnIndex) { switch (columnIndex) { case 0: return Integer.class; case 1: return String.class; case 2: return Long.class; default: throw new IllegalArgumentException("columnIndex"); } } @Override public Object getValueAt(int rowIndex, int columnIndex) { switch (columnIndex) { case 0: return decisionStatistics.get(rowIndex).getDecision(); case 1: return decisionStatistics.get(rowIndex).getRuleName(); case 2: return decisionStatistics.get(rowIndex).getCount(); default: throw new IllegalArgumentException("columnIndex"); } } }); final List<LookaheadStatistic> lookaheadStatistics = new ArrayList<>(); if (fileParseResult != null) { for (int i = 0; i < fileParseResult.decisionInvocations.length; i++) { int ruleIndex = atn.decisionToState.get(i).ruleIndex; String ruleName = parserInterpreterData.ruleNames.get(ruleIndex); double averageLookaheadSll; if (fileParseResult.decisionInvocations[i] > 0) { averageLookaheadSll = (double)fileParseResult.totalLookaheadSll[i] / (double)fileParseResult.decisionInvocations[i]; } else { averageLookaheadSll = -1; } double averageLookaheadLl; if (fileParseResult.fullContextFallback[i] > 0) { averageLookaheadLl = (double)fileParseResult.totalLookaheadLl[i] / (double)fileParseResult.fullContextFallback[i]; } else { averageLookaheadLl = -1; } long minLookaheadSll = fileParseResult.minLookaheadSll[i]; long maxLookaheadSll = fileParseResult.maxLookaheadSll[i]; long minLookaheadLl = fileParseResult.minLookaheadLl[i]; long maxLookaheadLl = fileParseResult.maxLookaheadLl[i]; long totalTransitions = fileParseResult.parserTotalTransitions[i]; lookaheadStatistics.add(new LookaheadStatistic(i, ruleName, averageLookaheadSll, averageLookaheadLl, minLookaheadSll, maxLookaheadSll, minLookaheadLl, maxLookaheadLl, totalTransitions)); } } tblLookahead.setModel(new AbstractTableModel() { @Override public int getRowCount() { return lookaheadStatistics.size(); } @Override public int getColumnCount() { return 9; } @Override public String getColumnName(int column) { switch (column) { case 0: return "Decision"; case 1: return "Rule"; case 2: return "Avg k (SLL)"; case 3: return "Avg k (LL)"; case 4: return "Min k (SLL)"; case 5: return "Max k (SLL)"; case 6: return "Min k (LL)"; case 7: return "Max k (LL)"; case 8: return "Cost"; default: throw new IllegalArgumentException("column"); } } @Override public Class<?> getColumnClass(int columnIndex) { switch (columnIndex) { case 0: return Integer.class; case 1: return String.class; case 2: return Double.class; case 3: return Double.class; case 4: return Long.class; case 5: return Long.class; case 6: return Long.class; case 7: return Long.class; case 8: return Long.class; default: throw new IllegalArgumentException("columnIndex"); } } @Override public Object getValueAt(int rowIndex, int columnIndex) { switch (columnIndex) { case 0: return lookaheadStatistics.get(rowIndex).getDecision(); case 1: return lookaheadStatistics.get(rowIndex).getRuleName(); case 2: return inRangeValue(lookaheadStatistics.get(rowIndex).getAverageLookaheadSll()); case 3: return inRangeValue(lookaheadStatistics.get(rowIndex).getAverageLookaheadLl()); case 4: return inRangeValue(lookaheadStatistics.get(rowIndex).getMinLookaheadSll()); case 5: return inRangeValue(lookaheadStatistics.get(rowIndex).getMaxLookaheadSll()); case 6: return inRangeValue(lookaheadStatistics.get(rowIndex).getMinLookaheadLl()); case 7: return inRangeValue(lookaheadStatistics.get(rowIndex).getMaxLookaheadLl()); case 8: return lookaheadStatistics.get(rowIndex).getTotalTransitions(); default: throw new IllegalArgumentException("columnIndex"); } } private Double inRangeValue(double value) { if (value < 0) { return null; } return value; } private Long inRangeValue(long value) { if (value == Long.MIN_VALUE || value == Long.MAX_VALUE) { return null; } return value; } }); final List<ConflictStatistic> conflictStatistics = new ArrayList<>(); if (fileParseResult != null) { for (int i = 0; i < fileParseResult.decisionInvocations.length; i++) { int ruleIndex = atn.decisionToState.get(i).ruleIndex; String ruleName = parserInterpreterData.ruleNames.get(ruleIndex); long count = fileParseResult.decisionInvocations[i]; long conflicts = fileParseResult.fullContextFallback[i]; long ambiguities = fileParseResult.ambiguousResult[i]; long contextSensitivities = fileParseResult.nonSll[i]; conflictStatistics.add(new ConflictStatistic(i, ruleName, count, conflicts, ambiguities, contextSensitivities)); } } tblConflicts.setModel(new AbstractTableModel() { @Override public int getRowCount() { return conflictStatistics.size(); } @Override public int getColumnCount() { return 6; } @Override public String getColumnName(int column) { switch (column) { case 0: return "Decision"; case 1: return "Rule"; case 2: return "Count"; case 3: return "Conflicts"; case 4: return "Ambiguities"; case 5: return "Context Sensitivities"; default: throw new IllegalArgumentException("column"); } } @Override public Class<?> getColumnClass(int columnIndex) { switch (columnIndex) { case 0: return Integer.class; case 1: return String.class; case 2: case 3: case 4: case 5: return Long.class; default: throw new IllegalArgumentException("columnIndex"); } } @Override public Object getValueAt(int rowIndex, int columnIndex) { switch (columnIndex) { case 0: return conflictStatistics.get(rowIndex).getDecision(); case 1: return conflictStatistics.get(rowIndex).getRuleName(); case 2: return conflictStatistics.get(rowIndex).getCount(); case 3: return conflictStatistics.get(rowIndex).getConflicts(); case 4: return conflictStatistics.get(rowIndex).getAmbiguities(); case 5: return conflictStatistics.get(rowIndex).getContextSensitivities(); default: throw new IllegalArgumentException("columnIndex"); } } }); final List<ParserStatistic> statistics = new ArrayList<>(); // number of tokens consumed statistics.add(new ParserStatistic("Tokens", fileParseResult.tokenCount)); // number of rule contexts created final long[] ruleCount = new long[1]; ParseTreeListener ruleCountListener = new ParseTreeListener() { @Override public void visitTerminal(TerminalNode node) { } @Override public void visitErrorNode(ErrorNode node) { } @Override public void enterEveryRule(ParserRuleContext ctx) { ruleCount[0]++; } @Override public void exitEveryRule(ParserRuleContext ctx) { } }; ParseTreeWalker.DEFAULT.walk(ruleCountListener, parseTree); statistics.add(new ParserStatistic("Rule Invocations", ruleCount[0])); // number of syntax errors reported statistics.add(new ParserStatistic("Syntax Errors", fileParseResult.getSyntaxErrors().size())); tblStatistics.setModel(new AbstractTableModel() { @Override public int getRowCount() { return statistics.size(); } @Override public int getColumnCount() { return 2; } @Override public String getColumnName(int column) { switch (column) { case 0: return "Statistic"; case 1: return "Value"; default: throw new IllegalArgumentException("column"); } } @Override public Class<?> getColumnClass(int columnIndex) { switch (columnIndex) { case 0: return String.class; case 1: return Long.class; default: throw new IllegalArgumentException("columnIndex"); } } @Override public Object getValueAt(int rowIndex, int columnIndex) { switch (columnIndex) { case 0: return statistics.get(rowIndex).getName(); case 1: return statistics.get(rowIndex).getValue(); default: throw new IllegalArgumentException("columnIndex"); } } }); } } } private static class RuleDetail { private final String ruleName; private final long instances; public RuleDetail(String ruleName, long instances) { this.ruleName = ruleName; this.instances = instances; } public String getRuleName() { return ruleName; } public long getInstances() { return instances; } } private static class DecisionStatistic { private final int decision; private final String ruleName; private final long count; public DecisionStatistic(int decision, String ruleName, long count) { this.decision = decision; this.ruleName = ruleName; this.count = count; } public int getDecision() { return decision; } public String getRuleName() { return ruleName; } public long getCount() { return count; } } private static class LookaheadStatistic { private final int decision; private final String ruleName; private final double averageLookaheadSll; private final double averageLookaheadLl; private final long minLookaheadSll; private final long maxLookaheadSll; private final long minLookaheadLl; private final long maxLookaheadLl; private final long totalTransitions; public LookaheadStatistic(int decision, String ruleName, double averageLookaheadSll, double averageLookaheadLl, long minLookaheadSll, long maxLookaheadSll, long minLookaheadLl, long maxLookaheadLl, long totalTransitions) { this.decision = decision; this.ruleName = ruleName; this.averageLookaheadSll = averageLookaheadSll; this.averageLookaheadLl = averageLookaheadLl; this.minLookaheadSll = minLookaheadSll; this.maxLookaheadSll = maxLookaheadSll; this.minLookaheadLl = minLookaheadLl; this.maxLookaheadLl = maxLookaheadLl; this.totalTransitions = totalTransitions; } public int getDecision() { return decision; } public String getRuleName() { return ruleName; } public double getAverageLookaheadSll() { return averageLookaheadSll; } public double getAverageLookaheadLl() { return averageLookaheadLl; } public long getMinLookaheadSll() { return minLookaheadSll; } public long getMaxLookaheadSll() { return maxLookaheadSll; } public long getMinLookaheadLl() { return minLookaheadLl; } public long getMaxLookaheadLl() { return maxLookaheadLl; } public long getTotalTransitions() { return totalTransitions; } } private static class ConflictStatistic { private final int decision; private final String ruleName; private final long count; private final long conflicts; private final long ambiguities; private final long contextSensitivities; public ConflictStatistic(int decision, String ruleName, long count, long conflicts, long ambiguities, long contextSensitivities) { this.decision = decision; this.ruleName = ruleName; this.count = count; this.conflicts = conflicts; this.ambiguities = ambiguities; this.contextSensitivities = contextSensitivities; } public int getDecision() { return decision; } public String getRuleName() { return ruleName; } public long getCount() { return count; } public long getConflicts() { return conflicts; } public long getAmbiguities() { return ambiguities; } public long getContextSensitivities() { return contextSensitivities; } } private static class ParserStatistic { private final String name; private final long value; public ParserStatistic(String name, long value) { this.name = name; this.value = value; } public String getName() { return name; } public long getValue() { return value; } } }