changeset 1459:b04b8fc5f4f4

GoodQueryParser
author Franklin Schmidt <fschmidt@gmail.com>
date Fri, 20 Mar 2020 11:06:53 -0600
parents 6b6c11c9164e
children 3ab0d043370f
files src/goodjava/lucene/queryparser/FieldParser.java src/goodjava/lucene/queryparser/GoodQueryParser.java src/goodjava/lucene/queryparser/MultiFieldParser.java src/goodjava/lucene/queryparser/NumberFieldParser.java src/goodjava/lucene/queryparser/SaneQueryParser.java src/goodjava/lucene/queryparser/StringFieldParser.java src/goodjava/lucene/queryparser/SynonymParser.java src/luan/modules/lucene/Lucene.luan src/luan/modules/lucene/LuceneIndex.java
diffstat 9 files changed, 340 insertions(+), 340 deletions(-) [+]
line wrap: on
line diff
--- a/src/goodjava/lucene/queryparser/FieldParser.java	Fri Mar 20 10:58:53 2020 -0600
+++ b/src/goodjava/lucene/queryparser/FieldParser.java	Fri Mar 20 11:06:53 2020 -0600
@@ -6,7 +6,7 @@
 
 
 public interface FieldParser {
-	public Query getQuery(SaneQueryParser qp,String field,String query) throws ParseException;
-	public Query getRangeQuery(SaneQueryParser qp,String field,String minQuery,String maxQuery,boolean includeMin,boolean includeMax) throws ParseException;
-	public SortField getSortField(SaneQueryParser qp,String field,boolean reverse) throws ParseException;
+	public Query getQuery(GoodQueryParser qp,String field,String query) throws ParseException;
+	public Query getRangeQuery(GoodQueryParser qp,String field,String minQuery,String maxQuery,boolean includeMin,boolean includeMax) throws ParseException;
+	public SortField getSortField(GoodQueryParser qp,String field,boolean reverse) throws ParseException;
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/goodjava/lucene/queryparser/GoodQueryParser.java	Fri Mar 20 11:06:53 2020 -0600
@@ -0,0 +1,316 @@
+package goodjava.lucene.queryparser;
+
+import java.util.List;
+import java.util.ArrayList;
+import java.util.regex.Pattern;
+import org.apache.lucene.search.Query;
+import org.apache.lucene.search.MatchAllDocsQuery;
+import org.apache.lucene.search.BooleanClause;
+import org.apache.lucene.search.BooleanQuery;
+import org.apache.lucene.search.Sort;
+import org.apache.lucene.search.SortField;
+import goodjava.parser.Parser;
+import goodjava.parser.ParseException;
+
+
+public class GoodQueryParser {
+
+	public static Query parseQuery(FieldParser fieldParser,String query) throws ParseException {
+		return new GoodQueryParser(fieldParser,query).parseQuery();
+	}
+
+	public static String quote(String s) {
+		s = s.replace("\\","\\\\");
+		s = s.replace("\b","\\b");
+		s = s.replace("\f","\\f");
+		s = s.replace("\n","\\n");
+		s = s.replace("\r","\\r");
+		s = s.replace("\t","\\t");
+		s = s.replace("\"","\\\"");
+		return "\""+s+"\"";
+	}
+
+	public static Sort parseSort(FieldParser fieldParser,String sort) throws ParseException {
+		return new GoodQueryParser(fieldParser,sort).parseSort();
+	}
+
+
+	private static final String NOT_IN_RANGE = " \t\r\n\":[]{}^+()";
+	private static final String NOT_IN_TERM = NOT_IN_RANGE + "-";
+	private static final String NOT_IN_FIELD = NOT_IN_TERM + ",";
+	private final FieldParser fieldParser;
+	private final Parser parser;
+
+	private GoodQueryParser(FieldParser fieldParser,String query) {
+		this.fieldParser = fieldParser;
+		this.parser = new Parser(query);
+		parser.begin();
+	}
+
+	ParseException exception(String msg) {
+		parser.failure();
+		return new ParseException(parser,msg);
+	}
+
+	ParseException exception(Exception cause) {
+		parser.failure();
+		return new ParseException(parser,cause);
+	}
+
+	private Query parseQuery() throws ParseException {
+		Spaces();
+		BooleanQuery bq = new BooleanQuery();
+		while( !parser.endOfInput() ) {
+			bq.add( Term(null) );
+		}
+		BooleanClause[] clauses = bq.getClauses();
+		switch( clauses.length ) {
+		case 0:
+			return new MatchAllDocsQuery();
+		case 1:
+			{
+				BooleanClause bc = clauses[0];
+				if( bc.getOccur() != BooleanClause.Occur.MUST_NOT )
+					return bc.getQuery();
+			}
+		default:
+			return bq;
+		}
+	}
+
+	private BooleanClause Term(String defaultField) throws ParseException {
+		BooleanClause.Occur occur;
+		if( parser.match('+') ) {
+			occur = BooleanClause.Occur.MUST;
+			Spaces();
+		} else if( parser.match('-') ) {
+			occur = BooleanClause.Occur.MUST_NOT;
+			Spaces();
+		} else {
+			occur = BooleanClause.Occur.SHOULD;
+		}
+		String field = QueryField();
+		if( field == null )
+			field = defaultField;
+		Query query = NestedTerm(field);
+		if( query == null )
+			query = RangeTerm(field);
+		if( query == null ) {
+			parser.begin();
+			String match = SimpleTerm(NOT_IN_TERM);
+			query = fieldParser.getQuery(this,field,match);
+			parser.success();
+		}
+		if( parser.match('^') ) {
+			Spaces();
+			int start = parser.begin();
+			try {
+				while( parser.anyOf("0123456789.") );
+				String match = parser.textFrom(start);
+				float boost = Float.parseFloat(match);
+				query.setBoost(boost);
+			} catch(NumberFormatException e) {
+				throw exception(e);
+			}
+			parser.success();
+			Spaces();
+		}
+		BooleanClause bc = new BooleanClause(query,occur);
+		return bc;
+	}
+
+	private Query NestedTerm(String field) throws ParseException {
+		parser.begin();
+		if( !parser.match('(') )
+			return parser.failure(null);
+		BooleanQuery bq = new BooleanQuery();
+		while( !parser.match(')') ) {
+			if( parser.endOfInput() )
+				throw exception("unclosed parentheses");
+			bq.add( Term(field) );
+		}
+		Spaces();
+		BooleanClause[] clauses = bq.getClauses();
+		switch( clauses.length ) {
+		case 0:
+			throw exception("empty parentheses");
+		case 1:
+			{
+				BooleanClause bc = clauses[0];
+				if( bc.getOccur() != BooleanClause.Occur.MUST_NOT )
+					return parser.success(bc.getQuery());
+			}
+		default:
+			return parser.success(bq);
+		}
+	}
+
+	private Query RangeTerm(String field) throws ParseException {
+		parser.begin();
+		if( !parser.anyOf("[{") )
+			return parser.failure(null);
+		boolean includeMin = parser.lastChar() == '[';
+		Spaces();
+		String minQuery = SimpleTerm(NOT_IN_RANGE);
+		TO();
+		String maxQuery = SimpleTerm(NOT_IN_RANGE);
+		if( !parser.anyOf("]}") )
+			throw exception("unclosed range");
+		boolean includeMax = parser.lastChar() == ']';
+		Spaces();
+		Query query = fieldParser.getRangeQuery(this,field,minQuery,maxQuery,includeMin,includeMax);
+		return parser.success(query);
+	}
+
+	private void TO() throws ParseException {
+		parser.begin();
+		if( !(parser.match("TO") && Space()) )
+			throw exception("'TO' expected");
+		Spaces();
+		parser.success();
+	}
+
+	private String SimpleTerm(String exclude) throws ParseException {
+		parser.begin();
+		String match = Quoted();
+		if( match==null )
+			match = Unquoted(exclude);
+		if( match.length() == 0 )
+			throw exception("invalid input");
+		return parser.success(match);
+	}
+
+	private String QueryField() throws ParseException {
+		parser.begin();
+		String match = Field();
+		if( match==null || !parser.match(':') )
+			return parser.failure((String)null);
+		Spaces();
+		return parser.success(match);
+	}
+
+	private String Field() throws ParseException {
+		parser.begin();
+		String match = Unquoted(NOT_IN_FIELD);
+		if( match.length()==0 )
+			return parser.failure((String)null);
+		match = StringFieldParser.escape(this,match);
+		return parser.success(match);
+	}
+
+	private String Quoted() throws ParseException {
+		parser.begin();
+		if( !parser.match('"') )
+			return parser.failure(null);
+		StringBuilder sb = new StringBuilder();
+		while( parser.anyChar() ) {
+			char c = parser.lastChar();
+			switch(c) {
+			case '"':
+				return parser.success(sb.toString());
+			case '\\':
+				if( parser.anyChar() ) {
+					c = parser.lastChar();
+					switch(c) {
+					case '"':
+					case '\\':
+						sb.append(c);
+						continue;
+					case 'b':
+						sb.append('\b');
+						continue;
+					case 'f':
+						sb.append('\f');
+						continue;
+					case 'n':
+						sb.append('\n');
+						continue;
+					case 'r':
+						sb.append('\r');
+						continue;
+					case 't':
+						sb.append('\t');
+						continue;
+					case 'u':
+						int n = 0;
+						for( int i=0; i<4; i++ ) {
+							int d;
+							if( parser.inCharRange('0','9') ) {
+								d = parser.lastChar() - '0';
+							} else if( parser.inCharRange('a','f') ) {
+								d = parser.lastChar() - 'a' + 10;
+							} else if( parser.inCharRange('A','F') ) {
+								d = parser.lastChar() - 'A' + 10;
+							} else {
+								throw exception("invalid hex digit");
+							}
+							n = 16*n + d;
+						}
+						sb.append((char)n);
+						continue;
+					}
+				}
+				throw exception("invalid escape char");
+			default:
+				sb.append(c);
+			}
+		}
+		parser.failure();
+		throw exception("unclosed string");
+	}
+
+	private String Unquoted(String exclude) throws ParseException {
+		int start = parser.begin();
+		while( parser.noneOf(exclude) ) {
+			checkEscape();
+		}
+		String match = parser.textFrom(start);
+		Spaces();
+		return parser.success(match);
+	}
+
+	private void checkEscape() {
+		if( parser.lastChar() == '\\' )
+			parser.anyChar();
+	}
+
+	private void Spaces() {
+		while( Space() );
+	}
+
+	private boolean Space() {
+		return parser.anyOf(" \t\r\n");
+	}
+
+
+	// sort
+
+	private Sort parseSort() throws ParseException {
+		Spaces();
+		if( parser.endOfInput() )
+			return null;
+		List<SortField> list = new ArrayList<SortField>();
+		list.add( SortField() );
+		while( !parser.endOfInput() ) {
+			parser.begin();
+			if( !parser.match(',') )
+				throw exception("',' expected");
+			Spaces();
+			parser.success();
+			list.add( SortField() );
+		}
+		return new Sort(list.toArray(new SortField[0]));
+	}
+
+	private SortField SortField() throws ParseException {
+		parser.begin();
+		String field = Field();
+		if( field==null )
+			throw exception("invalid input");
+		boolean reverse = !parser.matchIgnoreCase("asc") && parser.matchIgnoreCase("desc");
+		Spaces();
+		SortField sf = fieldParser.getSortField(this,field,reverse);
+		return parser.success(sf);
+	}
+
+}
--- a/src/goodjava/lucene/queryparser/MultiFieldParser.java	Fri Mar 20 10:58:53 2020 -0600
+++ b/src/goodjava/lucene/queryparser/MultiFieldParser.java	Fri Mar 20 11:06:53 2020 -0600
@@ -32,7 +32,7 @@
 		}
 	}
 
-	@Override public Query getQuery(SaneQueryParser qp,String field,String query) throws ParseException {
+	@Override public Query getQuery(GoodQueryParser qp,String field,String query) throws ParseException {
 		if( field == null ) {
 			if( defaultFieldParser == null )
 				throw qp.exception("no defaults were specified, so a field is required");
@@ -53,7 +53,7 @@
 		}
 	}
 
-	@Override public Query getRangeQuery(SaneQueryParser qp,String field,String minQuery,String maxQuery,boolean includeMin,boolean includeMax) throws ParseException {
+	@Override public Query getRangeQuery(GoodQueryParser qp,String field,String minQuery,String maxQuery,boolean includeMin,boolean includeMax) throws ParseException {
 		if( field == null ) {
 			if( defaultFieldParser == null )
 				throw qp.exception("no defaults were specified, so a field is required");
@@ -74,7 +74,7 @@
 		}
 	}
 
-	@Override public SortField getSortField(SaneQueryParser qp,String field,boolean reverse) throws ParseException {
+	@Override public SortField getSortField(GoodQueryParser qp,String field,boolean reverse) throws ParseException {
 		FieldParser fp = fields.get(field);
 		if( fp != null )
 			return fp.getSortField(qp,field,reverse);
--- a/src/goodjava/lucene/queryparser/NumberFieldParser.java	Fri Mar 20 10:58:53 2020 -0600
+++ b/src/goodjava/lucene/queryparser/NumberFieldParser.java	Fri Mar 20 11:06:53 2020 -0600
@@ -10,13 +10,13 @@
 
 public abstract class NumberFieldParser implements FieldParser {
 
-	@Override public final Query getQuery(SaneQueryParser qp,String field,String query) throws ParseException {
+	@Override public final Query getQuery(GoodQueryParser qp,String field,String query) throws ParseException {
 		if( query.equals("*") )
 			return new PrefixQuery(new Term(field,""));
 		return getRangeQuery(qp,field,query,query,true,true);
 	}
 
-	@Override public final Query getRangeQuery(SaneQueryParser qp,String field,String minQuery,String maxQuery,boolean includeMin,boolean includeMax) throws ParseException {
+	@Override public final Query getRangeQuery(GoodQueryParser qp,String field,String minQuery,String maxQuery,boolean includeMin,boolean includeMax) throws ParseException {
 		try {
 			return getRangeQuery(field,minQuery,maxQuery,includeMin,includeMax);
 		} catch(NumberFormatException e) {
@@ -26,7 +26,7 @@
 
 	abstract protected Query getRangeQuery(String field,String minQuery,String maxQuery,boolean includeMin,boolean includeMax);
 
-	@Override public SortField getSortField(SaneQueryParser qp,String field,boolean reverse) {
+	@Override public SortField getSortField(GoodQueryParser qp,String field,boolean reverse) {
 		return new SortField( field, sortType(), reverse );
 	}
 
--- a/src/goodjava/lucene/queryparser/SaneQueryParser.java	Fri Mar 20 10:58:53 2020 -0600
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,316 +0,0 @@
-package goodjava.lucene.queryparser;
-
-import java.util.List;
-import java.util.ArrayList;
-import java.util.regex.Pattern;
-import org.apache.lucene.search.Query;
-import org.apache.lucene.search.MatchAllDocsQuery;
-import org.apache.lucene.search.BooleanClause;
-import org.apache.lucene.search.BooleanQuery;
-import org.apache.lucene.search.Sort;
-import org.apache.lucene.search.SortField;
-import goodjava.parser.Parser;
-import goodjava.parser.ParseException;
-
-
-public class SaneQueryParser {
-
-	public static Query parseQuery(FieldParser fieldParser,String query) throws ParseException {
-		return new SaneQueryParser(fieldParser,query).parseQuery();
-	}
-
-	public static String quote(String s) {
-		s = s.replace("\\","\\\\");
-		s = s.replace("\b","\\b");
-		s = s.replace("\f","\\f");
-		s = s.replace("\n","\\n");
-		s = s.replace("\r","\\r");
-		s = s.replace("\t","\\t");
-		s = s.replace("\"","\\\"");
-		return "\""+s+"\"";
-	}
-
-	public static Sort parseSort(FieldParser fieldParser,String sort) throws ParseException {
-		return new SaneQueryParser(fieldParser,sort).parseSort();
-	}
-
-
-	private static final String NOT_IN_RANGE = " \t\r\n\":[]{}^+()";
-	private static final String NOT_IN_TERM = NOT_IN_RANGE + "-";
-	private static final String NOT_IN_FIELD = NOT_IN_TERM + ",";
-	private final FieldParser fieldParser;
-	private final Parser parser;
-
-	private SaneQueryParser(FieldParser fieldParser,String query) {
-		this.fieldParser = fieldParser;
-		this.parser = new Parser(query);
-		parser.begin();
-	}
-
-	ParseException exception(String msg) {
-		parser.failure();
-		return new ParseException(parser,msg);
-	}
-
-	ParseException exception(Exception cause) {
-		parser.failure();
-		return new ParseException(parser,cause);
-	}
-
-	private Query parseQuery() throws ParseException {
-		Spaces();
-		BooleanQuery bq = new BooleanQuery();
-		while( !parser.endOfInput() ) {
-			bq.add( Term(null) );
-		}
-		BooleanClause[] clauses = bq.getClauses();
-		switch( clauses.length ) {
-		case 0:
-			return new MatchAllDocsQuery();
-		case 1:
-			{
-				BooleanClause bc = clauses[0];
-				if( bc.getOccur() != BooleanClause.Occur.MUST_NOT )
-					return bc.getQuery();
-			}
-		default:
-			return bq;
-		}
-	}
-
-	private BooleanClause Term(String defaultField) throws ParseException {
-		BooleanClause.Occur occur;
-		if( parser.match('+') ) {
-			occur = BooleanClause.Occur.MUST;
-			Spaces();
-		} else if( parser.match('-') ) {
-			occur = BooleanClause.Occur.MUST_NOT;
-			Spaces();
-		} else {
-			occur = BooleanClause.Occur.SHOULD;
-		}
-		String field = QueryField();
-		if( field == null )
-			field = defaultField;
-		Query query = NestedTerm(field);
-		if( query == null )
-			query = RangeTerm(field);
-		if( query == null ) {
-			parser.begin();
-			String match = SimpleTerm(NOT_IN_TERM);
-			query = fieldParser.getQuery(this,field,match);
-			parser.success();
-		}
-		if( parser.match('^') ) {
-			Spaces();
-			int start = parser.begin();
-			try {
-				while( parser.anyOf("0123456789.") );
-				String match = parser.textFrom(start);
-				float boost = Float.parseFloat(match);
-				query.setBoost(boost);
-			} catch(NumberFormatException e) {
-				throw exception(e);
-			}
-			parser.success();
-			Spaces();
-		}
-		BooleanClause bc = new BooleanClause(query,occur);
-		return bc;
-	}
-
-	private Query NestedTerm(String field) throws ParseException {
-		parser.begin();
-		if( !parser.match('(') )
-			return parser.failure(null);
-		BooleanQuery bq = new BooleanQuery();
-		while( !parser.match(')') ) {
-			if( parser.endOfInput() )
-				throw exception("unclosed parentheses");
-			bq.add( Term(field) );
-		}
-		Spaces();
-		BooleanClause[] clauses = bq.getClauses();
-		switch( clauses.length ) {
-		case 0:
-			throw exception("empty parentheses");
-		case 1:
-			{
-				BooleanClause bc = clauses[0];
-				if( bc.getOccur() != BooleanClause.Occur.MUST_NOT )
-					return parser.success(bc.getQuery());
-			}
-		default:
-			return parser.success(bq);
-		}
-	}
-
-	private Query RangeTerm(String field) throws ParseException {
-		parser.begin();
-		if( !parser.anyOf("[{") )
-			return parser.failure(null);
-		boolean includeMin = parser.lastChar() == '[';
-		Spaces();
-		String minQuery = SimpleTerm(NOT_IN_RANGE);
-		TO();
-		String maxQuery = SimpleTerm(NOT_IN_RANGE);
-		if( !parser.anyOf("]}") )
-			throw exception("unclosed range");
-		boolean includeMax = parser.lastChar() == ']';
-		Spaces();
-		Query query = fieldParser.getRangeQuery(this,field,minQuery,maxQuery,includeMin,includeMax);
-		return parser.success(query);
-	}
-
-	private void TO() throws ParseException {
-		parser.begin();
-		if( !(parser.match("TO") && Space()) )
-			throw exception("'TO' expected");
-		Spaces();
-		parser.success();
-	}
-
-	private String SimpleTerm(String exclude) throws ParseException {
-		parser.begin();
-		String match = Quoted();
-		if( match==null )
-			match = Unquoted(exclude);
-		if( match.length() == 0 )
-			throw exception("invalid input");
-		return parser.success(match);
-	}
-
-	private String QueryField() throws ParseException {
-		parser.begin();
-		String match = Field();
-		if( match==null || !parser.match(':') )
-			return parser.failure((String)null);
-		Spaces();
-		return parser.success(match);
-	}
-
-	private String Field() throws ParseException {
-		parser.begin();
-		String match = Unquoted(NOT_IN_FIELD);
-		if( match.length()==0 )
-			return parser.failure((String)null);
-		match = StringFieldParser.escape(this,match);
-		return parser.success(match);
-	}
-
-	private String Quoted() throws ParseException {
-		parser.begin();
-		if( !parser.match('"') )
-			return parser.failure(null);
-		StringBuilder sb = new StringBuilder();
-		while( parser.anyChar() ) {
-			char c = parser.lastChar();
-			switch(c) {
-			case '"':
-				return parser.success(sb.toString());
-			case '\\':
-				if( parser.anyChar() ) {
-					c = parser.lastChar();
-					switch(c) {
-					case '"':
-					case '\\':
-						sb.append(c);
-						continue;
-					case 'b':
-						sb.append('\b');
-						continue;
-					case 'f':
-						sb.append('\f');
-						continue;
-					case 'n':
-						sb.append('\n');
-						continue;
-					case 'r':
-						sb.append('\r');
-						continue;
-					case 't':
-						sb.append('\t');
-						continue;
-					case 'u':
-						int n = 0;
-						for( int i=0; i<4; i++ ) {
-							int d;
-							if( parser.inCharRange('0','9') ) {
-								d = parser.lastChar() - '0';
-							} else if( parser.inCharRange('a','f') ) {
-								d = parser.lastChar() - 'a' + 10;
-							} else if( parser.inCharRange('A','F') ) {
-								d = parser.lastChar() - 'A' + 10;
-							} else {
-								throw exception("invalid hex digit");
-							}
-							n = 16*n + d;
-						}
-						sb.append((char)n);
-						continue;
-					}
-				}
-				throw exception("invalid escape char");
-			default:
-				sb.append(c);
-			}
-		}
-		parser.failure();
-		throw exception("unclosed string");
-	}
-
-	private String Unquoted(String exclude) throws ParseException {
-		int start = parser.begin();
-		while( parser.noneOf(exclude) ) {
-			checkEscape();
-		}
-		String match = parser.textFrom(start);
-		Spaces();
-		return parser.success(match);
-	}
-
-	private void checkEscape() {
-		if( parser.lastChar() == '\\' )
-			parser.anyChar();
-	}
-
-	private void Spaces() {
-		while( Space() );
-	}
-
-	private boolean Space() {
-		return parser.anyOf(" \t\r\n");
-	}
-
-
-	// sort
-
-	private Sort parseSort() throws ParseException {
-		Spaces();
-		if( parser.endOfInput() )
-			return null;
-		List<SortField> list = new ArrayList<SortField>();
-		list.add( SortField() );
-		while( !parser.endOfInput() ) {
-			parser.begin();
-			if( !parser.match(',') )
-				throw exception("',' expected");
-			Spaces();
-			parser.success();
-			list.add( SortField() );
-		}
-		return new Sort(list.toArray(new SortField[0]));
-	}
-
-	private SortField SortField() throws ParseException {
-		parser.begin();
-		String field = Field();
-		if( field==null )
-			throw exception("invalid input");
-		boolean reverse = !parser.matchIgnoreCase("asc") && parser.matchIgnoreCase("desc");
-		Spaces();
-		SortField sf = fieldParser.getSortField(this,field,reverse);
-		return parser.success(sf);
-	}
-
-}
--- a/src/goodjava/lucene/queryparser/StringFieldParser.java	Fri Mar 20 10:58:53 2020 -0600
+++ b/src/goodjava/lucene/queryparser/StringFieldParser.java	Fri Mar 20 11:06:53 2020 -0600
@@ -25,7 +25,7 @@
 		this.analyzer = analyzer;
 	}
 
-	@Override public Query getQuery(SaneQueryParser qp,String field,String query) throws ParseException {
+	@Override public Query getQuery(GoodQueryParser qp,String field,String query) throws ParseException {
 		String wildcard = wildcard(qp,query);
 		if( wildcard != null )
 			return new WildcardQuery(new Term(field,wildcard));
@@ -54,13 +54,13 @@
 		return pq;
 	}
 
-	@Override public Query getRangeQuery(SaneQueryParser qp,String field,String minQuery,String maxQuery,boolean includeMin,boolean includeMax) throws ParseException {
+	@Override public Query getRangeQuery(GoodQueryParser qp,String field,String minQuery,String maxQuery,boolean includeMin,boolean includeMax) throws ParseException {
 		minQuery = minQuery.equals("*") ? null : escape(qp,minQuery);
 		maxQuery = maxQuery.equals("*") ? null : escape(qp,maxQuery);
 		return TermRangeQuery.newStringRange(field,minQuery,maxQuery,includeMin,includeMax);
 	}
 
-	static String escape(SaneQueryParser qp,String s) throws ParseException {
+	static String escape(GoodQueryParser qp,String s) throws ParseException {
 		final char[] a = s.toCharArray();
 		int i, n;
 		if( a[0] == '"' ) {
@@ -84,7 +84,7 @@
 		return sb.toString();
 	}
 
-	private static String wildcard(SaneQueryParser qp,String s) throws ParseException {
+	private static String wildcard(GoodQueryParser qp,String s) throws ParseException {
 		final char[] a = s.toCharArray();
 		if( a[0] == '"' )
 			return null;
@@ -106,7 +106,7 @@
 		return hasWildcard ? sb.toString() : null;
 	}
 
-	@Override public SortField getSortField(SaneQueryParser qp,String field,boolean reverse) {
+	@Override public SortField getSortField(GoodQueryParser qp,String field,boolean reverse) {
 		return new SortField( field, SortField.Type.STRING, reverse );
 	}
 
--- a/src/goodjava/lucene/queryparser/SynonymParser.java	Fri Mar 20 10:58:53 2020 -0600
+++ b/src/goodjava/lucene/queryparser/SynonymParser.java	Fri Mar 20 11:06:53 2020 -0600
@@ -21,7 +21,7 @@
 		return synonymMap.get(query);
 	}
 
-	public Query getQuery(SaneQueryParser qp,String field,String query) throws ParseException {
+	public Query getQuery(GoodQueryParser qp,String field,String query) throws ParseException {
 		String[] synonyms = getSynonyms(query);
 		if( synonyms == null )
 			return fp.getQuery(qp,field,query);
@@ -33,11 +33,11 @@
 		return bq;
 	}
 
-	public Query getRangeQuery(SaneQueryParser qp,String field,String minQuery,String maxQuery,boolean includeMin,boolean includeMax) throws ParseException {
+	public Query getRangeQuery(GoodQueryParser qp,String field,String minQuery,String maxQuery,boolean includeMin,boolean includeMax) throws ParseException {
 		return fp.getRangeQuery(qp,field,minQuery,maxQuery,includeMin,includeMax);
 	}
 
-	public SortField getSortField(SaneQueryParser qp,String field,boolean reverse) throws ParseException {
+	public SortField getSortField(GoodQueryParser qp,String field,boolean reverse) throws ParseException {
 		return fp.getSortField(qp,field,reverse);
 	}
 }
--- a/src/luan/modules/lucene/Lucene.luan	Fri Mar 20 10:58:53 2020 -0600
+++ b/src/luan/modules/lucene/Lucene.luan	Fri Mar 20 11:06:53 2020 -0600
@@ -16,7 +16,7 @@
 local Rpc = require "luan:Rpc.luan"
 local LuceneIndex = require "java:luan.modules.lucene.LuceneIndex"
 local NumberFieldParser = require "java:goodjava.lucene.queryparser.NumberFieldParser"
-local SaneQueryParser = require "java:goodjava.lucene.queryparser.SaneQueryParser"
+local GoodQueryParser = require "java:goodjava.lucene.queryparser.GoodQueryParser"
 local Logging = require "luan:logging/Logging.luan"
 local logger = Logging.logger "Lucene"
 
@@ -31,7 +31,7 @@
 	double = NumberFieldParser.DOUBLE
 }
 
-Lucene.quote = SaneQueryParser.quote
+Lucene.quote = GoodQueryParser.quote
 
 function Lucene.index(index_dir,options)
 	type(index_dir)=="table" or error "index_dir must be table"
--- a/src/luan/modules/lucene/LuceneIndex.java	Fri Mar 20 10:58:53 2020 -0600
+++ b/src/luan/modules/lucene/LuceneIndex.java	Fri Mar 20 11:06:53 2020 -0600
@@ -68,7 +68,7 @@
 import org.apache.lucene.search.highlight.SimpleSpanFragmenter;
 import org.apache.lucene.search.highlight.QueryScorer;
 import org.apache.lucene.search.highlight.TokenGroup;
-import goodjava.lucene.queryparser.SaneQueryParser;
+import goodjava.lucene.queryparser.GoodQueryParser;
 import goodjava.lucene.queryparser.FieldParser;
 import goodjava.lucene.queryparser.MultiFieldParser;
 import goodjava.lucene.queryparser.StringFieldParser;
@@ -247,7 +247,7 @@
 	public void delete(String queryStr)
 		throws IOException, ParseException, SQLException, LuanException
 	{
-		Query query = SaneQueryParser.parseQuery(mfp,queryStr);
+		Query query = GoodQueryParser.parseQuery(mfp,queryStr);
 
 		boolean commit = !writeLock.isHeldByCurrentThread();
 		writeLock.lock();
@@ -511,7 +511,7 @@
 		throws LuanException, IOException, ParseException
 	{
 		Utils.checkNotNull(queryStr);
-		Query query = SaneQueryParser.parseQuery(mfp,queryStr);
+		Query query = GoodQueryParser.parseQuery(mfp,queryStr);
 		IndexSearcher searcher = threadLocalSearcher.get();
 		boolean inTransaction = searcher != null;
 		if( !inTransaction )
@@ -543,7 +543,7 @@
 				searcher.search(query,thcc);
 				return thcc.getTotalHits();
 			}
-			Sort sort = sortStr==null ? null : SaneQueryParser.parseSort(mfp,sortStr);
+			Sort sort = sortStr==null ? null : GoodQueryParser.parseSort(mfp,sortStr);
 			TopDocs td = sort==null ? searcher.search(query,n) : searcher.search(query,n,sort);
 			final ScoreDoc[] scoreDocs = td.scoreDocs;
 			DocFn docFn = new DocFn(fn.luan(),searcher,query);
@@ -729,7 +729,7 @@
 	public LuanFunction highlighter(String queryStr,final LuanFunction formatter,final Integer fragmentSize,String dotdotdot)
 		throws ParseException
 	{
-		Query query = SaneQueryParser.parseQuery(mfp,queryStr);
+		Query query = GoodQueryParser.parseQuery(mfp,queryStr);
 		Formatter fmt = new Formatter() {
 			public String highlightTerm(String originalText,TokenGroup tokenGroup) {
 				if( tokenGroup.getTotalScore() <= 0 )