Upgrade to ExtJS 4.0.1 - Released 05/18/2011
[extjs.git] / jsbuilder / src / Parser.js
1 // Singleton
2 Parser = new(Ext.extend(Object, {
3     params: {},
4
5     parse: function(filename) {
6         var stream = new Stream(filename),
7             ret;
8
9         Loader.require('Parser.Statement');
10         ret = (new Parser.Statement()).parse(stream);
11         stream.close();
12
13         return ret;
14     },
15
16     evaluate: function(name, value) {
17         var modifier = null,
18             param = (this.params.hasOwnProperty(name)) ? this.params[name] : false,
19             match;
20
21         if (value === undefined) {
22             value = true;
23         }
24
25         if (Ext.isString(value)) {
26             match = value.match(/^(\!|<=|>=|<|>)/);
27
28             if (match) {
29                 modifier = match[0];
30                 value = value.slice(modifier.length);
31             }
32
33             // Boolean
34             if (value === 'true') {
35                 value = true;
36             }
37             else if (value === 'false') {
38                 value = false;
39             }
40             // Numeric
41             else if (!isNaN(value)) {
42                 value = parseFloat(value);
43             }
44         }
45
46         switch (modifier) {
47             case '!':
48                 return (param !== value);
49             case '>':
50                 return (param > value);
51             case '<':
52                 return (param < value);
53             case '<=':
54                 return (param <= value);
55             case '>=':
56                 return (param >= value);
57             default:
58                 return (param === value);
59         }
60     },
61
62     setParams: function(params) {
63         this.params = params || {};
64     },
65
66     isCloseOf: function(str, statement) {
67         if (!statement.type) {
68             return false;
69         }
70
71         return str.trim().match(new RegExp("^\\/\\/(?:\\t|\\s)*<\\/" + ((statement.isInverted) ? "!" : "") + statement.type + ">$")) !== null;
72     },
73
74     isStatement: function(str) {
75         return this.parseStatementParts(str) !== null;
76     },
77
78     parseStatementParts: function(str) {
79         return str.trim().match(/^\/\/(?:\t|\s)*<([^\/]+)>$/);
80     },
81
82     parseStatementProperties: function(str) {
83         var properties = {},
84             expect = function(regexp) {
85                 var result = str.match(regexp);
86
87                 if (result !== null) {
88                     str = str.slice(result[0].length);
89                     return result[0];
90                 }
91
92                 return null;
93             },
94             name, equalSign, valueWrapper, valueCheck, value;
95
96         while (str.length > 0) {
97             expect(/^[^\w]+/i);
98             name = expect(/^[\w]+/i);
99
100             if (name === null) {
101                 break;
102             }
103
104             equalSign = expect(/^=/);
105
106             if (equalSign === null) {
107                 properties[name] = true;
108                 continue;
109             }
110
111             valueWrapper = expect(/^('|")/i);
112             valueCheck = valueWrapper || "\\s";
113
114             value = expect(new RegExp('^[^' + valueCheck + ']+'));
115
116             if (valueWrapper !== null) {
117                 expect(new RegExp(valueWrapper));
118             }
119
120             properties[name] = value;
121         }
122
123         return properties;
124     },
125
126     parseStatement: function(string) {
127         var str = string.trim(),
128             parts = this.parseStatementParts(str),
129             typeMatch, statement;
130
131         // Check if it's actually a valid statement
132         if (parts === null) {
133             return false;
134         }
135
136         str = parts[1];
137
138         typeMatch = str.match(/^(\!)?([\w]+)/i);
139
140         if (typeMatch === null) {
141             return false;
142         }
143
144         statement = {
145             properties: {}
146         };
147
148         statement.type = typeMatch[2];
149         statement.isInverted = (typeMatch[1] !== undefined);
150
151         str = str.substr(typeMatch[0].length, str.length).trim();
152         statement.properties = this.parseStatementProperties(str);
153
154         return statement;
155     }
156 }));