/* * JFLAP - Formal Languages and Automata Package * * * Susan H. Rodger * Computer Science Department * Duke University * August 27, 2009 * Copyright (c) 2002-2009 * All rights reserved. * JFLAP is open source software. Please see the LICENSE for terms. * */ package gui.grammar.parse; import grammar.Grammar; import gui.environment.Universe; import java.util.*; import javax.swing.table.*; /** * This is a table model for user definition of the first and follow sets for a * grammar. The first column are the variable names. The second column are the * first sets, the third column the follow sets. * * @author Thomas Finley */ public class FirstFollowModel extends AbstractTableModel { /** * Instantiates a new FirstFollowModel. * * @param grammar * the grammar for the first follow model, from which the * variables are extracted for the first column */ public FirstFollowModel(Grammar grammar) { variables = grammar.getVariables(); Arrays.sort(variables); terminals = grammar.getTerminals(); firstSets = new String[variables.length]; followSets = new String[variables.length]; Arrays.fill(firstSets, ""); Arrays.fill(followSets, ""); } /** * Retrives the first sets as shown in the table. * * @return the first sets, a map from all single symbols A in the grammar to * the set of symbols that represent FIRST(A) */ public Map getFirst() { return null; } /** * Retrieves the follow sets as shown in the table. * * @return the follow sets, a map from all single variables A in the grammar * to the set of symbols that represent FOLLOW(A) */ public Map getFollow() { return null; } /** * Set if the user can edit the first sets at this time. * * @param canEdit * true if editing is allowed */ public void setCanEditFirst(boolean canEdit) { canEditColumn[1] = canEdit; } /** * Set if the user can edit the follow sets at this time. * * @param canEdit * true if editing is allowed */ public void setCanEditFollow(boolean canEdit) { canEditColumn[2] = canEdit; } /** * There are as many rows as there are variables. * * @return the number of variables */ public int getRowCount() { return variables.length; } /** * There are always three columns for the variables, the first sets, and the * follow sets. * * @return 3 */ public int getColumnCount() { return 3; } /** * Returns the name of a particular column. * * @param column * the index of a column to get the name for */ public String getColumnName(int column) { return COLUMN_NAMES[column]; } /** * Returns the value at each column. * * @param row * the row to get data for * @param column * the column to get data for * @return the data for this column */ public Object getValueAt(int row, int column) { switch (column) { case 0: return variables[row]; case 1: return firstSets[row]; case 2: return followSets[row]; } return null; } /** * Returns if a table cell can be edited. * * @param row * the row of the cell * @param column * the column of the cell */ public boolean isCellEditable(int row, int column) { return canEditColumn[column]; } /** * Returns the character set at a particular location. * * @param row * the row to get the set for; this will be a set for the * variable at this row * @param column * the column to get the set for, which will be 1 for first and 2 * for follow */ public Set getSet(int row, int column) { String s = (String) getValueAt(row, column); Set set = new TreeSet(); for (int i = 0; i < s.length(); i++) { if (s.charAt(i) == '!') { set.add(""); continue; } set.add(s.substring(i, i + 1)); } return set; } /** * When a string value is used to define a set, it's possible that the * string value will contain multiple characters. This will take a string, * and return a string with not duplicate characters. Only the first * instance of a character is preserved, and others are discarded. So, if * one were to pass in abaacb, this would return the string abc. * * @param s * the string to process * @return the same string as was passed in but with duplicate characters * removed */ private String removeDuplicateCharacters(String s) { Set characters = new HashSet(); StringBuffer sb = new StringBuffer(); for (int i = 0; i < s.length(); i++) { Character c = new Character(s.charAt(i)); if (characters.add(c)) sb.append(c.charValue()); } return sb.toString(); } /** * Sets the value at each column. * * @param value * the new value * @param row * the row to change * @param column * the column to change */ public void setValueAt(Object value, int row, int column) { switch (column) { case 0: variables[row] = (String) value; break; case 1: firstSets[row] = removeDuplicateCharacters((String) value); break; case 2: followSets[row] = removeDuplicateCharacters((String) value); break; } } /** * Sets the set at a particular cell. * * @param set * the set for the cell * @param row * the row index of the cell to set the set for * @param column * the column index of the cell to set the set for */ public void setSet(Set set, int row, int column) { StringBuffer sb = new StringBuffer(); Iterator it = set.iterator(); while (it.hasNext()) { String element = (String) it.next(); if (element.length() == 0) element = "!"; sb.append(element); } setValueAt(sb.toString(), row, column); } /** The variables. */ private String[] variables; /** The terminals. */ private String[] terminals; /** The user defined first sets strings. */ private String[] firstSets; /** The user defined follow sets strings. */ private String[] followSets; /** The permissions to edit each column. */ private boolean[] canEditColumn = new boolean[] { false, false, false }; /** The lambda string. */ public static String LAMBDA = Universe.curProfile.getEmptyString(); /** The names of columns. */ public static String[] COLUMN_NAMES = { " ", "FIRST", "FOLLOW" }; }