diff options
author | Jose Antonio Marquez | 2012-05-16 15:42:37 -0700 |
---|---|---|
committer | Jose Antonio Marquez | 2012-05-16 15:42:37 -0700 |
commit | 857aafee732b6a85fa155ff4a05d1b8fde48f09d (patch) | |
tree | e06d330caee280aa05aec46391979e9abdcf974c /node_modules/montage/core/selector/property-language.js | |
parent | 5cc5d29736d8bf253e3a168cdd6443e839ffb23c (diff) | |
parent | fd54dabad7cbc27a0efb0957155c00d578912909 (diff) | |
download | ninja-857aafee732b6a85fa155ff4a05d1b8fde48f09d.tar.gz |
Merge branch 'refs/heads/Ninja-DOM-Architecture' into Document
Diffstat (limited to 'node_modules/montage/core/selector/property-language.js')
-rw-r--r-- | node_modules/montage/core/selector/property-language.js | 346 |
1 files changed, 346 insertions, 0 deletions
diff --git a/node_modules/montage/core/selector/property-language.js b/node_modules/montage/core/selector/property-language.js new file mode 100644 index 00000000..8269572c --- /dev/null +++ b/node_modules/montage/core/selector/property-language.js | |||
@@ -0,0 +1,346 @@ | |||
1 | /* <copyright> | ||
2 | This file contains proprietary software owned by Motorola Mobility, Inc.<br/> | ||
3 | No rights, expressed or implied, whatsoever to this software are provided by Motorola Mobility, Inc. hereunder.<br/> | ||
4 | (c) Copyright 2011 Motorola Mobility, Inc. All Rights Reserved. | ||
5 | </copyright> */ | ||
6 | |||
7 | var AbstractLanguage = require('./abstract-language').AbstractLanguage; | ||
8 | var Parser = require('./parser').Parser; | ||
9 | var Semantics = require('./semantics').Semantics; | ||
10 | var LANGUAGE = require('./language'); // late bound for dependency cycle | ||
11 | |||
12 | var VALUE = 'value'; | ||
13 | var LITERAL = 'literal'; | ||
14 | var GET = 'get'; | ||
15 | var BEGIN = 'begin'; | ||
16 | var END = 'end'; | ||
17 | var MAP = 'map'; | ||
18 | var COMMA = 'comma'; | ||
19 | var IT = 'it'; | ||
20 | var DOT = '.'; | ||
21 | var ARRAY = 'array'; | ||
22 | var SORTED = 'sorted'; | ||
23 | |||
24 | var PropertyLanguage = exports.PropertyLanguage = AbstractLanguage.create(AbstractLanguage, { | ||
25 | |||
26 | semantics: { | ||
27 | value: Semantics | ||
28 | }, | ||
29 | |||
30 | stringToToken: { | ||
31 | value: { | ||
32 | '(': {type: BEGIN}, | ||
33 | ')': {type: END}, | ||
34 | '*': {type: MAP}, | ||
35 | ',': {type: COMMA} | ||
36 | } | ||
37 | }, | ||
38 | |||
39 | tokenRe: { | ||
40 | value: /\(|\)|\d+|\w[\w\d]*|,|\*|\.|./g | ||
41 | }, | ||
42 | |||
43 | termStartRe: { | ||
44 | value: /[\(\w\d\*]/ | ||
45 | }, | ||
46 | |||
47 | separatorsRe: { | ||
48 | value: /[\(\)\.,]/ | ||
49 | }, | ||
50 | |||
51 | tokenize: { | ||
52 | value: function (string, emit) { | ||
53 | var tokens; | ||
54 | if (!emit) { | ||
55 | tokens = []; | ||
56 | emit = function (token) { | ||
57 | tokens.push(token); | ||
58 | } | ||
59 | } | ||
60 | var self = this; | ||
61 | var expectSeparator = false; | ||
62 | var expectTermStart = true; | ||
63 | var soFar = ''; | ||
64 | string.replace(self.tokenRe, function (token) { | ||
65 | if (expectSeparator) { | ||
66 | if (!self.separatorsRe.test(token)) { | ||
67 | throw new Error( | ||
68 | 'Expected punctuation after: ' + | ||
69 | JSON.stringify(soFar) + ", got: " + | ||
70 | JSON.stringify(string.slice(soFar.length)) | ||
71 | ); | ||
72 | } | ||
73 | expectSeparator = false; | ||
74 | } | ||
75 | if (expectTermStart) { | ||
76 | if (!self.termStartRe.test(token)) { | ||
77 | throw new Error( | ||
78 | 'Expected term after: ' + JSON.stringify(soFar) + ", got: " + | ||
79 | JSON.stringify(string.slice(soFar.length)) | ||
80 | ); | ||
81 | } | ||
82 | } | ||
83 | if (token === DOT) { | ||
84 | // ignore, used only for delimiting tokens, like a space | ||
85 | expectTermStart = true; | ||
86 | } else if (self.stringToToken[token]) { | ||
87 | emit(self.stringToToken[token]); | ||
88 | expectTermStart = false; | ||
89 | } else if (/^\d+$/.test(token)) { | ||
90 | emit({ | ||
91 | type: LITERAL, | ||
92 | value: +token | ||
93 | }); | ||
94 | expectSeparator = true; | ||
95 | expectTermStart = false; | ||
96 | } else if (/^\w[\w\d]*$/.test(token)) { | ||
97 | emit({ | ||
98 | type: LITERAL, | ||
99 | value: token | ||
100 | }); | ||
101 | expectSeparator = true; | ||
102 | expectTermStart = false; | ||
103 | } else { | ||
104 | throw new Error('Unexpected character: ' + JSON.stringify(token)); | ||
105 | } | ||
106 | soFar += token; | ||
107 | }) | ||
108 | return tokens; | ||
109 | } | ||
110 | }, | ||
111 | |||
112 | parse: { | ||
113 | value: function (string) { | ||
114 | var self = this; | ||
115 | var syntax; | ||
116 | var parser = Parser.newWithLanguage(self, function (_syntax) { | ||
117 | syntax = _syntax; | ||
118 | }); | ||
119 | self.tokenize(string, function (token) { | ||
120 | parser.emit(token); | ||
121 | }) | ||
122 | parser.emit(LANGUAGE.Language.tokens.eof); | ||
123 | return syntax; | ||
124 | } | ||
125 | }, | ||
126 | |||
127 | grammar: { | ||
128 | value: function () { | ||
129 | var self = this; | ||
130 | |||
131 | self.primary = self.parsePrimary(function (callback) { | ||
132 | return self.parseExpression(callback); | ||
133 | }); | ||
134 | |||
135 | var parseTuple = self.parseTuple(); | ||
136 | |||
137 | self.parseExpression = self.precedence(); | ||
138 | |||
139 | } | ||
140 | }, | ||
141 | |||
142 | parseTerm: { | ||
143 | value: function (consequent, alternate) { | ||
144 | var self = this; | ||
145 | return function (token) { | ||
146 | if (token.type === LITERAL) { | ||
147 | return self.optional(BEGIN, function (begin) { | ||
148 | if (begin) { | ||
149 | return self.primary(function (expression) { | ||
150 | return self.expect(END, function () { | ||
151 | return consequent({ | ||
152 | call: true, | ||
153 | type: token.value, | ||
154 | arg: expression | ||
155 | }); | ||
156 | }); | ||
157 | }); | ||
158 | } else { | ||
159 | return consequent({ | ||
160 | type: GET, | ||
161 | arg: token | ||
162 | }); | ||
163 | } | ||
164 | }); | ||
165 | } else if (token.type === MAP) { | ||
166 | return self.parseTerm(function (map) { | ||
167 | return consequent({ | ||
168 | type: MAP, | ||
169 | arg: { | ||
170 | type: map.type, | ||
171 | args: [ | ||
172 | {type: VALUE}, | ||
173 | map.arg | ||
174 | ] | ||
175 | } | ||
176 | }) | ||
177 | }, function () { | ||
178 | return consequent({ | ||
179 | type: IT, | ||
180 | arg: {type: VALUE} | ||
181 | }) | ||
182 | }); | ||
183 | } else if (token.type === BEGIN) { | ||
184 | return self.parseExpression(function (expression) { | ||
185 | return self.expect(END, function () { | ||
186 | return consequent({ | ||
187 | type: IT, | ||
188 | arg: expression | ||
189 | }); | ||
190 | }); | ||
191 | }); | ||
192 | } else { | ||
193 | return alternate()(token); | ||
194 | } | ||
195 | }; | ||
196 | } | ||
197 | }, | ||
198 | |||
199 | parsePrimary: { | ||
200 | value: function (parseExpression) { | ||
201 | var self = this; | ||
202 | var parseSelf = self.precedence(function (parsePrevious) { | ||
203 | return function (callback, previous) { | ||
204 | previous = previous || {type: VALUE}; | ||
205 | return self.parseTerm(function (term) { | ||
206 | var syntax; | ||
207 | if (term.call) { | ||
208 | if (term.arg.type !== VALUE) { | ||
209 | previous = { | ||