aboutsummaryrefslogtreecommitdiffstats
path: root/src/parser.js
diff options
context:
space:
mode:
authorMisko Hevery2010-12-07 11:42:34 -0800
committerMisko Hevery2010-12-08 14:39:22 -0800
commit23fc73081feb640164615930b36ef185c23a3526 (patch)
tree3354648159e348e97ba4b49c005d7c9e64a343bd /src/parser.js
parente5e69d9b90850eb653883f52c76e28dd870ee067 (diff)
downloadangular.js-23fc73081feb640164615930b36ef185c23a3526.tar.bz2
Refactor lexer to use regular expressions
Diffstat (limited to 'src/parser.js')
-rw-r--r--src/parser.js137
1 files changed, 47 insertions, 90 deletions
diff --git a/src/parser.js b/src/parser.js
index 01edb3f1..fec23899 100644
--- a/src/parser.js
+++ b/src/parser.js
@@ -32,7 +32,7 @@ function lex(text, parseStringsForObjects){
index = 0,
json = [],
ch,
- lastCh = ':'; // can start regexp
+ lastCh = ':';
while (index < text.length) {
ch = text.charAt(index);
@@ -71,6 +71,9 @@ function lex(text, parseStringsForObjects){
lastCh = ch;
}
return tokens;
+
+
+ //////////////////////////////////////////////
function is(chars) {
return chars.indexOf(ch) != -1;
@@ -95,10 +98,6 @@ function lex(text, parseStringsForObjects){
'A' <= ch && ch <= 'Z' ||
'_' == ch || ch == '$';
}
- function isExpOperator(ch) {
- return ch == '-' || ch == '+' || isNumber(ch);
- }
-
function throwError(error, start, end) {
end = end || index;
throw Error("Lexer Error: " + error + " at column" +
@@ -107,103 +106,61 @@ function lex(text, parseStringsForObjects){
" " + end) +
" in expression [" + text + "].");
}
+
+ function consume(regexp, processToken, errorMsg) {
+ var match = text.substr(index).match(regexp);
+ var token = {index: index};
+ var start = index;
+ if (!match) throwError(errorMsg);
+ index += match[0].length;
+ processToken(token, token.text = match[0], start);
+ tokens.push(token);
+ }
function readNumber() {
- var number = "";
- var start = index;
- while (index < text.length) {
- var ch = lowercase(text.charAt(index));
- if (ch == '.' || isNumber(ch)) {
- number += ch;
- } else {
- var peekCh = peek();
- if (ch == 'e' && isExpOperator(peekCh)) {
- number += ch;
- } else if (isExpOperator(ch) &&
- peekCh && isNumber(peekCh) &&
- number.charAt(number.length - 1) == 'e') {
- number += ch;
- } else if (isExpOperator(ch) &&
- (!peekCh || !isNumber(peekCh)) &&
- number.charAt(number.length - 1) == 'e') {
- throwError('Invalid exponent');
- } else {
- break;
- }
- }
- index++;
- }
- number = 1 * number;
- tokens.push({index:start, text:number, json:true,
- fn:function(){return number;}});
+ consume(/^(\d+)?(\.\d+)?([eE][+-]?\d+)?/, function(token, number){
+ token.text = number = 1 * number;
+ token.json = true;
+ token.fn = valueFn(number);
+ }, "Not a valid number");
}
+
function readIdent() {
- var ident = "";
- var start = index;
- var fn;
- while (index < text.length) {
- var ch = text.charAt(index);
- if (ch == '.' || isIdent(ch) || isNumber(ch)) {
- ident += ch;
- } else {
- break;
+ consume(/^[\w_\$][\w_\$\d]*(\.[\w_\$][\w_\$\d]*)*/, function(token, ident){
+ fn = OPERATORS[ident];
+ if (!fn) {
+ fn = getterFn(ident);
+ fn.isAssignable = ident;
}
- index++;
- }
- fn = OPERATORS[ident];
- tokens.push({
- index:start,
- text:ident,
- json: fn,
- fn:fn||extend(getterFn(ident), {
+ token.fn = OPERATORS[ident]||extend(getterFn(ident), {
assign:function(self, value){
return setter(self, ident, value);
}
- })
+ });
+ token.json = OPERATORS[ident];
});
}
function readString(quote) {
- var start = index;
- index++;
- var string = "";
- var rawString = quote;
- var escape = false;
- while (index < text.length) {
- var ch = text.charAt(index);
- rawString += ch;
- if (escape) {
- if (ch == 'u') {
- var hex = text.substring(index + 1, index + 5);
- if (!hex.match(/[\da-f]{4}/i))
- throwError( "Invalid unicode escape [\\u" + hex + "]");
- index += 4;
- string += String.fromCharCode(parseInt(hex, 16));
- } else {
- var rep = ESCAPE[ch];
- if (rep) {
- string += rep;
- } else {
- string += ch;
- }
- }
- escape = false;
- } else if (ch == '\\') {
- escape = true;
- } else if (ch == quote) {
- index++;
- tokens.push({index:start, text:rawString, string:string, json:true,
- fn:function(){
- return (string.length == dateParseLength) ?
- angular['String']['toDate'](string) : string;
- }});
- return;
- } else {
- string += ch;
- }
- index++;
- }
- throwError("Unterminated quote", start);
+ consume(/^(('(\\'|[^'])*')|("(\\"|[^"])*"))/, function(token, rawString, start){
+ var hasError;
+ var string = token.string = rawString.substr(1, rawString.length - 2).
+ replace(/(\\u(.?.?.?.?))|(\\(.))/g,
+ function(match, wholeUnicode, unicode, wholeEscape, escape){
+ if (unicode && !unicode.match(/[\da-fA-F]{4}/))
+ hasError = hasError || bind(null, throwError, "Invalid unicode escape [\\u" + unicode + "]", start);
+ return unicode ?
+ String.fromCharCode(parseInt(unicode, 16)) :
+ ESCAPE[escape] || escape;
+ });
+ (hasError||noop)();
+ token.json = true;
+ token.fn = function(){
+ return (string.length == dateParseLength) ?
+ angular['String']['toDate'](string) :
+ string;
+ };
+ }, "Unterminated string");
}
}