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
|