From 739f719ad6f26c007deb6b48134734588538bcbe Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Mon, 27 Feb 2012 08:37:21 +0100 Subject: [UP] py.parse 0.2 to py.js 0.4 ~ should probably go through a testing phase (checking its result against that of eval_domain_and_context) for a while, but apart from that it's supposed to work. 'stdlib' stuff (datetime.date.today, datetime.timedelta, time.localtime, time.time, time.strftime) still need to be written. Isn't there also a dateutil.relativedeleta somewhere? Anyway that needs to be done and the various evaluation contexts need to be defined, but the valuator itself should mostly work. bzr revid: xmo@openerp.com-20120227073721-nkgeiqacbzch8xev --- addons/web/static/lib/py.parse/.hg_archival.txt | 5 - addons/web/static/lib/py.parse/README | 1 - addons/web/static/lib/py.parse/TODO.rst | 14 - addons/web/static/lib/py.parse/lib/py.js | 546 ------------------------ addons/web/static/lib/py.parse/test/test.js | 90 ---- 5 files changed, 656 deletions(-) delete mode 100644 addons/web/static/lib/py.parse/.hg_archival.txt delete mode 100644 addons/web/static/lib/py.parse/README delete mode 100644 addons/web/static/lib/py.parse/TODO.rst delete mode 100644 addons/web/static/lib/py.parse/lib/py.js delete mode 100644 addons/web/static/lib/py.parse/test/test.js (limited to 'addons/web/static/lib/py.parse') diff --git a/addons/web/static/lib/py.parse/.hg_archival.txt b/addons/web/static/lib/py.parse/.hg_archival.txt deleted file mode 100644 index 43d5d80a9e4..00000000000 --- a/addons/web/static/lib/py.parse/.hg_archival.txt +++ /dev/null @@ -1,5 +0,0 @@ -repo: 076b192d0d8ab2b92d1dbcfa3da055382f30eaea -node: 87fb1b67d6a13f10a1a328104ee4d4b2c36801ec -branch: default -latesttag: 0.2 -latesttagdistance: 1 diff --git a/addons/web/static/lib/py.parse/README b/addons/web/static/lib/py.parse/README deleted file mode 100644 index 453f001ee15..00000000000 --- a/addons/web/static/lib/py.parse/README +++ /dev/null @@ -1 +0,0 @@ -Parser and evaluator of Python expressions diff --git a/addons/web/static/lib/py.parse/TODO.rst b/addons/web/static/lib/py.parse/TODO.rst deleted file mode 100644 index 3638b681ddc..00000000000 --- a/addons/web/static/lib/py.parse/TODO.rst +++ /dev/null @@ -1,14 +0,0 @@ -* Parser - since parsing expressions, try with a pratt parser - http://journal.stuffwithstuff.com/2011/03/19/pratt-parsers-expression-parsing-made-easy/ - http://effbot.org/zone/simple-top-down-parsing.htm - -Evaluator ---------- - -* Stop busyworking trivial binary operator -* Make it *trivial* to build Python type-wrappers -* Implement Python's `data model - protocols`_ - for *all* supported operations, optimizations can come later -* Automatically type-wrap everything (for now anyway) diff --git a/addons/web/static/lib/py.parse/lib/py.js b/addons/web/static/lib/py.parse/lib/py.js deleted file mode 100644 index 19f95a870bb..00000000000 --- a/addons/web/static/lib/py.parse/lib/py.js +++ /dev/null @@ -1,546 +0,0 @@ -var py = {}; -(function (exports) { - var NUMBER = /^\d$/, - NAME_FIRST = /^[a-zA-Z_]$/, - NAME = /^[a-zA-Z0-9_]$/; - - var create = function (o, props) { - function F() {} - F.prototype = o; - var inst = new F; - for(var name in props) { - if(!props.hasOwnProperty(name)) { continue; } - inst[name] = props[name]; - } - return inst; - }; - - var symbols = {}; - var comparators = {}; - var Base = { - nud: function () { throw new Error(this.id + " undefined as prefix"); }, - led: function (led) { throw new Error(this.id + " undefined as infix"); }, - toString: function () { - if (this.id === '(constant)' || this.id === '(number)' || this.id === '(name)' || this.id === '(string)') { - return [this.id.slice(0, this.id.length-1), ' ', this.value, ')'].join(''); - } else if (this.id === '(end)') { - return '(end)'; - } else if (this.id === '(comparator)' ) { - var repr = ['(comparator', this.expressions[0]]; - for (var i=0;i s.lbp) { - s.lbp = bp; - } - return s; - } - return symbols[id] = create(Base, { - id: id, - lbp: bp - }); - } - function constant(id) { - symbol(id).nud = function () { - this.id = "(constant)"; - this.value = id; - return this; - }; - } - function prefix(id, bp, nud) { - symbol(id).nud = nud || function () { - this.first = expression(bp); - return this - } - } - function infix(id, bp, led) { - symbol(id, bp).led = led || function (left) { - this.first = left; - this.second = expression(bp); - return this; - } - } - function infixr(id, bp) { - symbol(id, bp).led = function (left) { - this.first = left; - this.second = expression(bp - 1); - return this; - } - } - function comparator(id) { - comparators[id] = true; - var bp = 60; - infix(id, bp, function (left) { - this.id = '(comparator)'; - this.operators = [id]; - this.expressions = [left, expression(bp)]; - while (token.id in comparators) { - this.operators.push(token.id); - advance(); - this.expressions.push( - expression(bp)); - } - return this; - }); - } - - constant('None'); constant('False'); constant('True'); - - symbol('(number)').nud = function () { return this; }; - symbol('(name)').nud = function () { return this; }; - symbol('(string)').nud = function () { return this; }; - symbol('(end)'); - - symbol(':'); symbol(')'); symbol(']'); symbol('}'); symbol(','); - symbol('else'); - - symbol('lambda', 20).nud = function () { - this.first = []; - if (token.id !== ':') { - for(;;) { - if (token.id !== '(name)') { - throw new Error('Excepted an argument name'); - } - this.first.push(token); - advance(); - if (token.id !== ',') { - break; - } - advance(','); - } - } - advance(':'); - this.second = expression(); - return this; - }; - infix('if', 20, function (left) { - this.first = left; - this.second = expression(); - advance('else'); - this.third = expression(); - return this; - }); - - infixr('or', 30); infixr('and', 40); prefix('not', 50); - - comparator('in'); comparator('not in'); - comparator('is'); comparator('is not'); - comparator('<'); comparator('<='); - comparator('>'); comparator('>='); - comparator('<>'); comparator('!='); comparator('=='); - - infix('|', 70); infix('^', 80), infix('&', 90); - - infix('<<', 100); infix('>>', 100); - - infix('+', 110); infix('-', 110); - - infix('*', 120); infix('/', 120); - infix('//', 120), infix('%', 120); - - prefix('-', 130); prefix('+', 130); prefix('~', 130); - - infixr('**', 140); - - infix('.', 150, function (left) { - if (token.id !== '(name)') { - throw new Error('Expected attribute name, got ', token.id); - } - this.first = left; - this.second = token; - advance(); - return this; - }); - symbol('(', 150).nud = function () { - this.first = []; - var comma = false; - if (token.id !== ')') { - while (true) { - if (token.id === ')') { - break; - } - this.first.push(expression()); - if (token.id !== ',') { - break; - } - comma = true; - advance(','); - } - } - advance(')'); - if (!this.first.length || comma) { - return this; - } else { - return this.first[0]; - } - }; - symbol('(').led = function (left) { - this.first = left; - this.second = []; - if (token.id !== ")") { - for(;;) { - this.second.push(expression()); - if (token.id !== ',') { - break; - } - advance(','); - } - } - advance(")"); - return this; - - }; - infix('[', 150, function (left) { - this.first = left; - this.second = expression(); - advance("]"); - return this; - }); - symbol('[').nud = function () { - this.first = []; - if (token.id !== ']') { - for (;;) { - if (token.id === ']') { - break; - } - this.first.push(expression()); - if (token.id !== ',') { - break; - } - advance(','); - } - } - advance(']'); - return this; - }; - - symbol('{').nud = function () { - this.first = []; - if (token.id !== '}') { - for(;;) { - if (token.id === '}') { - break; - } - var key = expression(); - advance(':'); - var value = expression(); - this.first.push([key, value]); - if (token.id !== ',') { - break; - } - advance(','); - } - } - advance('}'); - return this; - }; - - var longops = { - '*': ['*'], - '<': ['<', '=', '>'], - '>': ['=', '>'], - '!': ['='], - '=': ['='], - '/': ['/'] - }; - function Tokenizer() { - this.states = ['initial']; - this.tokens = []; - } - Tokenizer.prototype = { - builder: function (empty) { - var key = this.states[0] + '_builder'; - if (empty) { - var value = this[key]; - delete this[key]; - return value; - } else { - return this[key] = this[key] || []; - } - }, - simple: function (type) { - this.tokens.push({type: type}); - }, - push: function (new_state) { - this.states.push(new_state); - }, - pop: function () { - this.states.pop(); - }, - - feed: function (str, index) { - var s = this.states; - return this[s[s.length - 1]](str, index); - }, - - initial: function (str, index) { - var character = str[index]; - - if (character in longops) { - var follow = longops[character]; - for(var i=0, len=follow.length; i> at index " + index - + ", character [[" + character + "]]" - + "; parsed so far: " + this.tokens); - }, - string: function (str, index) { - var character = str[index]; - if (character === '"' || character === "'") { - this.tokens.push(create(symbols['(string)'], { - value: this.builder(true).join('') - })); - this.pop(); - return index + 1; - } - this.builder().push(character); - return index + 1; - }, - number: function (str, index) { - var character = str[index]; - if (!(character == '.' || NUMBER.test(character))) { - this.tokens.push(create(symbols['(number)'], { - value: parseFloat(this.builder(true).join('')) - })); - this.pop(); - return index; - } - this.builder().push(character); - return index + 1; - }, - name: function (str, index) { - var character = str[index]; - if (!NAME.test(character)) { - var name = this.builder(true).join(''); - var symbol = symbols[name]; - if (symbol) { - if (name === 'in' && this.tokens[this.tokens.length-1].id === 'not') { - symbol = symbols['not in']; - this.tokens.pop(); - } else if (name === 'not' && this.tokens[this.tokens.length-1].id === 'is') { - symbol = symbols['is not']; - this.tokens.pop(); - } - this.tokens.push(create(symbol)); - } else { - this.tokens.push(create(symbols['(name)'], { - value: name - })); - } - this.pop(); - return index; - } - this.builder().push(character); - return index + 1; - } - }; - - exports.tokenize = function tokenize(str) { - var index = 0, - tokenizer = new Tokenizer(str); - str += '\0'; - - do { - index = tokenizer.feed(str, index); - } while (index !== str.length); - return tokenizer.tokens; - }; - - var token, next; - function expression(rbp) { - rbp = rbp || 0; - var t = token; - token = next(); - var left = t.nud(); - while (rbp < token.lbp) { - t = token; - token = next(); - left = t.led(left); - } - return left; - } - function advance(id) { - if (id && token.id !== id) { - throw new Error( - 'Expected "' + id + '", got "' + token.id + '"'); - } - token = next(); - } - - exports.object = create({}, {}); - exports.bool = function (arg) { return !!arg; }; - exports.tuple = create(exports.object, { - __contains__: function (value) { - for(var i=0, len=this.values.length; i': return a > b; - case '>=': return a >= b; - case 'in': - if (typeof b === 'string') { - return b.indexOf(a) !== -1; - } - return b.__contains__(a); - case 'not in': - if (typeof b === 'string') { - return b.indexOf(a) === -1; - } - return !b.__contains__(a); - } - throw new Error('SyntaxError: unknown comparator [[' + operator + ']]'); - }; - exports.evaluate = function (expr, context) { - switch (expr.id) { - case '(name)': - var val = context[expr.value]; - if (val === undefined) { - throw new Error("NameError: name '" + expr.value + "' is not defined"); - } - return val; - case '(string)': - case '(number)': - return expr.value; - case '(constant)': - if (expr.value === 'None') - return null; - else if (expr.value === 'False') - return false; - else if (expr.value === 'True') - return true; - throw new Error("SyntaxError: unknown constant '" + expr.value + "'"); - case '(comparator)': - var result, left = exports.evaluate(expr.expressions[0], context); - for(var i=0; i= 3')); -assert.ok(py.eval('3 >= 3')); -assert.ok(!py.eval('5 < 3')); -assert.ok(py.eval('1 < 3 < 5')); -assert.ok(py.eval('5 > 3 > 1')); -assert.ok(py.eval('1 < 3 > 2 == 2 > -2 not in (0, 1, 2)')); -// string rich comparisons -assert.ok(py.eval( - 'date >= current', {date: '2010-06-08', current: '2010-06-05'})); - -// Boolean operators -assert.ok(py.eval( - "foo == 'foo' or foo == 'bar'", {foo: 'bar'})); -assert.ok(py.eval( - "foo == 'foo' and bar == 'bar'", {foo: 'foo', bar: 'bar'})); -// - lazyness, second clauses NameError if not short-circuited -assert.ok(py.eval( - "foo == 'foo' or bar == 'bar'", {foo: 'foo'})); -assert.ok(!py.eval( - "foo == 'foo' and bar == 'bar'", {foo: 'bar'})); - -// contains (in) -assert.ok(py.eval( - "foo in ('foo', 'bar')", {foo: 'bar'})); -assert.ok(py.eval('1 in (1, 2, 3, 4)')); -assert.ok(!py.eval('1 in (2, 3, 4)')); -assert.ok(py.eval('type in ("url",)', {type: 'url'})); -assert.ok(!py.eval('type in ("url",)', {type: 'ur'})); -assert.ok(py.eval('1 not in (2, 3, 4)')); -assert.ok(py.eval('type not in ("url",)', {type: 'ur'})); - -assert.ok(py.eval( - "foo in ['foo', 'bar']", {foo: 'bar'})); -// string contains -assert.ok(py.eval('type in "view"', {type: 'view'})); -assert.ok(!py.eval('type in "view"', {type: 'bob'})); -assert.ok(py.eval('type in "url"', {type: 'ur'})); - -// Literals -assert.strictEqual(py.eval('False'), false); -assert.strictEqual(py.eval('True'), true); -assert.strictEqual(py.eval('None'), null); -assert.ok(py.eval('foo == False', {foo: false})); -assert.ok(!py.eval('foo == False', {foo: true})); - -// conversions -assert.strictEqual( - py.eval('bool(date_deadline)', {bool: py.bool, date_deadline: '2008'}), - true); - -// getattr -assert.ok(py.eval('foo.bar', {foo: {bar: true}})); -assert.ok(!py.eval('foo.bar', {foo: {bar: false}})); - -// complex expressions -assert.ok(py.eval( - "state=='pending' and not(date_deadline and (date_deadline < current_date))", - {state: 'pending', date_deadline: false})); -assert.ok(py.eval( - "state=='pending' and not(date_deadline and (date_deadline < current_date))", - {state: 'pending', date_deadline: '2010-05-08', current_date: '2010-05-08'}));; -- cgit v1.2.3