diff options
| author | Igor Minar | 2010-10-27 15:20:05 -0700 | 
|---|---|---|
| committer | Igor Minar | 2010-10-27 15:32:30 -0700 | 
| commit | c67af8a03819004c4aaa775805badd1e631af738 (patch) | |
| tree | 7426c057fd9bffd1a25fc9c191732d2e292716fe /src/Parser.js | |
| parent | 2da1de5a6da0cedf490c54509487c27ba018585a (diff) | |
| download | angular.js-c67af8a03819004c4aaa775805badd1e631af738.tar.bz2 | |
rename src/Parser.js to src/parser.js
Diffstat (limited to 'src/Parser.js')
| -rw-r--r-- | src/Parser.js | 663 | 
1 files changed, 0 insertions, 663 deletions
diff --git a/src/Parser.js b/src/Parser.js deleted file mode 100644 index 8dc8f9c2..00000000 --- a/src/Parser.js +++ /dev/null @@ -1,663 +0,0 @@ -var OPERATORS = { -    'null':function(self){return _null;}, -    'true':function(self){return true;}, -    'false':function(self){return false;}, -    $undefined:noop, -    '+':function(self, a,b){return (isDefined(a)?a:0)+(isDefined(b)?b:0);}, -    '-':function(self, a,b){return (isDefined(a)?a:0)-(isDefined(b)?b:0);}, -    '*':function(self, a,b){return a*b;}, -    '/':function(self, a,b){return a/b;}, -    '%':function(self, a,b){return a%b;}, -    '^':function(self, a,b){return a^b;}, -    '=':function(self, a,b){return setter(self, a, b);}, -    '==':function(self, a,b){return a==b;}, -    '!=':function(self, a,b){return a!=b;}, -    '<':function(self, a,b){return a<b;}, -    '>':function(self, a,b){return a>b;}, -    '<=':function(self, a,b){return a<=b;}, -    '>=':function(self, a,b){return a>=b;}, -    '&&':function(self, a,b){return a&&b;}, -    '||':function(self, a,b){return a||b;}, -    '&':function(self, a,b){return a&b;}, -//    '|':function(self, a,b){return a|b;}, -    '|':function(self, a,b){return b(self, a);}, -    '!':function(self, a){return !a;} -}; -var ESCAPE = {"n":"\n", "f":"\f", "r":"\r", "t":"\t", "v":"\v", "'":"'", '"':'"'}; - -function lex(text, parseStringsForObjects){ -  var dateParseLength = parseStringsForObjects ? 20 : -1, -      tokens = [], -      token, -      index = 0, -      json = [], -      ch, -      lastCh = ':'; // can start regexp - -  while (index < text.length) { -    ch = text.charAt(index); -    if (is('"\'')) { -      readString(ch); -    } else if (isNumber(ch) || is('.') && isNumber(peek())) { -      readNumber(); -    } else if ( was('({[:,;') && is('/') ) { -      readRegexp(); -    } else if (isIdent(ch)) { -      readIdent(); -      if (was('{,') && json[0]=='{' && -         (token=tokens[tokens.length-1])) { -        token.json = token.text.indexOf('.') == -1; -      } -    } else if (is('(){}[].,;:')) { -      tokens.push({index:index, text:ch, json:is('{}[]:,')}); -      if (is('{[')) json.unshift(ch); -      if (is('}]')) json.shift(); -      index++; -    } else if (isWhitespace(ch)) { -      index++; -      continue; -    } else { -      var ch2 = ch + peek(), -          fn = OPERATORS[ch], -          fn2 = OPERATORS[ch2]; -      if (fn2) { -        tokens.push({index:index, text:ch2, fn:fn2}); -        index += 2; -      } else if (fn) { -        tokens.push({index:index, text:ch, fn:fn, json: was('[,:') && is('+-')}); -        index += 1; -      } else { -        throw "Lexer Error: Unexpected next character [" + -            text.substring(index) + -            "] in expression '" + text + -            "' at column '" + (index+1) + "'."; -      } -    } -    lastCh = ch; -  } -  return tokens; - -  function is(chars) { -    return chars.indexOf(ch) != -1; -  } - -  function was(chars) { -    return chars.indexOf(lastCh) != -1; -  } - -  function peek() { -    return index + 1 < text.length ? text.charAt(index + 1) : false; -  } -  function isNumber(ch) { -    return '0' <= ch && ch <= '9'; -  } -  function isWhitespace(ch) { -    return ch == ' ' || ch == '\r' || ch == '\t' || -           ch == '\n' || ch == '\v' || ch == '\u00A0'; // IE treats non-breaking space as \u00A0 -  } -  function isIdent(ch) { -    return 'a' <= ch && ch <= 'z' || -           'A' <= ch && ch <= 'Z' || -           '_' == ch || ch == '$'; -  } -  function isExpOperator(ch) { -    return ch == '-' || ch == '+'; -  } -  function readNumber() { -    var number = ""; -    var start = index; -    while (index < text.length) { -      var ch = 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') { -          throw 'Lexer found invalid exponential value "' + text + '"'; -        } else { -          break; -        } -      } -      index++; -    } -    number = 1 * number; -    tokens.push({index:start, text:number, json:true, -      fn:function(){return number;}}); -  } -  function readIdent() { -    var ident = ""; -    var start = index; -    while (index < text.length) { -      var ch = text.charAt(index); -      if (ch == '.' || isIdent(ch) || isNumber(ch)) { -        ident += ch; -      } else { -        break; -      } -      index++; -    } -    var fn = OPERATORS[ident]; -    if (!fn) { -      fn = getterFn(ident); -      fn.isAssignable = ident; -    } -    tokens.push({index:start, text:ident, fn:fn, 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)) -            throw "Lexer Error: Invalid unicode escape [\\u" + -              hex + "] starting at column '" + -              start + "' in expression '" + text + "'."; -          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++; -    } -    throw "Lexer Error: Unterminated quote [" + -        text.substring(start) + "] starting at column '" + -        (start+1) + "' in expression '" + text + "'."; -  } -  function readRegexp(quote) { -    var start = index; -    index++; -    var regexp = ""; -    var escape = false; -    while (index < text.length) { -      var ch = text.charAt(index); -      if (escape) { -        regexp += ch; -        escape = false; -      } else if (ch === '\\') { -        regexp += ch; -        escape = true; -      } else if (ch === '/') { -        index++; -        var flags = ""; -        if (isIdent(text.charAt(index))) { -          readIdent(); -          flags = tokens.pop().text; -        } -        var compiledRegexp = new RegExp(regexp, flags); -        tokens.push({index:start, text:regexp, flags:flags, -          fn:function(){return compiledRegexp;}}); -        return; -      } else { -        regexp += ch; -      } -      index++; -    } -    throw "Lexer Error: Unterminated RegExp [" + -        text.substring(start) + "] starting at column '" + -        (start+1) + "' in expression '" + text + "'."; -  } -} - -///////////////////////////////////////// - -function parser(text, json){ -  var ZERO = valueFn(0), -      tokens = lex(text, json); -  return { -      assertAllConsumed: assertAllConsumed, -      primary: primary, -      statements: statements, -      validator: validator, -      filter: filter, -      watch: watch -  }; - -  /////////////////////////////////// - -  function error(msg, token) { -    throw "Token '" + token.text + -      "' is " + msg + " at column='" + -      (token.index + 1) + "' of expression '" + -      text + "' starting at '" + text.substring(token.index) + "'."; -  } - -  function peekToken() { -    if (tokens.length === 0) -      throw "Unexpected end of expression: " + text; -    return tokens[0]; -  } - -  function peek(e1, e2, e3, e4) { -    if (tokens.length > 0) { -      var token = tokens[0]; -      var t = token.text; -      if (t==e1 || t==e2 || t==e3 || t==e4 || -          (!e1 && !e2 && !e3 && !e4)) { -        return token; -      } -    } -    return false; -  } - -  function expect(e1, e2, e3, e4){ -    var token = peek(e1, e2, e3, e4); -    if (token) { -      if (json && !token.json) { -        index = token.index; -        throw "Expression at column='" + -          token.index + "' of expression '" + -          text + "' starting at '" + text.substring(token.index) + -          "' is not valid json."; -      } -      tokens.shift(); -      this.currentToken = token; -      return token; -    } -    return false; -  } - -  function consume(e1){ -    if (!expect(e1)) { -      var token = peek(); -      throw "Expecting '" + e1 + "' at column '" + -          (token.index+1) + "' in '" + -          text + "' got '" + -          text.substring(token.index) + "'."; -    } -  } - -  function unaryFn(fn, right) { -    return function(self) { -      return fn(self, right(self)); -    }; -  } - -  function binaryFn(left, fn, right) { -    return function(self) { -      return fn(self, left(self), right(self)); -    }; -  } - -  function hasTokens () { -    return tokens.length > 0; -  } - -  function assertAllConsumed(){ -    if (tokens.length !== 0) { -      throw "Did not understand '" + text.substring(tokens[0].index) + -          "' while evaluating '" + text + "'."; -    } -  } - -  function statements(){ -    var statements = []; -    while(true) { -      if (tokens.length > 0 && !peek('}', ')', ';', ']')) -        statements.push(filterChain()); -      if (!expect(';')) { -        return function (self){ -          var value; -          for ( var i = 0; i < statements.length; i++) { -            var statement = statements[i]; -            if (statement) -              value = statement(self); -          } -          return value; -        }; -      } -    } -  } - -  function filterChain(){ -    var left = expression(); -    var token; -    while(true) { -      if ((token = expect('|'))) { -        left = binaryFn(left, token.fn, filter()); -      } else { -        return left; -      } -    } -  } - -  function filter(){ -    return pipeFunction(angularFilter); -  } - -  function validator(){ -    return pipeFunction(angularValidator); -  } - -  function pipeFunction(fnScope){ -    var fn = functionIdent(fnScope); -    var argsFn = []; -    var token; -    while(true) { -      if ((token = expect(':'))) { -        argsFn.push(expression()); -      } else { -        var fnInvoke = function(self, input){ -          var args = [input]; -          for ( var i = 0; i < argsFn.length; i++) { -            args.push(argsFn[i](self)); -          } -          return fn.apply(self, args); -        }; -        return function(){ -          return fnInvoke; -        }; -      } -    } -  } - -  function expression(){ -    return throwStmt(); -  } - -  function throwStmt(){ -    if (expect('throw')) { -      var throwExp = assignment(); -      return function (self) { -        throw throwExp(self); -      }; -    } else { -      return assignment(); -    } -  } - -  function assignment(){ -    var left = logicalOR(); -    var token; -    if (token = expect('=')) { -      if (!left.isAssignable) { -        throw "Left hand side '" + -        text.substring(0, token.index) + "' of assignment '" + -        text.substring(token.index) + "' is not assignable."; -      } -      var ident = function(){return left.isAssignable;}; -      return binaryFn(ident, token.fn, logicalOR()); -    } else { -      return left; -    } -  } - -  function logicalOR(){ -    var left = logicalAND(); -    var token; -    while(true) { -      if ((token = expect('||'))) { -        left = binaryFn(left, token.fn, logicalAND()); -      } else { -        return left; -      } -    } -  } - -  function logicalAND(){ -    var left = equality(); -    var token; -    if ((token = expect('&&'))) { -      left = binaryFn(left, token.fn, logicalAND()); -    } -    return left; -  } - -  function equality(){ -    var left = relational(); -    var token; -    if ((token = expect('==','!='))) { -      left = binaryFn(left, token.fn, equality()); -    } -    return left; -  } - -  function relational(){ -    var left = additive(); -    var token; -    if (token = expect('<', '>', '<=', '>=')) { -      left = binaryFn(left, token.fn, relational()); -    } -    return left; -  } - -  function additive(){ -    var left = multiplicative(); -    var token; -    while(token = expect('+','-')) { -      left = binaryFn(left, token.fn, multiplicative()); -    } -    return left; -  } - -  function multiplicative(){ -    var left = unary(); -    var token; -    while(token = expect('*','/','%')) { -      left = binaryFn(left, token.fn, unary()); -    } -    return left; -  } - -  function unary(){ -    var token; -    if (expect('+')) { -      return primary(); -    } else if (token = expect('-')) { -      return binaryFn(ZERO, token.fn, unary()); -    } else if (token = expect('!')) { -      return unaryFn(token.fn, unary()); -    } else { -      return primary(); -    } -  } - -  function functionIdent(fnScope) { -    var token = expect(); -    var element = token.text.split('.'); -    var instance = fnScope; -    var key; -    for ( var i = 0; i < element.length; i++) { -      key = element[i]; -      if (instance) -        instance = instance[key]; -    } -    if (typeof instance != $function) { -      throw "Function '" + token.text + "' at column '" + -      (token.index+1)  + "' in '" + text + "' is not defined."; -    } -    return instance; -  } - -  function primary() { -    var primary; -    if (expect('(')) { -      var expression = filterChain(); -      consume(')'); -      primary = expression; -    } else if (expect('[')) { -      primary = arrayDeclaration(); -    } else if (expect('{')) { -      primary = object(); -    } else { -      var token = expect(); -      primary = token.fn; -      if (!primary) { -        error("not a primary expression", token); -      } -    } -    var next; -    while (next = expect('(', '[', '.')) { -      if (next.text === '(') { -        primary = functionCall(primary); -      } else if (next.text === '[') { -        primary = objectIndex(primary); -      } else if (next.text === '.') { -        primary = fieldAccess(primary); -      } else { -        throw "IMPOSSIBLE"; -      } -    } -    return primary; -  } - -  function fieldAccess(object) { -    var field = expect().text; -    var getter = getterFn(field); -    var fn = function (self){ -      return getter(object(self)); -    }; -    fn.isAssignable = field; -    return fn; -  } - -  function objectIndex(obj) { -    var indexFn = expression(); -    consume(']'); -    if (expect('=')) { -      var rhs = expression(); -      return function (self){ -        return obj(self)[indexFn(self)] = rhs(self); -      }; -    } else { -      return function (self){ -        var o = obj(self); -        var i = indexFn(self); -        return (o) ? o[i] : _undefined; -      }; -    } -  } - -  function functionCall(fn) { -    var argsFn = []; -    if (peekToken().text != ')') { -      do { -        argsFn.push(expression()); -      } while (expect(',')); -    } -    consume(')'); -    return function (self){ -      var args = []; -      for ( var i = 0; i < argsFn.length; i++) { -        args.push(argsFn[i](self)); -      } -      var fnPtr = fn(self) || noop; -      // IE stupidity! -      return fnPtr.apply ? -          fnPtr.apply(self, args) : -            fnPtr(args[0], args[1], args[2], args[3], args[4]); -    }; -  } - -  // This is used with json array declaration -  function arrayDeclaration () { -    var elementFns = []; -    if (peekToken().text != ']') { -      do { -        elementFns.push(expression()); -      } while (expect(',')); -    } -    consume(']'); -    return function (self){ -      var array = []; -      for ( var i = 0; i < elementFns.length; i++) { -        array.push(elementFns[i](self)); -      } -      return array; -    }; -  } - -  function object () { -    var keyValues = []; -    if (peekToken().text != '}') { -      do { -        var token = expect(), -        key = token.string || token.text; -        consume(":"); -        var value = expression(); -        keyValues.push({key:key, value:value}); -      } while (expect(',')); -    } -    consume('}'); -    return function (self){ -      var object = {}; -      for ( var i = 0; i < keyValues.length; i++) { -        var keyValue = keyValues[i]; -        var value = keyValue.value(self); -        object[keyValue.key] = value; -      } -      return object; -    }; -  } - -  function watch () { -    var decl = []; -    while(hasTokens()) { -      decl.push(watchDecl()); -      if (!expect(';')) { -        assertAllConsumed(); -      } -    } -    assertAllConsumed(); -    return function (self){ -      for ( var i = 0; i < decl.length; i++) { -        var d = decl[i](self); -        self.addListener(d.name, d.fn); -      } -    }; -  } - -  function watchDecl () { -    var anchorName = expect().text; -    consume(":"); -    var expressionFn; -    if (peekToken().text == '{') { -      consume("{"); -      expressionFn = statements(); -      consume("}"); -    } else { -      expressionFn = expression(); -    } -    return function(self) { -      return {name:anchorName, fn:expressionFn}; -    }; -  } -} - - - -  | 
