diff options
| author | Misko Hevery | 2010-12-07 11:42:34 -0800 |
|---|---|---|
| committer | Misko Hevery | 2010-12-08 14:39:22 -0800 |
| commit | 23fc73081feb640164615930b36ef185c23a3526 (patch) | |
| tree | 3354648159e348e97ba4b49c005d7c9e64a343bd /src/parser.js | |
| parent | e5e69d9b90850eb653883f52c76e28dd870ee067 (diff) | |
| download | angular.js-23fc73081feb640164615930b36ef185c23a3526.tar.bz2 | |
Refactor lexer to use regular expressions
Diffstat (limited to 'src/parser.js')
| -rw-r--r-- | src/parser.js | 137 |
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"); } } |
