Changeset 2645 in josm for trunk/src/org/openstreetmap/josm/actions
- Timestamp:
- 2009-12-16T21:27:28+01:00 (14 years ago)
- Location:
- trunk/src/org/openstreetmap/josm/actions/search
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/org/openstreetmap/josm/actions/search/PushbackTokenizer.java
r1641 r2645 3 3 4 4 import java.io.IOException; 5 import java.io.PushbackReader; 6 import java.util.LinkedList; 5 import java.io.Reader; 6 7 import org.openstreetmap.josm.actions.search.SearchCompiler.ParseError; 7 8 8 9 public class PushbackTokenizer { 9 private PushbackReader search;10 private final Reader search; 10 11 11 private LinkedList<String> pushBackBuf = new LinkedList<String>(); 12 private Token currentToken; 13 private String currentText; 14 private int c; 12 15 13 public PushbackTokenizer( PushbackReader search) {16 public PushbackTokenizer(Reader search) { 14 17 this.search = search; 18 getChar(); 19 } 20 21 public enum Token {NOT, OR, LEFT_PARENT, RIGHT_PARENT, COLON, EQUALS, KEY, EOF} 22 23 private void getChar() { 24 try { 25 c = search.read(); 26 } catch (IOException e) { 27 throw new RuntimeException(e.getMessage(), e); 28 } 15 29 } 16 30 … … 23 37 * @return The next token in the stream. 24 38 */ 25 public String nextToken() { 26 if (!pushBackBuf.isEmpty()) { 27 return pushBackBuf.removeLast(); 39 public Token nextToken() { 40 if (currentToken != null) { 41 Token result = currentToken; 42 currentToken = null; 43 return result; 28 44 } 29 45 30 try { 31 int next; 32 char c = ' '; 33 while (c == ' ' || c == '\t' || c == '\n') { 34 next = search.read(); 35 if (next == -1) 36 return null; 37 c = (char)next; 46 while (Character.isWhitespace(c)) { 47 getChar(); 48 } 49 switch (c) { 50 case -1: 51 getChar(); 52 return Token.EOF; 53 case ':': 54 getChar(); 55 return Token.COLON; 56 case '=': 57 getChar(); 58 return Token.EQUALS; 59 case '-': 60 getChar(); 61 return Token.NOT; 62 case '(': 63 getChar(); 64 return Token.LEFT_PARENT; 65 case ')': 66 getChar(); 67 return Token.RIGHT_PARENT; 68 case '|': 69 getChar(); 70 return Token.OR; 71 case '"': 72 { 73 StringBuilder s = new StringBuilder(); 74 while (c != -1 && c != '"') { 75 s.append((char)c); 76 getChar(); 38 77 } 39 StringBuilder s; 40 switch (c) { 41 case ':': 42 case '=': 43 next = search.read(); 44 if (next == -1 || next == ' ' || next == '\t') { 45 pushBack(" "); 46 } else { 47 search.unread(next); 48 } 49 return String.valueOf(c); 50 case '-': 51 return "-"; 52 case '(': 53 return "("; 54 case ')': 55 return ")"; 56 case '|': 57 return "|"; 58 case '"': 59 s = new StringBuilder(" "); 60 for (int nc = search.read(); nc != -1 && nc != '"'; nc = search.read()) 61 s.append((char)nc); 62 return s.toString(); 63 default: 64 s = new StringBuilder(); 65 for (;;) { 66 s.append(c); 67 next = search.read(); 68 if (next == -1) { 69 if (s.toString().equals("OR")) 70 return "|"; 71 return " "+s.toString(); 72 } 73 c = (char)next; 74 if (c == ' ' || c == '\t' || c == '"' || c == ':' || c == '(' || c == ')' || c == '|' || c == '=') { 75 search.unread(next); 76 if (s.toString().equals("OR")) 77 return "|"; 78 return " "+s.toString(); 79 } 78 getChar(); 79 currentText = s.toString(); 80 return Token.KEY; 81 } 82 default: 83 { 84 StringBuilder s = new StringBuilder(); 85 while (!(c == -1 || Character.isWhitespace(c) || c == '"'|| c == ':' || c == '(' || c == ')' || c == '|' || c == '=')) { 86 s.append((char)c); 87 getChar(); 80 88 } 81 } 82 } catch (IOException e) { 83 throw new RuntimeException(e.getMessage(), e); 89 currentText = s.toString(); 90 if ("or".equals(currentText)) 91 return Token.OR; 92 else 93 return Token.KEY; 94 } 84 95 } 85 96 } 86 97 87 public boolean readIfEqual( String tok) {88 StringnextTok = nextToken();89 if (nextTok == null ? tok == null : nextTok.equals(tok))98 public boolean readIfEqual(Token token) { 99 Token nextTok = nextToken(); 100 if (nextTok == null ? token == null : nextTok == token) 90 101 return true; 91 pushBack(nextTok);102 currentToken = nextTok; 92 103 return false; 93 104 } 94 105 95 106 public String readText() { 96 StringnextTok = nextToken();97 if (nextTok != null && nextTok.startsWith(" "))98 return nextTok.substring(1);99 pushBack(nextTok);107 Token nextTok = nextToken(); 108 if (nextTok == Token.KEY) 109 return currentText; 110 currentToken = nextTok; 100 111 return null; 101 112 } 102 113 103 public void pushBack(String tok) { 104 pushBackBuf.addLast(tok); 114 public String readText(String errorMessage) throws ParseError { 115 String text = readText(); 116 if (text == null) 117 throw new ParseError(errorMessage); 118 else 119 return text; 120 } 121 122 public String getText() { 123 return currentText; 105 124 } 106 125 } -
trunk/src/org/openstreetmap/josm/actions/search/SearchCompiler.java
r2636 r2645 14 14 15 15 import org.openstreetmap.josm.Main; 16 import org.openstreetmap.josm.actions.search.PushbackTokenizer.Token; 16 17 import org.openstreetmap.josm.data.osm.Node; 17 18 import org.openstreetmap.josm.data.osm.OsmPrimitive; … … 23 24 24 25 /** 25 * Implements a google-like search. 26 * @author Imi 26 Implements a google-like search. 27 <br> 28 Grammar: 29 <pre> 30 expression = 31 fact | expression 32 fact expression 33 fact 34 35 fact = 36 ( expression ) 37 -fact 38 term=term 39 term:term 40 term 41 </pre> 42 43 @author Imi 27 44 */ 28 45 public class SearchCompiler { … … 184 201 } 185 202 186 p rivatestatic class ExactKeyValue extends Match {203 public static class ExactKeyValue extends Match { 187 204 188 205 private enum Mode { … … 201 218 throw new ParseError(tr("Key cannot be empty when tag operator is used. Sample use: key=value")); 202 219 this.key = key; 203 this.value = value ;220 this.value = value == null?"":value; 204 221 if ("".equals(value) && "*".equals(key)) { 205 222 mode = Mode.NONE; … … 527 544 } else if (osm instanceof Relation) { 528 545 for (RelationMember member : ((Relation)osm).getMembers()) { 529 if (member.getMember() != null) { 530 // TODO Nullable member will not be allowed 531 isParent |= child.match(member.getMember()); 532 } 546 isParent |= child.match(member.getMember()); 533 547 } 534 548 } … … 576 590 577 591 public Match parse() throws ParseError { 578 Match m = parse Juxta();579 if (!tokenizer.readIfEqual( null))592 Match m = parseExpression(); 593 if (!tokenizer.readIfEqual(Token.EOF)) 580 594 throw new ParseError(tr("Unexpected token: {0}", tokenizer.nextToken())); 581 595 return m; 582 596 } 583 597 584 private Match parseJuxta() throws ParseError { 585 Match juxta = new Always(); 586 587 Match m; 588 while ((m = parseOr()) != null) { 589 juxta = new And(m, juxta); 590 } 591 592 return juxta; 593 } 594 595 private Match parseOr() throws ParseError { 596 Match a = parseNot(); 597 if (tokenizer.readIfEqual("|")) { 598 Match b = parseNot(); 599 if (a == null || b == null) 600 throw new ParseError(tr("Missing arguments for or.")); 601 return new Or(a, b); 602 } 603 return a; 604 } 605 606 private Match parseNot() throws ParseError { 607 if (tokenizer.readIfEqual("-")) { 608 Match m = parseParens(); 609 if (m == null) 610 throw new ParseError(tr("Missing argument for not.")); 611 return new Not(m); 612 } 613 return parseParens(); 614 } 615 616 private Match parseParens() throws ParseError { 617 if (tokenizer.readIfEqual("(")) { 618 Match m = parseJuxta(); 619 if (!tokenizer.readIfEqual(")")) 620 throw new ParseError(tr("Expected closing parenthesis.")); 621 return m; 622 } 623 return parsePat(); 624 } 625 626 private Match parsePat() throws ParseError { 627 String tok = tokenizer.readText(); 628 629 if (tokenizer.readIfEqual(":")) { 630 String tok2 = tokenizer.readText(); 631 if (tok == null) { 632 tok = ""; 633 } 634 if (tok2 == null) { 635 tok2 = ""; 636 } 637 return parseKV(tok, tok2); 638 } 639 640 if (tokenizer.readIfEqual("=")) { 641 String tok2 = tokenizer.readText(); 642 if (tok == null) { 643 tok = ""; 644 } 645 if (tok2 == null) { 646 tok2 = ""; 647 } 648 return new ExactKeyValue(regexSearch, tok, tok2); 649 } 650 651 if (tok == null) 598 private Match parseExpression() throws ParseError { 599 Match factor = parseFactor(); 600 if (factor == null) 652 601 return null; 653 else if (tok.equals("modified")) 654 return new Modified(); 655 else if (tok.equals("incomplete")) 656 return new Incomplete(); 657 else if (tok.equals("untagged")) 658 return new Untagged(); 659 else if (tok.equals("selected")) 660 return new Selected(); 661 else if (tok.equals("child")) 662 return new Child(parseParens()); 663 else if (tok.equals("parent")) 664 return new Parent(parseParens()); 602 if (tokenizer.readIfEqual(Token.OR)) 603 return new Or(factor, parseExpression(tr("Missing parameter for OR"))); 604 else { 605 Match expression = parseExpression(); 606 if (expression == null) 607 return factor; 608 else 609 return new And(factor, expression); 610 } 611 } 612 613 private Match parseExpression(String errorMessage) throws ParseError { 614 Match expression = parseExpression(); 615 if (expression == null) 616 throw new ParseError(errorMessage); 665 617 else 666 return new Any(tok, regexSearch, caseSensitive); 667 } 618 return expression; 619 } 620 621 private Match parseFactor() throws ParseError { 622 if (tokenizer.readIfEqual(Token.LEFT_PARENT)) { 623 Match expression = parseExpression(); 624 if (!tokenizer.readIfEqual(Token.RIGHT_PARENT)) 625 throw new ParseError(tr("Missing right parent")); 626 return expression; 627 } else if (tokenizer.readIfEqual(Token.NOT)) 628 return new Not(parseFactor(tr("Missing operator for NOT"))); 629 else if (tokenizer.readIfEqual(Token.KEY)) { 630 String key = tokenizer.getText(); 631 if (tokenizer.readIfEqual(Token.EQUALS)) 632 return new ExactKeyValue(regexSearch, key, tokenizer.readText()); 633 else if (tokenizer.readIfEqual(Token.COLON)) 634 return parseKV(key, tokenizer.readText()); 635 else if ("modified".equals(key)) 636 return new Modified(); 637 else if ("incomplete".equals(key)) 638 return new Incomplete(); 639 else if ("untagged".equals(key)) 640 return new Untagged(); 641 else if ("selected".equals(key)) 642 return new Selected(); 643 else if ("child".equals(key)) 644 return new Child(parseFactor()); 645 else if ("parent".equals(key)) 646 return new Parent(parseFactor()); 647 else 648 return new Any(key, regexSearch, caseSensitive); 649 } else 650 return null; 651 } 652 653 private Match parseFactor(String errorMessage) throws ParseError { 654 Match fact = parseFactor(); 655 if (fact == null) 656 throw new ParseError(errorMessage); 657 else 658 return fact; 659 } 660 661 668 662 669 663 private Match parseKV(String key, String value) throws ParseError { 664 if (value == null) { 665 value = ""; 666 } 670 667 if (key.equals("type")) 671 668 return new ExactType(value);
Note:
See TracChangeset
for help on using the changeset viewer.