1 package cz.cuni.amis.pogamut.shady;
2
3
4
5
6
7
8 public interface IArgument<T> {
9
10 T getValue();
11 }
12
13
14
15
16
17 class Arg<T> implements IArgument<T> {
18
19 private final T value;
20
21 public Arg(T value) {
22 this.value = value;
23 }
24
25 @Override
26 public T getValue() {
27 return value;
28 }
29
30 @Override
31 public boolean equals(Object obj) {
32 if (obj == null) {
33 return false;
34 }
35 if (obj == this) {
36 return true;
37 }
38 if (!(obj instanceof IArgument)) {
39 return false;
40 }
41 IArgument arg = (IArgument) obj;
42 return this.value == null ? arg.getValue() == null : value.equals(arg.getValue());
43 }
44 }
45
46 class ArgInt extends Arg<Integer> {
47
48 public ArgInt(int number) {
49 super(number);
50 }
51 }
52
53 class ArgFloat extends Arg<Double> {
54
55 public ArgFloat(double number) {
56 super(number);
57 }
58 }
59
60 class ArgChar extends Arg<Character> {
61
62 public ArgChar(char character) {
63 super(character);
64 }
65
66
67
68
69
70
71
72
73
74 public static char unescape(String escapedChar) throws ParseException {
75 if (escapedChar.length() == 0) {
76 throw new ParseException("The string representing the escaped character must have legth > 0.");
77 }
78 StringBuilder sb = new StringBuilder(escapedChar);
79 char result = parseCharacter(sb);
80 if (sb.length() > 0)
81 throw new ParseException("There still are some unparsed characters remaining(" + sb.length() + "):" + sb.toString());
82 return result;
83 }
84
85
86
87
88
89
90
91
92
93 protected static char parseCharacter(StringBuilder sb) throws ParseException {
94 char result = sb.charAt(0);
95 sb.deleteCharAt(0);
96 if (result == '\\') {
97 Character parsed = ArgChar.parseEscapeSequence(sb);
98 if (parsed == null) {
99 throw new ParseException("Unable to unescape sequence:" + sb.toString());
100 }
101 result = parsed;
102 }
103 return result;
104 }
105
106
107
108
109
110
111 public static char parseCharacterListeral(String charLiteral) throws ParseException {
112 StringBuilder sb = new StringBuilder(charLiteral);
113 if (sb.charAt(0) != '\'') {
114 throw new ParseException("Expecting \' at the start of " + charLiteral.toString());
115 }
116 sb.deleteCharAt(0);
117
118 char result = parseCharacter(sb);
119
120 if (sb.length() != 1) {
121 throw new ParseException("Expecting exactly one character (single quote), but " + sb.length() + " characters remain:" + sb.toString());
122 }
123 if (sb.charAt(0) != '\'') {
124 throw new ParseException("Expecting ending double quote, but got: " + sb.charAt(0));
125 }
126 return result;
127 }
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143 protected static Character parseEscapeSequence(StringBuilder sb) {
144
145 Character octal = parseOctal(sb);
146 if (octal != null) {
147 return octal;
148 }
149
150 Character simpleEscape = parseSingleEscape(sb);
151 if (simpleEscape != null) {
152 return simpleEscape;
153 }
154 Character unicode = parseUnicode(sb);
155 if (unicode != null) {
156 return unicode;
157 }
158 return null;
159 }
160
161
162
163
164
165
166
167
168 protected static Character parseOctal(StringBuilder sb) {
169 if (sb.length() >= 3) {
170 String octal3 = sb.substring(0, 3);
171 if (octal3.matches("[0-3][0-7][0-7]")) {
172 sb.delete(0, 3);
173 return Character.toChars(Integer.parseInt(octal3, 8))[0];
174 }
175 }
176 if (sb.length() >= 2) {
177 String octal2 = sb.substring(0, 2);
178 if (octal2.matches("[0-7][0-7]")) {
179 sb.delete(0, 2);
180 return Character.toChars(Integer.parseInt(octal2, 8))[0];
181 }
182 }
183 String octal1 = sb.substring(0, 1);
184 if (octal1.matches("[0-7]")) {
185 sb.delete(0, 1);
186 return Character.toChars(Integer.parseInt(octal1, 8))[0];
187 }
188 return null;
189 }
190
191
192
193
194
195
196
197
198
199
200 protected static Character parseSingleEscape(StringBuilder sb) {
201 char ch = sb.charAt(0);
202 char res;
203 switch (ch) {
204 case 'b':
205 res = '\b';
206 break;
207 case 't':
208 res = '\t';
209 break;
210 case 'n':
211 res = '\n';
212 break;
213 case 'f':
214 res = '\f';
215 break;
216 case 'r':
217 res = '\r';
218 break;
219 case '"':
220 res = '\"';
221 break;
222 case '\'':
223 res = '\'';
224 break;
225 case '\\':
226 res = '\\';
227 break;
228 default:
229 return null;
230 }
231 sb.deleteCharAt(0);
232 return res;
233 }
234
235
236
237
238
239
240
241
242
243
244 protected static Character parseUnicode(StringBuilder sb) {
245 String regexp = "u+\\p{XDigit}\\p{XDigit}\\p{XDigit}\\p{XDigit}.*";
246 if (sb.toString().matches(regexp)) {
247 while (sb.charAt(0) == 'u') {
248 sb.deleteCharAt(0);
249 }
250 String hexaString = sb.substring(0, 4);
251 sb.delete(0, 4);
252 return Character.toChars(Integer.parseInt(hexaString, 16))[0];
253 }
254 return null;
255 }
256 }