{"id":16758154,"url":"https://github.com/foo123/xpresion","last_synced_at":"2025-08-29T17:24:52.585Z","repository":{"id":22078056,"uuid":"25407488","full_name":"foo123/Xpresion","owner":"foo123","description":"Xpresion: simple and flexible Expression Parser Engine with variables support for PHP, Python, JavaScript","archived":false,"fork":false,"pushed_at":"2022-09-24T15:24:53.000Z","size":285,"stargazers_count":10,"open_issues_count":0,"forks_count":4,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-03-24T14:51:26.307Z","etag":null,"topics":["browser","configurable","expression-evaluator","expression-parser","expression-parser-engine","extendable","flexible","node-js","php","python"],"latest_commit_sha":null,"homepage":"https://foo123.github.io/examples/xpresion/","language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/foo123.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2014-10-18T19:21:47.000Z","updated_at":"2023-01-15T03:27:39.000Z","dependencies_parsed_at":"2023-01-11T21:28:21.785Z","dependency_job_id":null,"html_url":"https://github.com/foo123/Xpresion","commit_stats":null,"previous_names":[],"tags_count":9,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/foo123%2FXpresion","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/foo123%2FXpresion/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/foo123%2FXpresion/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/foo123%2FXpresion/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/foo123","download_url":"https://codeload.github.com/foo123/Xpresion/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248261905,"owners_count":21074224,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["browser","configurable","expression-evaluator","expression-parser","expression-parser-engine","extendable","flexible","node-js","php","python"],"created_at":"2024-10-13T04:04:19.299Z","updated_at":"2025-04-10T17:12:10.178Z","avatar_url":"https://github.com/foo123.png","language":"PHP","funding_links":[],"categories":[],"sub_categories":[],"readme":"Xpr3s10n\n========\n\nA simple, fast and flexible **eXpression Parser Engine** (with custom functions and variables support) for `PHP`, `Python`, `Node.js` and `Browser`\n\n\n![Xpresion](/xpresion.jpg)\n\n**light-weight (~29kB minified, ~10kB zipped)**\n\n\nversion **1.0.1** [Xpresion.js](https://raw.githubusercontent.com/foo123/Xpresion/master/src/js/Xpresion.js), [Xpresion.min.js](https://raw.githubusercontent.com/foo123/Xpresion/master/src/js/Xpresion.min.js)\n\n\n**see also:**\n\n* [ModelView](https://github.com/foo123/modelview.js) a simple, fast, powerful and flexible MVVM framework for JavaScript\n* [tico](https://github.com/foo123/tico) a tiny, super-simple MVC framework for PHP\n* [LoginManager](https://github.com/foo123/LoginManager) a simple, barebones agnostic login manager for PHP, JavaScript, Python\n* [SimpleCaptcha](https://github.com/foo123/simple-captcha) a simple, image-based, mathematical captcha with increasing levels of difficulty for PHP, JavaScript, Python\n* [Dromeo](https://github.com/foo123/Dromeo) a flexible, and powerful agnostic router for PHP, JavaScript, Python\n* [PublishSubscribe](https://github.com/foo123/PublishSubscribe) a simple and flexible publish-subscribe pattern implementation for PHP, JavaScript, Python\n* [Importer](https://github.com/foo123/Importer) simple class \u0026amp; dependency manager and loader for PHP, JavaScript, Python\n* [Contemplate](https://github.com/foo123/Contemplate) a fast and versatile isomorphic template engine for PHP, JavaScript, Python\n* [HtmlWidget](https://github.com/foo123/HtmlWidget) html widgets, made as simple as possible, both client and server, both desktop and mobile, can be used as (template) plugins and/or standalone for PHP, JavaScript, Python (can be used as [plugins for Contemplate](https://github.com/foo123/Contemplate/blob/master/src/js/plugins/plugins.txt))\n* [Paginator](https://github.com/foo123/Paginator)  simple and flexible pagination controls generator for PHP, JavaScript, Python\n* [Formal](https://github.com/foo123/Formal) a simple and versatile (Form) Data validation framework based on Rules for PHP, JavaScript, Python\n* [Dialect](https://github.com/foo123/Dialect) a cross-vendor \u0026amp; cross-platform SQL Query Builder, based on [GrammarTemplate](https://github.com/foo123/GrammarTemplate), for PHP, JavaScript, Python\n* [DialectORM](https://github.com/foo123/DialectORM) an Object-Relational-Mapper (ORM) and Object-Document-Mapper (ODM), based on [Dialect](https://github.com/foo123/Dialect), for PHP, JavaScript, Python\n* [Unicache](https://github.com/foo123/Unicache) a simple and flexible agnostic caching framework, supporting various platforms, for PHP, JavaScript, Python\n* [Xpresion](https://github.com/foo123/Xpresion) a simple and flexible eXpression parser engine (with custom functions and variables support), based on [GrammarTemplate](https://github.com/foo123/GrammarTemplate), for PHP, JavaScript, Python\n* [Regex Analyzer/Composer](https://github.com/foo123/RegexAnalyzer) Regular Expression Analyzer and Composer for PHP, JavaScript, Python\n\n\n### Contents\n\n* [Features](#features)\n* [Examples](#examples)\n* [Live Examples](#live-examples)\n* [API](#api)\n* [Platform Support](#platform-support)\n* [Performance](#performance)\n* [Todo](#todo)\n* [Etymology of *\"expression\"*](https://en.wiktionary.org/wiki/expression) a latinised form of [*\"έκφραση\"* (etymology)](https://en.wiktionary.org/wiki/%CE%AD%CE%BA%CF%86%CF%81%CE%B1%CF%83%CE%B7), compare [etymology of *\"phrase\"*](https://en.wiktionary.org/wiki/phrase) (for an example of phonetic / linguistic equivalent transformations during historic evolution see [Grimm's law](https://en.wikipedia.org/wiki/Grimm's_law))\n\n\n\n\n\n[![Xpresion Live](https://github.com/foo123/Xpresion/raw/master/xpresion.png)](https://foo123.github.io/examples/xpresion)\n\n\n#### Features \n\n**(v. 1.0.0+)**\n\n`Xpresion` **is not an expression parser**, it does not parse expressions. It is a **parser engine**. \nIt builds parsers, which parse (custom) expressions. Effectively it is a small [rewrite system](http://en.wikipedia.org/wiki/Abstract_rewriting_system)\n\nThis is accomplished by configuring the `Xpresion` engine to fit the needed expression syntax.\nConfiguration is intutive, easy and flexible (see examples).\n\nHowever, since `Xpresion` is a parser engine, adding a default configuration, it can itself be a parser as well (out-of-the-box).\n\n**NOTE:** `Xpresion` (v.1.0.0+) uses [Grammar Templates](https://github.com/foo123/GrammarTemplate) for operator output. This is more flexible than simply using [String Templates](https://github.com/foo123/StringTemplate) as previously, since it supports blocks of optional code, default values, optional placeholders and many other things. Only make sure to escape (with `\\` character) all `\"\u003c\"`,`\"\u003e\"`,`\"[\"`,`\"]\"` literal characters inside the output you define for operators and functions (see default configuration example below)\n\n**Features:**\n\n1. simple, intuitive, flexible, fast\n1. support an adequate expression syntax out of the box (i.e numbers, strings, regexes, reserved tokens, arithmetical/logical operators, ternary operators, some advanced functions, variables)\n3. highly flexible and configurable (regexes, outputs, functions, operators, aliases, runtime functions, etc..)\n4. support (user-defined) variables, (user-defined) functions\n5. define custom operators (prefix, infix, postfix, left/right association, etc..) seamlessly\n6. define polymorphic operators / operator overloading seamlessly (e.g **subtraction** and **unary negation**)\n7. define n-ary operators seamlessly (e.g **ternary if-then-else**, etc..)\n8. define aliases of operators/functions seamlessly\n9. define new custom expression syntaxes easily (e.g via another `configuration` or by extending `defaultConfiguration` )\n10. implementations for `Node.js` and `Browser`, `PHP`, `Python` (only one class per implementation)\n\n\n**If you use `Xpresion` in your application and you want to share it, feel free to submit an example link**\n\n\n#### Live Examples\n\n* [Interactive Playground Example](https://foo123.github.io/examples/xpresion)\n\n#### Examples\n\n**(see test/test.js)**\n\n**javascript**\n```javascript\nvar echo = console.log, \n    Xpresion = require(__dirname+'/../src/js/Xpresion.js')\n;\n\nfunction test_expr(expr, evaluate)\n{\n    evaluate = evaluate || false;\n    echo('==========================================');\n    var xpr = null;\n    try {\n        // uses defaultConfiguration by default\n        xpr = Xpresion(expr);\n    } catch (err ) {\n        xpr = null;\n        echo(err.toString());\n    }\n    if ( xpr )\n    {\n        var debug = evaluate ? xpr.debug(evaluate instanceof Object ? evaluate : {}) : xpr.debug();\n        echo(debug);\n    }\n}\n\necho( 'Xpresion.VERSION ' + Xpresion.VERSION + \"\\n\" );\n\ntest_expr('13');\ntest_expr('1.32');\ntest_expr('-0.12');\ntest_expr('-3');\ntest_expr('(\"1,2,3\")+3',true);\ntest_expr('\"1,2,3\"+3',true);\ntest_expr('\"1,2,3\"+3+4',true);\ntest_expr('[1,2,3]+3',true);\ntest_expr('-3+2',true);\ntest_expr('1-3+2',true);\ntest_expr('1+-3',true);\ntest_expr('+1+3',true);\ntest_expr('2*-1');\ntest_expr('2*(-1)');\ntest_expr('2^-1');\ntest_expr('2^(-1)');\ntest_expr('2^-1^3');\ntest_expr('-2^-1^3');\ntest_expr('2^(-1)^3');\ntest_expr('sqrt(2)', true);\ntest_expr('$v');\ntest_expr('$v.key.0.key', {'v':{'key':[{'key':'correct'},'foo']}});\ntest_expr('True');\ntest_expr('\"string\"');\ntest_expr('[\"a\",\"rra\",\"y\"]');\ntest_expr('`^regex?`i');\ntest_expr('0 == 1');\ntest_expr('TRUE == False');\ntest_expr('TRUE is False');\ntest_expr('1+2');\ntest_expr('1+2+3');\ntest_expr('1+2*3');\ntest_expr('1*2+3');\ntest_expr('1*2*3');\ntest_expr('1+2/3');\ntest_expr('1*2/3');\ntest_expr('1^2');\ntest_expr('1^2^3');\ntest_expr('1^(2^3)');\ntest_expr('(1^2)^3');\ntest_expr('((1^2))^3');\ntest_expr('`^regex?`i matches \"string\"');\ntest_expr('`^regex?`i matches \"string\" and `^regex?`i matches \"string2\"');\ntest_expr('$v in [\"a\",\"b\",\"c\"]');\ntest_expr('1 ? : (1+2) (3+4)');\ntest_expr('1 ? sum(1,2) : (3+4)');\ntest_expr('1 ? 1+2 : (3+4)');\ntest_expr('1 ? (2+3) : 2 ? (3+4) : (4+5)');\ntest_expr('date(\"Y-m-d H:i:s\")', true);\ntest_expr('time()', true);\ntest_expr('date(\"Y-m-d H:i:s\", time())');\ntest_expr('pow(1,pow(2,3))');\ntest_expr('pow(pow(2,3),4)');\ntest_expr('pow(pow(1,2),pow(2,3))');\n```\n\n**output**\n```text\nXpresion.VERSION 1.0.0\n\n==========================================\nExpression: 13\nVariables : []\nEvaluator : 13\n==========================================\nExpression: 1.32\nVariables : []\nEvaluator : 1.32\n==========================================\nExpression: -0.12\nVariables : []\nEvaluator : (-0.12)\n==========================================\nExpression: -3\nVariables : []\nEvaluator : (-3)\n==========================================\nExpression: (\"1,2,3\")+3\nVariables : []\nEvaluator : (\"1,2,3\"+String(3))\nData      : {}\nResult    : \"1,2,33\"\n==========================================\nExpression: \"1,2,3\"+3\nVariables : []\nEvaluator : (\"1,2,3\"+String(3))\nData      : {}\nResult    : \"1,2,33\"\n==========================================\nExpression: \"1,2,3\"+3+4\nVariables : []\nEvaluator : ((\"1,2,3\"+String(3))+String(4))\nData      : {}\nResult    : \"1,2,334\"\n==========================================\nExpression: [1,2,3]+3\nVariables : []\nEvaluator : Fn.ary_merge([1,2,3],3)\nData      : {}\nResult    : [1,2,3,3]\n==========================================\nExpression: -3+2\nVariables : []\nEvaluator : ((-3)+2)\nData      : {}\nResult    : -1\n==========================================\nExpression: 1-3+2\nVariables : []\nEvaluator : ((1-3)+2)\nData      : {}\nResult    : 0\n==========================================\nExpression: 1+-3\nVariables : []\nEvaluator : (1+(-3))\nData      : {}\nResult    : -2\n==========================================\nExpression: +1+3\nVariables : []\nEvaluator : (1+3)\nData      : {}\nResult    : 4\n==========================================\nExpression: 2*-1\nVariables : []\nEvaluator : (2*(-1))\n==========================================\nExpression: 2*(-1)\nVariables : []\nEvaluator : (2*(-1))\n==========================================\nExpression: 2^-1\nVariables : []\nEvaluator : Math.pow(2,(-1))\n==========================================\nExpression: 2^(-1)\nVariables : []\nEvaluator : Math.pow(2,(-1))\n==========================================\nExpression: 2^-1^3\nVariables : []\nEvaluator : Math.pow(2,Math.pow((-1),3))\n==========================================\nExpression: -2^-1^3\nVariables : []\nEvaluator : Math.pow((-2),Math.pow((-1),3))\n==========================================\nExpression: 2^(-1)^3\nVariables : []\nEvaluator : Math.pow(2,Math.pow((-1),3))\n==========================================\nExpression: sqrt(2)\nVariables : []\nEvaluator : Math.sqrt(2)\nData      : {}\nResult    : 1.4142135623730951\n==========================================\nExpression: $v\nVariables : [v]\nEvaluator : Var[\"v\"]\n==========================================\nExpression: $v.key.0.key\nVariables : [v]\nEvaluator : Xpresion.GET(Var[\"v\"],[\"key\",\"0\",\"key\"])\nData      : {\n    \"v\": {\n        \"key\": [\n            {\n                \"key\": \"correct\"\n            },\n            \"foo\"\n        ]\n    }\n}\nResult    : \"correct\"\n==========================================\nExpression: True\nVariables : []\nEvaluator : true\n==========================================\nExpression: \"string\"\nVariables : []\nEvaluator : \"string\"\n==========================================\nExpression: [\"a\",\"rra\",\"y\"]\nVariables : []\nEvaluator : [\"a\",\"rra\",\"y\"]\n==========================================\nExpression: `^regex?`i\nVariables : []\nEvaluator : Cache.re_1\n==========================================\nExpression: 0 == 1\nVariables : []\nEvaluator : (0==1)\n==========================================\nExpression: TRUE == False\nVariables : []\nEvaluator : (true==false)\n==========================================\nExpression: TRUE is False\nVariables : []\nEvaluator : (true===false)\n==========================================\nExpression: 1+2\nVariables : []\nEvaluator : (1+2)\n==========================================\nExpression: 1+2+3\nVariables : []\nEvaluator : ((1+2)+3)\n==========================================\nExpression: 1+2*3\nVariables : []\nEvaluator : (1+(2*3))\n==========================================\nExpression: 1*2+3\nVariables : []\nEvaluator : ((1*2)+3)\n==========================================\nExpression: 1*2*3\nVariables : []\nEvaluator : ((1*2)*3)\n==========================================\nExpression: 1+2/3\nVariables : []\nEvaluator : (1+(2/3))\n==========================================\nExpression: 1*2/3\nVariables : []\nEvaluator : ((1*2)/3)\n==========================================\nExpression: 1^2\nVariables : []\nEvaluator : Math.pow(1,2)\n==========================================\nExpression: 1^2^3\nVariables : []\nEvaluator : Math.pow(1,Math.pow(2,3))\n==========================================\nExpression: 1^(2^3)\nVariables : []\nEvaluator : Math.pow(1,Math.pow(2,3))\n==========================================\nExpression: (1^2)^3\nVariables : []\nEvaluator : Math.pow(Math.pow(1,2),3)\n==========================================\nExpression: ((1^2))^3\nVariables : []\nEvaluator : Math.pow(Math.pow(1,2),3)\n==========================================\nExpression: `^regex?`i matches \"string\"\nVariables : []\nEvaluator : Fn.match(\"string\",Cache.re_1)\n==========================================\nExpression: `^regex?`i matches \"string\" and `^regex?`i matches \"string2\"\nVariables : []\nEvaluator : (Fn.match(\"string\",Cache.re_1)\u0026\u0026Fn.match(\"string2\",Cache.re_1))\n==========================================\nExpression: $v in [\"a\",\"b\",\"c\"]\nVariables : [v]\nEvaluator : Fn.contains([\"a\",\"b\",\"c\"],Var[\"v\"])\n==========================================\nError: Xpresion Error: Operator \":\" expecting 1 prior argument(s) at \"1 ? : (1+2) (3+4)\"\n==========================================\nExpression: 1 ? sum(1,2) : (3+4)\nVariables : []\nEvaluator : (1?Fn.sum(1,2):(3+4))\n==========================================\nExpression: 1 ? 1+2 : (3+4)\nVariables : []\nEvaluator : (1?(1+2):(3+4))\n==========================================\nExpression: 1 ? (2+3) : 2 ? (3+4) : (4+5)\nVariables : []\nEvaluator : (1?(2+3):(2?(3+4):(4+5)))\n==========================================\nExpression: date(\"Y-m-d H:i:s\")\nVariables : []\nEvaluator : Fn.date(\"Y-m-d H:i:s\")\nData      : {}\nResult    : \"2019-03-19 13:00:31\"\n==========================================\nExpression: time()\nVariables : []\nEvaluator : Fn.time()\nData      : {}\nResult    : 1552993231\n==========================================\nExpression: date(\"Y-m-d H:i:s\", time())\nVariables : []\nEvaluator : Fn.date(\"Y-m-d H:i:s\",Fn.time())\n==========================================\nExpression: pow(1,pow(2,3))\nVariables : []\nEvaluator : Math.pow(1,Math.pow(2,3))\n==========================================\nExpression: pow(pow(2,3),4)\nVariables : []\nEvaluator : Math.pow(Math.pow(2,3),4)\n==========================================\nExpression: pow(pow(1,2),pow(2,3))\nVariables : []\nEvaluator : Math.pow(Math.pow(1,2),Math.pow(2,3))\n```\n\n#### API\n\n```javascript\n\n// define a new configuration\nvar conf = Xpresion.Configuration();\n// or extend default configuration\nvar conf = Xpresion.defaultConfiguration();\n\n// define an operator\nconf.defOp({\n    '===' :{\n             'input'        : [1,'===',1]           // input\n            ,'output'       : '(\u003c$.0\u003e===\u003c$.1\u003e)'     // output (GrammarTemplate)\n            ,'otype'        : Xpresion.T_BOL        // output type BOOLEAN, default = Xpresion.T_MIX = mixed\n            ,'fixity'       : Xpresion.INFIX        // operator fixity`\n            ,'associativity': Xpresion.LEFT         // operator associativity\n            ,'priority'     : 40                    // operator priority\n        }\n});\n\n// define an alias\nconf.defOp({\n    'is': Xpresion.Alias('===')\n});\n\n// define a function (functional operator)\nconf.defFunc({\n    'len': {\n             'input'    : 'len',\n            ,'output'   : 'Fn.len(\u003c$.0\u003e)' // \u003c$.0\u003e matches all arguments passed not only one, separated by comma\n            ,'otype'    : Xpresion.T_NUM\n        }\n});\n\n// define a runtime function (called during evaluation) which implements the 'len' function\nconf.defRuntimeFunc({\n    'len'    :   function( v ) { \n                    if ( null==v ) return 0;\n                    if ( v instanceof String || v instanceof Array ) return v.length;\n                    if ( v instanceof Object ) return Object.keys(v).length;\n                    return 1;\n                }\n});\n\n// new Xpresion(..) will also work\nvar expr = Xpresion( \"1+2+$v\" [, conf=Xpresion.defaultConfiguration()] );\n\n// !note! will trow an error if parsing the expression fails, so better to catch it and handle it\n\ntry {\n    expr = Xpresion( \"1+2+$v\", conf );\n} catch(e) {\n    console.log(e.toString());\n}\n\n\nconsole.log(expr.debug({'v': 3}));\n\n// class methods==============================\n\n// get or set the Xpresion.defaultConfiguration()\nvar defaultConf = Xpresion.defaultConfiguration();\nXpresion.defaultConfiguration(newConf);\n\n// methods====================================\n\n// returns debug information about the expresion, plus the evaluated result if data given\nexpr.debug([Object data]);\n\n// evaluates the expresion based on given data (as variables) and returns the result\nexpr.evaluate(Object data );\n\n// properties=================================\n\nexpr.variables; // array of variable names referenced in the expression\nexpr.evaluatorString; // evaluator function as string\nexpr.evaluator; // actual function that evaluates the expression\n\n```\n\n**default Xpresion Configuration**\n\n```javascript\n// default out-of-the-box Xpresion parser configuration\n// e.g https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Operator_Precedence\n\nXpresion.defaultConfiguration(Configuration({\n// regular expressions for tokens\n// ===============================\n're' : {\n 't_spc'        :  /^(\\s+)/\n,'t_nonspc'     :  /^(\\S+)/\n,'t_special'    :  /^([*.\\\\\\-+\\/\\^\\$\\(\\)\\[\\]|?\u003c:\u003e\u0026~%!#@=_,;{}]+)/\n,'t_num'        :  /^(\\d+(\\.\\d+)?)/\n,'t_ident'      :  /^([a-zA-Z_][a-zA-Z0-9_]*)\\b/\n,'t_var'        :  /^\\$([a-zA-Z0-9_][a-zA-Z0-9_.]*)\\b/\n}\n\n// block-type tokens (eg strings and regexes)\n// ==========================================\n,'blocks' : {\n '\\'': {\n    'type': T_STR,\n    'parse': Xpresion.parse_delimited_block\n }\n,'\"': Alias('\\'')\n,'`': {\n    'type': T_REX,\n    'parse': Xpresion.parse_delimited_block,\n    'rest': parse_re_flags\n}\n}\n\n// reserved keywords and literals\n// ===============================\n,'reserved' : {\n 'null'     : Tok(T_IDE, 'null', 'null')\n,'false'    : Tok(T_BOL, 'false', 'false')\n,'true'     : Tok(T_BOL, 'true', 'true')\n,'infinity' : Tok(T_NUM, 'Infinity', 'Infinity')\n,'nan'      : Tok(T_NUM, 'NaN', 'NaN')\n// aliases\n,'none'     : Alias('null')\n,'inf'      : Alias('infinity')\n}\n\n// operators\n// ==========\n,'operators' : {\n// bra-kets as n-ary operators\n// negative number of arguments, indicate optional arguments (experimental)\n '('    :   {\n                'input'         : ['(',-1,')']\n                ,'output'       : '\u003c$.0\u003e'\n                ,'otype'        : T_DUM\n                ,'fixity'       : POSTFIX\n                ,'associativity': RIGHT\n                ,'priority'     : 0\n            }\n,')'    :   {'input':[-1,')']}\n,'['    :   {\n                'input'         : ['[',-1,']']\n                ,'output'       : '\\\\[\u003c$.0\u003e\\\\]'\n                ,'otype'        : T_ARY\n                ,'fixity'       : POSTFIX\n                ,'associativity': RIGHT\n                ,'priority'     : 2\n            }\n,']'    :   {'input':[-1,']']}\n,','    :   {\n                'input'         : [1,',',1]\n                ,'output'       : '\u003c$.0\u003e,\u003c$.1\u003e'\n                ,'otype'        : T_DFT\n                ,'fixity'       : INFIX\n                ,'associativity': LEFT\n                ,'priority'     : 103\n            }\n// n-ary (ternary) if-then-else operator\n,'?'    :   {\n                'input'         : [1,'?',1,':',1]\n                ,'output'       : '(\u003c$.0\u003e?\u003c$.1\u003e:\u003c$.2\u003e)'\n                ,'otype'        : T_BOL\n                ,'fixity'       : INFIX\n                ,'associativity': RIGHT\n                ,'priority'     : 100\n            }\n,':'    :   {'input':[1,':',1]}\n\n,'!'    :   {\n                'input'         : ['!',1]\n                ,'output'       : '!\u003c$.0\u003e'\n                ,'otype'        : T_BOL\n                ,'fixity'       : PREFIX\n                ,'associativity': RIGHT\n                ,'priority'     : 10\n            }\n,'~'    :   {\n                'input'         : ['~',1]\n                ,'output'       : '~\u003c$.0\u003e'\n                ,'otype'        : T_NUM\n                ,'fixity'       : PREFIX\n                ,'associativity': RIGHT\n                ,'priority'     : 10\n            }\n,'^'    :   {\n                'input'         : [1,'^',1]\n                ,'output'       : 'Math.pow(\u003c$.0\u003e,\u003c$.1\u003e)'\n                ,'otype'        : T_NUM\n                ,'fixity'       : INFIX\n                ,'associativity': RIGHT\n                ,'priority'     : 11\n            }\n,'*'    :   {\n                'input'         : [1,'*',1]\n                ,'output'       : '(\u003c$.0\u003e*\u003c$.1\u003e)'\n                ,'otype'        : T_NUM\n                ,'fixity'       : INFIX\n                ,'associativity': LEFT\n                ,'priority'     : 20\n            }\n,'/'    :   {\n                'input'         : [1,'/',1]\n                ,'output'       : '(\u003c$.0\u003e/\u003c$.1\u003e)'\n                ,'otype'        : T_NUM\n                ,'fixity'       : INFIX\n                ,'associativity': LEFT\n                ,'priority'     : 20\n            }\n,'%'    :   {\n                'input'         : [1,'%',1]\n                ,'output'       : '(\u003c$.0\u003e%\u003c$.1\u003e)'\n                ,'otype'        : T_NUM\n                ,'fixity'       : INFIX\n                ,'associativity': LEFT\n                ,'priority'     : 20\n            }\n// addition/concatenation/unary plus as polymorphic operators\n,'+'    :   {'polymorphic':[\n            // array concatenation\n            [\n            function(curr,Xpresion){return curr.TOK \u0026\u0026 (!curr.PREV_IS_OP) \u0026\u0026 (curr.DEDUCED_TYPE===Xpresion.T_ARY);},\n            {\n                'input'         : [1,'+',1]\n                ,'output'       : 'Fn.ary_merge(\u003c$.0\u003e,\u003c$.1\u003e)'\n                ,'otype'        : T_ARY\n                ,'fixity'       : INFIX\n                ,'associativity': LEFT\n                ,'priority'     : 25\n            }\n            ]\n            // string concatenation\n            ,[\n            function(curr,Xpresion){return curr.TOK \u0026\u0026 (!curr.PREV_IS_OP) \u0026\u0026 (curr.DEDUCED_TYPE===Xpresion.T_STR);},\n            {\n                'input'         : [1,'+',1]\n                ,'output'       : '(\u003c$.0\u003e+String(\u003c$.1\u003e))'\n                ,'otype'        : T_STR\n                ,'fixity'       : INFIX\n                ,'associativity': LEFT\n                ,'priority'     : 25\n            }\n            ]\n            // numeric addition\n            ,[\n            function(curr,Xpresion){return curr.TOK \u0026\u0026 !curr.PREV_IS_OP;},\n            {\n                'input'         : [1,'+',1]\n                ,'output'       : '(\u003c$.0\u003e+\u003c$.1\u003e)'\n                ,'otype'        : T_NUM\n                ,'fixity'       : INFIX\n                ,'associativity': LEFT\n                ,'priority'     : 25\n            }\n            ]\n            // unary plus\n            ,[\n            function(curr,Xpresion){return (!curr.TOK) || curr.PREV_IS_OP;},\n            {\n                'input'         : ['+',1]\n                ,'output'       : '\u003c$.0\u003e'\n                ,'otype'        : T_NUM\n                ,'fixity'       : PREFIX\n                ,'associativity': RIGHT\n                ,'priority'     : 4\n            }\n            ]\n            ]}\n,'-'    :   {'polymorphic':[\n            // numeric subtraction\n            [\n            function(curr,Xpresion){return curr.TOK \u0026\u0026 !curr.PREV_IS_OP;},\n            {\n                'input'         : [1,'-',1]\n                ,'output'       : '(\u003c$.0\u003e-\u003c$.1\u003e)'\n                ,'otype'        : T_NUM\n                ,'fixity'       : INFIX\n                ,'associativity': LEFT\n                ,'priority'     : 25\n            }\n            ]\n            // unary negation\n            ,[\n            function(curr,Xpresion){return (!curr.TOK) || curr.PREV_IS_OP;},\n            {\n                'input'         : ['-',1]\n                ,'output'       : '(-\u003c$.0\u003e)'\n                ,'otype'        : T_NUM\n                ,'fixity'       : PREFIX\n                ,'associativity': RIGHT\n                ,'priority'     : 4\n            }\n            ]\n            ]}\n,'\u003e\u003e'   :   {\n                'input'         : [1,'\u003e\u003e',1]\n                ,'output'       : '(\u003c$.0\u003e\\\\\u003e\\\\\u003e\u003c$.1\u003e)'\n                ,'otype'        : T_NUM\n                ,'fixity'       : INFIX\n                ,'associativity': LEFT\n                ,'priority'     : 30\n            }\n,'\u003c\u003c'   :   {\n                'input'         : [1,'\u003c\u003c',1]\n                ,'output'       : '(\u003c$.0\u003e\\\\\u003c\\\\\u003c\u003c$.1\u003e)'\n                ,'otype'        : T_NUM\n                ,'fixity'       : INFIX\n                ,'associativity': LEFT\n                ,'priority'     : 30\n            }\n,'\u003e'    :   {\n                'input'         : [1,'\u003e',1]\n                ,'output'       : '(\u003c$.0\u003e\\\\\u003e\u003c$.1\u003e)'\n                ,'otype'        : T_BOL\n                ,'fixity'       : INFIX\n                ,'associativity': LEFT\n                ,'priority'     : 35\n            }\n,'\u003c'    :   {\n                'input'         : [1,'\u003c',1]\n                ,'output'       : '(\u003c$.0\u003e\\\\\u003c\u003c$.1\u003e)'\n                ,'otype'        : T_BOL\n                ,'fixity'       : INFIX\n                ,'associativity': LEFT\n                ,'priority'     : 35\n            }\n,'\u003e='   :   {\n                'input'         : [1,'\u003e=',1]\n                ,'output'       : '(\u003c$.0\u003e\\\\\u003e=\u003c$.1\u003e)'\n                ,'otype'        : T_BOL\n                ,'fixity'       : INFIX\n                ,'associativity': LEFT\n                ,'priority'     : 35\n            }\n,'\u003c='   :   {\n                'input'         : [1,'\u003c=',1]\n                ,'output'       : '(\u003c$.0\u003e\\\\\u003c=\u003c$.1\u003e)'\n                ,'otype'        : T_BOL\n                ,'fixity'       : INFIX\n                ,'associativity': LEFT\n                ,'priority'     : 35\n            }\n,'=='   :   {'polymorphic':[\n            // array equivalence\n            [\n            function(curr,Xpresion){return curr.DEDUCED_TYPE===Xpresion.T_ARY;},\n            {\n                'input'         : [1,'==',1]\n                ,'output'       : 'Fn.ary_eq(\u003c$.0\u003e,\u003c$.1\u003e)'\n                ,'otype'        : T_BOL\n                ,'fixity'       : INFIX\n                ,'associativity': LEFT\n                ,'priority'     : 40\n            }\n            ]\n            // default equivalence\n            ,[\n            function(curr,Xpresion){return true;},\n            {\n                'input'         : [1,'==',1]\n                ,'output'       : '(\u003c$.0\u003e==\u003c$.1\u003e)'\n                ,'otype'        : T_BOL\n                ,'fixity'       : INFIX\n                ,'associativity': LEFT\n                ,'priority'     : 40\n            }\n            ]\n            ]}\n,'!='   :   {\n                'input'         : [1,'!=',1]\n                ,'output'       : '(\u003c$.0\u003e!=\u003c$.1\u003e)'\n                ,'otype'        : T_BOL\n                ,'fixity'       : INFIX\n                ,'associativity': LEFT\n                ,'priority'     : 40\n            }\n,'is'   :   {\n                'input'         : [1,'is',1]\n                ,'output'       : '(\u003c$.0\u003e===\u003c$.1\u003e)'\n                ,'otype'        : T_BOL\n                ,'fixity'       : INFIX\n                ,'associativity': LEFT\n                ,'priority'     : 40\n            }\n,'matches': {\n                'input'         : [1,'matches',1]\n                ,'output'       : 'Fn.match(\u003c$.1\u003e,\u003c$.0\u003e)'\n                ,'otype'        : T_BOL\n                ,'fixity'       : INFIX\n                ,'associativity': NONE\n                ,'priority'     : 40\n            }\n,'in'   :   {\n                'input'         : [1,'in',1]\n                ,'output'       : 'Fn.contains(\u003c$.1\u003e,\u003c$.0\u003e)'\n                ,'otype'        : T_BOL\n                ,'fixity'       : INFIX\n                ,'associativity': NONE\n                ,'priority'     : 40\n            }\n,'\u0026'    :   {\n                'input'         : [1,'\u0026',1]\n                ,'output'       : '(\u003c$.0\u003e\u0026\u003c$.1\u003e)'\n                ,'otype'        : T_NUM\n                ,'fixity'       : INFIX\n                ,'associativity': LEFT\n                ,'priority'     : 45\n            }\n,'|'    :   {\n                'input'         : [1,'|',1]\n                ,'output'       : '(\u003c$.0\u003e|\u003c$.1\u003e)'\n                ,'otype'        : T_NUM\n                ,'fixity'       : INFIX\n                ,'associativity': LEFT\n                ,'priority'     : 46\n            }\n,'\u0026\u0026'   :   {\n                'input'         : [1,'\u0026\u0026',1]\n                ,'output'       : '(\u003c$.0\u003e\u0026\u0026\u003c$.1\u003e)'\n                ,'otype'        : T_BOL\n                ,'fixity'       : INFIX\n                ,'associativity': LEFT\n                ,'priority'     : 47\n            }\n,'||'   :   {\n                'input'         : [1,'||',1]\n                ,'output'       : '(\u003c$.0\u003e||\u003c$.1\u003e)'\n                ,'otype'        : T_BOL\n                ,'fixity'       : INFIX\n                ,'associativity': LEFT\n                ,'priority'     : 48\n            }\n//------------------------------------------\n//                aliases\n//-------------------------------------------\n,'or'    :  Alias( '||' )\n,'and'   :  Alias( '\u0026\u0026' )\n,'not'   :  Alias( '!' )\n}\n\n// functional operators\n// ====================\n,'functions' : {\n 'min'      : {\n                'input'     : 'min'\n                ,'output'   : 'Math.min(\u003c$.0\u003e)'\n                ,'otype'    : T_NUM\n            }\n,'max'      : {\n                'input'     : 'max'\n                ,'output'   : 'Math.max(\u003c$.0\u003e)'\n                ,'otype'    : T_NUM\n            }\n,'pow'      : {\n                'input'     : 'pow'\n                ,'output'   : 'Math.pow(\u003c$.0\u003e)'\n                ,'otype'    : T_NUM\n            }\n,'sqrt'     : {\n                'input'     : 'sqrt'\n                ,'output'   : 'Math.sqrt(\u003c$.0\u003e)'\n                ,'otype'    : T_NUM\n            }\n,'len'      : {\n                'input'     : 'len'\n                ,'output'   : 'Fn.len(\u003c$.0\u003e)'\n                ,'otype'    : T_NUM\n            }\n,'int'      : {\n                'input'     : 'int'\n                ,'output'   : 'parseInt(\u003c$.0\u003e)'\n                ,'otype'    : T_NUM\n            }\n,'float'    : {\n                'input'     : 'float'\n                ,'output'   : 'parseFloat(\u003c$.0\u003e)'\n                ,'otype'    : T_NUM\n            }\n,'str'      : {\n                'input'     : 'str'\n                ,'output'   : 'String(\u003c$.0\u003e)'\n                ,'otype'    : T_STR\n            }\n,'array'    : {\n                'input'     : 'array'\n                ,'output'   : 'Fn.ary(\u003c$.0\u003e)'\n                ,'otype'    : T_ARY\n            }\n,'clamp'    : {\n                'input'     : 'clamp'\n                ,'output'   : 'Fn.clamp(\u003c$.0\u003e)'\n                ,'otype'    : T_NUM\n            }\n,'sum'      : {\n                'input'     : 'sum'\n                ,'output'   : 'Fn.sum(\u003c$.0\u003e)'\n                ,'otype'    : T_NUM\n            }\n,'avg'      : {\n                'input'     : 'avg'\n                ,'output'   : 'Fn.avg(\u003c$.0\u003e)'\n                ,'otype'    : T_NUM\n            }\n,'time'     : {\n                'input'     : 'avg'\n                ,'output'   : 'Fn.time()'\n                ,'otype'    : T_NUM\n                ,'arity'    : 0\n            }\n,'date'     : {\n                'input'     : 'date'\n                ,'output'   : 'Fn.date(\u003c$.0\u003e)'\n                ,'otype'    : T_STR\n            }\n//---------------------------------------\n//                aliases\n//----------------------------------------\n // ...\n}\n\n// runtime (implementation) functions\n// ==================================\n,'runtime' : {\n'clamp'        : function( v, m, M ) {\n                    if ( m \u003e M ) return v \u003e m ? m : (v \u003c M ? M : v);\n                    else return v \u003e M ? M : (v \u003c m ? m : v);\n                }\n,'len'          : function( v ) {\n                    if ( v )\n                    {\n                        if ( is_array(v) || is_string(v) ) return v.length;\n                        if ( is_object(v) ) return Keys(v).length;\n                        return 1;\n                    }\n                    return 0;\n                }\n,'sum'          : function( ) {\n                    var args = arguments, i, l, s = 0;\n                    if (args[0] \u0026\u0026 is_array(args[0]) ) args = args[0];\n                    l = args.length;\n                    if ( l \u003e 0 ) { for(i=0; i\u003cl; i++) s += args[i]; }\n                    return s;\n                }\n,'avg'          : function( ) {\n                    var args = arguments, i, l, s = 0;\n                    if (args[0] \u0026\u0026 is_array(args[0]) ) args = args[0];\n                    l = args.length;\n                    if ( l \u003e 0 ) { for(i=0; i\u003cl; i++) s += args[i]; s = s/l;}\n                    return s;\n                }\n,'ary'          : function( x ) {\n                    return is_array(x) ? x : [x];\n                }\n,'ary_eq'       : function( a1, a2 ) {\n                    var l = a1.length, i;\n                    if ( l===a2.length )\n                    {\n                        for (i=0; i\u003cl; i++)\n                            if ( a1[i]!=a2[i] ) return false;\n                    }\n                    else return false;\n                    return true;\n                }\n,'ary_merge'    : function(a1, a2) {\n                    return [ ].concat( a1 ).concat( a2 );\n                }\n,'match'        : function( str, regex ) {\n                    return regex.test( str );\n                }\n,'contains'     : function( o, i ) {\n                    return is_array(o) || is_string(o) ? -1 \u003c o.indexOf( i ) : hasOwnProperty.call(o, i);\n                }\n,'time'         : time\n,'date'         : date\n}\n}));\n```\n\n#### Platform Support\n\n* `PHP` **5.3.0+**\n* `Python` **2.x or 3.x**\n* `Node` **0.8+**\n* `Browser` **all**\n\n\n#### Performance \n\nexpression parsing algorithm can be seen as a **variation and generalisation** of [Shunting-Yard algorithm](http://en.wikipedia.org/wiki/Shunting-yard_algorithm), \nrunning in linear-time ( `O(n)` ) in the input sequence\n\n\n#### TODO\n\n* use [Grammar Template](https://github.com/foo123/GrammarTemplate) for more powerful and flexible rewrite output [DONE]\n* add full support for optional arguments in `operators`/`functions`  [ALMOST DONE]\n* add support for (`xml`-like) `tags` in `expressions`\n* performance/unit tests [DONE PARTIALLY]\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffoo123%2Fxpresion","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffoo123%2Fxpresion","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffoo123%2Fxpresion/lists"}