waypoint -- parser.coffee can parse basic functions

This commit is contained in:
Jeremy Ashkenas
2010-02-07 15:37:05 -05:00
parent 56499984ca
commit a347183f3d
4 changed files with 363 additions and 326 deletions

View File

@@ -2,36 +2,193 @@
exports.Node = function Node() { exports.Node = function Node() {
var __a; var __a;
var arguments = Array.prototype.slice.call(arguments, 0); 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; 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; 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;
})(); })();

View File

@@ -36,44 +36,30 @@
], ],
// All types of expressions in our language. The basic unit of CoffeeScript // All types of expressions in our language. The basic unit of CoffeeScript
// is the expression. // is the expression.
Expression: [o("Value"), 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" // A block of expressions. Note that the Rewriter will convert some postfix
// o "Code" // forms into blocks for us, by altering the token stream.
// o "Operation" Block: [o("INDENT Expressions OUTDENT", function() {
// o "Assign" return $2;
// o "If" }), o("INDENT OUTDENT", function() {
// o "Try" return new Expressions();
// 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()
// ]
// All hard-coded values. These can be printed straight to JavaScript. // All hard-coded values. These can be printed straight to JavaScript.
Literal: [o("NUMBER", function() { Literal: [o("NUMBER", function() {
return new LiteralNode(yytext); return new LiteralNode(yytext);
}), o("STRING", function() { }), o("STRING", function() {
return new LiteralNode($1); return new LiteralNode(yytext);
}), o("JS", function() { }), o("JS", function() {
return new LiteralNode($1); return new LiteralNode(yytext);
}), o("REGEX", function() { }), o("REGEX", function() {
return new LiteralNode($1); return new LiteralNode(yytext);
}), o("BREAK", function() { }), o("BREAK", function() {
return new LiteralNode($1); return new LiteralNode(yytext);
}), o("CONTINUE", function() { }), o("CONTINUE", function() {
return new LiteralNode($1); return new LiteralNode(yytext);
}), o("ARGUMENTS", function() { }), o("ARGUMENTS", function() {
return new LiteralNode($1); return new LiteralNode(yytext);
}), o("TRUE", function() { }), o("TRUE", function() {
return new LiteralNode(true); return new LiteralNode(true);
}), o("FALSE", function() { }), o("FALSE", function() {
@@ -88,28 +74,30 @@
return new LiteralNode(false); return new LiteralNode(false);
}) })
], ],
// # Assignment to a variable (or index). // Assignment to a variable (or index).
// Assign: [ Assign: [o("Value ASSIGN Expression", function() {
// o "Value ASSIGN Expression", -> new AssignNode($1, $3) return new AssignNode($1, $3);
// ] })
// ],
// # Assignment within an object literal (can be quoted). // Assignment within an object literal (can be quoted).
// AssignObj: [ AssignObj: [o("IDENTIFIER ASSIGN Expression", function() {
// o "IDENTIFIER ASSIGN Expression", -> new AssignNode(new ValueNode($1), $3, 'object') return new AssignNode(new ValueNode(yytext), $3, 'object');
// o "STRING ASSIGN Expression", -> new AssignNode(new ValueNode(new LiteralNode($1)), $3, 'object') }), o("STRING ASSIGN Expression", function() {
// o "Comment" return new AssignNode(new ValueNode(new LiteralNode(yytext)), $3, 'object');
// ] }), o("Comment")
// ],
// # A return statement. // A return statement.
// Return: [ Return: [o("RETURN Expression", function() {
// o "RETURN Expression", -> new ReturnNode($2) return new ReturnNode($2);
// o "RETURN", -> new ReturnNode(new ValueNode(new LiteralNode('null'))) }), o("RETURN", function() {
// ] return new ReturnNode(new ValueNode(new LiteralNode('null')));
// })
// # A comment. ],
// Comment: [ // A comment.
// o "COMMENT", -> new CommentNode($1) Comment: [o("COMMENT", function() {
// ] return new CommentNode(yytext);
})
],
// //
// # Arithmetic and logical operators // # Arithmetic and logical operators
// # For Ruby's Operator precedence, see: [ // # For Ruby's Operator precedence, see: [
@@ -171,91 +159,39 @@
// o "Expression INSTANCEOF Expression", -> new OpNode($2, $1, $3) // o "Expression INSTANCEOF Expression", -> new OpNode($2, $1, $3)
// o "Expression IN Expression", -> new OpNode($2, $1, $3) // o "Expression IN Expression", -> new OpNode($2, $1, $3)
// ] // ]
// // The existence operator.
// # Try abbreviated expressions to make the grammar build faster: Existence: [o("Expression ?", function() {
// return new ExistenceNode($1);
// # UnaryOp: [ })
// # o "!" ],
// # o "!!" // Function definition.
// # o "NOT" Code: [o("PARAM_START ParamList PARAM_END FuncGlyph Block", function() {
// # o "~" return new CodeNode($2, $5, $4);
// # o "--" }), o("FuncGlyph Block", function() {
// # o "++" return new CodeNode([], $2, $1);
// # o "DELETE" })
// # o "TYPEOF" ],
// # ] // The symbols to signify functions, and bound functions.
// # FuncGlyph: [o("->", function() {
// # BinaryOp: [ return 'func';
// # o "*" }), o("=>", function() {
// # o "/" return 'boundfunc';
// # o "%" })
// # o "+" ],
// # o "-" // The parameters to a function definition.
// # o "<<" ParamList: [o("Param", function() {
// # o ">>" return [$1];
// # o ">>>" }), o("ParamList , Param", function() {
// # o "&" return $1.push($3);
// # o "|" })
// # o "^" ],
// # o "<=" // A Parameter (or ParamSplat) in a function definition.
// # o "<" Param: [o("PARAM", function() {
// # o ">" return yytext;
// # o ">=" }), o("PARAM . . .", function() {
// # o "==" return new SplatNode(yytext);
// # 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)
// ]
//
// # A regular splat. // # A regular splat.
// Splat: [ // Splat: [
// o "Expression . . .", -> new SplatNode($1) // o "Expression . . .", -> new SplatNode($1)

View File

@@ -1,31 +1,30 @@
exports.Node: -> @values: arguments exports.Node: -> @values: arguments; @name: this.constructor.name
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.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

View File

@@ -62,39 +62,39 @@ grammar: {
# is the expression. # is the expression.
Expression: [ Expression: [
o "Value" o "Value"
# o "Call" o "Call"
# o "Code" o "Code"
# o "Operation" o "Operation"
# o "Assign" o "Assign"
# o "If" o "If"
# o "Try" o "Try"
# o "Throw" o "Throw"
# o "Return" o "Return"
# o "While" o "While"
# o "For" o "For"
# o "Switch" o "Switch"
# o "Extends" o "Extends"
# o "Splat" o "Splat"
# o "Existence" o "Existence"
# o "Comment" o "Comment"
] ]
# # A block of expressions. Note that the Rewriter will convert some postfix # A block of expressions. Note that the Rewriter will convert some postfix
# # forms into blocks for us, by altering the token stream. # forms into blocks for us, by altering the token stream.
# Block: [ Block: [
# o "INDENT Expressions OUTDENT", -> $2 o "INDENT Expressions OUTDENT", -> $2
# o "INDENT OUTDENT", -> new Expressions() o "INDENT OUTDENT", -> new Expressions()
# ] ]
# All hard-coded values. These can be printed straight to JavaScript. # All hard-coded values. These can be printed straight to JavaScript.
Literal: [ Literal: [
o "NUMBER", -> new LiteralNode(yytext) o "NUMBER", -> new LiteralNode(yytext)
o "STRING", -> new LiteralNode($1) o "STRING", -> new LiteralNode(yytext)
o "JS", -> new LiteralNode($1) o "JS", -> new LiteralNode(yytext)
o "REGEX", -> new LiteralNode($1) o "REGEX", -> new LiteralNode(yytext)
o "BREAK", -> new LiteralNode($1) o "BREAK", -> new LiteralNode(yytext)
o "CONTINUE", -> new LiteralNode($1) o "CONTINUE", -> new LiteralNode(yytext)
o "ARGUMENTS", -> new LiteralNode($1) o "ARGUMENTS", -> new LiteralNode(yytext)
o "TRUE", -> new LiteralNode(true) o "TRUE", -> new LiteralNode(true)
o "FALSE", -> new LiteralNode(false) o "FALSE", -> new LiteralNode(false)
o "YES", -> new LiteralNode(true) o "YES", -> new LiteralNode(true)
@@ -103,28 +103,28 @@ grammar: {
o "OFF", -> new LiteralNode(false) o "OFF", -> new LiteralNode(false)
] ]
# # Assignment to a variable (or index). # Assignment to a variable (or index).
# Assign: [ Assign: [
# o "Value ASSIGN Expression", -> new AssignNode($1, $3) o "Value ASSIGN Expression", -> new AssignNode($1, $3)
# ] ]
#
# # Assignment within an object literal (can be quoted). # Assignment within an object literal (can be quoted).
# AssignObj: [ AssignObj: [
# o "IDENTIFIER ASSIGN Expression", -> new AssignNode(new ValueNode($1), $3, 'object') o "IDENTIFIER ASSIGN Expression", -> new AssignNode(new ValueNode(yytext), $3, 'object')
# o "STRING ASSIGN Expression", -> new AssignNode(new ValueNode(new LiteralNode($1)), $3, 'object') o "STRING ASSIGN Expression", -> new AssignNode(new ValueNode(new LiteralNode(yytext)), $3, 'object')
# o "Comment" o "Comment"
# ] ]
#
# # A return statement. # A return statement.
# Return: [ Return: [
# o "RETURN Expression", -> new ReturnNode($2) o "RETURN Expression", -> new ReturnNode($2)
# o "RETURN", -> new ReturnNode(new ValueNode(new LiteralNode('null'))) o "RETURN", -> new ReturnNode(new ValueNode(new LiteralNode('null')))
# ] ]
#
# # A comment. # A comment.
# Comment: [ Comment: [
# o "COMMENT", -> new CommentNode($1) o "COMMENT", -> new CommentNode(yytext)
# ] ]
# #
# # Arithmetic and logical operators # # Arithmetic and logical operators
# # For Ruby's Operator precedence, see: [ # # For Ruby's Operator precedence, see: [
@@ -186,91 +186,36 @@ grammar: {
# o "Expression INSTANCEOF Expression", -> new OpNode($2, $1, $3) # o "Expression INSTANCEOF Expression", -> new OpNode($2, $1, $3)
# o "Expression IN Expression", -> new OpNode($2, $1, $3) # o "Expression IN Expression", -> new OpNode($2, $1, $3)
# ] # ]
#
# # Try abbreviated expressions to make the grammar build faster: # The existence operator.
# Existence: [
# # UnaryOp: [ o "Expression ?", -> new ExistenceNode($1)
# # o "!" ]
# # o "!!"
# # o "NOT" # Function definition.
# # o "~" Code: [
# # o "--" o "PARAM_START ParamList PARAM_END FuncGlyph Block", -> new CodeNode($2, $5, $4)
# # o "++" o "FuncGlyph Block", -> new CodeNode([], $2, $1)
# # o "DELETE" ]
# # o "TYPEOF"
# # ] # The symbols to signify functions, and bound functions.
# # FuncGlyph: [
# # BinaryOp: [ o "->", -> 'func'
# # o "*" o "=>", -> 'boundfunc'
# # o "/" ]
# # o "%"
# # o "+" # The parameters to a function definition.
# # o "-" ParamList: [
# # o "<<" o "Param", -> [$1]
# # o ">>" o "ParamList , Param", -> $1.push($3)
# # o ">>>" ]
# # o "&"
# # o "|" # A Parameter (or ParamSplat) in a function definition.
# # o "^" Param: [
# # o "<=" o "PARAM", -> yytext
# # o "<" o "PARAM . . .", -> new SplatNode(yytext)
# # 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)
# ]
#
# # A regular splat. # # A regular splat.
# Splat: [ # Splat: [
# o "Expression . . .", -> new SplatNode($1) # o "Expression . . .", -> new SplatNode($1)