From e1a702e9a1778b2504dadbd3321fe0da64f73259 Mon Sep 17 00:00:00 2001 From: Onoshko Dan Date: Sat, 19 Apr 2014 01:27:47 +0700 Subject: [PATCH] new syntax added `some?? || isset some`, `Type some, some2`, `a ? b` --- README.md | 15 ++++++++------- lib/ast.js | 4 +++- lib/output.js | 2 +- lib/parse.js | 34 ++++++++++++++++++++++------------ lib/translate.js | 37 ++++++++++++++++++++++++++++++++++++- 5 files changed, 70 insertions(+), 22 deletions(-) diff --git a/README.md b/README.md index 105fa072..83f4fdbd 100644 --- a/README.md +++ b/README.md @@ -9,9 +9,10 @@ ColaScript is a language that compiles in JavaScript. This language is similar t ## Operators: ### Unary -- `varname?` +- `varname??` and alternative `isset varname` - which is better? status: done - bool exist = SOME?; + bool exist = SOME??; + bool exist2 = isset SOME; ### Binary @@ -31,13 +32,13 @@ ColaScript is a language that compiles in JavaScript. This language is similar t undef = 6; def ?= undef; // def == 6 -- `a ? b` +- `a ? b`, status: done - int a = 5, b = 3; + var a = undefined, b = 3; - a = a > 10 ? b; // a == 5 + a ? b == 3; a = 11; - a = a > 10 ? b; // a == 3 + a ? b == 1; - `is`, status: done @@ -116,7 +117,7 @@ ColaScript is a language that compiles in JavaScript. This language is similar t ## Vars -- declaration with type +- declaration with type, status: done, only declaration int b = 584; Array arr = []; diff --git a/lib/ast.js b/lib/ast.js index 39bf250c..7f692842 100644 --- a/lib/ast.js +++ b/lib/ast.js @@ -108,6 +108,8 @@ Cola.AST_Node = Cola.DEFNODE("Node", "start end", { } }, null); +Cola.AST_Noop = Cola.DEFNODE("Noop", null, null, Cola.AST_Node); + Cola.AST_Node.warn_function = null; Cola.AST_Node.warn = function(txt, props) { if (Cola.AST_Node.warn_function) @@ -535,7 +537,7 @@ Cola.AST_Definitions = Cola.DEFNODE("Definitions", "definitions", { } }, Cola.AST_Statement); -Cola.AST_Var = Cola.DEFNODE("Var", null, { +Cola.AST_Var = Cola.DEFNODE("Var", "type", { $documentation: "A `var` statement" }, Cola.AST_Definitions); diff --git a/lib/output.js b/lib/output.js index a1d5687d..55b20d19 100644 --- a/lib/output.js +++ b/lib/output.js @@ -1167,7 +1167,7 @@ Cola.OutputStream.prototype.parent = function(n) { // innermost node in the current output) is lexically the first in // a statement. function first_in_statement(output) { - var a = output.stack(), i = a.length, node = a[--i], p = a[--i]; + var a = output.stack, i = a.length, node = a[--i], p = a[--i]; while (i > 0) { if (p instanceof Cola.AST_Statement && p.body === node) return true; diff --git a/lib/parse.js b/lib/parse.js index 9be82dc7..e73fb60d 100644 --- a/lib/parse.js +++ b/lib/parse.js @@ -49,7 +49,7 @@ !window.Cola && (window.Cola = {}); Cola.KEYWORDS = 'break case catch const continue debugger default delete do else finally for function if in instanceof new return switch throw try typeof var void while with'; -Cola.cKEYWORDS = Cola.KEYWORDS.replace(' void', '') + ' is isnt class singleton injector'; +Cola.cKEYWORDS = Cola.KEYWORDS.replace(' void', '') + ' isset is isnt class singleton injector'; Cola.KEYWORDS_ATOM = 'false null true'; Cola.cKEYWORDS_ATOM = Cola.KEYWORDS_ATOM + ' on yes off no'; @@ -123,16 +123,18 @@ Cola.OPERATORS = [ "&&", "||", // ColaScript + "isset", "is", "isnt", "**", "%%", - "?=" + "?=", + "??" ]; Cola.cOPERATORS = Cola.makePredicate(Cola.OPERATORS); -Cola.OPERATORS = Cola.OPERATORS.slice(0, Cola.OPERATORS.length - 5); +Cola.OPERATORS = Cola.OPERATORS.slice(0, Cola.OPERATORS.length - 7); Cola.OPERATORS.push('void'); Cola.OPERATORS = Cola.makePredicate(Cola.OPERATORS); @@ -263,10 +265,12 @@ Cola.Tokenizer = function ($TEXT, filename, is_js, html5_comments) { this.KEYWORDS = Cola.KEYWORDS; this.KEYWORDS_ATOM = Cola.KEYWORDS_ATOM; this.OPERATORS = Cola.OPERATORS; + this.UNARY_POSTFIX = Cola.UNARY_POSTFIX; } else { this.KEYWORDS = Cola.cKEYWORDS; this.KEYWORDS_ATOM = Cola.cKEYWORDS_ATOM; this.OPERATORS = Cola.cOPERATORS; + this.UNARY_POSTFIX = Cola.cUNARY_POSTFIX; } this.is_js = !!is_js; @@ -331,7 +335,7 @@ Cola.Tokenizer.prototype.start_token = function () { }; Cola.Tokenizer.prototype.token = function (type, value, is_comment) { - this.S.regex_allowed = ((type == "operator" && !Cola.UNARY_POSTFIX(value)) || + this.S.regex_allowed = ((type == "operator" && !this.UNARY_POSTFIX(value)) || (type == "keyword" && Cola.KEYWORDS_BEFORE_EXPRESSION(value)) || (type == "punc" && Cola.PUNC_BEFORE_EXPRESSION(value))); this.prev_was_dot = (type == "punc" && value == "."); @@ -717,6 +721,7 @@ Cola.UNARY_PREFIX = Cola.makePredicate([ "+" ]); Cola.cUNARY_PREFIX = Cola.makePredicate([ + "isset", "typeof", "delete", "--", @@ -728,9 +733,10 @@ Cola.cUNARY_PREFIX = Cola.makePredicate([ ]); Cola.UNARY_POSTFIX = Cola.makePredicate([ "--", "++" ]); +Cola.cUNARY_POSTFIX = Cola.makePredicate([ "--", "++", "??" ]); Cola.ASSIGNMENT = Cola.makePredicate([ "=", "+=", "-=", "/=", "*=", "%=", ">>=", "<<=", ">>>=", "|=", "^=", "&=" ]); -Cola.cASSIGNMENT = Cola.makePredicate([ "=", "+=", "-=", "/=", "*=", "%=", ">>=", "<<=", ">>>=", "|=", "^=", "&="/* ColaScript */, "?=" ]); +Cola.cASSIGNMENT = Cola.makePredicate([ "=", "+=", "-=", "/=", "*=", "%=", ">>=", "<<=", ">>>=", "|=", "^=", "&=", "?=" ]); Cola.mergeTokens = function (a, ret) { for (var i = 0; i < a.length; ++i) { @@ -787,8 +793,6 @@ Cola.parse = function ($TEXT, options) { Cola.Parser = function ($TEXT, options) { var _this = this; - this.is_js = !!options.is_js; - this.options = Cola.defaults(options, { strict : false, filename : null, @@ -798,6 +802,7 @@ Cola.Parser = function ($TEXT, options) { is_js : false }); + this.is_js = !!this.options.is_js; this.tokenizer = typeof $TEXT == "string" ? new Cola.Tokenizer($TEXT, this.options.filename, this.is_js, this.options.html5_comments) : $TEXT; this.S = { @@ -817,10 +822,12 @@ Cola.Parser = function ($TEXT, options) { this.UNARY_PREFIX = Cola.UNARY_PREFIX; this.PRECEDENCE = Cola.PRECEDENCE; this.ASSIGNMENT = Cola.ASSIGNMENT; + this.UNARY_POSTFIX = Cola.UNARY_POSTFIX; } else { this.UNARY_PREFIX = Cola.cUNARY_PREFIX; this.PRECEDENCE = Cola.cPRECEDENCE; this.ASSIGNMENT = Cola.cASSIGNMENT; + this.UNARY_POSTFIX = Cola.cUNARY_POSTFIX; } }; @@ -938,7 +945,7 @@ Cola.Parser.prototype.handle_regexp = function () { }; Cola.Parser.prototype.statement = Cola.Parser.embed_tokens(function() { - var tmp, _this = this; + var tmp, type, _this = this; this.handle_regexp(); switch (this.S.token.type) { case "string": @@ -954,6 +961,7 @@ Cola.Parser.prototype.statement = Cola.Parser.embed_tokens(function() { return this.simple_statement(); case "name": + if(Cola.is_token(this.peek(), "name")) return type = this.S.token.value, this.next(), tmp = this.var_(false, type), this.semicolon(), tmp; return Cola.is_token(this.peek(), "punc", ":") ? this.labeled_statement() : this.simple_statement(); @@ -1288,10 +1296,12 @@ Cola.Parser.prototype.vardefs = function (no_in, in_const) { return a; }; -Cola.Parser.prototype.var_ = function(no_in) { +Cola.Parser.prototype.var_ = function(no_in, type) { + !type && (type = "dynamic"); return new Cola.AST_Var({ start : this.prev(), definitions : this.vardefs(no_in, false), + type : type, end : this.prev() }); }; @@ -1609,7 +1619,7 @@ Cola.Parser.prototype.maybe_unary = function(allow_calls) { return ex; } var val = this.expr_atom(allow_calls); - while (this.is("operator") && Cola.UNARY_POSTFIX(this.S.token.value) && !this.S.token.nlb) { + while (this.is("operator") && this.UNARY_POSTFIX(this.S.token.value) && !this.S.token.nlb) { val = this.make_unary(Cola.AST_UnaryPostfix, this.S.token.value, val); val.start = start; val.end = this.S.token; @@ -1652,12 +1662,12 @@ Cola.Parser.prototype.maybe_conditional = function(no_in) { if (this.is("operator", "?")) { this.next(); var yes = this.expression(false); - this.expect(":"); + return new Cola.AST_Conditional({ start : start, condition : expr, consequent : yes, - alternative : this.expression(false, no_in), + alternative : this.is_js || this.is('punc',':') ? (this.expect(":"), this.expression(false, no_in)) : new Cola.AST_Noop(), end : this.prev() }); } diff --git a/lib/translate.js b/lib/translate.js index a8469355..1275ceed 100644 --- a/lib/translate.js +++ b/lib/translate.js @@ -113,7 +113,7 @@ Cola.AST_Toplevel.prototype.toJavaScript = function(){ name : '$_cola_isntset', start : props.start, end : props.start - }); + }); node = new Cola.AST_Conditional({ start : new Cola.AST_Token({ nlb : false, type : 'punc', value : '(' }), @@ -124,6 +124,25 @@ Cola.AST_Toplevel.prototype.toJavaScript = function(){ }); } else + if(node instanceof Cola.AST_Conditional && node.alternative instanceof Cola.AST_Noop){ + $_cola_hash[$_cola_isset.i] = true; + + props = { + args : [node.condition], + start : new Cola.AST_Token({ nlb : false, type : 'name', value : '$_cola_isset' }), + end : new Cola.AST_Token({ nlb : false, type : 'punc', value : ')' }) + }; + props.expression = new Cola.AST_SymbolRef({ + name : '$_cola_isset', + start : props.start, + end : props.start + }); + + node.alternative = node.consequent; + node.consequent = node.condition; + node.condition = new Cola.AST_Call(props); + } else + if(node instanceof Cola.AST_Binary && node.operator == 'is'){ $_cola_hash[$_cola_is.i] = true; props = { @@ -156,6 +175,22 @@ Cola.AST_Toplevel.prototype.toJavaScript = function(){ node = new Cola.AST_Call(props); } else + if(node instanceof Cola.AST_UnaryPostfix && node.operator == '??' || node instanceof Cola.AST_UnaryPrefix && node.operator == 'isset'){ + $_cola_hash[$_cola_isset.i] = true; + props = { + args : [node.expression], + start : new Cola.AST_Token({ nlb : false, type : 'name', value : '$_cola_isset' }), + end : new Cola.AST_Token({ nlb : false, type : 'punc', value : ')' }) + }; + props.expression = new Cola.AST_SymbolRef({ + name : '$_cola_isset', + start : props.start, + end : props.start + }); + + node = new Cola.AST_Call(props); + } else + if(node instanceof Cola.AST_StringTemplate){ newNode = new Cola.AST_Binary({ operator : '+',