From a347183f3d87bc528a91b605e52834935fd5bc7d Mon Sep 17 00:00:00 2001 From: Jeremy Ashkenas Date: Sun, 7 Feb 2010 15:37:05 -0500 Subject: [PATCH] waypoint -- parser.coffee can parse basic functions --- lib/coffee_script/nodes.js | 213 +++++++++++++++++++++++++++++++----- lib/coffee_script/parser.js | 206 ++++++++++++---------------------- src/nodes.coffee | 57 +++++----- src/parser.coffee | 213 +++++++++++++----------------------- 4 files changed, 363 insertions(+), 326 deletions(-) diff --git a/lib/coffee_script/nodes.js b/lib/coffee_script/nodes.js index 54e6956c..aef4cad1 100644 --- a/lib/coffee_script/nodes.js +++ b/lib/coffee_script/nodes.js @@ -2,36 +2,193 @@ exports.Node = function Node() { var __a; var arguments = Array.prototype.slice.call(arguments, 0); - __a = this.values = arguments; + this.values = arguments; + __a = this.name = this.constructor.name; return Node === this.constructor ? this : __a; }; - exports.Node.wrap = function wrap(values) { + exports.Expressions = function Expressions() { + var __a; + var arguments = Array.prototype.slice.call(arguments, 0); + this.name = this.constructor.name; + __a = this.values = arguments; + return Expressions === this.constructor ? this : __a; + }; + exports.LiteralNode = function LiteralNode() { + var __a; + var arguments = Array.prototype.slice.call(arguments, 0); + this.name = this.constructor.name; + __a = this.values = arguments; + return LiteralNode === this.constructor ? this : __a; + }; + exports.ReturnNode = function ReturnNode() { + var __a; + var arguments = Array.prototype.slice.call(arguments, 0); + this.name = this.constructor.name; + __a = this.values = arguments; + return ReturnNode === this.constructor ? this : __a; + }; + exports.CommentNode = function CommentNode() { + var __a; + var arguments = Array.prototype.slice.call(arguments, 0); + this.name = this.constructor.name; + __a = this.values = arguments; + return CommentNode === this.constructor ? this : __a; + }; + exports.CallNode = function CallNode() { + var __a; + var arguments = Array.prototype.slice.call(arguments, 0); + this.name = this.constructor.name; + __a = this.values = arguments; + return CallNode === this.constructor ? this : __a; + }; + exports.ExtendsNode = function ExtendsNode() { + var __a; + var arguments = Array.prototype.slice.call(arguments, 0); + this.name = this.constructor.name; + __a = this.values = arguments; + return ExtendsNode === this.constructor ? this : __a; + }; + exports.ValueNode = function ValueNode() { + var __a; + var arguments = Array.prototype.slice.call(arguments, 0); + this.name = this.constructor.name; + __a = this.values = arguments; + return ValueNode === this.constructor ? this : __a; + }; + exports.AccessorNode = function AccessorNode() { + var __a; + var arguments = Array.prototype.slice.call(arguments, 0); + this.name = this.constructor.name; + __a = this.values = arguments; + return AccessorNode === this.constructor ? this : __a; + }; + exports.IndexNode = function IndexNode() { + var __a; + var arguments = Array.prototype.slice.call(arguments, 0); + this.name = this.constructor.name; + __a = this.values = arguments; + return IndexNode === this.constructor ? this : __a; + }; + exports.RangeNode = function RangeNode() { + var __a; + var arguments = Array.prototype.slice.call(arguments, 0); + this.name = this.constructor.name; + __a = this.values = arguments; + return RangeNode === this.constructor ? this : __a; + }; + exports.SliceNode = function SliceNode() { + var __a; + var arguments = Array.prototype.slice.call(arguments, 0); + this.name = this.constructor.name; + __a = this.values = arguments; + return SliceNode === this.constructor ? this : __a; + }; + exports.AssignNode = function AssignNode() { + var __a; + var arguments = Array.prototype.slice.call(arguments, 0); + this.name = this.constructor.name; + __a = this.values = arguments; + return AssignNode === this.constructor ? this : __a; + }; + exports.OpNode = function OpNode() { + var __a; + var arguments = Array.prototype.slice.call(arguments, 0); + this.name = this.constructor.name; + __a = this.values = arguments; + return OpNode === this.constructor ? this : __a; + }; + exports.CodeNode = function CodeNode() { + var __a; + var arguments = Array.prototype.slice.call(arguments, 0); + this.name = this.constructor.name; + __a = this.values = arguments; + return CodeNode === this.constructor ? this : __a; + }; + exports.SplatNode = function SplatNode() { + var __a; + var arguments = Array.prototype.slice.call(arguments, 0); + this.name = this.constructor.name; + __a = this.values = arguments; + return SplatNode === this.constructor ? this : __a; + }; + exports.ObjectNode = function ObjectNode() { + var __a; + var arguments = Array.prototype.slice.call(arguments, 0); + this.name = this.constructor.name; + __a = this.values = arguments; + return ObjectNode === this.constructor ? this : __a; + }; + exports.ArrayNode = function ArrayNode() { + var __a; + var arguments = Array.prototype.slice.call(arguments, 0); + this.name = this.constructor.name; + __a = this.values = arguments; + return ArrayNode === this.constructor ? this : __a; + }; + exports.PushNode = function PushNode() { + var __a; + var arguments = Array.prototype.slice.call(arguments, 0); + this.name = this.constructor.name; + __a = this.values = arguments; + return PushNode === this.constructor ? this : __a; + }; + exports.ClosureNode = function ClosureNode() { + var __a; + var arguments = Array.prototype.slice.call(arguments, 0); + this.name = this.constructor.name; + __a = this.values = arguments; + return ClosureNode === this.constructor ? this : __a; + }; + exports.WhileNode = function WhileNode() { + var __a; + var arguments = Array.prototype.slice.call(arguments, 0); + this.name = this.constructor.name; + __a = this.values = arguments; + return WhileNode === this.constructor ? this : __a; + }; + exports.ForNode = function ForNode() { + var __a; + var arguments = Array.prototype.slice.call(arguments, 0); + this.name = this.constructor.name; + __a = this.values = arguments; + return ForNode === this.constructor ? this : __a; + }; + exports.TryNode = function TryNode() { + var __a; + var arguments = Array.prototype.slice.call(arguments, 0); + this.name = this.constructor.name; + __a = this.values = arguments; + return TryNode === this.constructor ? this : __a; + }; + exports.ThrowNode = function ThrowNode() { + var __a; + var arguments = Array.prototype.slice.call(arguments, 0); + this.name = this.constructor.name; + __a = this.values = arguments; + return ThrowNode === this.constructor ? this : __a; + }; + exports.ExistenceNode = function ExistenceNode() { + var __a; + var arguments = Array.prototype.slice.call(arguments, 0); + this.name = this.constructor.name; + __a = this.values = arguments; + return ExistenceNode === this.constructor ? this : __a; + }; + exports.ParentheticalNode = function ParentheticalNode() { + var __a; + var arguments = Array.prototype.slice.call(arguments, 0); + this.name = this.constructor.name; + __a = this.values = arguments; + return ParentheticalNode === this.constructor ? this : __a; + }; + exports.IfNode = function IfNode() { + var __a; + var arguments = Array.prototype.slice.call(arguments, 0); + this.name = this.constructor.name; + __a = this.values = arguments; + return IfNode === this.constructor ? this : __a; + }; + exports.Expressions.wrap = function wrap(values) { return this.values = values; }; - exports.Expressions = exports.Node; - exports.LiteralNode = exports.Node; - exports.ReturnNode = exports.Node; - exports.CommentNode = exports.Node; - exports.CallNode = exports.Node; - exports.ExtendsNode = exports.Node; - exports.ValueNode = exports.Node; - exports.AccessorNode = exports.Node; - exports.IndexNode = exports.Node; - exports.RangeNode = exports.Node; - exports.SliceNode = exports.Node; - exports.AssignNode = exports.Node; - exports.OpNode = exports.Node; - exports.CodeNode = exports.Node; - exports.SplatNode = exports.Node; - exports.ObjectNode = exports.Node; - exports.ArrayNode = exports.Node; - exports.PushNode = exports.Node; - exports.ClosureNode = exports.Node; - exports.WhileNode = exports.Node; - exports.ForNode = exports.Node; - exports.TryNode = exports.Node; - exports.ThrowNode = exports.Node; - exports.ExistenceNode = exports.Node; - exports.ParentheticalNode = exports.Node; - exports.IfNode = exports.Node; })(); \ No newline at end of file diff --git a/lib/coffee_script/parser.js b/lib/coffee_script/parser.js index 7d431217..2a9fe562 100644 --- a/lib/coffee_script/parser.js +++ b/lib/coffee_script/parser.js @@ -36,44 +36,30 @@ ], // All types of expressions in our language. The basic unit of CoffeeScript // is the expression. - Expression: [o("Value"), - // o "Call" - // o "Code" - // o "Operation" - // o "Assign" - // o "If" - // o "Try" - // o "Throw" - // o "Return" - // o "While" - // o "For" - // o "Switch" - // o "Extends" - // o "Splat" - // o "Existence" - // o "Comment" + Expression: [o("Value"), o("Call"), o("Code"), o("Operation"), o("Assign"), o("If"), o("Try"), o("Throw"), o("Return"), o("While"), o("For"), o("Switch"), o("Extends"), o("Splat"), o("Existence"), o("Comment")], + // A block of expressions. Note that the Rewriter will convert some postfix + // forms into blocks for us, by altering the token stream. + Block: [o("INDENT Expressions OUTDENT", function() { + return $2; + }), o("INDENT OUTDENT", function() { + return new Expressions(); + }) ], - // # A block of expressions. Note that the Rewriter will convert some postfix - // # forms into blocks for us, by altering the token stream. - // Block: [ - // o "INDENT Expressions OUTDENT", -> $2 - // o "INDENT OUTDENT", -> new Expressions() - // ] // All hard-coded values. These can be printed straight to JavaScript. Literal: [o("NUMBER", function() { return new LiteralNode(yytext); }), o("STRING", function() { - return new LiteralNode($1); + return new LiteralNode(yytext); }), o("JS", function() { - return new LiteralNode($1); + return new LiteralNode(yytext); }), o("REGEX", function() { - return new LiteralNode($1); + return new LiteralNode(yytext); }), o("BREAK", function() { - return new LiteralNode($1); + return new LiteralNode(yytext); }), o("CONTINUE", function() { - return new LiteralNode($1); + return new LiteralNode(yytext); }), o("ARGUMENTS", function() { - return new LiteralNode($1); + return new LiteralNode(yytext); }), o("TRUE", function() { return new LiteralNode(true); }), o("FALSE", function() { @@ -88,28 +74,30 @@ return new LiteralNode(false); }) ], - // # Assignment to a variable (or index). - // Assign: [ - // o "Value ASSIGN Expression", -> new AssignNode($1, $3) - // ] - // - // # Assignment within an object literal (can be quoted). - // AssignObj: [ - // o "IDENTIFIER ASSIGN Expression", -> new AssignNode(new ValueNode($1), $3, 'object') - // o "STRING ASSIGN Expression", -> new AssignNode(new ValueNode(new LiteralNode($1)), $3, 'object') - // o "Comment" - // ] - // - // # A return statement. - // Return: [ - // o "RETURN Expression", -> new ReturnNode($2) - // o "RETURN", -> new ReturnNode(new ValueNode(new LiteralNode('null'))) - // ] - // - // # A comment. - // Comment: [ - // o "COMMENT", -> new CommentNode($1) - // ] + // Assignment to a variable (or index). + Assign: [o("Value ASSIGN Expression", function() { + return new AssignNode($1, $3); + }) + ], + // Assignment within an object literal (can be quoted). + AssignObj: [o("IDENTIFIER ASSIGN Expression", function() { + return new AssignNode(new ValueNode(yytext), $3, 'object'); + }), o("STRING ASSIGN Expression", function() { + return new AssignNode(new ValueNode(new LiteralNode(yytext)), $3, 'object'); + }), o("Comment") + ], + // A return statement. + Return: [o("RETURN Expression", function() { + return new ReturnNode($2); + }), o("RETURN", function() { + return new ReturnNode(new ValueNode(new LiteralNode('null'))); + }) + ], + // A comment. + Comment: [o("COMMENT", function() { + return new CommentNode(yytext); + }) + ], // // # Arithmetic and logical operators // # For Ruby's Operator precedence, see: [ @@ -171,91 +159,39 @@ // o "Expression INSTANCEOF Expression", -> new OpNode($2, $1, $3) // 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) - // ] - // - // # Function definition. - // Code: [ - // o "PARAM_START ParamList PARAM_END FuncGlyph Block", -> new CodeNode($2, $5, $4) - // o "FuncGlyph Block", -> new CodeNode([], $2, $1) - // ] - // - // # The symbols to signify functions, and bound functions. - // FuncGlyph: [ - // o "->", -> 'func' - // o "=>", -> 'boundfunc' - // ] - // - // # The parameters to a function definition. - // ParamList: [ - // o "Param", -> [$1] - // o "ParamList , Param", -> $1.push($3) - // ] - // - // # A Parameter (or ParamSplat) in a function definition. - // Param: [ - // o "PARAM" - // o "PARAM . . .", -> new SplatNode($1) - // ] - // + // The existence operator. + Existence: [o("Expression ?", function() { + return new ExistenceNode($1); + }) + ], + // Function definition. + Code: [o("PARAM_START ParamList PARAM_END FuncGlyph Block", function() { + return new CodeNode($2, $5, $4); + }), o("FuncGlyph Block", function() { + return new CodeNode([], $2, $1); + }) + ], + // The symbols to signify functions, and bound functions. + FuncGlyph: [o("->", function() { + return 'func'; + }), o("=>", function() { + return 'boundfunc'; + }) + ], + // The parameters to a function definition. + ParamList: [o("Param", function() { + return [$1]; + }), o("ParamList , Param", function() { + return $1.push($3); + }) + ], + // A Parameter (or ParamSplat) in a function definition. + Param: [o("PARAM", function() { + return yytext; + }), o("PARAM . . .", function() { + return new SplatNode(yytext); + }) + ], // # A regular splat. // Splat: [ // o "Expression . . .", -> new SplatNode($1) diff --git a/src/nodes.coffee b/src/nodes.coffee index c4cc7c19..82bf2456 100644 --- a/src/nodes.coffee +++ b/src/nodes.coffee @@ -1,31 +1,30 @@ -exports.Node: -> @values: arguments -exports.Node.wrap: (values) -> @values: values - -exports.Expressions : exports.Node -exports.LiteralNode : exports.Node -exports.ReturnNode : exports.Node -exports.CommentNode : exports.Node -exports.CallNode : exports.Node -exports.ExtendsNode : exports.Node -exports.ValueNode : exports.Node -exports.AccessorNode : exports.Node -exports.IndexNode : exports.Node -exports.RangeNode : exports.Node -exports.SliceNode : exports.Node -exports.AssignNode : exports.Node -exports.OpNode : exports.Node -exports.CodeNode : exports.Node -exports.SplatNode : exports.Node -exports.ObjectNode : exports.Node -exports.ArrayNode : exports.Node -exports.PushNode : exports.Node -exports.ClosureNode : exports.Node -exports.WhileNode : exports.Node -exports.ForNode : exports.Node -exports.TryNode : exports.Node -exports.ThrowNode : exports.Node -exports.ExistenceNode : exports.Node -exports.ParentheticalNode : exports.Node -exports.IfNode : exports.Node +exports.Node: -> @values: arguments; @name: this.constructor.name +exports.Expressions : -> @name: this.constructor.name; @values: arguments +exports.LiteralNode : -> @name: this.constructor.name; @values: arguments +exports.ReturnNode : -> @name: this.constructor.name; @values: arguments +exports.CommentNode : -> @name: this.constructor.name; @values: arguments +exports.CallNode : -> @name: this.constructor.name; @values: arguments +exports.ExtendsNode : -> @name: this.constructor.name; @values: arguments +exports.ValueNode : -> @name: this.constructor.name; @values: arguments +exports.AccessorNode : -> @name: this.constructor.name; @values: arguments +exports.IndexNode : -> @name: this.constructor.name; @values: arguments +exports.RangeNode : -> @name: this.constructor.name; @values: arguments +exports.SliceNode : -> @name: this.constructor.name; @values: arguments +exports.AssignNode : -> @name: this.constructor.name; @values: arguments +exports.OpNode : -> @name: this.constructor.name; @values: arguments +exports.CodeNode : -> @name: this.constructor.name; @values: arguments +exports.SplatNode : -> @name: this.constructor.name; @values: arguments +exports.ObjectNode : -> @name: this.constructor.name; @values: arguments +exports.ArrayNode : -> @name: this.constructor.name; @values: arguments +exports.PushNode : -> @name: this.constructor.name; @values: arguments +exports.ClosureNode : -> @name: this.constructor.name; @values: arguments +exports.WhileNode : -> @name: this.constructor.name; @values: arguments +exports.ForNode : -> @name: this.constructor.name; @values: arguments +exports.TryNode : -> @name: this.constructor.name; @values: arguments +exports.ThrowNode : -> @name: this.constructor.name; @values: arguments +exports.ExistenceNode : -> @name: this.constructor.name; @values: arguments +exports.ParentheticalNode : -> @name: this.constructor.name; @values: arguments +exports.IfNode : -> @name: this.constructor.name; @values: arguments +exports.Expressions.wrap : (values) -> @values: values diff --git a/src/parser.coffee b/src/parser.coffee index 17477d3a..83568539 100644 --- a/src/parser.coffee +++ b/src/parser.coffee @@ -62,39 +62,39 @@ grammar: { # is the expression. Expression: [ o "Value" - # o "Call" - # o "Code" - # o "Operation" - # o "Assign" - # o "If" - # o "Try" - # o "Throw" - # o "Return" - # o "While" - # o "For" - # o "Switch" - # o "Extends" - # o "Splat" - # o "Existence" - # o "Comment" + o "Call" + o "Code" + o "Operation" + o "Assign" + o "If" + o "Try" + o "Throw" + o "Return" + o "While" + o "For" + o "Switch" + o "Extends" + o "Splat" + o "Existence" + o "Comment" ] - # # A block of expressions. Note that the Rewriter will convert some postfix - # # forms into blocks for us, by altering the token stream. - # Block: [ - # o "INDENT Expressions OUTDENT", -> $2 - # o "INDENT OUTDENT", -> new Expressions() - # ] + # A block of expressions. Note that the Rewriter will convert some postfix + # forms into blocks for us, by altering the token stream. + Block: [ + o "INDENT Expressions OUTDENT", -> $2 + o "INDENT OUTDENT", -> new Expressions() + ] # All hard-coded values. These can be printed straight to JavaScript. Literal: [ o "NUMBER", -> new LiteralNode(yytext) - o "STRING", -> new LiteralNode($1) - o "JS", -> new LiteralNode($1) - o "REGEX", -> new LiteralNode($1) - o "BREAK", -> new LiteralNode($1) - o "CONTINUE", -> new LiteralNode($1) - o "ARGUMENTS", -> new LiteralNode($1) + o "STRING", -> new LiteralNode(yytext) + o "JS", -> new LiteralNode(yytext) + o "REGEX", -> new LiteralNode(yytext) + o "BREAK", -> new LiteralNode(yytext) + o "CONTINUE", -> new LiteralNode(yytext) + o "ARGUMENTS", -> new LiteralNode(yytext) o "TRUE", -> new LiteralNode(true) o "FALSE", -> new LiteralNode(false) o "YES", -> new LiteralNode(true) @@ -103,28 +103,28 @@ grammar: { o "OFF", -> new LiteralNode(false) ] - # # Assignment to a variable (or index). - # Assign: [ - # o "Value ASSIGN Expression", -> new AssignNode($1, $3) - # ] - # - # # Assignment within an object literal (can be quoted). - # AssignObj: [ - # o "IDENTIFIER ASSIGN Expression", -> new AssignNode(new ValueNode($1), $3, 'object') - # o "STRING ASSIGN Expression", -> new AssignNode(new ValueNode(new LiteralNode($1)), $3, 'object') - # o "Comment" - # ] - # - # # A return statement. - # Return: [ - # o "RETURN Expression", -> new ReturnNode($2) - # o "RETURN", -> new ReturnNode(new ValueNode(new LiteralNode('null'))) - # ] - # - # # A comment. - # Comment: [ - # o "COMMENT", -> new CommentNode($1) - # ] + # Assignment to a variable (or index). + Assign: [ + o "Value ASSIGN Expression", -> new AssignNode($1, $3) + ] + + # Assignment within an object literal (can be quoted). + AssignObj: [ + o "IDENTIFIER ASSIGN Expression", -> new AssignNode(new ValueNode(yytext), $3, 'object') + o "STRING ASSIGN Expression", -> new AssignNode(new ValueNode(new LiteralNode(yytext)), $3, 'object') + o "Comment" + ] + + # A return statement. + Return: [ + o "RETURN Expression", -> new ReturnNode($2) + o "RETURN", -> new ReturnNode(new ValueNode(new LiteralNode('null'))) + ] + + # A comment. + Comment: [ + o "COMMENT", -> new CommentNode(yytext) + ] # # # Arithmetic and logical operators # # For Ruby's Operator precedence, see: [ @@ -186,91 +186,36 @@ grammar: { # o "Expression INSTANCEOF Expression", -> new OpNode($2, $1, $3) # 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) - # ] - # - # # Function definition. - # Code: [ - # o "PARAM_START ParamList PARAM_END FuncGlyph Block", -> new CodeNode($2, $5, $4) - # o "FuncGlyph Block", -> new CodeNode([], $2, $1) - # ] - # - # # The symbols to signify functions, and bound functions. - # FuncGlyph: [ - # o "->", -> 'func' - # o "=>", -> 'boundfunc' - # ] - # - # # The parameters to a function definition. - # ParamList: [ - # o "Param", -> [$1] - # o "ParamList , Param", -> $1.push($3) - # ] - # - # # A Parameter (or ParamSplat) in a function definition. - # Param: [ - # o "PARAM" - # o "PARAM . . .", -> new SplatNode($1) - # ] - # + + # The existence operator. + Existence: [ + o "Expression ?", -> new ExistenceNode($1) + ] + + # Function definition. + Code: [ + o "PARAM_START ParamList PARAM_END FuncGlyph Block", -> new CodeNode($2, $5, $4) + o "FuncGlyph Block", -> new CodeNode([], $2, $1) + ] + + # The symbols to signify functions, and bound functions. + FuncGlyph: [ + o "->", -> 'func' + o "=>", -> 'boundfunc' + ] + + # The parameters to a function definition. + ParamList: [ + o "Param", -> [$1] + o "ParamList , Param", -> $1.push($3) + ] + + # A Parameter (or ParamSplat) in a function definition. + Param: [ + o "PARAM", -> yytext + o "PARAM . . .", -> new SplatNode(yytext) + ] + # # A regular splat. # Splat: [ # o "Expression . . .", -> new SplatNode($1)