source: imaps-frontend/node_modules/css-tree/lib/syntax/node/AnPlusB.js

main
Last change on this file was d565449, checked in by stefan toskovski <stefantoska84@…>, 4 weeks ago

Update repo after prototype presentation

  • Property mode set to 100644
File size: 9.3 KB
Line 
1var cmpChar = require('../../tokenizer').cmpChar;
2var isDigit = require('../../tokenizer').isDigit;
3var TYPE = require('../../tokenizer').TYPE;
4
5var WHITESPACE = TYPE.WhiteSpace;
6var COMMENT = TYPE.Comment;
7var IDENT = TYPE.Ident;
8var NUMBER = TYPE.Number;
9var DIMENSION = TYPE.Dimension;
10var PLUSSIGN = 0x002B; // U+002B PLUS SIGN (+)
11var HYPHENMINUS = 0x002D; // U+002D HYPHEN-MINUS (-)
12var N = 0x006E; // U+006E LATIN SMALL LETTER N (n)
13var DISALLOW_SIGN = true;
14var ALLOW_SIGN = false;
15
16function checkInteger(offset, disallowSign) {
17 var pos = this.scanner.tokenStart + offset;
18 var code = this.scanner.source.charCodeAt(pos);
19
20 if (code === PLUSSIGN || code === HYPHENMINUS) {
21 if (disallowSign) {
22 this.error('Number sign is not allowed');
23 }
24 pos++;
25 }
26
27 for (; pos < this.scanner.tokenEnd; pos++) {
28 if (!isDigit(this.scanner.source.charCodeAt(pos))) {
29 this.error('Integer is expected', pos);
30 }
31 }
32}
33
34function checkTokenIsInteger(disallowSign) {
35 return checkInteger.call(this, 0, disallowSign);
36}
37
38function expectCharCode(offset, code) {
39 if (!cmpChar(this.scanner.source, this.scanner.tokenStart + offset, code)) {
40 var msg = '';
41
42 switch (code) {
43 case N:
44 msg = 'N is expected';
45 break;
46 case HYPHENMINUS:
47 msg = 'HyphenMinus is expected';
48 break;
49 }
50
51 this.error(msg, this.scanner.tokenStart + offset);
52 }
53}
54
55// ... <signed-integer>
56// ... ['+' | '-'] <signless-integer>
57function consumeB() {
58 var offset = 0;
59 var sign = 0;
60 var type = this.scanner.tokenType;
61
62 while (type === WHITESPACE || type === COMMENT) {
63 type = this.scanner.lookupType(++offset);
64 }
65
66 if (type !== NUMBER) {
67 if (this.scanner.isDelim(PLUSSIGN, offset) ||
68 this.scanner.isDelim(HYPHENMINUS, offset)) {
69 sign = this.scanner.isDelim(PLUSSIGN, offset) ? PLUSSIGN : HYPHENMINUS;
70
71 do {
72 type = this.scanner.lookupType(++offset);
73 } while (type === WHITESPACE || type === COMMENT);
74
75 if (type !== NUMBER) {
76 this.scanner.skip(offset);
77 checkTokenIsInteger.call(this, DISALLOW_SIGN);
78 }
79 } else {
80 return null;
81 }
82 }
83
84 if (offset > 0) {
85 this.scanner.skip(offset);
86 }
87
88 if (sign === 0) {
89 type = this.scanner.source.charCodeAt(this.scanner.tokenStart);
90 if (type !== PLUSSIGN && type !== HYPHENMINUS) {
91 this.error('Number sign is expected');
92 }
93 }
94
95 checkTokenIsInteger.call(this, sign !== 0);
96 return sign === HYPHENMINUS ? '-' + this.consume(NUMBER) : this.consume(NUMBER);
97}
98
99// An+B microsyntax https://www.w3.org/TR/css-syntax-3/#anb
100module.exports = {
101 name: 'AnPlusB',
102 structure: {
103 a: [String, null],
104 b: [String, null]
105 },
106 parse: function() {
107 /* eslint-disable brace-style*/
108 var start = this.scanner.tokenStart;
109 var a = null;
110 var b = null;
111
112 // <integer>
113 if (this.scanner.tokenType === NUMBER) {
114 checkTokenIsInteger.call(this, ALLOW_SIGN);
115 b = this.consume(NUMBER);
116 }
117
118 // -n
119 // -n <signed-integer>
120 // -n ['+' | '-'] <signless-integer>
121 // -n- <signless-integer>
122 // <dashndashdigit-ident>
123 else if (this.scanner.tokenType === IDENT && cmpChar(this.scanner.source, this.scanner.tokenStart, HYPHENMINUS)) {
124 a = '-1';
125
126 expectCharCode.call(this, 1, N);
127
128 switch (this.scanner.getTokenLength()) {
129 // -n
130 // -n <signed-integer>
131 // -n ['+' | '-'] <signless-integer>
132 case 2:
133 this.scanner.next();
134 b = consumeB.call(this);
135 break;
136
137 // -n- <signless-integer>
138 case 3:
139 expectCharCode.call(this, 2, HYPHENMINUS);
140
141 this.scanner.next();
142 this.scanner.skipSC();
143
144 checkTokenIsInteger.call(this, DISALLOW_SIGN);
145
146 b = '-' + this.consume(NUMBER);
147 break;
148
149 // <dashndashdigit-ident>
150 default:
151 expectCharCode.call(this, 2, HYPHENMINUS);
152 checkInteger.call(this, 3, DISALLOW_SIGN);
153 this.scanner.next();
154
155 b = this.scanner.substrToCursor(start + 2);
156 }
157 }
158
159 // '+'? n
160 // '+'? n <signed-integer>
161 // '+'? n ['+' | '-'] <signless-integer>
162 // '+'? n- <signless-integer>
163 // '+'? <ndashdigit-ident>
164 else if (this.scanner.tokenType === IDENT || (this.scanner.isDelim(PLUSSIGN) && this.scanner.lookupType(1) === IDENT)) {
165 var sign = 0;
166 a = '1';
167
168 // just ignore a plus
169 if (this.scanner.isDelim(PLUSSIGN)) {
170 sign = 1;
171 this.scanner.next();
172 }
173
174 expectCharCode.call(this, 0, N);
175
176 switch (this.scanner.getTokenLength()) {
177 // '+'? n
178 // '+'? n <signed-integer>
179 // '+'? n ['+' | '-'] <signless-integer>
180 case 1:
181 this.scanner.next();
182 b = consumeB.call(this);
183 break;
184
185 // '+'? n- <signless-integer>
186 case 2:
187 expectCharCode.call(this, 1, HYPHENMINUS);
188
189 this.scanner.next();
190 this.scanner.skipSC();
191
192 checkTokenIsInteger.call(this, DISALLOW_SIGN);
193
194 b = '-' + this.consume(NUMBER);
195 break;
196
197 // '+'? <ndashdigit-ident>
198 default:
199 expectCharCode.call(this, 1, HYPHENMINUS);
200 checkInteger.call(this, 2, DISALLOW_SIGN);
201 this.scanner.next();
202
203 b = this.scanner.substrToCursor(start + sign + 1);
204 }
205 }
206
207 // <ndashdigit-dimension>
208 // <ndash-dimension> <signless-integer>
209 // <n-dimension>
210 // <n-dimension> <signed-integer>
211 // <n-dimension> ['+' | '-'] <signless-integer>
212 else if (this.scanner.tokenType === DIMENSION) {
213 var code = this.scanner.source.charCodeAt(this.scanner.tokenStart);
214 var sign = code === PLUSSIGN || code === HYPHENMINUS;
215
216 for (var i = this.scanner.tokenStart + sign; i < this.scanner.tokenEnd; i++) {
217 if (!isDigit(this.scanner.source.charCodeAt(i))) {
218 break;
219 }
220 }
221
222 if (i === this.scanner.tokenStart + sign) {
223 this.error('Integer is expected', this.scanner.tokenStart + sign);
224 }
225
226 expectCharCode.call(this, i - this.scanner.tokenStart, N);
227 a = this.scanner.source.substring(start, i);
228
229 // <n-dimension>
230 // <n-dimension> <signed-integer>
231 // <n-dimension> ['+' | '-'] <signless-integer>
232 if (i + 1 === this.scanner.tokenEnd) {
233 this.scanner.next();
234 b = consumeB.call(this);
235 } else {
236 expectCharCode.call(this, i - this.scanner.tokenStart + 1, HYPHENMINUS);
237
238 // <ndash-dimension> <signless-integer>
239 if (i + 2 === this.scanner.tokenEnd) {
240 this.scanner.next();
241 this.scanner.skipSC();
242 checkTokenIsInteger.call(this, DISALLOW_SIGN);
243 b = '-' + this.consume(NUMBER);
244 }
245 // <ndashdigit-dimension>
246 else {
247 checkInteger.call(this, i - this.scanner.tokenStart + 2, DISALLOW_SIGN);
248 this.scanner.next();
249 b = this.scanner.substrToCursor(i + 1);
250 }
251 }
252 } else {
253 this.error();
254 }
255
256 if (a !== null && a.charCodeAt(0) === PLUSSIGN) {
257 a = a.substr(1);
258 }
259
260 if (b !== null && b.charCodeAt(0) === PLUSSIGN) {
261 b = b.substr(1);
262 }
263
264 return {
265 type: 'AnPlusB',
266 loc: this.getLocation(start, this.scanner.tokenStart),
267 a: a,
268 b: b
269 };
270 },
271 generate: function(node) {
272 var a = node.a !== null && node.a !== undefined;
273 var b = node.b !== null && node.b !== undefined;
274
275 if (a) {
276 this.chunk(
277 node.a === '+1' ? '+n' : // eslint-disable-line operator-linebreak, indent
278 node.a === '1' ? 'n' : // eslint-disable-line operator-linebreak, indent
279 node.a === '-1' ? '-n' : // eslint-disable-line operator-linebreak, indent
280 node.a + 'n' // eslint-disable-line operator-linebreak, indent
281 );
282
283 if (b) {
284 b = String(node.b);
285 if (b.charAt(0) === '-' || b.charAt(0) === '+') {
286 this.chunk(b.charAt(0));
287 this.chunk(b.substr(1));
288 } else {
289 this.chunk('+');
290 this.chunk(b);
291 }
292 }
293 } else {
294 this.chunk(String(node.b));
295 }
296 }
297};
Note: See TracBrowser for help on using the repository browser.