Skip to content

Commit f2cede8

Browse files
committed
Cleanup parser code to expose smaller API
1 parent 26d90b1 commit f2cede8

File tree

7 files changed

+31
-54
lines changed

7 files changed

+31
-54
lines changed

src/JSON.js

+2-7
Original file line numberDiff line numberDiff line change
@@ -35,19 +35,14 @@ function toJson(obj, pretty) {
3535
function fromJson(json, useNative) {
3636
if (!isString(json)) return json;
3737

38-
var obj, p, expression;
38+
var obj;
3939

4040
try {
4141
if (useNative && window.JSON && window.JSON.parse) {
4242
obj = JSON.parse(json);
4343
return transformDates(obj);
4444
}
45-
46-
p = parser(json, true);
47-
expression = p.primary();
48-
p.assertAllConsumed();
49-
return expression();
50-
45+
return parser(json, true).primary()();
5146
} catch (e) {
5247
error("fromJson error: ", json, e);
5348
throw e;

src/Scope.js

-1
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,6 @@ function expressionCompile(exp){
9292
if (!fn) {
9393
var p = parser(exp);
9494
var fnSelf = p.statements();
95-
p.assertAllConsumed();
9695
fn = compileCache[exp] = extend(
9796
function(){ return fnSelf(this);},
9897
{fnSelf: fnSelf});

src/parser.js

+18-35
Original file line numberDiff line numberDiff line change
@@ -240,22 +240,29 @@ function parser(text, json){
240240
function (){ throwError("is not valid json", {text:text, index:0}); };
241241
}
242242
return {
243-
assertAllConsumed: assertAllConsumed,
244-
assignable: assignable,
245-
primary: primary,
246-
statements: statements,
247-
validator: validator,
248-
formatter: formatter,
249-
filter: filter,
250-
//TODO: delete me, since having watch in UI is logic in UI. (leftover form getangular)
251-
watch: watch
243+
assignable: assertConsumed(assignable),
244+
primary: assertConsumed(primary),
245+
statements: assertConsumed(statements),
246+
validator: assertConsumed(validator),
247+
formatter: assertConsumed(formatter),
248+
filter: assertConsumed(filter)
252249
};
253250

251+
function assertConsumed(fn) {
252+
return function(){
253+
var value = fn();
254+
if (tokens.length !== 0) {
255+
throwError("is an unexpected token", tokens[0]);
256+
}
257+
return value;
258+
};
259+
}
260+
254261
///////////////////////////////////
255262
function throwError(msg, token) {
256-
throw Error("Parse Error: Token '" + token.text +
263+
throw Error("Syntax Error: Token '" + token.text +
257264
"' " + msg + " at column " +
258-
(token.index + 1) + " of expression [" +
265+
(token.index + 1) + " of the expression [" +
259266
text + "] starting at [" + text.substring(token.index) + "].");
260267
}
261268

@@ -313,12 +320,6 @@ function parser(text, json){
313320
return tokens.length > 0;
314321
}
315322

316-
function assertAllConsumed(){
317-
if (tokens.length !== 0) {
318-
throwError("is extra token not part of expression", tokens[0]);
319-
}
320-
}
321-
322323
function statements(){
323324
var statements = [];
324325
while(true) {
@@ -639,24 +640,6 @@ function parser(text, json){
639640
};
640641
}
641642

642-
//TODO: delete me, since having watch in UI is logic in UI. (leftover form getangular)
643-
function watch () {
644-
var decl = [];
645-
while(hasTokens()) {
646-
decl.push(watchDecl());
647-
if (!expect(';')) {
648-
assertAllConsumed();
649-
}
650-
}
651-
assertAllConsumed();
652-
return function (self){
653-
for ( var i = 0; i < decl.length; i++) {
654-
var d = decl[i](self);
655-
self.addListener(d.name, d.fn);
656-
}
657-
};
658-
}
659-
660643
function watchDecl () {
661644
var anchorName = expect().text;
662645
consume(":");

test/BinderSpec.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -581,7 +581,7 @@ describe('Binder', function(){
581581

582582
browserTrigger(second, 'click');
583583
assertTrue(second.hasClass("ng-exception"));
584-
expect(errorLogs.shift()[0]).toMatchError(/Parse Error: Token ':' not a primary expression/);
584+
expect(errorLogs.shift()[0]).toMatchError(/Syntax Error: Token ':' not a primary expression/);
585585
});
586586

587587
it('ItShouldSelectTheCorrectRadioBox', function(){

test/JsonSpec.js

+7-7
Original file line numberDiff line numberDiff line change
@@ -163,37 +163,37 @@ describe('json', function(){
163163
describe('security', function(){
164164
it('should not allow naked expressions', function(){
165165
expect(function(){fromJson('1+2');}).
166-
toThrow(new Error("Parse Error: Token '+' is extra token not part of expression at column 2 of expression [1+2] starting at [+2]."));
166+
toThrow(new Error("Syntax Error: Token '+' is an unexpected token at column 2 of the expression [1+2] starting at [+2]."));
167167
});
168168

169169
it('should not allow naked expressions group', function(){
170170
expect(function(){fromJson('(1+2)');}).
171-
toThrow(new Error("Parse Error: Token '(' is not valid json at column 1 of expression [(1+2)] starting at [(1+2)]."));
171+
toThrow(new Error("Syntax Error: Token '(' is not valid json at column 1 of the expression [(1+2)] starting at [(1+2)]."));
172172
});
173173

174174
it('should not allow expressions in objects', function(){
175175
expect(function(){fromJson('{a:abc()}');}).
176-
toThrow(new Error("Parse Error: Token 'abc' is not valid json at column 4 of expression [{a:abc()}] starting at [abc()}]."));
176+
toThrow(new Error("Syntax Error: Token 'abc' is not valid json at column 4 of the expression [{a:abc()}] starting at [abc()}]."));
177177
});
178178

179179
it('should not allow expressions in arrays', function(){
180180
expect(function(){fromJson('[1+2]');}).
181-
toThrow(new Error("Parse Error: Token '+' is not valid json at column 3 of expression [[1+2]] starting at [+2]]."));
181+
toThrow(new Error("Syntax Error: Token '+' is not valid json at column 3 of the expression [[1+2]] starting at [+2]]."));
182182
});
183183

184184
it('should not allow vars', function(){
185185
expect(function(){fromJson('[1, x]');}).
186-
toThrow(new Error("Parse Error: Token 'x' is not valid json at column 5 of expression [[1, x]] starting at [x]]."));
186+
toThrow(new Error("Syntax Error: Token 'x' is not valid json at column 5 of the expression [[1, x]] starting at [x]]."));
187187
});
188188

189189
it('should not allow dereference', function(){
190190
expect(function(){fromJson('["".constructor]');}).
191-
toThrow(new Error("Parse Error: Token '.' is not valid json at column 4 of expression [[\"\".constructor]] starting at [.constructor]]."));
191+
toThrow(new Error("Syntax Error: Token '.' is not valid json at column 4 of the expression [[\"\".constructor]] starting at [.constructor]]."));
192192
});
193193

194194
it('should not allow expressions ofter valid json', function(){
195195
expect(function(){fromJson('[].constructor');}).
196-
toThrow(new Error("Parse Error: Token '.' is not valid json at column 3 of expression [[].constructor] starting at [.constructor]."));
196+
toThrow(new Error("Syntax Error: Token '.' is not valid json at column 3 of the expression [[].constructor] starting at [.constructor]."));
197197
});
198198

199199
it('should not allow object dereference', function(){

test/ParserSpec.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,7 @@ describe('parser', function() {
200200

201201
expect(function() {
202202
scope.$eval("1|nonExistant");
203-
}).toThrow(new Error("Parse Error: Token 'nonExistant' should be a function at column 3 of expression [1|nonExistant] starting at [nonExistant]."));
203+
}).toThrow(new Error("Syntax Error: Token 'nonExistant' should be a function at column 3 of the expression [1|nonExistant] starting at [nonExistant]."));
204204

205205
scope.$set('offset', 3);
206206
expect(scope.$eval("'abcd'|upper._case")).toEqual("ABCD");

test/widgetsSpec.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -537,15 +537,15 @@ describe("widget", function(){
537537
compile('<input type="text" name="throw \'\'" value="x"/>');
538538
expect(element.hasClass('ng-exception')).toBeTruthy();
539539
expect(scope.$service('$log').error.logs.shift()[0]).
540-
toMatchError(/Parse Error: Token '''' is extra token not part of expression/);
540+
toMatchError(/Syntax Error: Token '''' is an unexpected token/);
541541
});
542542

543543
it('should report error on ng:change exception', function(){
544544
compile('<button ng:change="a-2=x">click</button>');
545545
browserTrigger(element);
546546
expect(element.hasClass('ng-exception')).toBeTruthy();
547547
expect(scope.$service('$log').error.logs.shift()[0]).
548-
toMatchError(/Parse Error: Token '=' implies assignment but \[a-2\] can not be assigned to/);
548+
toMatchError(/Syntax Error: Token '=' implies assignment but \[a-2\] can not be assigned to/);
549549
});
550550
});
551551

0 commit comments

Comments
 (0)