source: josm/trunk/src/org/openstreetmap/josm/tools/template_engine/TemplateParser.java@ 11241

Last change on this file since 11241 was 10378, checked in by Don-vip, 8 years ago

Checkstyle 6.19: enable SingleSpaceSeparator and fix violations

  • Property svn:eol-style set to native
File size: 5.2 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.tools.template_engine;
3
4import static org.openstreetmap.josm.tools.I18n.tr;
5
6import java.util.ArrayList;
7import java.util.Arrays;
8import java.util.Collection;
9import java.util.List;
10
11import org.openstreetmap.josm.actions.search.SearchCompiler;
12import org.openstreetmap.josm.actions.search.SearchCompiler.Match;
13import org.openstreetmap.josm.tools.template_engine.Tokenizer.Token;
14import org.openstreetmap.josm.tools.template_engine.Tokenizer.TokenType;
15
16/**
17 * Template parser.
18 */
19public class TemplateParser {
20 private final Tokenizer tokenizer;
21
22 private static final Collection<TokenType> EXPRESSION_END_TOKENS = Arrays.asList(TokenType.EOF);
23 private static final Collection<TokenType> CONDITION_WITH_APOSTROPHES_END_TOKENS = Arrays.asList(TokenType.APOSTROPHE);
24
25 /**
26 * Constructs a new {@code TemplateParser}.
27 * @param template template to parse
28 */
29 public TemplateParser(String template) {
30 this.tokenizer = new Tokenizer(template);
31 }
32
33 private Token check(TokenType expectedToken) throws ParseError {
34 Token token = tokenizer.nextToken();
35 if (token.getType() != expectedToken)
36 throw new ParseError(token, expectedToken);
37 else
38 return token;
39 }
40
41 /**
42 * Parse the template.
43 * @return the resulting template entry
44 * @throws ParseError if the template cannot be parsed
45 */
46 public TemplateEntry parse() throws ParseError {
47 return parseExpression(EXPRESSION_END_TOKENS);
48 }
49
50 private TemplateEntry parseExpression(Collection<TokenType> endTokens) throws ParseError {
51 List<TemplateEntry> entries = new ArrayList<>();
52 while (true) {
53 TemplateEntry templateEntry;
54 Token token = tokenizer.lookAhead();
55 if (token.getType() == TokenType.CONDITION_START) {
56 templateEntry = parseCondition();
57 } else if (token.getType() == TokenType.CONTEXT_SWITCH_START) {
58 templateEntry = parseContextSwitch();
59 } else if (token.getType() == TokenType.VARIABLE_START) {
60 templateEntry = parseVariable();
61 } else if (endTokens.contains(token.getType()))
62 return CompoundTemplateEntry.fromArray(entries.toArray(new TemplateEntry[entries.size()]));
63 else if (token.getType() == TokenType.TEXT) {
64 tokenizer.nextToken();
65 templateEntry = new StaticText(token.getText());
66 } else
67 throw new ParseError(token);
68 entries.add(templateEntry);
69 }
70 }
71
72 private TemplateEntry parseVariable() throws ParseError {
73 check(TokenType.VARIABLE_START);
74 String variableName = check(TokenType.TEXT).getText();
75 check(TokenType.END);
76
77 return new Variable(variableName);
78 }
79
80 private void skipWhitespace() throws ParseError {
81 Token token = tokenizer.lookAhead();
82 if (token.getType() == TokenType.TEXT && token.getText().trim().isEmpty()) {
83 tokenizer.nextToken();
84 }
85 }
86
87 private TemplateEntry parseCondition() throws ParseError {
88 check(TokenType.CONDITION_START);
89 Condition result = new Condition();
90 while (true) {
91
92 TemplateEntry condition;
93 Token searchExpression = tokenizer.skip('\'');
94 check(TokenType.APOSTROPHE);
95 condition = parseExpression(CONDITION_WITH_APOSTROPHES_END_TOKENS);
96 check(TokenType.APOSTROPHE);
97 if (searchExpression.getText().trim().isEmpty()) {
98 result.getEntries().add(condition);
99 } else {
100 try {
101 result.getEntries().add(new SearchExpressionCondition(
102 SearchCompiler.compile(searchExpression.getText()), condition));
103 } catch (SearchCompiler.ParseError e) {
104 throw new ParseError(searchExpression.getPosition(), e);
105 }
106 }
107 skipWhitespace();
108
109 Token token = tokenizer.lookAhead();
110 if (token.getType() == TokenType.END) {
111 tokenizer.nextToken();
112 return result;
113 } else {
114 check(TokenType.PIPE);
115 }
116 }
117 }
118
119 private TemplateEntry parseContextSwitch() throws ParseError {
120
121 check(TokenType.CONTEXT_SWITCH_START);
122 Token searchExpression = tokenizer.skip('\'');
123 check(TokenType.APOSTROPHE);
124 TemplateEntry template = parseExpression(CONDITION_WITH_APOSTROPHES_END_TOKENS);
125 check(TokenType.APOSTROPHE);
126 ContextSwitchTemplate result;
127 if (searchExpression.getText().trim().isEmpty())
128 throw new ParseError(tr("Expected search expression"));
129 else {
130 try {
131 Match match = SearchCompiler.compile(searchExpression.getText());
132 result = new ContextSwitchTemplate(match, template, searchExpression.getPosition());
133 } catch (SearchCompiler.ParseError e) {
134 throw new ParseError(searchExpression.getPosition(), e);
135 }
136 }
137 skipWhitespace();
138 check(TokenType.END);
139 return result;
140 }
141}
Note: See TracBrowser for help on using the repository browser.