/**
* Copyright 2010-2014 Three Crickets LLC.
* <p>
* The contents of this file are subject to the terms of a BSD license. See
* attached license.txt.
* <p>
* Alternatively, you can obtain a royalty free commercial license with less
* limitations, transferable or non-transferable, directly from Three Crickets
* at http://threecrickets.com/
*/
package org.sikuli.syntaxhighlight.grammar;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.sikuli.syntaxhighlight.Def;
import org.sikuli.syntaxhighlight.NestedDef;
import org.sikuli.syntaxhighlight.ResolutionException;
/**
* @author Tal Liron
*/
public class Grammar extends NestedDef<Grammar>
{
//
// Attributes
//
public State getState( String stateName )
{
State state = statesByName.get( stateName );
if( state == null )
{
state = new State( stateName );
statesByName.put( stateName, state );
addDef( state );
}
return state;
}
public State resolveState( String stateName ) throws ResolutionException
{
if( stateName.startsWith( "#pop" ) )
{
int depth = 1;
if( stateName.length() > 4 )
{
String depthString = stateName.substring( 5 );
try
{
depth = Integer.parseInt( depthString );
}
catch( NumberFormatException x )
{
throw new ResolutionException( x );
}
}
return new RelativeState( false, depth );
}
else if( stateName.startsWith( "#push" ) )
{
int depth = 1;
if( stateName.length() > 5 )
{
String depthString = stateName.substring( 6 );
try
{
depth = Integer.parseInt( depthString );
}
catch( NumberFormatException x )
{
throw new ResolutionException( x );
}
}
return new RelativeState( true, depth );
}
State state = getState( stateName );
if( state.isResolved() )
return state;
else
return null;
}
public List<State> resolveStates( List<String> stateNames ) throws ResolutionException
{
ArrayList<State> states = new ArrayList<State>();
for( String stateName : stateNames )
{
String[] combinedStateName = stateName.split( "\\+" );
if( combinedStateName.length > 1 )
{
State combinedState = null;
for( String singleStateName : combinedStateName )
{
State state = resolveState( singleStateName );
if( state == null )
return null;
if( combinedState == null )
combinedState = state;
else
combinedState = new State( combinedState, state );
}
states.add( combinedState );
}
else
{
State state = resolveState( stateName );
if( state == null )
return null;
states.add( state );
}
}
return states;
}
//
// Operations
//
public void resolve() throws ResolutionException
{
resolve( this );
// Are we resolved?
for( Map.Entry<String, State> entry : statesByName.entrySet() )
{
if( !entry.getValue().isResolved() )
{
String message = "Unresolved state: " + entry.getKey();
Def<Grammar> cause = entry.getValue().getCause( this );
while( cause != null )
{
message += ", cause: " + cause;
cause = cause.getCause( this );
}
throw new ResolutionException( message );
}
}
}
// //////////////////////////////////////////////////////////////////////////
// Private
private final Map<String, State> statesByName = new HashMap<String, State>();
}