Author: mic...@jb... Date: 2006-06-21 00:17:31 -0400 (Wed, 21 Jun 2006) New Revision: 4790 Added: labs/jbossrules/trunk/drools-compiler/src/main/java/org/drools/lang/dsl/LineBasedExpander.java labs/jbossrules/trunk/drools-compiler/src/main/resources/org/drools/lang/dsl/ labs/jbossrules/trunk/drools-compiler/src/main/resources/org/drools/lang/dsl/rule1.drl labs/jbossrules/trunk/drools-compiler/src/test/java/org/drools/lang/dsl/LineExpanderTest.java Log: JBRULES-268 Added: labs/jbossrules/trunk/drools-compiler/src/main/java/org/drools/lang/dsl/LineBasedExpander.java =================================================================== --- labs/jbossrules/trunk/drools-compiler/src/main/java/org/drools/lang/dsl/LineBasedExpander.java 2006-06-21 00:52:41 UTC (rev 4789) +++ labs/jbossrules/trunk/drools-compiler/src/main/java/org/drools/lang/dsl/LineBasedExpander.java 2006-06-21 04:17:31 UTC (rev 4790) @@ -0,0 +1,178 @@ +package org.drools.lang.dsl; + +import java.util.StringTokenizer; + +import org.drools.lang.Expander; + +/** + * This is a simple line based expander front end for the DRL parser. + * Kind of a micro parser in itself. + * This tries to keep the whitespace and lines intact, but it is not + * guaranteed to preserve the exact spacing or line numbers. + * + * TODO: To replace the in-parser implementation in 3.1 + + * + * @author Michael Neale + */ +public class LineBasedExpander { + + private String source; + private StringBuffer output = new StringBuffer(); + private boolean lhs; + private boolean rhs; + private int lineNumber = 0; + private Expander expander; + + /** Pass in the unexpanded rule(s), and and the expander to apply */ + public LineBasedExpander(String rawSource, + Expander exp) { + source = rawSource; + this.expander = exp; + } + + /** + * This will apply the expander. And return the result. + */ + public String expand() { + StringTokenizer st = new StringTokenizer( source, + "\r\n" ); + + while ( st.hasMoreTokens() ) { + lineNumber++; + String raw = st.nextToken(); + String line = raw.trim(); + + if ( matchesKeyword( "when", + line ) ) { + lhs(); + appendLine( raw ); + } else if ( matchesKeyword( "then", + line ) ) { + rhs(); + appendLine( raw ); + } else if ( matchesKeyword( "end", + line ) ) { + endRule(); + appendLine( raw ); + output.append( "\n" ); + } else if ( matchesKeyword( "query", + line ) ) { + query(); + appendLine( raw ); + } else { + consume( raw ); + } + } + return output.toString(); + + } + + private void appendLine(String raw) { + output.append( raw ); + output.append( "\n" ); + } + + /** + * @return The expanded rule(s). + */ + public String getExpanded() { + return output.toString(); + } + + private void consume(String raw) { + if ( lhs ) { + appendLine( expand( "when", + raw ) ); + } else if ( rhs ) { + appendLine( expand( "then", + raw ) ); + } else { + appendLine( raw ); + + } + + } + + private String expand(String scope, + String raw) { + String trimmed = raw.trim(); + + if ( trimmed.startsWith( ">" ) ) { + return raw.substring( 1 ); + } else { + return "\t\t" + //some space to make it look purrty + expander.expand( scope, + normaliseSpaces( raw ) ); + } + } + + /** + * This will match the token, ignoring any single line comments. + */ + boolean matchesKeyword(String token, + String line) { + if ( line.length() < token.length() ) return false; + if ( !line.startsWith( token ) ) return false; + + String rest = line.substring( token.length() ).trim(); + + if ( rest.length() == 0 ) return true; + char next = rest.charAt( 0 ); + if ( next == '#' || next == '/' ) { + return true; + } else { + return false; + } + + } + + /** + * This will normalise all spaces (no 2 spaces in a row). + * Strings (single or double quoted) are left alone. + */ + String normaliseSpaces(String original) { + + boolean singleQ = false; + boolean doubleQ = false; + boolean prevSpace = false; + + StringBuffer buf = new StringBuffer(); + char[] cs = original.trim().toCharArray(); + for ( int i = 0; i < cs.length; i++ ) { + char c = cs[i]; + if ( Character.isWhitespace( c ) && !(singleQ || doubleQ) ) { + if ( !prevSpace ) { + buf.append( ' ' ); + prevSpace = true; + } + } else { + prevSpace = false; + if ( c == '\'' ) singleQ = !singleQ; + if ( c == '\"' ) doubleQ = !doubleQ; + buf.append( c ); + } + } + return buf.toString(); + } + + private void query() { + lhs(); + } + + private void endRule() { + this.lhs = false; + this.rhs = false; + + } + + private void rhs() { + this.rhs = true; + this.lhs = false; + + } + + private void lhs() { + this.lhs = true; + } + +} Property changes on: labs/jbossrules/trunk/drools-compiler/src/main/java/org/drools/lang/dsl/LineBasedExpander.java ___________________________________________________________________ Name: svn:eol-style + native Added: labs/jbossrules/trunk/drools-compiler/src/main/resources/org/drools/lang/dsl/rule1.drl =================================================================== --- labs/jbossrules/trunk/drools-compiler/src/main/resources/org/drools/lang/dsl/rule1.drl 2006-06-21 00:52:41 UTC (rev 4789) +++ labs/jbossrules/trunk/drools-compiler/src/main/resources/org/drools/lang/dsl/rule1.drl 2006-06-21 04:17:31 UTC (rev 4790) @@ -0,0 +1,12 @@ +package foo + +expander foo + +rule "new rule" + activation-group "boo" + when + line 1 + line 2 + then + line 3 +end Property changes on: labs/jbossrules/trunk/drools-compiler/src/main/resources/org/drools/lang/dsl/rule1.drl ___________________________________________________________________ Name: svn:eol-style + native Added: labs/jbossrules/trunk/drools-compiler/src/test/java/org/drools/lang/dsl/LineExpanderTest.java =================================================================== --- labs/jbossrules/trunk/drools-compiler/src/test/java/org/drools/lang/dsl/LineExpanderTest.java 2006-06-21 00:52:41 UTC (rev 4789) +++ labs/jbossrules/trunk/drools-compiler/src/test/java/org/drools/lang/dsl/LineExpanderTest.java 2006-06-21 04:17:31 UTC (rev 4790) @@ -0,0 +1,103 @@ +package org.drools.lang.dsl; + +import java.io.BufferedReader; +import java.io.InputStream; +import java.io.InputStreamReader; + +import org.drools.lang.Expander; + +import junit.framework.Assert; +import junit.framework.TestCase; + +public class LineExpanderTest extends TestCase { + + + private String readFile(String name) throws Exception { + + final InputStream in = getClass().getResourceAsStream( name ); + + final InputStreamReader reader = new InputStreamReader( in ); + + final StringBuffer text = new StringBuffer(); + + final char[] buf = new char[1024]; + int len = 0; + + while ( (len = reader.read( buf )) >= 0 ) { + text.append( buf, + 0, + len ); + } + return text.toString(); + } + + public void testFile() throws Exception { + Expander exp = new Expander() { + + public String expand(String scope, + String pattern) { + if (scope.equals( "when" )) { + if (!( + (pattern.trim().equals( "line 1" )) + || + (pattern.trim().equals( "line 2" )) + )) { + Assert.fail( "expected line 1 or line 2 only." ); + + } + } + if (scope.equals("then")) { + Assert.assertEquals( "line 3", pattern.trim() ); + } + return "expanded: " + pattern.trim(); + + } + + }; + LineBasedExpander ex = new LineBasedExpander(readFile("rule1.drl"), exp); + String result = ex.expand(); + assertNotNull(result); + System.out.println(result); + assertTrue(result.indexOf( "expanded: line 1" ) > result.indexOf( "when" )); + assertTrue(result.indexOf( "expanded: line 2" ) > result.indexOf( "expanded: line 1" )); + assertTrue(result.indexOf( "then" ) > result.indexOf( "expanded: line 2" )); + assertTrue(result.indexOf( "expanded: line 3" ) > result.indexOf( "then" )); + + + } + + public void testMatchingStart() { + LineBasedExpander exp = new LineBasedExpander("blah", null); + String when = "when"; + String end = "end"; + assertTrue(exp.matchesKeyword( when, " when".trim() )); + assertTrue(exp.matchesKeyword( when, "\twhen#foo".trim() )); + assertFalse(exp.matchesKeyword( when, "\tlwhen#foo".trim() )); + assertTrue(exp.matchesKeyword( when, "when".trim() )); + assertTrue(exp.matchesKeyword( end, "end".trim() )); + + assertTrue(exp.matchesKeyword( end, "\nend //comment".trim() )); + assertTrue(exp.matchesKeyword( end, "end//comment".trim() )); + + assertFalse(exp.matchesKeyword( end, "\n\"end\" //comment".trim() )); + assertFalse(exp.matchesKeyword( end, "\nkend//comment".trim() )); + assertFalse(exp.matchesKeyword( when, "\nend".trim() )); + assertFalse(exp.matchesKeyword( end, "\nkend//comment".trim() )); + } + + public void testNormaliseSpaces() { + String test = " this has more spaces, then is \t necessary"; + String res = "this has more spaces, then is necessary"; + + LineBasedExpander ex = new LineBasedExpander("ignore", null); + assertEquals(res, ex.normaliseSpaces( test )); + + assertEquals(">yeah", ex.normaliseSpaces( ">yeah" )); + assertEquals("yeah man", ex.normaliseSpaces( "yeah man" )); + + assertEquals("'with ' some \"\tquotes\"", + ex.normaliseSpaces( "'with ' some \"\tquotes\" " )); + + } + +} Property changes on: labs/jbossrules/trunk/drools-compiler/src/test/java/org/drools/lang/dsl/LineExpanderTest.java ___________________________________________________________________ Name: svn:eol-style + native |