Revisão | 4b49016f499d085bd55d7af49ea116bf427d4b21 (tree) |
---|---|
Hora | 2015-11-06 12:21:14 |
Autor | MirrgieRiana |
Commiter | MirrgieRiana |
ArgumentsParse: 構文候補表示
@@ -1,5 +1,7 @@ | ||
1 | 1 | package mirrg.compile.bromine; |
2 | 2 | |
3 | +import java.util.ArrayList; | |
4 | + | |
3 | 5 | import mirrg.compile.bromine.cache.CacheBromine; |
4 | 6 | |
5 | 7 | public class ArgumentsParse |
@@ -14,4 +16,18 @@ | ||
14 | 16 | this.cache = cache; |
15 | 17 | } |
16 | 18 | |
19 | + public ArrayList<String> hints = new ArrayList<>(); | |
20 | + public int currentIndex = 0; | |
21 | + | |
22 | + public void report(int index, String string) | |
23 | + { | |
24 | + if (index > currentIndex) { | |
25 | + currentIndex = index; | |
26 | + hints.clear(); | |
27 | + } | |
28 | + if (index >= currentIndex) { | |
29 | + hints.add(string); | |
30 | + } | |
31 | + } | |
32 | + | |
17 | 33 | } |
@@ -5,11 +5,13 @@ | ||
5 | 5 | |
6 | 6 | public final N node; |
7 | 7 | public final int length; |
8 | + public final ArgumentsParse argumentsParse; | |
8 | 9 | |
9 | - public ResponseParse(N node, int length) | |
10 | + public ResponseParse(N node, int length, ArgumentsParse argumentsParse) | |
10 | 11 | { |
11 | 12 | this.node = node; |
12 | 13 | this.length = length; |
14 | + this.argumentsParse = argumentsParse; | |
13 | 15 | } |
14 | 16 | |
15 | 17 | } |
@@ -21,7 +21,7 @@ | ||
21 | 21 | @Override |
22 | 22 | protected NonnullIterable<ResponseParse<N>> parseImpl(ArgumentsParse arguments, int index) |
23 | 23 | { |
24 | - return NonnullIterable.of(new ResponseParse<>(functionNode.apply(new TagFixed(index, 0)), 0)); | |
24 | + return NonnullIterable.of(new ResponseParse<>(functionNode.apply(new TagFixed(index, 0)), 0, arguments)); | |
25 | 25 | } |
26 | 26 | |
27 | 27 | } |
@@ -25,7 +25,7 @@ | ||
25 | 25 | return syntax.parse(arguments, index) |
26 | 26 | .map(response -> { |
27 | 27 | if (response == null) return null; |
28 | - return new ResponseParse<>(functionNode.apply(response.node), response.length); | |
28 | + return new ResponseParse<>(functionNode.apply(response.node), response.length, arguments); | |
29 | 29 | }); |
30 | 30 | } |
31 | 31 |
@@ -25,7 +25,7 @@ | ||
25 | 25 | { |
26 | 26 | return NonnullIterable.of( |
27 | 27 | syntax.parse(arguments, index), |
28 | - NonnullIterable.of(new ResponseParse<>(functionNode.apply(new TagFixed(index, 0)), 0))) | |
28 | + NonnullIterable.of(new ResponseParse<>(functionNode.apply(new TagFixed(index, 0)), 0, arguments))) | |
29 | 29 | .flatMap(iterator -> iterator); |
30 | 30 | } |
31 | 31 |
@@ -12,11 +12,13 @@ | ||
12 | 12 | public class SyntaxRegex<N> extends Syntax<N> |
13 | 13 | { |
14 | 14 | |
15 | + public final String regex; | |
15 | 16 | public final Pattern pattern; |
16 | 17 | public final Function<TagRegex, N> functionNode; |
17 | 18 | |
18 | 19 | public SyntaxRegex(String regex, Function<TagRegex, N> functionNode) |
19 | 20 | { |
21 | + this.regex = regex; | |
20 | 22 | this.pattern = Pattern.compile("\\A" + regex); |
21 | 23 | this.functionNode = functionNode; |
22 | 24 | } |
@@ -31,8 +33,11 @@ | ||
31 | 33 | |
32 | 34 | return NonnullIterable.of(new ResponseParse<>(functionNode.apply( |
33 | 35 | new TagRegex(index, string.length(), string, matcher, pattern)), |
34 | - string.length())); | |
36 | + string.length(), arguments)); | |
35 | 37 | } else { |
38 | + | |
39 | + arguments.report(index, "\"" + regex + "\""); | |
40 | + | |
36 | 41 | return NonnullIterable.empty(); |
37 | 42 | } |
38 | 43 | } |
@@ -22,14 +22,24 @@ | ||
22 | 22 | @Override |
23 | 23 | protected NonnullIterable<ResponseParse<N>> parseImpl(ArgumentsParse arguments, int index) |
24 | 24 | { |
25 | - if (this.string.length() + index > arguments.source.length()) return NonnullIterable.empty(); | |
25 | + if (this.string.length() + index > arguments.source.length()) { | |
26 | + | |
27 | + arguments.report(index, "'" + string + "'"); | |
28 | + | |
29 | + return NonnullIterable.empty(); | |
30 | + } | |
26 | 31 | |
27 | 32 | for (int i = 0; i < this.string.length(); i++) { |
28 | - if (this.string.charAt(i) != arguments.source.charAt(i + index)) return NonnullIterable.empty(); | |
33 | + if (this.string.charAt(i) != arguments.source.charAt(i + index)) { | |
34 | + | |
35 | + arguments.report(index, "'" + string + "'"); | |
36 | + | |
37 | + return NonnullIterable.empty(); | |
38 | + } | |
29 | 39 | } |
30 | 40 | |
31 | 41 | return NonnullIterable.of(new ResponseParse<>(functionNode.apply( |
32 | 42 | new TagString(index, this.string.length(), this.string)), |
33 | - this.string.length())); | |
43 | + this.string.length(), arguments)); | |
34 | 44 | } |
35 | 45 | } |
@@ -19,7 +19,7 @@ | ||
19 | 19 | protected NonnullIterable<ResponseParse<OUT>> parseImpl(ArgumentsParse arguments, int index) |
20 | 20 | { |
21 | 21 | return syntax.parse(arguments, index) |
22 | - .map(response -> new ResponseParse<>(response.node, response.length)); | |
22 | + .map(response -> new ResponseParse<>(response.node, response.length, arguments)); | |
23 | 23 | } |
24 | 24 | |
25 | 25 | } |
@@ -71,7 +71,7 @@ | ||
71 | 71 | // 長さが許可されているかは分からないが、とりあえずまとまった構文列が解析できた。 |
72 | 72 | if (isLengthAllowed(length)) { |
73 | 73 | // この長さは許可されている |
74 | - return new ResponseParse<>(cloner.apply(node), offsets.getLast()); | |
74 | + return new ResponseParse<>(cloner.apply(node), offsets.getLast(), arguments); | |
75 | 75 | } |
76 | 76 | |
77 | 77 | } |
@@ -111,7 +111,7 @@ | ||
111 | 111 | // 長さが許可されているかは分からないが、とりあえずまとまった構文列が解析できた。 |
112 | 112 | if (isLengthAllowed(length)) { |
113 | 113 | // この長さは許可されている |
114 | - return new ResponseParse<>(cloner.apply(node), offsets.getLast()); | |
114 | + return new ResponseParse<>(cloner.apply(node), offsets.getLast(), arguments); | |
115 | 115 | } |
116 | 116 | |
117 | 117 | } |
@@ -17,6 +17,9 @@ | ||
17 | 17 | this.syntax = syntax; |
18 | 18 | } |
19 | 19 | |
20 | + /** | |
21 | + * パースに失敗時、nullが返る。 | |
22 | + */ | |
20 | 23 | public N compile(String source) |
21 | 24 | { |
22 | 25 | NonnullIterable<ResponseParse<N>> responses = syntax.parse(new ArgumentsParse(source, new CacheBromine(source)), 0); |
@@ -26,4 +29,22 @@ | ||
26 | 29 | return next == null ? null : next.node; |
27 | 30 | } |
28 | 31 | |
32 | + /** | |
33 | + * パースに失敗時、nodeがnullであるものが返る。 | |
34 | + */ | |
35 | + public ResponseParse<N> getResponse(String source) | |
36 | + { | |
37 | + ArgumentsParse argumentsParse = new ArgumentsParse(source, new CacheBromine(source)); | |
38 | + NonnullIterable<ResponseParse<N>> responses = syntax.parse(argumentsParse, 0); | |
39 | + NonnullIterator<ResponseParse<N>> iterator = responses.nonnullIterator(); | |
40 | + ResponseParse<N> responseParse = iterator.next(); | |
41 | + return responseParse == null ? new ResponseParse<>(null, 0, argumentsParse) : responseParse; | |
42 | + } | |
43 | + | |
44 | + public NonnullIterator<ResponseParse<N>> getResponses(String source) | |
45 | + { | |
46 | + NonnullIterable<ResponseParse<N>> responses = syntax.parse(new ArgumentsParse(source, new CacheBromine(source)), 0); | |
47 | + return responses.nonnullIterator(); | |
48 | + } | |
49 | + | |
29 | 50 | } |
@@ -360,6 +360,43 @@ | ||
360 | 360 | assertEquals((Integer) 14, compiler.compile("i14").t); |
361 | 361 | } |
362 | 362 | |
363 | + @Test | |
364 | + public void test_hints() | |
365 | + { | |
366 | + Syntax<Object> syntaxA = HBromine.or(Object.class) | |
367 | + .or(HBromine.string("true", tag -> true)) | |
368 | + .or(HBromine.string("false", tag -> false)) | |
369 | + .or(HBromine.regex("\\d+", tag -> (Integer) Integer.parseInt(tag.string))) | |
370 | + .or(HBromine.regex("[a-zA-Z_][a-zA-Z0-9_]*", tag -> tag.string)) | |
371 | + .or(HBromine.regex("\\d*\\.\\d+", tag -> (Double) Double.parseDouble(tag.string))); | |
372 | + Syntax<Object[]> syntaxCall = HBromine.serial( | |
373 | + node -> node.clone(), | |
374 | + tag -> new Object[2]) | |
375 | + .and(HBromine.regex("[a-zA-Z_][a-zA-Z0-9_]*", tag -> tag.string), | |
376 | + (node, index, tag) -> node[0] = tag, (node, index) -> node[0] = null) | |
377 | + .and(HBromine.string("(", tag -> null), | |
378 | + (node, index, tag) -> {} , (node, index) -> {}) | |
379 | + .and(syntaxA, | |
380 | + (node, index, tag) -> node[1] = tag, (node, index) -> node[1] = null) | |
381 | + .and(HBromine.string(")", tag -> null), | |
382 | + (node, index, tag) -> {} , (node, index) -> {}) | |
383 | + .and(HBromine.string(";", tag -> null), | |
384 | + (node, index, tag) -> {} , (node, index) -> {}); | |
385 | + CompilerBromine<Object[]> compiler = HBromine.createCompiler(HBromine.root(syntaxCall)); | |
386 | + | |
387 | + assertEquals("func1", compiler.compile("func1(34);")[0].toString()); | |
388 | + assertEquals("34", compiler.compile("func1(34);")[1].toString()); | |
389 | + assertEquals("r4", compiler.compile("func1(r4);")[1].toString()); | |
390 | + assertArrayEquals(new String[] { | |
391 | + "'true'", | |
392 | + "'false'", | |
393 | + "\"\\d+\"", | |
394 | + "\"[a-zA-Z_][a-zA-Z0-9_]*\"", | |
395 | + "\"\\d*\\.\\d+\"", | |
396 | + }, compiler.getResponse("func1(").argumentsParse.hints.toArray(new String[0])); | |
397 | + | |
398 | + } | |
399 | + | |
363 | 400 | public static void main(String[] args) |
364 | 401 | { |
365 | 402 | new TestBromine().test_002(); |