diff --git a/lib/coffee_script/parser.js b/lib/coffee_script/parser.js index df64ad11..a03ee696 100644 --- a/lib/coffee_script/parser.js +++ b/lib/coffee_script/parser.js @@ -1,5 +1,5 @@ (function(){ - var Parser, __a, __b, __c, __d, __e, __f, bnf, grammar, name, non_terminal, o, option, parser, part, tokens, unwrap; + var Parser, __a, __b, __c, __d, __e, __f, bnf, grammar, name, non_terminal, o, operators, option, parser, part, tokens, unwrap; var __hasProp = Object.prototype.hasOwnProperty; Parser = require('jison').Parser; // DSL =================================================================== @@ -15,6 +15,8 @@ return [pattern_string, '$$ = $1;']; } }; + // Precedence =========================================================== + operators = [["left", '?'], ["right", 'NOT', '!', '!!', '~', '++', '--'], ["left", '*', '/', '%'], ["left", '+', '-'], ["left", '<<', '>>', '>>>'], ["left", '&', '|', '^'], ["left", '<=', '<', '>', '>='], ["right", '==', '!=', 'IS', 'ISNT'], ["left", '&&', '||', 'AND', 'OR'], ["right", '-=', '+=', '/=', '*=', '%='], ["right", 'DELETE', 'INSTANCEOF', 'TYPEOF'], ["left", '.'], ["right", 'INDENT'], ["left", 'OUTDENT'], ["right", 'WHEN', 'LEADING_WHEN', 'IN', 'OF', 'BY'], ["right", 'THROW', 'FOR', 'NEW', 'SUPER'], ["left", 'EXTENDS'], ["left", '||=', '&&=', '?='], ["right", 'ASSIGN', 'RETURN'], ["right", '->', '=>', 'UNLESS', 'IF', 'ELSE', 'WHILE']]; // Grammar ============================================================== grammar = { // All parsing will end in this rule, being the trunk of the AST. @@ -194,6 +196,59 @@ return new OpNode($2, $1, $3); }) ], + // Try abbreviated expressions to make the grammar build faster: + // UnaryOp: [ + // o "!" + // o "!!" + // o "NOT" + // o "~" + // o "--" + // o "++" + // o "DELETE" + // o "TYPEOF" + // ] + // + // BinaryOp: [ + // o "*" + // o "/" + // o "%" + // o "+" + // o "-" + // o "<<" + // o ">>" + // o ">>>" + // o "&" + // o "|" + // o "^" + // o "<=" + // o "<" + // o ">" + // o ">=" + // o "==" + // o "!=" + // o "IS" + // o "ISNT" + // o "&&" + // o "||" + // o "AND" + // o "OR" + // o "?" + // o "-=" + // o "+=" + // o "/=" + // o "*=" + // o "%=" + // o "||=" + // o "&&=" + // o "?=" + // o "INSTANCEOF" + // o "IN" + // ] + // + // Operation: [ + // o "Expression BinaryOp Expression", -> new OpNode($2, $1, $3) + // o "UnaryOp Expression", -> new OpNode($1, $2) + // ] // The existence operator. Existence: [o("Expression ?", function() { return new ExistenceNode($1); @@ -532,7 +587,8 @@ tokens = tokens.join(" "); parser = new Parser({ tokens: tokens, - bnf: bnf + bnf: bnf, + operators: operators }, { debug: false }); diff --git a/src/parser.coffee b/src/parser.coffee index 698d159e..4fde8663 100644 --- a/src/parser.coffee +++ b/src/parser.coffee @@ -13,6 +13,31 @@ o: (pattern_string, func) -> else [pattern_string, '$$ = $1;'] +# Precedence =========================================================== + +operators: [ + ["left", '?'] + ["right", 'NOT', '!', '!!', '~', '++', '--'] + ["left", '*', '/', '%'] + ["left", '+', '-'] + ["left", '<<', '>>', '>>>'] + ["left", '&', '|', '^'] + ["left", '<=', '<', '>', '>='] + ["right", '==', '!=', 'IS', 'ISNT'] + ["left", '&&', '||', 'AND', 'OR'] + ["right", '-=', '+=', '/=', '*=', '%='] + ["right", 'DELETE', 'INSTANCEOF', 'TYPEOF'] + ["left", '.'] + ["right", 'INDENT'] + ["left", 'OUTDENT'] + ["right", 'WHEN', 'LEADING_WHEN', 'IN', 'OF', 'BY'] + ["right", 'THROW', 'FOR', 'NEW', 'SUPER'] + ["left", 'EXTENDS'] + ["left", '||=', '&&=', '?='] + ["right", 'ASSIGN', 'RETURN'] + ["right", '->', '=>', 'UNLESS', 'IF', 'ELSE', 'WHILE'] +] + # Grammar ============================================================== grammar: { @@ -167,6 +192,61 @@ grammar: { o "Expression IN Expression", -> new OpNode($2, $1, $3) ] + # Try abbreviated expressions to make the grammar build faster: + + # UnaryOp: [ + # o "!" + # o "!!" + # o "NOT" + # o "~" + # o "--" + # o "++" + # o "DELETE" + # o "TYPEOF" + # ] + # + # BinaryOp: [ + # o "*" + # o "/" + # o "%" + # o "+" + # o "-" + # o "<<" + # o ">>" + # o ">>>" + # o "&" + # o "|" + # o "^" + # o "<=" + # o "<" + # o ">" + # o ">=" + # o "==" + # o "!=" + # o "IS" + # o "ISNT" + # o "&&" + # o "||" + # o "AND" + # o "OR" + # o "?" + # o "-=" + # o "+=" + # o "/=" + # o "*=" + # o "%=" + # o "||=" + # o "&&=" + # o "?=" + # o "INSTANCEOF" + # o "IN" + # ] + # + # Operation: [ + # o "Expression BinaryOp Expression", -> new OpNode($2, $1, $3) + # o "UnaryOp Expression", -> new OpNode($1, $2) + # ] + # The existence operator. Existence: [ o "Expression ?", -> new ExistenceNode($1) @@ -426,7 +506,7 @@ for name, non_terminal of grammar option[1] = "return " + option[1] option tokens: tokens.join(" ") -parser: new Parser({tokens: tokens, bnf: bnf}, {debug: false}) +parser: new Parser({tokens: tokens, bnf: bnf, operators: operators}, {debug: false}) # Thin wrapper around the real lexer parser.lexer: {