2 * Copyright (c) 2007 Derek Wischusen
4 * Permission is hereby granted, free of charge, to any person obtaining a copy of
5 * this software and associated documentation files (the "Software"), to deal in
6 * the Software without restriction, including without limitation the rights to
7 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
8 * of the Software, and to permit persons to whom the Software is furnished to do
9 * so, subject to the following conditions:
11 * The above copyright notice and this permission notice shall be included in all
12 * copies or substantial portions of the Software.
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26 import flash.utils.Dictionary;
28 import org.as3yaml.nodes.*;
29 import org.rxr.actionscript.io.StringReader;
31 public class Resolver {
32 private static var yamlImplicitResolvers : Dictionary = new Dictionary();
33 private static var yamlPathResolvers : Dictionary = new Dictionary();
35 private var resolverExactPaths : Array = new Array();
36 private var resolverPrefixPaths : Array = new Array();
38 public static function addImplicitResolver(tag : String, regexp : RegExp, first : String) : void {
39 var firstVal : String = (null == first)?"":first;
40 for(var i:int=0,j:int=firstVal.length;i<j;i++) {
41 var theC : String = firstVal.charAt(i);
42 var curr : Array = yamlImplicitResolvers[theC] as Array;
45 yamlImplicitResolvers[theC] = curr;
47 curr.push([tag,regexp]);
51 // public static function addPathResolver(tag : String, path : List, kind : Class) : void {
52 // var newPath : Array = new Array();
53 // var nodeCheck : Object = null;
54 // var indexCheck : Object = null;
55 // for(var iter : Iterator = path.iterator();iter.hasNext();) {
56 // var element : Object = iter.next();
57 // if(element is List) {
58 // var eList : List = element as List;
59 // if(eList.size() == 2) {
60 // nodeCheck = eList.get(0);
61 // indexCheck = eList.get(1);
62 // } else if(eList.size() == 1) {
63 // nodeCheck = eList.get(0);
66 // throw new ResolverException("Invalid path element: " + element);
70 // indexCheck = element;
73 // if(nodeCheck is String) {
74 // nodeCheck = ScalarNode;
75 // } else if(nodeCheck is List) {
76 // nodeCheck = SequenceNode;
77 // } else if(nodeCheck is Map) {
78 // nodeCheck = MappingNode;
79 // } else if(null != nodeCheck && !ScalarNode == (nodeCheck) && !SequenceNode == (nodeCheck) && !MappingNode == (nodeCheck)) {
80 // throw new ResolverException("Invalid node checker: " + nodeCheck);
82 // if(!(indexCheck is String || indexCheck is int) && null != indexCheck) {
83 // throw new ResolverException("Invalid index checker: " + indexCheck);
85 // newPath.push([nodeCheck,indexCheck]);
87 // var newKind : Class = null;
88 // if(String == kind) {
89 // newKind = ScalarNode;
90 // } else if(List == kind) {
91 // newKind = SequenceNode;
92 // } else if(Map == kind) {
93 // newKind = MappingNode;
94 // } else if(kind != null && !ScalarNode == kind && !SequenceNode == kind && !MappingNode == kind) {
95 // throw new ResolverException("Invalid node kind: " + kind);
99 // var x : Array = new Array();
101 // var y : Array = new Array();
104 // yamlPathResolvers[y] = tag;
107 public function descendResolver(currentNode : Node, currentIndex : Object) : void {
108 var exactPaths : Dictionary = new Dictionary();
109 var prefixPaths : Array = new Array();
111 if(null != currentNode) {
112 var depth : int = resolverPrefixPaths.length;
113 for(var xi:int=0; xi < resolverPrefixPaths[0].length; xi++) {
114 var obj : Array = resolverPrefixPaths[0][xi] as Array;
115 path = obj[0] as Array;
116 if(checkResolverPrefix(depth,path, obj[1],currentNode,currentIndex)) {
117 if(path.size() > depth) {
118 prefixPaths.push([path,obj[1]]);
120 var resPath : Array = new Array();
122 resPath.push(obj[1]);
123 exactPaths[obj[1]] = yamlPathResolvers[resPath];
128 for(var keyObj : Object in yamlPathResolvers) {
129 var key : Array = keyObj as Array;
130 path = key[0] as Array;
131 var kind : Class = key[1] as Class;
133 exactPaths[kind] = yamlPathResolvers[key];
135 prefixPaths.push(key);
139 resolverExactPaths.unshift(exactPaths);
140 resolverPrefixPaths.unshift(prefixPaths);
143 public function ascendResolver() : void {
144 resolverExactPaths.shift();
145 resolverPrefixPaths.shift();
148 public function checkResolverPrefix(depth : int, path : Array, kind : Class, currentNode : Node, currentIndex : Object) : Boolean {
149 var check : Array = path[depth-1];
150 var nodeCheck : Object = check[0];
151 var indexCheck : Object = check[1];
152 if(nodeCheck is String) {
153 if(!currentNode.getTag() == (nodeCheck)) {
156 } else if(null != nodeCheck) {
157 if(!(nodeCheck).isInstance(currentNode)) {
161 if(indexCheck == true && currentIndex != null) {
164 if(indexCheck == true && currentIndex == null) {
167 if(indexCheck is String) {
168 if(!(currentIndex is ScalarNode && indexCheck == ((ScalarNode(currentIndex)).getValue()))) {
171 } else if(indexCheck is int) {
172 if(!currentIndex == (indexCheck)) {
179 public function resolve(kind : Class, value : String, implicit : Array) : String {
180 var resolvers : Array = null;
181 if(kind == ScalarNode && implicit[0]) {
183 resolvers = yamlImplicitResolvers[""] as Array;
185 resolvers = yamlImplicitResolvers[value.charAt(0)] as Array;
187 if(resolvers == null) {
188 resolvers = new Array();
190 if(yamlImplicitResolvers[null]) {
191 resolvers.concat(yamlImplicitResolvers[null]);
193 for(var xi:int=0; xi < resolvers.length; xi++) {
194 var val : Array = resolvers[xi];
195 if((RegExp(val[1])).exec(value)) {
196 return val[0] as String;
200 var exactPaths : Dictionary = resolverExactPaths[0] as Dictionary;
201 if(exactPaths[kind]) {
202 return exactPaths[kind] as String;
204 if(exactPaths[null]) {
205 return exactPaths[null] as String;
207 if(kind == ScalarNode) {
208 return YAML.DEFAULT_SCALAR_TAG;
209 } else if(kind == SequenceNode) {
210 return YAML.DEFAULT_SEQUENCE_TAG;
211 } else if(kind == MappingNode) {
212 return YAML.DEFAULT_MAPPING_TAG;
218 addImplicitResolver("tag:yaml.org,2002:bool",new RegExp("^(?:yes|Yes|YES|no|No|NO|true|True|TRUE|false|False|FALSE|on|On|ON|off|Off|OFF)$"),"yYnNtTfFoO");
219 addImplicitResolver("tag:yaml.org,2002:float",new RegExp("^(?:[-+]?(?:[0-9][0-9_]*)\\.[0-9_]*(?:[eE][-+][0-9]+)?|[-+]?(?:[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))$"),"-+0123456789.");
220 addImplicitResolver("tag:yaml.org,2002:int",new RegExp("^(?:[-+]?0b[0-1_]+|[-+]?0[0-7_]+|[-+]?(?:0|[1-9][0-9_]*)|[-+]?0x[0-9a-fA-F_]+|[-+]?[1-9][0-9_]*(?::[0-5]?[0-9])+)$"),"-+0123456789");
221 addImplicitResolver("tag:yaml.org,2002:merge",new RegExp("^(?:<<)$"),"<");
222 addImplicitResolver("tag:yaml.org,2002:null",new RegExp("^(?:~|null|Null|NULL| )$"),"~nN\x00");
223 addImplicitResolver("tag:yaml.org,2002:timestamp",new RegExp("^(?:[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])?))?)$"),"0123456789");
224 addImplicitResolver("tag:yaml.org,2002:value",new RegExp("^(?:=)$"),"=");
225 // The following implicit resolver is only for documentation purposes. It cannot work
226 // because plain scalars cannot start with '!', '&', or '*'.
227 addImplicitResolver("tag:yaml.org,2002:yaml",new RegExp("^(?:!|&|\\*)$"),"!&*");