import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; /** * Regular expression token definitions are implemented as a {@link Map} * that maps each (states,kind) pair to a {@link List} of regular * expressions in declaration order. Inner class {@link #Datum} holds the * parts of a regular expression token definition. * * @layer<collect> */ public class RegexTokensData extends HashMap { public void addNode( RegexDefinitionNode node ) { List states = statesList( ( StatesNode ) node.arg[0].arg [0] ) ; String kind = node.arg[1].tok[0].getTokenName() ; boolean noCase = ( node.arg[2].arg [0] != null ) ; List regexList = new ArrayList( ( ( AstList ) node.arg[3] ) . toList() ) ; Datum newDatum = new Datum( states, kind, noCase, regexList ) ; String key = newDatum.getKey() ; if ( ! containsKey( key ) ) { put( key, newDatum ) ; return ; } Datum oldDatum = ( Datum ) get( key ) ; oldDatum.regexList.addAll( regexList ) ; } /** * Formats regular expression tokens by concatenating them with blank * line separators. * * @layer<collect> */ public String toString() { if ( size() < 1 ) return "// No regular expression tokens in Bali grammar." ; List keys = new ArrayList( keySet() ) ; Collections.sort( keys ) ; StringBuffer buffer = new StringBuffer() ; for ( Iterator p = keys.iterator() ; p.hasNext() ; ) { Datum value = ( Datum ) get( p.next() ) ; buffer.append( value ).append( Main.LINE_SEPARATOR ) ; } return buffer.toString() ; } static protected class Datum { public Datum( List states, String kind, boolean noCase, List re ) { this.states = states ; this.kind = kind ; this.noCase = noCase ; this.regexList = re ; this.key = keyToString() ; } public String getKey() { return key ; } public String keyToString() { StringBuffer buffer = new StringBuffer() ; if ( states.size() > 0 ) { buffer.append( '<' ) ; Iterator p = states.iterator() ; buffer.append( p.next().toString() ) ; while ( p.hasNext() ) buffer.append( ',' ).append( p.next().toString() ) ; buffer.append( "> " ) ; } buffer.append( kind ) ; if ( noCase ) buffer.append( " IGNORE_CASE" ) ; return buffer.toString() ; } public String toString() { StringBuffer buffer = new StringBuffer( key ) ; buffer.append( ": {" ) ; Iterator p = regexList.iterator() ; buffer.append( p.next().toString() ) ; while ( p.hasNext() ) buffer.append( " | " ).append( p.next().toString() ) ; buffer.append( Main.LINE_SEPARATOR ).append( '}' ) ; return buffer.toString() ; } final protected String key ; final protected String kind ; final protected boolean noCase ; final protected List regexList ; final protected List states ; } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ /** * Returns the list of states for this regular expression token as a * {@link List} of {@link String} objects naming the states. An empty * {@link List} means *all* states. * * @layer<collect> */ final private List statesList( StatesNode node ) { if ( node == null ) return Collections.EMPTY_LIST ; StatesSpecifier subNode = ( StatesSpecifier ) node.arg[0] ; if ( subNode instanceof StarStatesNode ) return Collections.EMPTY_LIST ; Main.DEBUG.info( "subNode.class=" + subNode.getClass() + "; subNode=" + subNode ) ; List states = new ArrayList() ; Iterator p = ( ( AstList )subNode.arg[0] ).toList().iterator() ; while ( p.hasNext() ) { StateNameNode nameNode = ( StateNameNode ) p.next() ; states.add( nameNode.tok[0].getTokenName() ) ; } return Collections.unmodifiableList( Arrays.asList( states.toArray( new String [states.size()] ) ) ) ; } }