diff options
Diffstat (limited to 'project/JavaCommon/src/com/modulus/dataread/expressions')
17 files changed, 1189 insertions, 0 deletions
diff --git a/project/JavaCommon/src/com/modulus/dataread/expressions/AbstractStatement.java b/project/JavaCommon/src/com/modulus/dataread/expressions/AbstractStatement.java new file mode 100644 index 0000000..c2ec699 --- /dev/null +++ b/project/JavaCommon/src/com/modulus/dataread/expressions/AbstractStatement.java @@ -0,0 +1,125 @@ +package com.modulus.dataread.expressions; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +/** + * this class outlines a rough diagram of what a statement + * looks like. The major importance is how it already + * correctly implements the tree fasion that statements + * should in theory be ordered in. + * + * @author jrahm + * + */ +public abstract class AbstractStatement implements Statement, Serializable{ + private static final long serialVersionUID = -6717726729821743941L; + private Collection<Statement> children; + private int line = -1; + + /** + * the header of this statement. + */ + protected String header; + + /** + * Creates a new AbstractStatement with the + * default header being an empty string. + */ + public AbstractStatement(){ + this.children = new ArrayList<Statement>(); + this.header = ""; + } + + @Override + public void addChild(Statement child) { + this.children.add(child); + } + + @Override + public Statement[] getChildren() { + return children.toArray(new Statement[children.size()]); + } + + @Override + public String getHeader() { + return header; + } + + @Override + public void removeChild(Statement child) { + this.children.remove(child); + } + + @Override + public String toString(){ + return toString(0); + } + + public String toString( int recur ){ + StringBuffer buffer = new StringBuffer(); + String tab = ""; + for(int i = 0;i < recur;i++) + tab += '\t'; + + + buffer.append(tab + header); + + if(children.size() > 0){ + buffer.append("{\n"); + for(Statement child : children){ + buffer.append(child.toString( recur + 1 ) + "\n"); + } + buffer.append(tab + "}"); + } else{ + buffer.append(";"); + } + + return buffer.toString(); + } + + @Override + public Statement getChildByHeader(String header){ + + for(Statement child : children){ + String chHeader = child.getHeader(); + + if(chHeader.equals(header)) + return child; + } + + return null; + } + + @Override + public Statement[] getChildrenByHeader(String header){ + List<Statement> ret = new ArrayList<Statement>(); + + for(Statement child : children){ + String chHeader = child.getHeader(); + + if(chHeader.equals(header)) + ret.add(child); + } + + return ret.toArray(new Statement[ret.size()]); + } + + public int getLineNumber(){ + return line; + } + + public void setLineNumber(int line){ + this.line = line; + } + + public boolean hasChildren(){ + return !children.isEmpty(); + } + + public void clearChildren(){ + this.children.clear(); + } +} diff --git a/project/JavaCommon/src/com/modulus/dataread/expressions/ExpressionParser.java b/project/JavaCommon/src/com/modulus/dataread/expressions/ExpressionParser.java new file mode 100644 index 0000000..c62243a --- /dev/null +++ b/project/JavaCommon/src/com/modulus/dataread/expressions/ExpressionParser.java @@ -0,0 +1,5 @@ +package com.modulus.dataread.expressions; + +public interface ExpressionParser { + ExpressionPart parseExpressions( String exp ); +} diff --git a/project/JavaCommon/src/com/modulus/dataread/expressions/ExpressionPart.java b/project/JavaCommon/src/com/modulus/dataread/expressions/ExpressionPart.java new file mode 100644 index 0000000..bf4e8d8 --- /dev/null +++ b/project/JavaCommon/src/com/modulus/dataread/expressions/ExpressionPart.java @@ -0,0 +1,136 @@ +package com.modulus.dataread.expressions; + +/** + * This class is used to help to assemble the code into more + * readable code for the computer, it sets the system based on + * a more of a stack-ish way so the virtual machine can linearly + * push/pop arguments and call functions. + * + * @author jrahm + * + */ +public abstract class ExpressionPart { + + // Null if function is global + private ExpressionPart caller; + private ExpressionPart[] args; + + private String function; + private boolean primary = false; + + private ExpressionPart(){} + + /** + * This creates a new Expression part meant to handle multi-part + * expressions such as expressions with parenthesis, functions + * inside of functions and so on. + * + * Q-Bar is set up to be very functional, to the point where every entity is made + * of functions being called on arguments and such. + * + * @param caller the caller of the function (null if the function is global) + * @param function the function to be called + * @param args the arguments of the function + * @return an expression part that describes this layout + */ + public static ExpressionPart makePrimaryExpressionPart( ExpressionPart caller, String function, ExpressionPart[] args ){ + ExpressionPart ths = new ExpressionPart(){ + private String compile; + @Override + public String compilePart() { + + if( compile == null ){ + StringBuffer buf = new StringBuffer(); + ExpressionPart caller = this.getCaller(); + + // else + // buf.append( "$global$" ); + for(ExpressionPart part : this.getArgs()){ + buf.append(' '); + buf.append( part.compilePart() ); + } + + if(caller != null) + buf.append( " " + caller.compilePart() ); + + buf.append(' '); + if(this.getFunction().trim().length() > 0){ + if(caller != null){ + // \u00FF is the marker for what is an instance function + buf.append( "\u00FF" + this.getFunction() ); + } + else{ + // \u00FE is the marker for a global function + buf.append( "\u00FE" + this.getFunction() ); + } + } + compile = buf.toString().replaceAll("\\s+", " "); + } + + return compile; + } + }; + + ths.caller = caller; + ths.function = function; + ths.args = args; + + ths.primary = true; + + return ths; + } + + /** + * This method returns an expression part that is made entirely up + * of one single variable name. On a side note, these parts are the + * recursive base case for the compilation. + * + * The name of the variable is stored in the function value, as a variable + * name can be thought of as a function that returns that point in + * memory. + * + * @param name the name of the variable. + * @return A base case ExpressionPart + */ + public static ExpressionPart makeExpressionPart( String name ){ + ExpressionPart ths = new ExpressionPart(){ + @Override + public String compilePart() { + return this.getFunction(); + } + }; + ths.function = name; + + return ths; + } + + /** + * @return the caller + */ + public ExpressionPart getCaller() { + return caller; + } + + /** + * @return the args + */ + public ExpressionPart[] getArgs() { + return args; + } + + /** + * @return the function + */ + public String getFunction() { + return function; + } + + /** + * @return the primary + */ + public boolean isPrimary() { + return primary; + } + + public abstract String compilePart(); +} diff --git a/project/JavaCommon/src/com/modulus/dataread/expressions/FlowStatement.java b/project/JavaCommon/src/com/modulus/dataread/expressions/FlowStatement.java new file mode 100644 index 0000000..df51f2b --- /dev/null +++ b/project/JavaCommon/src/com/modulus/dataread/expressions/FlowStatement.java @@ -0,0 +1,3 @@ +package com.modulus.dataread.expressions; + +public enum FlowStatement { WHILE, FOR, IF, ELSE, RETURN, NONE } diff --git a/project/JavaCommon/src/com/modulus/dataread/expressions/LineNumberException.java b/project/JavaCommon/src/com/modulus/dataread/expressions/LineNumberException.java new file mode 100644 index 0000000..29cb0a1 --- /dev/null +++ b/project/JavaCommon/src/com/modulus/dataread/expressions/LineNumberException.java @@ -0,0 +1,25 @@ +package com.modulus.dataread.expressions; + +public class LineNumberException extends RuntimeException{ + private int line; + + public LineNumberException( int line ) { + super(); + this.line = line; + } + + public LineNumberException(String message, int line) { + super(message + " line " + line); + this.line = line; + } + + public LineNumberException(String message, Throwable cause, int line) { + super(message + " line " + line, cause); + this.line = line; + } + + public int getLine(){ + return line; + } + +} diff --git a/project/JavaCommon/src/com/modulus/dataread/expressions/ParseRules.java b/project/JavaCommon/src/com/modulus/dataread/expressions/ParseRules.java new file mode 100644 index 0000000..a48f3b9 --- /dev/null +++ b/project/JavaCommon/src/com/modulus/dataread/expressions/ParseRules.java @@ -0,0 +1,84 @@ +package com.modulus.dataread.expressions; + +/** + * Interface defines a set of rules used to parse + * text files. These rules include such rules like + * in string or folder start and end etc. + * + * @author jrahm + * + */ +public interface ParseRules { + /** + * First formats the code to make + * life much easier for the parser. + * + * This should be the first method to be + * called at all times. + */ + void format(); + + /** + * Signals these parse rules that the user has read the character at + * the point <code>off</code> of which the parser dictates how much + * code to skip. + * + * @param off point in the code which was read + * @return how many characters the parser should skip. + */ + int read( int off ); + + /** + * Returns true if the parser is in quotes, false otherwise. + * + * @return true if the parser is in quotes, false otherwuse. + */ + boolean inQuotes(); + + /** + * Returns true if the parser is in a + * comment or not. + * + * @return true if the parser is in a + * comment or not. + */ + boolean inComment(); + + /** + * returns true if at position <code>off</code> + * a folder is being opened. + * + * @param off the position in the code + * @return true if at position <code>off</code> a + * folder is being opened. + */ + boolean openFolder( int off ); + + /** + * returns true if at position <code>off</code> + * a folder is being closed in the code. + * + * @param off the position of the parser + * @return if a folder is being closed at position <code>off</code> + */ + boolean closeFolder( int off ); + + /** + * returns true if a statement is terminated at position <code>off</code> + * + * @param off the position in the code. + * @return true if a statement is terminated at position <code>off</code> + */ + boolean statementTerminated( int off ); + + /** + * Returns the code which these parse rules are using. + * @return the code which these parse rules are using. + */ + String getCode(); + + /** + * Returns the line number of this reader + */ + int getLineNumber(); +} diff --git a/project/JavaCommon/src/com/modulus/dataread/expressions/Statement.java b/project/JavaCommon/src/com/modulus/dataread/expressions/Statement.java new file mode 100644 index 0000000..27df480 --- /dev/null +++ b/project/JavaCommon/src/com/modulus/dataread/expressions/Statement.java @@ -0,0 +1,105 @@ +package com.modulus.dataread.expressions; + +/** + * This interface is used to store interpreted + * information from a text file in a way that + * most represents a tree. for easy parsing + * for an interpreter or compiler. + * + * @author jrahm + * + */ +public interface Statement { + + /** + * Returns the child statements of this class + * + * @return the child statements of this class + */ + Statement[] getChildren(); + + /** + * Adds a child statement to this Statement + * + * @param child the child statement to add + */ + void addChild(Statement child); + + /** + * Removes a child statement from this Statement object + * + * @param child this child to remove from this statement + */ + void removeChild(Statement child); + + /** + * Sets the header for this statement object + * + * @param header the header for this statement. + */ + void setHeader(String header); + + /** + * returns the header for this statement object + * @return + */ + String getHeader(); + + /** + * side effect method to get nicely formatted printouts + * of the statement class. + * @param recur + * @return + */ + String toString( int recur ); + + /** + * Returns the child of this Statement that has + * the header <code>header</code>. If there is no + * child with that header, then the method should + * then return <code>null</code>. If there are multiple + * children with the same header, then the first one should + * be returned. If all children with that header should be + * returned, then use the <code>getChildrenByHeader</code> method. + * + * @param header the header of the child to return + * @return a child with the header <code>header</code> + */ + Statement getChildByHeader(String header); + + /** + * Returns an array of children of this Statement that have + * the header <code>header</code>. If no children have that header, + * then an empty array is returned. + * + * @param header the header of the children to return. + * @return an array of children that have the header <code>header</code> + */ + Statement[] getChildrenByHeader(String header); + + /** + * Returns the line number that this statement starts on. + * @return the line number that this statement starts on. + */ + int getLineNumber(); + + /** + * Sets the line number that this statement + * starts on. + * + * @param line the line this statement starts on. + */ + void setLineNumber(int line); + + /** + * Returns true if this statement has children, false otherwise. + * + * @return true if this statement has children. + */ + boolean hasChildren(); + + /** + * Deletes all children from this statement + */ + void clearChildren(); +}
\ No newline at end of file diff --git a/project/JavaCommon/src/com/modulus/dataread/expressions/StatementFactory.java b/project/JavaCommon/src/com/modulus/dataread/expressions/StatementFactory.java new file mode 100644 index 0000000..16da8aa --- /dev/null +++ b/project/JavaCommon/src/com/modulus/dataread/expressions/StatementFactory.java @@ -0,0 +1,28 @@ +package com.modulus.dataread.expressions; + +import java.util.Map; + +/** + * Interface describes how an object is supposed to + * generate statements. This class is to be used int tandem + * with the ExpressionParser interface to generate + * Statements of a specific type; + * + * @author jrahm + * + * @param <T> the type of statement this StatementFactory creates + */ +public interface StatementFactory<T extends Statement> { + + /** + * Creates a new statement with the type <code>T</code> based + * on what the parameters contain. + * + * The parameters contain useful information about where the parser + * currently is and how to create the new statement. + * + * @param params the parameters + * @return a new statement of type <code>T</code> based off of the parameters. + */ + T generateStatement(Map<String, Object> params); +} diff --git a/project/JavaCommon/src/com/modulus/dataread/expressions/StatementFormatter.java b/project/JavaCommon/src/com/modulus/dataread/expressions/StatementFormatter.java new file mode 100644 index 0000000..8070034 --- /dev/null +++ b/project/JavaCommon/src/com/modulus/dataread/expressions/StatementFormatter.java @@ -0,0 +1,26 @@ +package com.modulus.dataread.expressions; + +import java.io.Serializable; + +/** + * Classes that implement this interface are used + * to format string before they become a part of + * a statement. + * + * These classes are the classes responsible for making + * sure the headers are formatted in such a way that they might + * be easy to parse. + * + * @author jrahm + */ +public interface StatementFormatter extends Serializable{ + /** + * Given the String <code>header</code> as a header of a statement, + * format it so it can easily be parsed by custom parsing + * techniques. + * + * @param header the header to parse + * @return a formatted version of the header. + */ + String formatHeader(String header); +} diff --git a/project/JavaCommon/src/com/modulus/dataread/expressions/StatementTreeParser.java b/project/JavaCommon/src/com/modulus/dataread/expressions/StatementTreeParser.java new file mode 100644 index 0000000..854d4d2 --- /dev/null +++ b/project/JavaCommon/src/com/modulus/dataread/expressions/StatementTreeParser.java @@ -0,0 +1,21 @@ +package com.modulus.dataread.expressions; + +/** + * Interface which describes how an expression parser + * will handle information from an interpreter file. + * + * @author jrahm + * + * @param S the statement type which is used to create this class + */ +public interface StatementTreeParser { + + /** + * Parse a block of code into statements using the statement factory <code>factory</code> + * to generate the statements to use. + * @param <T> the type of statement to use. + * @param factory the factory to generate the statements + * @return a Statement of type <code>T</code> that represents the code parsed + */ + <T extends Statement> Statement parseStatements(StatementFactory<T> factory); +} diff --git a/project/JavaCommon/src/com/modulus/dataread/expressions/impl/AbstractParseRules.java b/project/JavaCommon/src/com/modulus/dataread/expressions/impl/AbstractParseRules.java new file mode 100644 index 0000000..ebdb2dc --- /dev/null +++ b/project/JavaCommon/src/com/modulus/dataread/expressions/impl/AbstractParseRules.java @@ -0,0 +1,197 @@ +package com.modulus.dataread.expressions.impl; + +import com.modulus.dataread.expressions.ParseRules; + +/** + * Class which implements ParseRules with rules + * of a language which is very close to the C Programming + * Language and others based off it. + * + * @author jrahm + */ +public abstract class AbstractParseRules implements ParseRules{ + private static final String w = "\\s"; + + private int lineNumber = 0; + /* + * the code this class will follow + */ + private String code; + /* + * value which tells this class + * if it is in quotes or not. + */ + private boolean inQuotes = false; + + /* + * value which dictates if the parser + * is in comments. + */ + private boolean inComments = false; + + /* + * this tells if the parser is in + * a comment delimited by '//' + */ + private boolean inLineComment = false; + /** + * Constructs a new CBasedParseRules object with <code>code</code> + * as the code which is being parsed. + * + * @param code the code to be parsed. + */ + public AbstractParseRules(String code){ + this.code = code; + format(); + + deleteComments(); + } + + @Override + public boolean closeFolder(int off) { + + return code.startsWith(this.getCloseFolderString(), off); + } + + @Override + public boolean inComment() { + return inComments || inLineComment; + } + + @Override + public boolean inQuotes() { + return inQuotes; + } + + @Override + public boolean openFolder(int off) { + return code.startsWith( this.getOpenFolderString(), off ); + } + + /* + * this is where most of the logic + * goes for this class, this method is + * what dictates the flow of the parser + * and whether or not the parser is in + * quotes or comments etc. + * + * @see com.modulus.dataread.expressions.ParseRules#read(int) + */ + @Override + public int read(int off) { + // Here we will handle to see if the parser + // has run into a string literal. + + // System.out.print( code.charAt(off) ); + if(code.charAt(off) == '"'){ + if( off == 0 || code.charAt(off - 1) != '\\' ){ + inQuotes = !inQuotes; + } + } + + return 1; + } + + public boolean statementTerminated( int off ){ + boolean tmp = code.startsWith( this.getStatementTerminatingCharacter(), off ) && !inQuotes(); + + // if(tmp) { + // System.out.printf("%s\t%s\t%s\n", code.substring(off), off, inQuotes ); + // } + + return tmp; + } + + @Override + public void format() { + // for most C-based languages white space can just be + // Truncated like so. + // this.code = this.code.replaceAll(w+"+\n"+w+"+", "\n"); + this.code = this.code.replace('\n', '\u0088'); + // this.code = this.code.replaceAll(w+"+", " "); + // this.code = this.code.replaceAll(w+"*\\}"+w+"*", "}"); + // this.code = this.code.replaceAll(w+"*;"+w+"*", ";"); + StringBuffer total = new StringBuffer(); + + int i = 0; + int old = 0; + + boolean inQuotes = false; + + while( i != this.code.length() ) { + old = i; + i = code.indexOf('"', i+1); + + if( i == -1 ) + i = this.code.length(); + + String sub = code.substring(old, i); + + if(!inQuotes) { + sub = sub.replaceAll(w+"+", " "); + sub = sub.replaceAll(w+"*\\}"+w+"*", "}"); + sub = sub.replaceAll(w+"*;"+w+"*", ";"); + } + + total.append(sub); + + inQuotes = !inQuotes; + } + total.append( code.substring(old) ); + + code = total.toString(); + //this.code = this.code.replaceAll("[^;]\\}", ";}"); + + // System.out.println("Format: " + this.code); + } + + public String getCode(){ + return code.replace('\u0088', '\n'); + } + + @Override + public int getLineNumber() { + return lineNumber; + } + + private void deleteComments(){ + StringBuffer code2 = new StringBuffer(); + + for( int i = 0;i < code.length(); i ++){ + if(code.startsWith( this.getCommentOpen(), i )){ + while(!code.startsWith( this.getCommentClose(), i)){ + if(code.charAt(i) == '\u0088') + code2.append(code.charAt(i)); + i ++; + } + i += this.getCommentClose().length(); + } + + if(code.startsWith( this.getLineCommentDelimeter(), i)){ + while(code.charAt(i) != '\u0088'){ + i++; + } + } + + code2.append( code.charAt(i) ); + } + + code = code2.toString(); + } + + public abstract String getOpenFolderString(); + + public abstract String getCloseFolderString(); + + public abstract String getStatementTerminatingCharacter(); + + public abstract String getStringDelimiter(); + + public abstract String getEscapeSequence(); + + public abstract String getCommentOpen(); + + public abstract String getCommentClose(); + + public abstract String getLineCommentDelimeter(); +} diff --git a/project/JavaCommon/src/com/modulus/dataread/expressions/impl/CBasedParseRules.java b/project/JavaCommon/src/com/modulus/dataread/expressions/impl/CBasedParseRules.java new file mode 100644 index 0000000..33dad25 --- /dev/null +++ b/project/JavaCommon/src/com/modulus/dataread/expressions/impl/CBasedParseRules.java @@ -0,0 +1,57 @@ +package com.modulus.dataread.expressions.impl; + +public class CBasedParseRules extends AbstractParseRules{ + + public CBasedParseRules(String code) { + super(code); + } + + @Override + public String getOpenFolderString() { + // TODO Auto-generated method stub + return "{"; + } + + @Override + public String getCloseFolderString() { + // TODO Auto-generated method stub + return "}"; + } + + @Override + public String getStatementTerminatingCharacter() { + // TODO Auto-generated method stub + return ";"; + } + + @Override + public String getStringDelimiter() { + // TODO Auto-generated method stub + return "\""; + } + + @Override + public String getEscapeSequence() { + // TODO Auto-generated method stub + return "\\"; + } + + @Override + public String getCommentOpen() { + // TODO Auto-generated method stub + return "/*"; + } + + @Override + public String getCommentClose() { + // TODO Auto-generated method stub + return "*/"; + } + + @Override + public String getLineCommentDelimeter() { + // TODO Auto-generated method stub + return "//"; + } + +}
\ No newline at end of file diff --git a/project/JavaCommon/src/com/modulus/dataread/expressions/impl/FormatStatement.java b/project/JavaCommon/src/com/modulus/dataread/expressions/impl/FormatStatement.java new file mode 100644 index 0000000..8a4b3ad --- /dev/null +++ b/project/JavaCommon/src/com/modulus/dataread/expressions/impl/FormatStatement.java @@ -0,0 +1,52 @@ +package com.modulus.dataread.expressions.impl; + +import com.modulus.dataread.expressions.AbstractStatement; +import com.modulus.dataread.expressions.StatementFormatter; + +/** + * This class that extends AbstractStatement will first + * format its header before it sets the actual header to + * what the user sends, using a statement formatter. + * + * @author jrahm + * + */ +public class FormatStatement extends AbstractStatement{ + private static final long serialVersionUID = -4973798175965745298L; + private StatementFormatter formatter; + + /** + * This creates a new Statement with <code>formatter</code> + * as the default formatter for this Statement. + * + * @param formatter the formatter for this statement + */ + public FormatStatement(StatementFormatter formatter){ + this.formatter = formatter; + } + + protected FormatStatement(){ + } + + @Override + public void setHeader(String header) { + this.header = formatter.formatHeader(header); + } + + /** + * Returns the formatter for this Statement + * @return the formatter for this Statement + */ + public StatementFormatter getFormatter(){ + return formatter; + } + + /** + * Sets the formatter for this statement + * @param formatter the formatter for this statement + */ + public void setFormatter(StatementFormatter formatter){ + this.formatter = formatter; + } + +} diff --git a/project/JavaCommon/src/com/modulus/dataread/expressions/impl/SimpleExpressionParser.java b/project/JavaCommon/src/com/modulus/dataread/expressions/impl/SimpleExpressionParser.java new file mode 100644 index 0000000..22f1be5 --- /dev/null +++ b/project/JavaCommon/src/com/modulus/dataread/expressions/impl/SimpleExpressionParser.java @@ -0,0 +1,139 @@ +package com.modulus.dataread.expressions.impl; + +import com.modulus.common.TwoTypeBean; +import com.modulus.dataread.expressions.StatementTreeParser; +import com.modulus.dataread.expressions.ParseRules; +import com.modulus.dataread.expressions.Statement; +import com.modulus.dataread.expressions.StatementFactory; + +/** + * This simple expression parser is meant not to do anything fancy + * all it does is break up the file into a tree based on the folders + * in the file. + * + * @author jrahm + * + */ +public class SimpleExpressionParser implements StatementTreeParser{ + /* + * used by methods to keep track of + * the number of lines + */ + private int line = 0; + /* + * The rules to parse by + */ + private ParseRules rules; + + /** + * Creates a new <code>SimpleExpressionParser</code> based + * off of the rules that was given to it. + * + * @param rules the rules to parse by + */ + public SimpleExpressionParser(ParseRules rules){ + this.rules = rules; + } + + @Override + public <T extends Statement> Statement parseStatements(StatementFactory<T> factory) { + // set the line counter to 1 + this.line = 1; + return recurParseStatement(factory, 0).getObject1(); + } + + /* + * Setup a recursive parser to + * return a tree of statements + */ + private <T extends Statement> TwoTypeBean<T, Integer> recurParseStatement(StatementFactory<T> factory, int off){ + // System.out.println(" parseStatements"); + final String code = rules.getCode(); + + // statement which will be returned in the end, + // this statement is the parent of all the other + // statements + T ret = factory.generateStatement(null); + int i = off; + + + // start an iteration through the + // string + for( ;i < code.length(); i ++ ){ + + // if the next character is a new line character, + // the increment the line counter + if(code.charAt(i) == '\n') + line ++; + + // check to see if the rules say that here a statement + // is to be terminated + if( rules.statementTerminated(i) ){ + + // if so, then it is time to manifest a new statement + // header is equal to the substring of the code from + // off to i + String header = code.substring(off, i); + + // create a new child from the type provided + T child = factory.generateStatement(null); + + // set the line number to what it should be + child.setLineNumber( this.line ); + + // set the header + child.setHeader( header ); + + // we are done with creating this beam, so it is time to + // return it + return new TwoTypeBean<T, Integer>(child, i); + } + + // if the rules say that at this point, + // a folder is opened, then it is time to + // use recursion to implement a tree. + else if ( rules.openFolder(i) ){ + + // the header is from off to when the + // folder is being closed + String header = code.substring(off, i); + + // set the header + ret.setHeader(header); + + // set the line number + ret.setLineNumber(line); + + // it is time to increment i by the + // amount the rules say to. + i += rules.read(i); + + // while the folder is not closed + while( !rules.closeFolder(i) ){ + + // read the next statement + TwoTypeBean<T, Integer> bean = recurParseStatement(factory, i); + + // the second object is the offset + //that the previous call terminated with + i = bean.getObject2(); + + // add this child to the main bean + ret.addChild(bean.getObject1()); + + // increment the incrementer by how + // much the rules say to + i += rules.read(i); + } + + // When finished reading this file, it is time + // to return the main bean. + return new TwoTypeBean<T, Integer>(ret, i); + } + } + + // System.out.println(" /parseStatements"); + return new TwoTypeBean<T, Integer>(ret, i); + } + +} diff --git a/project/JavaCommon/src/com/modulus/dataread/expressions/impl/SimpleStatement.java b/project/JavaCommon/src/com/modulus/dataread/expressions/impl/SimpleStatement.java new file mode 100644 index 0000000..f32cfca --- /dev/null +++ b/project/JavaCommon/src/com/modulus/dataread/expressions/impl/SimpleStatement.java @@ -0,0 +1,19 @@ +package com.modulus.dataread.expressions.impl; + +import com.modulus.dataread.expressions.AbstractStatement; + +public class SimpleStatement extends AbstractStatement { + private static final long serialVersionUID = -8730515046885236907L; + + public SimpleStatement(){} + + public SimpleStatement(String string) { + super(); + this.setHeader(string); + } + + @Override + public void setHeader(String header) { + this.header = header; + } +} diff --git a/project/JavaCommon/src/com/modulus/dataread/expressions/impl/SimpleStatementTreeParser.java b/project/JavaCommon/src/com/modulus/dataread/expressions/impl/SimpleStatementTreeParser.java new file mode 100644 index 0000000..70ebd95 --- /dev/null +++ b/project/JavaCommon/src/com/modulus/dataread/expressions/impl/SimpleStatementTreeParser.java @@ -0,0 +1,162 @@ +package com.modulus.dataread.expressions.impl; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileInputStream; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.util.Map; + +import com.modulus.common.TwoTypeBean; +import com.modulus.dataread.expressions.LineNumberException; +import com.modulus.dataread.expressions.StatementFormatter; +import com.modulus.dataread.expressions.StatementTreeParser; +import com.modulus.dataread.expressions.ParseRules; +import com.modulus.dataread.expressions.Statement; +import com.modulus.dataread.expressions.StatementFactory; + +/** + * This simple expression parser is meant not to do anything fancy + * all it does is break up the file into a tree based on the folders + * in the file. + * + * @author jrahm + * + */ +public class SimpleStatementTreeParser implements StatementTreeParser{ + + /* + * used by methods to keep track of + * the number of lines + */ + private int line = 0; + /* + * The rules to parse by + */ + private ParseRules rules; + + /** + * Creates a new <code>SimpleExpressionParser</code> based + * off of the rules that was given to it. + * + * @param rules the rules to parse by + */ + public SimpleStatementTreeParser(ParseRules rules){ + this.rules = rules; + } + + @Override + public <T extends Statement> Statement parseStatements(StatementFactory<T> factory) { + // set the line counter to 1 + this.line = 0; + return recurParseStatement(factory, 0).getObject1(); + } + + /* + * Setup a recursive parser to + * return a tree of statements + */ + private <T extends Statement> TwoTypeBean<T, Integer> recurParseStatement(StatementFactory<T> factory, int off){ + try{ + // System.out.println(" parseStatements"); + final String code = rules.getCode(); + + // statement which will be returned in the end, + // this statement is the parent of all the other + // statements + T ret = factory.generateStatement(null); + int i = off; + int n = 0; + + // start an iteration through the + // string + for( ;i < code.length(); n++, i += rules.read(i) ){ + // if the next character is a new line character, + // the increment the line counter + // System.out.println( i ); + if(code.charAt(i) == '\n'){ + line ++; + // that is all a new line does; + continue; + } + + // check to see if the rules say that here a statement + // is to be terminated + if( rules.statementTerminated(i) ){ + + // if so, then it is time to manifest a new statement + // header is equal to the substring of the code from + // off to i + String header = code.substring(off, i); + + // create a new child from the type provided + T child = factory.generateStatement(null); + + // set the header + child.setHeader( header ); + + // set the line number to what it should be + child.setLineNumber( this.line ); + + // we are done with creating this beam, so it is time to + // return it + return new TwoTypeBean<T, Integer>(child, i); + } + + // if the rules say that at this point, + // a folder is opened, then it is time to + // use recursion to implement a tree. + else if ( rules.openFolder(i) ){ + + // the header is from off to when the + // folder is being closed + String header = code.substring(off, i); + + // set the header + ret.setHeader(header); + + // set the line number + ret.setLineNumber(line); + + // it is time to increment i by the + // amount the rules say to. + i += rules.read(i); + + // while the folder is not closed + while( !rules.closeFolder(i) ){ + + // read the next statement + TwoTypeBean<T, Integer> bean = recurParseStatement(factory, i); + + // the second object is the offset + //that the previous call terminated with + i = bean.getObject2(); + + // add this child to the main bean + ret.addChild(bean.getObject1()); + + // increment the incrementer by how + // much the rules say to + i += rules.read(i); + + while(code.charAt(i) == '\n'){ + line ++; + i++; + } + } + + // When finished reading this file, it is time + // to return the main bean. + return new TwoTypeBean<T, Integer>(ret, i); + } + + } + + // System.out.println(" /parseStatements"); + return new TwoTypeBean<T, Integer>(ret, i); + } catch( Exception e ){ + throw new LineNumberException("Sytax error", e, line); + } + } + +} diff --git a/project/JavaCommon/src/com/modulus/dataread/expressions/impl/StatementParser.java b/project/JavaCommon/src/com/modulus/dataread/expressions/impl/StatementParser.java new file mode 100644 index 0000000..7a91585 --- /dev/null +++ b/project/JavaCommon/src/com/modulus/dataread/expressions/impl/StatementParser.java @@ -0,0 +1,5 @@ +package com.modulus.dataread.expressions.impl; + +public class StatementParser { + +} |