/*
*
* Copyright (c) 2007
* Adrian Michel
* http://www.tradery.com
*
* Permission to use, copy, modify, distribute and sell this software
* and its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies and
* that both that copyright notice and this permission notice appear
* in supporting documentation. Adrian Michel makes no
* representations about the suitability of this software for any
* purpose. It is provided "as is" without express or implied warranty.
*/
package com.tradery.contentmodel;
import com.tradery.cmdline.CmdLineApp;
import java.util.Vector;
import java.util.Stack;
public class ContentModel extends CmdLineApp
{
private static final String HELP_FLAG = "help";
private static final String QUESTION_FLAG = "?";
private static final String DUMP_STATE_MACHINE = "s";
private static final String DUMP_EXPRESSION = "e";
private static final String DUMP_SYNTAX_TREE = "t";
private static final String DUMP_ALL = "a";
private static final String REVERSE_POLISH_NOTATION = "r";
private boolean dumpExpression = false;
private boolean dumpStateMachine = false;
private boolean dumpSyntaxTree = false;
private boolean reversePolishNotation = false;
public ContentModel()
{
super("ContentModel"); // Pass through the name of the executable as it appears in the filesystem
// Register options that can be specified on the commandline along with help text
registerOption(HELP_FLAG, "help", "Dump verbose help about options to the screen", true);
registerOption(QUESTION_FLAG, "usage", "Give usage information", true);
registerOption(DUMP_STATE_MACHINE, "dump state machine", "Dumps info about the state machine", true);
registerOption(DUMP_EXPRESSION, "dump content model expression", "Dumps the regular expression that is being analysed", true);
registerOption(DUMP_SYNTAX_TREE, "dump the syntax tree", "Dumps detailed info about the syntax tree", true);
registerOption(DUMP_ALL, "dump all the info", "Dumps detailed info about the syntax tree, expression and state machine", true);
registerOption(REVERSE_POLISH_NOTATION, "reverse polish notation flag", "Accepts content model regular expressions in reverse polish notation, where character \"^\" is Pop", true );
registerRemaining("Remaining parameters", "Content model expression and strings", "Content model expression and strings to be checked against this content model" );
}
public static void main (String[] args)
{
ContentModel model = new ContentModel();
try
{
// Run the application
model.run(args);
}
catch(CmdLineInvalidOption e)
{
// Give the user help if they specify an invalid option
System.out.println(e.getName() + ": Invalid Option -" + e.getOption() + " " + e.getMessage());
System.out.println(model.usageString());
}
catch(CmdLineException e)
{
// Log any parsing errors
System.out.println(e.getName() + ": " + e.getMessage());
}
}
public static void runDFA( AbstractState state, SyntaxTree m, String str )
{
ModelWriter.println( "--------- Running the State Machine ---------" );
boolean b = true;
String s = new String();
boolean inWord = false;
for( int n = 0; n < str.length() && b; n++ )
{
char c = str.charAt( n );
switch( c )
{
case ',':
case ' ':
case '\t':
case '\n':
case '\r':
if( inWord )
{
if( !state.doTransition( s ) )
{
b = false;
break;
}
inWord = false;
s = "";
}
break;
default:
inWord = true;
s += str.substring( n, n + 1 );
break;
}
}
if( inWord )
{
if( !state.doTransition( s ) )
b = false;
}
if( b )
b = state.canTerminate();
ModelWriter.print( "\"" + str + "\" " );
ModelWriter.println( ( b ? "matches " : "doesn't match ") + m.toString() );
}
public void processOption( String opt, String value )
{
if( opt.equals( DUMP_STATE_MACHINE ) )
dumpStateMachine = true;
else if( opt.equals( DUMP_EXPRESSION ) )
dumpExpression = true;
else if( opt.equals( DUMP_SYNTAX_TREE ) )
dumpSyntaxTree = true;
else if( opt.equals( REVERSE_POLISH_NOTATION ) )
reversePolishNotation = true;
else if( opt.equals( DUMP_ALL ) )
{
dumpStateMachine = true;
dumpSyntaxTree = true;
dumpExpression = true;
}
else if( opt.equals( HELP_FLAG ) )
{
help();
}
else if( opt.equals( QUESTION_FLAG ) )
{
help();
}
else
{
help();
}
}
void help() { System.out.println( helpString() ); }
public void processApplication( String[] args )
{
try
{
if( args == null )
{
help();
return;
}
AbstractExpression e;
if( reversePolishNotation )
e = new ReversePolishNotationFE( "" );
else
e = new DirectNotationFE( "" );
SyntaxTree m = (SyntaxTree)e;
e.parse( args[ 0 ] );
if( dumpExpression )
m.dumpExpression();
m.compile();
if( dumpSyntaxTree )
m.dump();
if( dumpStateMachine )
m.dumpStateMachine();
for( int n = 1; n < args.length; n++ )
{
AbstractState state = m.getInitialState();
runDFA( state, m, args[ n ] );
}
}
catch( AmbiguousContentModelException e )
{
ModelWriter.println( "Content model is ambiguous" );
}
catch( BadLimitsException e )
{
ModelWriter.print( "Bad limits in range: " + e.toString() );
}
}
}
// unambiguous
// (a|b)*,a,b,b
// a?,b
// (a,b,e,f)*|(c,d)|(g,h)
// (a[2,3],b[2,3])[5,6]
// (a|b)+
// a?
// (b)(b*a)*
// a?,b?,c?
// (a+,b+,d+)?,c
// ((a?,b?,h,i)|(c*,d?,k)+|e|(f,g))
// (a*,b?,c)
// c,d,e*
// (a|b|c)[2,4]
// a[2,4],(a|b)[1,1],(a,b,c?)*
// (a|b)[2,3]
// ambiguous
// a*|(a,b)
// (a,b)|(a,c)
// (a,b)*|(a,c)
// a,(b,a)*,(b|<empty>)
// a|(a,b)