1 | |
|
2 | |
|
3 | |
|
4 | |
|
5 | |
|
6 | |
|
7 | |
|
8 | |
|
9 | |
|
10 | |
|
11 | |
|
12 | |
|
13 | |
|
14 | |
|
15 | |
|
16 | |
|
17 | |
|
18 | |
package net.sf.jmatchparser.template.engine.template; |
19 | |
|
20 | |
import java.io.BufferedReader; |
21 | |
import java.io.IOException; |
22 | |
import java.util.ArrayList; |
23 | |
import java.util.HashSet; |
24 | |
import java.util.List; |
25 | |
import java.util.Set; |
26 | |
import java.util.regex.Pattern; |
27 | |
|
28 | |
import net.sf.jmatchparser.template.Formatter; |
29 | |
import net.sf.jmatchparser.template.MatchTemplate.MatchTemplateResolver; |
30 | |
import net.sf.jmatchparser.template.engine.operation.CheckFinishedOperation; |
31 | |
import net.sf.jmatchparser.template.engine.operation.Operation.OperationResult; |
32 | |
import net.sf.jmatchparser.template.engine.template.command.plain.Command; |
33 | |
|
34 | |
public class PlainMatchTemplateImpl extends MatchTemplateImpl { |
35 | |
|
36 | 203 | private final Set<String> usedNames = new HashSet<String>(); |
37 | 203 | private final Set<String> defines = new HashSet<String>(); |
38 | 203 | private final String[] specialTags = new String[] { "«", "»", null, null }; |
39 | |
|
40 | |
public PlainMatchTemplateImpl(MatchTemplateResolver resolver, String templateName, BufferedReader br, Formatter[] formatters) throws IOException { |
41 | 203 | super(formatters); |
42 | 203 | load(resolver, "", templateName, br); |
43 | 188 | appendOperation(new CheckFinishedOperation(getCurrentTemplatePosition(), OperationResult.FINISHED)); |
44 | 188 | } |
45 | |
|
46 | |
private void load(MatchTemplateResolver resolver, String prefix, String templateName, BufferedReader br) throws IOException { |
47 | 205 | if (br == null) |
48 | 4 | br = resolver.resolve(templateName); |
49 | 205 | if (!includedTemplateFileNames.contains(templateName)) |
50 | 204 | includedTemplateFileNames.add(templateName); |
51 | 205 | List<PlainBlockCommandState> openBlockStates = new ArrayList<PlainBlockCommandState>(); |
52 | |
|
53 | 205 | String templateNameUnique = prefix + templateName; |
54 | 206 | while (usedNames.contains(templateNameUnique)) { |
55 | 1 | templateNameUnique += "_"; |
56 | |
} |
57 | 205 | usedNames.add(templateNameUnique); |
58 | |
String line; |
59 | 205 | boolean active = true; |
60 | 205 | List<Boolean> activeStack = new ArrayList<Boolean>(); |
61 | 205 | List<String> activeStackTemplatePositions = new ArrayList<String>(); |
62 | 205 | int lineNumber = 0; |
63 | 1194 | while ((line = br.readLine()) != null) { |
64 | 1001 | lineNumber++; |
65 | 1001 | setCurrentTemplatePosition("[" + templateNameUnique + ":" + lineNumber + "]\t" + line); |
66 | |
try { |
67 | 1001 | if ((active || line.trim().startsWith("$")) && line.trim().length() > 0 && !line.trim().startsWith("#")) { |
68 | 1143 | while (line.startsWith(" ") || line.startsWith("\t")) |
69 | 153 | line = line.substring(1); |
70 | 990 | int pos = line.indexOf(" "); |
71 | 990 | int pos2 = line.indexOf("\t"); |
72 | 990 | if (pos2 != -1 && (pos == -1 || pos > pos2)) |
73 | 5 | pos = pos2; |
74 | |
String commandName, parameters; |
75 | 990 | if (pos == -1) { |
76 | 271 | commandName = line.toLowerCase(); |
77 | 271 | parameters = ""; |
78 | |
} else { |
79 | 719 | commandName = line.substring(0, pos).toLowerCase(); |
80 | 719 | parameters = line.substring(pos + 1); |
81 | |
} |
82 | 990 | if (commandName.startsWith("$")) { |
83 | 43 | if (commandName.equals("$include")) { |
84 | 3 | if (active) { |
85 | 2 | String tp = getCurrentTemplatePosition(); |
86 | 2 | load(resolver, templateNameUnique + "|", parameters, null); |
87 | 2 | setCurrentTemplatePosition(tp); |
88 | 2 | } |
89 | 40 | } else if (commandName.equals("$ifdef")) { |
90 | 8 | activeStackTemplatePositions.add(getCurrentTemplatePosition()); |
91 | 8 | activeStack.add(active); |
92 | 8 | active &= defines.contains(parameters); |
93 | 32 | } else if (commandName.equals("$ifndef")) { |
94 | 7 | activeStackTemplatePositions.add(getCurrentTemplatePosition()); |
95 | 7 | activeStack.add(active); |
96 | 7 | active &= !defines.contains(parameters); |
97 | 25 | } else if (commandName.equals("$endif")) { |
98 | 14 | activeStackTemplatePositions.remove(activeStackTemplatePositions.size() - 1); |
99 | 14 | active = activeStack.remove(activeStack.size() - 1); |
100 | 11 | } else if (commandName.equals("$define")) { |
101 | 3 | if (active) { |
102 | 2 | defines.add(parameters); |
103 | |
} |
104 | 8 | } else if (commandName.equals("$undef")) { |
105 | 2 | if (active) { |
106 | 1 | defines.remove(parameters); |
107 | |
} |
108 | 6 | } else if (commandName.equals("$specialtags")) { |
109 | 5 | if (active) { |
110 | 4 | String[] parts = parameters.substring(1).split(Pattern.quote(parameters.substring(0, 1)), -1); |
111 | 4 | if (parts[parts.length - 1].length() > 0) |
112 | 1 | throw new RuntimeException("Separator missing at end"); |
113 | 3 | if (parts.length == 3) { |
114 | 1 | specialTags[0] = parts[0]; |
115 | 1 | specialTags[1] = parts[1]; |
116 | 1 | specialTags[2] = null; |
117 | 1 | specialTags[3] = null; |
118 | 2 | } else if (parts.length == 5) { |
119 | 1 | specialTags[0] = parts[0]; |
120 | 1 | specialTags[1] = parts[1]; |
121 | 1 | specialTags[2] = parts[2]; |
122 | 1 | specialTags[3] = parts[3]; |
123 | |
} else { |
124 | 1 | throw new RuntimeException("Invalid number of tags"); |
125 | |
} |
126 | 2 | } |
127 | |
} else { |
128 | 1 | throw new RuntimeException("Unsupported preprocessor command: " + commandName); |
129 | |
} |
130 | |
} else { |
131 | 947 | Command cmd = Command.getCommand(commandName); |
132 | 947 | boolean parsed = false; |
133 | 947 | if (cmd != null) { |
134 | 790 | PlainBlockCommandState bcs = cmd.parse(this, parameters); |
135 | 784 | if (bcs != null) |
136 | 97 | openBlockStates.add(bcs); |
137 | 784 | parsed = true; |
138 | 784 | } else if (openBlockStates.size() > 0) { |
139 | 155 | PlainBlockCommandState bcs = openBlockStates.remove(openBlockStates.size() - 1); |
140 | 155 | if (bcs.canParse(commandName)) { |
141 | 154 | bcs = bcs.parseCommand(this, commandName, parameters); |
142 | 154 | parsed = true; |
143 | 154 | if (bcs != null) |
144 | 60 | openBlockStates.add(bcs); |
145 | |
} |
146 | |
} |
147 | 941 | if (!parsed) { |
148 | 3 | throw new RuntimeException("Unsupported command: " + commandName); |
149 | |
} |
150 | |
} |
151 | |
} |
152 | 12 | } catch (RuntimeException ex) { |
153 | 12 | throw new RuntimeException("Cannot parse line:\n\t" + getCurrentTemplatePosition(), ex); |
154 | 989 | } |
155 | |
} |
156 | 193 | br.close(); |
157 | 193 | if (openBlockStates.size() != 0) { |
158 | 2 | String pos = openBlockStates.get(openBlockStates.size() - 1).getStartPosition(); |
159 | 2 | throw new IOException("Unclosed block at position:\n\t" + pos); |
160 | |
} |
161 | 191 | if (activeStackTemplatePositions.size() != 0) { |
162 | 1 | String templatePosition = activeStackTemplatePositions.get(activeStackTemplatePositions.size() - 1); |
163 | 1 | throw new IOException("Unclosed preprocessor command:\n\t" + templatePosition); |
164 | |
} |
165 | 190 | setCurrentTemplatePosition("[" + templateNameUnique + ":" + (lineNumber + 1) + "]\t[End of file]"); |
166 | 190 | } |
167 | |
|
168 | |
@Override |
169 | |
public String[] getSpecialTags() { |
170 | 682 | return specialTags; |
171 | |
} |
172 | |
} |