1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.yaml.snakeyaml.resolver;
18
19 import java.util.ArrayList;
20 import java.util.HashMap;
21 import java.util.List;
22 import java.util.Map;
23 import java.util.regex.Pattern;
24
25 import org.yaml.snakeyaml.nodes.NodeId;
26 import org.yaml.snakeyaml.nodes.Tag;
27
28
29
30
31
32 public class Resolver {
33 public static final Pattern BOOL = Pattern
34 .compile("^(?:yes|Yes|YES|no|No|NO|true|True|TRUE|false|False|FALSE|on|On|ON|off|Off|OFF)$");
35
36
37
38
39
40 public static final Pattern FLOAT = Pattern
41 .compile("^([-+]?(\\.[0-9]+|[0-9_]+(\\.[0-9_]*)?)([eE][-+]?[0-9]+)?|[-+]?[0-9][0-9_]*(?::[0-5]?[0-9])+\\.[0-9_]*|[-+]?\\.(?:inf|Inf|INF)|\\.(?:nan|NaN|NAN))$");
42 public static final Pattern INT = Pattern
43 .compile("^(?:[-+]?0b[0-1_]+|[-+]?0[0-7_]+|[-+]?(?:0|[1-9][0-9_]*)|[-+]?0x[0-9a-fA-F_]+|[-+]?[1-9][0-9_]*(?::[0-5]?[0-9])+)$");
44 public static final Pattern MERGE = Pattern.compile("^(?:<<)$");
45 public static final Pattern NULL = Pattern.compile("^(?:~|null|Null|NULL| )$");
46 public static final Pattern EMPTY = Pattern.compile("^$");
47 public static final Pattern TIMESTAMP = Pattern
48 .compile("^(?:[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]|[0-9][0-9][0-9][0-9]-[0-9][0-9]?-[0-9][0-9]?(?:[Tt]|[ \t]+)[0-9][0-9]?:[0-9][0-9]:[0-9][0-9](?:\\.[0-9]*)?(?:[ \t]*(?:Z|[-+][0-9][0-9]?(?::[0-9][0-9])?))?)$");
49 public static final Pattern VALUE = Pattern.compile("^(?:=)$");
50 public static final Pattern YAML = Pattern.compile("^(?:!|&|\\*)$");
51
52 protected Map<Character, List<ResolverTuple>> yamlImplicitResolvers = new HashMap<Character, List<ResolverTuple>>();
53
54
55
56
57
58
59
60
61 public Resolver(boolean respectDefaultImplicitScalars) {
62 if (respectDefaultImplicitScalars) {
63 addImplicitResolvers();
64 }
65 }
66
67 protected void addImplicitResolvers() {
68 addImplicitResolver(Tag.BOOL, BOOL, "yYnNtTfFoO");
69
70
71
72
73
74 addImplicitResolver(Tag.INT, INT, "-+0123456789");
75 addImplicitResolver(Tag.FLOAT, FLOAT, "-+0123456789.");
76 addImplicitResolver(Tag.MERGE, MERGE, "<");
77 addImplicitResolver(Tag.NULL, NULL, "~nN\0");
78 addImplicitResolver(Tag.NULL, EMPTY, null);
79 addImplicitResolver(Tag.TIMESTAMP, TIMESTAMP, "0123456789");
80 addImplicitResolver(Tag.VALUE, VALUE, "=");
81
82
83
84
85 addImplicitResolver(Tag.YAML, YAML, "!&*");
86 }
87
88 public Resolver() {
89 this(true);
90 }
91
92 public void addImplicitResolver(Tag tag, Pattern regexp, String first) {
93 if (first == null) {
94 List<ResolverTuple> curr = yamlImplicitResolvers.get(null);
95 if (curr == null) {
96 curr = new ArrayList<ResolverTuple>();
97 yamlImplicitResolvers.put(null, curr);
98 }
99 curr.add(new ResolverTuple(tag, regexp));
100 } else {
101 char[] chrs = first.toCharArray();
102 for (int i = 0, j = chrs.length; i < j; i++) {
103 Character theC = new Character(chrs[i]);
104 if (theC == 0) {
105
106 theC = null;
107 }
108 List<ResolverTuple> curr = yamlImplicitResolvers.get(theC);
109 if (curr == null) {
110 curr = new ArrayList<ResolverTuple>();
111 yamlImplicitResolvers.put(theC, curr);
112 }
113 curr.add(new ResolverTuple(tag, regexp));
114 }
115 }
116 }
117
118 public Tag resolve(NodeId kind, String value, boolean implicit) {
119 if (kind == NodeId.scalar && implicit) {
120 List<ResolverTuple> resolvers = null;
121 if (value.length() == 0) {
122 resolvers = yamlImplicitResolvers.get('\0');
123 } else {
124 resolvers = yamlImplicitResolvers.get(value.charAt(0));
125 }
126 if (resolvers != null) {
127 for (ResolverTuple v : resolvers) {
128 Tag tag = v.getTag();
129 Pattern regexp = v.getRegexp();
130 if (regexp.matcher(value).matches()) {
131 return tag;
132 }
133 }
134 }
135 if (yamlImplicitResolvers.containsKey(null)) {
136 for (ResolverTuple v : yamlImplicitResolvers.get(null)) {
137 Tag tag = v.getTag();
138 Pattern regexp = v.getRegexp();
139 if (regexp.matcher(value).matches()) {
140 return tag;
141 }
142 }
143 }
144 }
145 switch (kind) {
146 case scalar:
147 return Tag.STR;
148 case sequence:
149 return Tag.SEQ;
150 default:
151 return Tag.MAP;
152 }
153 }
154 }