From: <jbo...@li...> - 2006-01-15 04:51:40
|
Author: mic...@jb... Date: 2006-01-14 23:51:17 -0500 (Sat, 14 Jan 2006) New Revision: 2099 Modified: trunk/labs/jbossrules/drools-natural-dsl/src/main/java/org/drools/natural/NaturalLanguageCompiler.java trunk/labs/jbossrules/drools-natural-dsl/src/main/java/org/drools/natural/ast/BaseSyntaxNode.java trunk/labs/jbossrules/drools-natural-dsl/src/main/java/org/drools/natural/ast/ExpressionContext.java trunk/labs/jbossrules/drools-natural-dsl/src/main/java/org/drools/natural/ast/LeftInfix.java trunk/labs/jbossrules/drools-natural-dsl/src/main/java/org/drools/natural/ast/LeftRightInfix.java trunk/labs/jbossrules/drools-natural-dsl/src/main/java/org/drools/natural/ast/LiteralNode.java trunk/labs/jbossrules/drools-natural-dsl/src/main/java/org/drools/natural/ast/RightInfix.java trunk/labs/jbossrules/drools-natural-dsl/src/main/java/org/drools/natural/grammar/NaturalGrammar.java trunk/labs/jbossrules/drools-natural-dsl/src/main/java/org/drools/natural/grammar/SimpleGrammar.java trunk/labs/jbossrules/drools-natural-dsl/src/main/java/org/drools/natural/lexer/SimpleSnippetLexer.java trunk/labs/jbossrules/drools-natural-dsl/src/test/java/org/drools/natural/NaturalLanguageCompilerTest.java trunk/labs/jbossrules/drools-natural-dsl/src/test/java/org/drools/natural/grammar/SimpleGrammarTest.java trunk/labs/jbossrules/drools-natural-dsl/src/test/java/org/drools/natural/lexer/GrammarAwareLexerTest.java Log: improvements, can ignore unknown items etc. Modified: trunk/labs/jbossrules/drools-natural-dsl/src/main/java/org/drools/natural/NaturalLanguageCompiler.java =================================================================== --- trunk/labs/jbossrules/drools-natural-dsl/src/main/java/org/drools/natural/NaturalLanguageCompiler.java 2006-01-14 17:28:55 UTC (rev 2098) +++ trunk/labs/jbossrules/drools-natural-dsl/src/main/java/org/drools/natural/NaturalLanguageCompiler.java 2006-01-15 04:51:17 UTC (rev 2099) @@ -1,7 +1,10 @@ package org.drools.natural; +import java.util.Properties; + import org.drools.natural.ast.ExpressionContext; import org.drools.natural.grammar.NaturalGrammar; +import org.drools.natural.grammar.SimpleGrammar; import org.drools.natural.lexer.GrammarAwareLexer; import org.drools.natural.lexer.NaturalSnippetLexer; import org.drools.natural.lexer.SimpleSnippetLexer; @@ -22,7 +25,24 @@ grammar = g; } + public NaturalLanguageCompiler(Properties p) { + grammar = new SimpleGrammar(p); + } + /** + * Build a natural expression. + * This method uses the grammar configuration to + * work out the type of expression it is. + * See NaturalGrammar#compileExpression + * and NaturalGrammar#compileNaturalExpression. + */ + public String compile(String expression) { + if (grammar.delimitersRequired()) { + return this.compileExpression(expression); + } else { + return this.compileNaturalExpression(expression); + } + } /** * Will parse a natural language expression into a compiled version, according to Modified: trunk/labs/jbossrules/drools-natural-dsl/src/main/java/org/drools/natural/ast/BaseSyntaxNode.java =================================================================== --- trunk/labs/jbossrules/drools-natural-dsl/src/main/java/org/drools/natural/ast/BaseSyntaxNode.java 2006-01-14 17:28:55 UTC (rev 2098) +++ trunk/labs/jbossrules/drools-natural-dsl/src/main/java/org/drools/natural/ast/BaseSyntaxNode.java 2006-01-15 04:51:17 UTC (rev 2099) @@ -18,6 +18,7 @@ public BaseSyntaxNode next; public BaseSyntaxNode prev; public String originalValue; + protected ExpressionContext context; /** * Node types return true when all their argument needs have been satisfied. @@ -40,14 +41,14 @@ { BaseSyntaxNode currentNode = this; - boolean flag = true; - while (currentNode != null && flag == true) { + boolean satisfied = true; + while (currentNode != null && satisfied == true) { if (currentNode.isThisCorrectType( nodeType )) { - flag = flag && currentNode.isSatisfied(); + satisfied = satisfied && currentNode.isSatisfied(); } currentNode = currentNode.next; } - return flag; + return satisfied; } @@ -122,6 +123,10 @@ return this; } } + + public void setContext(ExpressionContext context) { + this.context = context; + } } Modified: trunk/labs/jbossrules/drools-natural-dsl/src/main/java/org/drools/natural/ast/ExpressionContext.java =================================================================== --- trunk/labs/jbossrules/drools-natural-dsl/src/main/java/org/drools/natural/ast/ExpressionContext.java 2006-01-14 17:28:55 UTC (rev 2098) +++ trunk/labs/jbossrules/drools-natural-dsl/src/main/java/org/drools/natural/ast/ExpressionContext.java 2006-01-15 04:51:17 UTC (rev 2099) @@ -18,8 +18,9 @@ private BaseSyntaxNode firstNode; private BaseSyntaxNode prevNode; - private NaturalGrammar grammar; - + NaturalGrammar grammar; + private boolean ignoreUnknownTokens = false; + public ExpressionContext(NaturalGrammar grammar) { this.grammar = grammar; } @@ -45,7 +46,7 @@ public String render() { buildTreeByOrderOfPrecedence(); - return firstNode.findStartNode().renderAll(); + return firstNode.findStartNode().renderAll().trim(); } @@ -65,6 +66,7 @@ */ private void addNode(BaseSyntaxNode thisNode) { + thisNode.setContext(this); if (firstNode == null) { firstNode = thisNode; } else { @@ -74,8 +76,8 @@ prevNode = thisNode; } + - Modified: trunk/labs/jbossrules/drools-natural-dsl/src/main/java/org/drools/natural/ast/LeftInfix.java =================================================================== --- trunk/labs/jbossrules/drools-natural-dsl/src/main/java/org/drools/natural/ast/LeftInfix.java 2006-01-14 17:28:55 UTC (rev 2098) +++ trunk/labs/jbossrules/drools-natural-dsl/src/main/java/org/drools/natural/ast/LeftInfix.java 2006-01-15 04:51:17 UTC (rev 2099) @@ -44,10 +44,10 @@ - public List getArguments() { + List getArguments() { return this.args; } - + public String render() { List vars = super.getVariableNameList(); Modified: trunk/labs/jbossrules/drools-natural-dsl/src/main/java/org/drools/natural/ast/LeftRightInfix.java =================================================================== --- trunk/labs/jbossrules/drools-natural-dsl/src/main/java/org/drools/natural/ast/LeftRightInfix.java 2006-01-14 17:28:55 UTC (rev 2098) +++ trunk/labs/jbossrules/drools-natural-dsl/src/main/java/org/drools/natural/ast/LeftRightInfix.java 2006-01-15 04:51:17 UTC (rev 2099) @@ -59,15 +59,16 @@ InfixNode.Direction.RIGHT ); } - public List getArgumentsLeft() + List getArgumentsLeft() { return this.argsLeft; } - public List getArgumentsRight() + List getArgumentsRight() { return this.argsRight; } + public String render() { Modified: trunk/labs/jbossrules/drools-natural-dsl/src/main/java/org/drools/natural/ast/LiteralNode.java =================================================================== --- trunk/labs/jbossrules/drools-natural-dsl/src/main/java/org/drools/natural/ast/LiteralNode.java 2006-01-14 17:28:55 UTC (rev 2098) +++ trunk/labs/jbossrules/drools-natural-dsl/src/main/java/org/drools/natural/ast/LiteralNode.java 2006-01-15 04:51:17 UTC (rev 2099) @@ -14,14 +14,14 @@ super.originalValue = val; } - public boolean equals(Object obj) { - if (!(obj instanceof LiteralNode)) { - return false; - } else { - LiteralNode in = (LiteralNode) obj; - return in.originalValue.equals(super.originalValue); - } - } +// public boolean equals(Object obj) { +// if (!(obj instanceof LiteralNode)) { +// return false; +// } else { +// LiteralNode in = (LiteralNode) obj; +// return in.originalValue.equals(super.originalValue); +// } +// } public boolean isSatisfied() { @@ -39,13 +39,29 @@ /** * if the previous node is also a literal or a sub, then * a space will be inserted to honour the intent of the original. + * + * For literals, if context says to ignore unknown, + * then they will NEVER be included in the output + * unless they are an argument to an infix operator. */ public String render() { + if (ignoreUnknown()) { + return ""; + } + if (prev != null) { return SPACE + super.originalValue; } else { return super.originalValue; } } + + private boolean ignoreUnknown() { + return context != null + && + context.grammar.ignoreUnknownTokens() + && + super.parent == null; + } } Modified: trunk/labs/jbossrules/drools-natural-dsl/src/main/java/org/drools/natural/ast/RightInfix.java =================================================================== --- trunk/labs/jbossrules/drools-natural-dsl/src/main/java/org/drools/natural/ast/RightInfix.java 2006-01-14 17:28:55 UTC (rev 2098) +++ trunk/labs/jbossrules/drools-natural-dsl/src/main/java/org/drools/natural/ast/RightInfix.java 2006-01-15 04:51:17 UTC (rev 2099) @@ -43,11 +43,11 @@ - public List getArguments() { + List getArguments() { return this.args; } + - public String render() { List vars = super.getVariableNameList(); Modified: trunk/labs/jbossrules/drools-natural-dsl/src/main/java/org/drools/natural/grammar/NaturalGrammar.java =================================================================== --- trunk/labs/jbossrules/drools-natural-dsl/src/main/java/org/drools/natural/grammar/NaturalGrammar.java 2006-01-14 17:28:55 UTC (rev 2098) +++ trunk/labs/jbossrules/drools-natural-dsl/src/main/java/org/drools/natural/grammar/NaturalGrammar.java 2006-01-15 04:51:17 UTC (rev 2099) @@ -1,17 +1,19 @@ package org.drools.natural.grammar; -import java.util.List; /** - * All Grammars must implement this simple interface. SimpleGrammar is the default implementation. + * All Grammars must implement this simple interface. + * SimpleGrammar is the default implementation. * - * * @author <a href="mailto:mic...@gm..."> Michael Neale</a> - * */ public interface NaturalGrammar { + + public static final String IGNORE_UNKNOWN_TOKENS = "ignore.unknown"; + public static final String REQUIRE_DELIMITERS = "require.delimiters"; + /** * Return an expression matching that token. */ @@ -24,4 +26,18 @@ */ public abstract String[] listNaturalItems(); + /** + * @return True if unknown tokens are to be ignored for + * this grammar configuration. + * Unknown does not include arguments to infix operators of course. + */ + public boolean ignoreUnknownTokens(); + + /** + * @return True if tokens containing spaces must be delimited, + * to help out the lexer. + */ + public boolean delimitersRequired(); + + } \ No newline at end of file Modified: trunk/labs/jbossrules/drools-natural-dsl/src/main/java/org/drools/natural/grammar/SimpleGrammar.java =================================================================== --- trunk/labs/jbossrules/drools-natural-dsl/src/main/java/org/drools/natural/grammar/SimpleGrammar.java 2006-01-14 17:28:55 UTC (rev 2098) +++ trunk/labs/jbossrules/drools-natural-dsl/src/main/java/org/drools/natural/grammar/SimpleGrammar.java 2006-01-15 04:51:17 UTC (rev 2099) @@ -8,38 +8,42 @@ import org.drools.natural.NaturalLanguageException; /** - * Holds the simple grammar for a natural expressions. + * Holds the simple grammar for a pseudo natural language/dsl. * @author <a href="mailto:mic...@gm..."> Michael Neale</a> * */ public class SimpleGrammar implements Serializable, NaturalGrammar { + private static final long serialVersionUID = -6587260296556962105L; - private static final long serialVersionUID = -6587260296556962105L; - private final Map dictionary; + private Properties dictionary; - public SimpleGrammar() { - dictionary = new HashMap(); + init(new Properties()); } public SimpleGrammar(Properties props) { - dictionary = props; + init(props); + } + + private void init(Properties map) { + dictionary = map; } + public void addToDictionary(String token, String expression) { if (dictionary.containsKey(token)) { throw new NaturalLanguageException("The token [" + token + "] is already in the dictionary."); } - dictionary.put(token, expression); + dictionary.setProperty(token, expression); } /* (non-Javadoc) * @see org.drools.natural.grammar.NaturalGrammar#getExpression(java.lang.String) */ public String getExpression(String token) { - return (String) dictionary.get(token); + return dictionary.getProperty(token); } /* (non-Javadoc) @@ -54,6 +58,17 @@ return (String[]) this.dictionary.keySet().toArray(new String[dictionary.size()]); } + public boolean ignoreUnknownTokens() { + String s = (String) this.dictionary.getProperty(IGNORE_UNKNOWN_TOKENS); + return Boolean.parseBoolean(s); + + } + + public boolean delimitersRequired() { + String s = (String) this.dictionary.getProperty(REQUIRE_DELIMITERS, "false"); + return Boolean.parseBoolean(s); + } + Modified: trunk/labs/jbossrules/drools-natural-dsl/src/main/java/org/drools/natural/lexer/SimpleSnippetLexer.java =================================================================== --- trunk/labs/jbossrules/drools-natural-dsl/src/main/java/org/drools/natural/lexer/SimpleSnippetLexer.java 2006-01-14 17:28:55 UTC (rev 2098) +++ trunk/labs/jbossrules/drools-natural-dsl/src/main/java/org/drools/natural/lexer/SimpleSnippetLexer.java 2006-01-15 04:51:17 UTC (rev 2099) @@ -28,7 +28,6 @@ public SimpleSnippetLexer(String snippet) { - this.snippet = snippet.toCharArray( ); this.tokens = new ArrayList( ); this.currentToken = new StringBuffer( ); Modified: trunk/labs/jbossrules/drools-natural-dsl/src/test/java/org/drools/natural/NaturalLanguageCompilerTest.java =================================================================== --- trunk/labs/jbossrules/drools-natural-dsl/src/test/java/org/drools/natural/NaturalLanguageCompilerTest.java 2006-01-14 17:28:55 UTC (rev 2098) +++ trunk/labs/jbossrules/drools-natural-dsl/src/test/java/org/drools/natural/NaturalLanguageCompilerTest.java 2006-01-15 04:51:17 UTC (rev 2099) @@ -1,5 +1,8 @@ package org.drools.natural; +import java.util.Properties; + +import org.drools.natural.grammar.NaturalGrammar; import org.drools.natural.grammar.SimpleGrammar; import junit.framework.TestCase; @@ -23,10 +26,12 @@ grammar.addToDictionary("->", "${left}.${right}()"); grammar.addToDictionary("or", "||"); grammar.addToDictionary("and", "&&"); + grammar.addToDictionary("less than", "${left} < ${right}"); + grammar.addToDictionary("ignore.unknown", "true"); } public void testNaturalLanguage() { - String snippet = "bob [likes cheese] or [age of] bob < 21 " + + String snippet = "bob [likes cheese] or [age of] bob [less than] 21 " + "or bob equals mark and bob -> health equals good"; NaturalLanguageCompiler parser = new NaturalLanguageCompiler(grammar); @@ -37,13 +42,19 @@ } public void testLookNoBracketsMum() { - String snippet = "bob likes cheese or age of bob < 21 " + + String snippet = "check that bob likes cheese or check the age of bob less than 21 " + "or bob equals mark and bob -> health equals good"; + NaturalLanguageCompiler parser = new NaturalLanguageCompiler(grammar); String result = parser.compileNaturalExpression(snippet); assertEquals("bob.likesCheese() || ageOf(bob) < 21 || bob.equals(mark) && bob.health().equals(good)", result); + + //now check it to make sure it doesn't require brackets by default + result = parser.compile(snippet); + assertEquals("bob.likesCheese() || ageOf(bob) < 21 || bob.equals(mark) && bob.health().equals(good)", result); + } public void testNaturalLanguageNesting() { @@ -57,7 +68,8 @@ public void testNotInDictionary() { String snippet = "nothing is in the dictionary"; - NaturalLanguageCompiler parser = new NaturalLanguageCompiler(grammar); + + NaturalLanguageCompiler parser = new NaturalLanguageCompiler(new SimpleGrammar(new Properties())); assertEquals(snippet, parser.compileExpression(snippet)); snippet = "[well some is like bob likes cheese, but by using brackets is all escaped]"; @@ -65,5 +77,13 @@ assertEquals(bracketsRemoved, parser.compileExpression(snippet)); } + + public void testIgnoreUnknown() { + NaturalLanguageCompiler parser = new NaturalLanguageCompiler(grammar); + String snippet = "that bob likes cheese"; + assertEquals("bob.likesCheese()", parser.compileNaturalExpression(snippet)); + } + + } Modified: trunk/labs/jbossrules/drools-natural-dsl/src/test/java/org/drools/natural/grammar/SimpleGrammarTest.java =================================================================== --- trunk/labs/jbossrules/drools-natural-dsl/src/test/java/org/drools/natural/grammar/SimpleGrammarTest.java 2006-01-14 17:28:55 UTC (rev 2098) +++ trunk/labs/jbossrules/drools-natural-dsl/src/test/java/org/drools/natural/grammar/SimpleGrammarTest.java 2006-01-15 04:51:17 UTC (rev 2099) @@ -38,7 +38,7 @@ { SimpleGrammar g = new SimpleGrammar( ); g.addToDictionary( "A", - "${all-left}.getSomething()" ); + "${left}.getSomething()" ); assertEquals( "A", g.listNaturalItems( )[0] ); @@ -52,5 +52,18 @@ assertEquals(0, g.listNaturalItems().length); } + public void testConfigParams() { + SimpleGrammar g = new SimpleGrammar( ); + g.addToDictionary( "A", + "${left}.getSomething()" ); + assertFalse(g.ignoreUnknownTokens()); + g.addToDictionary(NaturalGrammar.IGNORE_UNKNOWN_TOKENS, "true"); + assertTrue(g.ignoreUnknownTokens()); + + assertFalse(g.delimitersRequired()); + g.addToDictionary(NaturalGrammar.REQUIRE_DELIMITERS, "true"); + assertTrue(g.delimitersRequired()); + } + } Modified: trunk/labs/jbossrules/drools-natural-dsl/src/test/java/org/drools/natural/lexer/GrammarAwareLexerTest.java =================================================================== --- trunk/labs/jbossrules/drools-natural-dsl/src/test/java/org/drools/natural/lexer/GrammarAwareLexerTest.java 2006-01-14 17:28:55 UTC (rev 2098) +++ trunk/labs/jbossrules/drools-natural-dsl/src/test/java/org/drools/natural/lexer/GrammarAwareLexerTest.java 2006-01-15 04:51:17 UTC (rev 2099) @@ -77,6 +77,14 @@ { return items; } + + public boolean ignoreUnknownTokens() { + return false; + } + + public boolean delimitersRequired() { + return false; + } } |