2010-02-11 04:24:05 +00:00
( function ( ) {
2010-03-07 16:41:56 +00:00
var Parser , _a , _b , _c , _d , _e , _f , _g , _h , alt , alternatives , grammar , name , o , operators , token , tokens , unwrap ;
2010-03-30 20:48:43 +00:00
var _ _hasProp = Object . prototype . hasOwnProperty ;
2010-03-07 16:41:56 +00:00
// The CoffeeScript parser is generated by [Jison](http://github.com/zaach/jison)
// from this grammar file. Jison is a bottom-up parser generator, similar in
// style to [Bison](http://www.gnu.org/software/bison), implemented in JavaScript.
2010-03-07 17:47:03 +00:00
// It can recognize [LALR(1), LR(0), SLR(1), and LR(1)](http://en.wikipedia.org/wiki/LR_grammar)
2010-03-07 16:41:56 +00:00
// type grammars. To create the Jison parser, we list the pattern to match
// on the left-hand side, and the action to take (usually the creation of syntax
// tree nodes) on the right. As the parser runs, it
// shifts tokens from our token stream, from left to right, and
// [attempts to match](http://en.wikipedia.org/wiki/Bottom-up_parsing)
// the token sequence against the rules below. When a match can be made, it
2010-03-07 17:47:03 +00:00
// reduces into the [nonterminal](http://en.wikipedia.org/wiki/Terminal_and_nonterminal_symbols)
2010-03-07 16:41:56 +00:00
// (the enclosing name at the top), and we proceed from there.
// If you run the `cake build:parser` command, Jison constructs a parse table
// from our rules and saves it into `lib/parser.js`.
// The only dependency is on the **Jison.Parser**.
2010-02-11 04:24:05 +00:00
Parser = require ( 'jison' ) . Parser ;
2010-03-07 16:41:56 +00:00
// Jison DSL
// ---------
// Since we're going to be wrapped in a function by Jison in any case, if our
// action immediately returns a value, we can optimize by removing the function
// wrapper and just returning the value directly.
2010-02-11 04:24:05 +00:00
unwrap = /function\s*\(\)\s*\{\s*return\s*([\s\S]*);\s*\}/ ;
2010-03-07 16:41:56 +00:00
// Our handy DSL for Jison grammar generation, thanks to
// [Tim Caswell](http://github.com/creationix). For every rule in the grammar,
// we pass the pattern-defining string, the action to run, and extra options,
// optionally. If no action is specified, we simply pass the value of the
// previous nonterminal.
o = function o ( pattern _string , action , options ) {
2010-02-11 04:24:05 +00:00
var match ;
2010-03-07 16:41:56 +00:00
if ( ! ( action ) ) {
2010-02-11 04:24:05 +00:00
return [ pattern _string , '$$ = $1;' , options ] ;
}
2010-04-04 06:59:44 +00:00
action = ( match = ( action + '' ) . match ( unwrap ) ) ? match [ 1 ] : ( "(" + action + "())" ) ;
return [ pattern _string , ( "$$ = " + action + ";" ) , options ] ;
2010-02-11 04:24:05 +00:00
} ;
2010-03-07 16:41:56 +00:00
// Grammatical Rules
// -----------------
// In all of the rules that follow, you'll see the name of the nonterminal as
// the key to a list of alternative matches. With each match's action, the
// dollar-sign variables are provided by Jison as references to the value of
// their numeric position, so in this rule:
// "Expression UNLESS Expression"
// `$1` would be the value of the first `Expression`, `$2` would be the token
// for the `UNLESS` terminal, and `$3` would be the value of the second
// `Expression`.
2010-02-11 04:24:05 +00:00
grammar = {
2010-03-07 16:41:56 +00:00
// The **Root** is the top-level node in the syntax tree. Since we parse bottom-up,
2010-04-26 03:54:47 +00:00
// all parsing must end here.: // The **Root** is the top-level node in the syntax tree. Since we parse bottom-up,
2010-03-07 16:41:56 +00:00
// all parsing must end here.
2010-02-11 04:24:05 +00:00
Root : [ o ( "" , function ( ) {
return new Expressions ( ) ;
} ) , o ( "TERMINATOR" , function ( ) {
return new Expressions ( ) ;
2010-04-05 14:26:23 +00:00
} ) , o ( "Body" ) , o ( "Block TERMINATOR" )
2010-02-11 04:24:05 +00:00
] ,
2010-04-26 03:54:47 +00:00
// Any list of statements and expressions, seperated by line breaks or semicolons.: // Any list of statements and expressions, seperated by line breaks or semicolons.
2010-04-05 14:26:23 +00:00
Body : [ o ( "Line" , function ( ) {
2010-02-11 04:24:05 +00:00
return Expressions . wrap ( [ $1 ] ) ;
2010-04-05 14:26:23 +00:00
} ) , o ( "Body TERMINATOR Line" , function ( ) {
2010-02-11 04:24:05 +00:00
return $1 . push ( $3 ) ;
2010-04-05 14:26:23 +00:00
} ) , o ( "Body TERMINATOR" )
] ,
2010-04-26 03:54:47 +00:00
// Expressions and statements, which make up a line in a body.: // Expressions and statements, which make up a line in a body.
2010-04-05 14:26:23 +00:00
Line : [ o ( "Expression" ) , o ( "Statement" ) ] ,
2010-04-26 03:54:47 +00:00
// Pure statements which cannot be expressions.: // Pure statements which cannot be expressions.
2010-04-05 14:26:23 +00:00
Statement : [ o ( "Return" ) , o ( "Throw" ) , o ( "BREAK" , function ( ) {
2010-04-22 03:21:48 +00:00
return new LiteralNode ( $1 ) ;
2010-04-05 14:26:23 +00:00
} ) , o ( "CONTINUE" , function ( ) {
2010-04-22 03:21:48 +00:00
return new LiteralNode ( $1 ) ;
2010-04-05 14:26:23 +00:00
} )
2010-02-11 04:24:05 +00:00
] ,
2010-03-07 16:41:56 +00:00
// All the different types of expressions in our language. The basic unit of
2010-04-05 14:26:23 +00:00
// CoffeeScript is the **Expression** -- everything that can be an expression
// is one. Expressions serve as the building blocks of many other rules, making
2010-04-26 03:54:47 +00:00
// them somewhat circular.: // All the different types of expressions in our language. The basic unit of
// CoffeeScript is the **Expression** -- everything that can be an expression
// is one. Expressions serve as the building blocks of many other rules, making
2010-04-05 14:26:23 +00:00
// them somewhat circular.
Expression : [ o ( "Value" ) , o ( "Call" ) , o ( "Curry" ) , o ( "Code" ) , o ( "Operation" ) , o ( "Assign" ) , o ( "If" ) , o ( "Try" ) , o ( "While" ) , o ( "For" ) , o ( "Switch" ) , o ( "Extends" ) , o ( "Class" ) , o ( "Splat" ) , o ( "Existence" ) , o ( "Comment" ) , o ( "Extension" ) ] ,
2010-03-07 16:41:56 +00:00
// A an indented block of expressions. Note that the [Rewriter](rewriter.html)
// will convert some postfix forms into blocks for us, by adjusting the
2010-04-26 03:54:47 +00:00
// token stream.: // A an indented block of expressions. Note that the [Rewriter](rewriter.html)
// will convert some postfix forms into blocks for us, by adjusting the
2010-03-07 16:41:56 +00:00
// token stream.
2010-04-05 14:26:23 +00:00
Block : [ o ( "INDENT Body OUTDENT" , function ( ) {
2010-02-11 04:24:05 +00:00
return $2 ;
} ) , o ( "INDENT OUTDENT" , function ( ) {
return new Expressions ( ) ;
2010-03-10 21:18:17 +00:00
} ) , o ( "TERMINATOR Comment" , function ( ) {
return Expressions . wrap ( [ $2 ] ) ;
2010-02-11 04:24:05 +00:00
} )
] ,
2010-04-26 03:54:47 +00:00
// A literal identifier, a variable name or property.: // A literal identifier, a variable name or property.
2010-02-11 04:24:05 +00:00
Identifier : [ o ( "IDENTIFIER" , function ( ) {
2010-04-22 03:21:48 +00:00
return new LiteralNode ( $1 ) ;
2010-02-11 04:24:05 +00:00
} )
] ,
2010-03-07 16:41:56 +00:00
// Alphanumerics are separated from the other **Literal** matchers because
2010-04-26 03:54:47 +00:00
// they can also serve as keys in object literals.: // Alphanumerics are separated from the other **Literal** matchers because
2010-03-07 16:41:56 +00:00
// they can also serve as keys in object literals.
2010-02-11 04:24:05 +00:00
AlphaNumeric : [ o ( "NUMBER" , function ( ) {
2010-04-22 03:21:48 +00:00
return new LiteralNode ( $1 ) ;
2010-02-11 04:24:05 +00:00
} ) , o ( "STRING" , function ( ) {
2010-04-22 03:21:48 +00:00
return new LiteralNode ( $1 ) ;
2010-02-11 04:24:05 +00:00
} )
] ,
2010-03-07 16:41:56 +00:00
// All of our immediate values. These can (in general), be passed straight
2010-04-26 03:54:47 +00:00
// through and printed to JavaScript.: // All of our immediate values. These can (in general), be passed straight
2010-03-07 16:41:56 +00:00
// through and printed to JavaScript.
Literal : [ o ( "AlphaNumeric" ) , o ( "JS" , function ( ) {
2010-04-22 03:21:48 +00:00
return new LiteralNode ( $1 ) ;
2010-02-11 04:24:05 +00:00
} ) , o ( "REGEX" , function ( ) {
2010-04-22 03:21:48 +00:00
return new LiteralNode ( $1 ) ;
2010-02-11 04:24:05 +00:00
} ) , o ( "TRUE" , function ( ) {
return new LiteralNode ( true ) ;
} ) , o ( "FALSE" , function ( ) {
return new LiteralNode ( false ) ;
} ) , o ( "YES" , function ( ) {
return new LiteralNode ( true ) ;
} ) , o ( "NO" , function ( ) {
return new LiteralNode ( false ) ;
} ) , o ( "ON" , function ( ) {
return new LiteralNode ( true ) ;
} ) , o ( "OFF" , function ( ) {
return new LiteralNode ( false ) ;
} )
] ,
2010-04-26 03:54:47 +00:00
// Assignment of a variable, property, or index to a value.: // Assignment of a variable, property, or index to a value.
2010-03-28 17:06:16 +00:00
Assign : [ o ( "Assignable ASSIGN Expression" , function ( ) {
2010-02-11 04:24:05 +00:00
return new AssignNode ( $1 , $3 ) ;
} )
] ,
2010-03-07 16:41:56 +00:00
// Assignment when it happens within an object literal. The difference from
2010-04-26 03:54:47 +00:00
// the ordinary **Assign** is that these allow numbers and strings as keys.: // Assignment when it happens within an object literal. The difference from
2010-03-07 16:41:56 +00:00
// the ordinary **Assign** is that these allow numbers and strings as keys.
2010-04-26 02:21:53 +00:00
AssignObj : [ o ( "Identifier" , function ( ) {
return new ValueNode ( $1 ) ;
2010-04-26 03:54:47 +00:00
} ) , o ( "AlphaNumeric" ) , o ( "Identifier ASSIGN Expression" , function ( ) {
2010-02-11 04:24:05 +00:00
return new AssignNode ( new ValueNode ( $1 ) , $3 , 'object' ) ;
} ) , o ( "AlphaNumeric ASSIGN Expression" , function ( ) {
return new AssignNode ( new ValueNode ( $1 ) , $3 , 'object' ) ;
} ) , o ( "Comment" )
] ,
2010-04-26 03:54:47 +00:00
// A return statement from a function body.: // A return statement from a function body.
2010-02-11 04:24:05 +00:00
Return : [ o ( "RETURN Expression" , function ( ) {
return new ReturnNode ( $2 ) ;
} ) , o ( "RETURN" , function ( ) {
return new ReturnNode ( new ValueNode ( new LiteralNode ( 'null' ) ) ) ;
} )
] ,
2010-03-07 16:41:56 +00:00
// A comment. Because CoffeeScript passes comments through to JavaScript, we
// have to parse comments like any other construct, and identify all of the
2010-04-26 03:54:47 +00:00
// positions in which they can occur in the grammar.: // A comment. Because CoffeeScript passes comments through to JavaScript, we
// have to parse comments like any other construct, and identify all of the
2010-03-07 16:41:56 +00:00
// positions in which they can occur in the grammar.
2010-02-11 04:24:05 +00:00
Comment : [ o ( "COMMENT" , function ( ) {
2010-04-22 03:21:48 +00:00
return new CommentNode ( $1 ) ;
2010-02-11 04:24:05 +00:00
} )
] ,
2010-04-26 03:54:47 +00:00
// [The existential operator](http://jashkenas.github.com/coffee-script/#existence).: // [The existential operator](http://jashkenas.github.com/coffee-script/#existence).
2010-02-11 04:24:05 +00:00
Existence : [ o ( "Expression ?" , function ( ) {
return new ExistenceNode ( $1 ) ;
} )
] ,
2010-03-07 16:41:56 +00:00
// The **Code** node is the function literal. It's defined by an indented block
// of **Expressions** preceded by a function arrow, with an optional parameter
2010-04-26 03:54:47 +00:00
// list.: // The **Code** node is the function literal. It's defined by an indented block
// of **Expressions** preceded by a function arrow, with an optional parameter
2010-03-07 16:41:56 +00:00
// list.
2010-02-11 04:24:05 +00:00
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 ) ;
} )
] ,
2010-03-07 16:41:56 +00:00
// CoffeeScript has two different symbols for functions. `->` is for ordinary
2010-04-26 03:54:47 +00:00
// functions, and `=>` is for functions bound to the current value of *this*.: // CoffeeScript has two different symbols for functions. `->` is for ordinary
2010-03-07 16:41:56 +00:00
// functions, and `=>` is for functions bound to the current value of *this*.
2010-02-11 04:24:05 +00:00
FuncGlyph : [ o ( "->" , function ( ) {
return 'func' ;
} ) , o ( "=>" , function ( ) {
return 'boundfunc' ;
} )
] ,
2010-04-26 03:54:47 +00:00
// An optional, trailing comma.: // An optional, trailing comma.
2010-04-26 01:17:46 +00:00
OptComma : [ o ( '' ) , o ( ',' ) ] ,
2010-04-26 03:54:47 +00:00
// The list of parameters that a function accepts can be of any length.: // The list of parameters that a function accepts can be of any length.
2010-02-15 23:03:00 +00:00
ParamList : [ o ( "" , function ( ) {
return [ ] ;
} ) , o ( "Param" , function ( ) {
2010-02-11 04:24:05 +00:00
return [ $1 ] ;
} ) , o ( "ParamList , Param" , function ( ) {
return $1 . concat ( [ $3 ] ) ;
} )
] ,
2010-03-07 16:41:56 +00:00
// A single parameter in a function definition can be ordinary, or a splat
2010-04-26 03:54:47 +00:00
// that hoovers up the remaining arguments.: // A single parameter in a function definition can be ordinary, or a splat
2010-03-07 16:41:56 +00:00
// that hoovers up the remaining arguments.
2010-02-11 04:24:05 +00:00
Param : [ o ( "PARAM" , function ( ) {
2010-04-22 03:21:48 +00:00
return new LiteralNode ( $1 ) ;
2010-02-11 04:24:05 +00:00
} ) , o ( "Param . . ." , function ( ) {
return new SplatNode ( $1 ) ;
} )
] ,
2010-04-26 03:54:47 +00:00
// A splat that occurs outside of a parameter list.: // A splat that occurs outside of a parameter list.
2010-02-11 04:24:05 +00:00
Splat : [ o ( "Expression . . ." , function ( ) {
return new SplatNode ( $1 ) ;
} )
] ,
2010-04-26 03:54:47 +00:00
// Variables and properties that can be assigned to.: // Variables and properties that can be assigned to.
2010-03-28 17:14:35 +00:00
SimpleAssignable : [ o ( "Identifier" , function ( ) {
2010-02-11 04:24:05 +00:00
return new ValueNode ( $1 ) ;
2010-03-28 17:06:16 +00:00
} ) , o ( "Value Accessor" , function ( ) {
return $1 . push ( $2 ) ;
} ) , o ( "Invocation Accessor" , function ( ) {
return new ValueNode ( $1 , [ $2 ] ) ;
} ) , o ( "ThisProperty" )
] ,
2010-04-26 03:54:47 +00:00
// Everything that can be assigned to.: // Everything that can be assigned to.
2010-03-28 17:14:35 +00:00
Assignable : [ o ( "SimpleAssignable" ) , o ( "Array" , function ( ) {
return new ValueNode ( $1 ) ;
} ) , o ( "Object" , function ( ) {
return new ValueNode ( $1 ) ;
} )
] ,
2010-03-28 17:06:16 +00:00
// The types of things that can be treated as values -- assigned to, invoked
2010-04-26 03:54:47 +00:00
// as functions, indexed into, named as a class, etc.: // The types of things that can be treated as values -- assigned to, invoked
2010-03-28 17:06:16 +00:00
// as functions, indexed into, named as a class, etc.
Value : [ o ( "Assignable" ) , o ( "Literal" , function ( ) {
return new ValueNode ( $1 ) ;
2010-02-11 04:24:05 +00:00
} ) , o ( "Parenthetical" , function ( ) {
return new ValueNode ( $1 ) ;
} ) , o ( "Range" , function ( ) {
return new ValueNode ( $1 ) ;
2010-03-28 17:06:16 +00:00
} ) , o ( "This" ) , o ( "NULL" , function ( ) {
return new ValueNode ( new LiteralNode ( 'null' ) ) ;
2010-02-11 04:24:05 +00:00
} )
] ,
2010-03-07 16:41:56 +00:00
// The general group of accessors into an object, by property, by prototype
2010-04-26 03:54:47 +00:00
// or by array index or slice.: // The general group of accessors into an object, by property, by prototype
2010-03-07 16:41:56 +00:00
// or by array index or slice.
2010-02-11 04:24:05 +00:00
Accessor : [ o ( "PROPERTY_ACCESS Identifier" , function ( ) {
return new AccessorNode ( $2 ) ;
} ) , o ( "PROTOTYPE_ACCESS Identifier" , function ( ) {
return new AccessorNode ( $2 , 'prototype' ) ;
2010-03-16 21:39:36 +00:00
} ) , o ( "::" , function ( ) {
return new AccessorNode ( new LiteralNode ( 'prototype' ) ) ;
2010-02-11 04:24:05 +00:00
} ) , o ( "SOAK_ACCESS Identifier" , function ( ) {
return new AccessorNode ( $2 , 'soak' ) ;
} ) , o ( "Index" ) , o ( "Slice" , function ( ) {
return new SliceNode ( $1 ) ;
} )
] ,
2010-04-26 03:54:47 +00:00
// Indexing into an object or array using bracket notation.: // Indexing into an object or array using bracket notation.
2010-02-11 04:24:05 +00:00
Index : [ o ( "INDEX_START Expression INDEX_END" , function ( ) {
return new IndexNode ( $2 ) ;
2010-02-24 05:06:01 +00:00
} ) , o ( "SOAKED_INDEX_START Expression SOAKED_INDEX_END" , function ( ) {
return new IndexNode ( $2 , 'soak' ) ;
2010-02-11 04:24:05 +00:00
} )
] ,
2010-04-26 03:54:47 +00:00
// In CoffeeScript, an object literal is simply a list of assignments.: // In CoffeeScript, an object literal is simply a list of assignments.
2010-04-26 01:17:46 +00:00
Object : [ o ( "{ AssignList OptComma }" , function ( ) {
2010-02-11 04:24:05 +00:00
return new ObjectNode ( $2 ) ;
2010-02-27 23:57:45 +00:00
} )
] ,
2010-03-07 16:41:56 +00:00
// Assignment of properties within an object literal can be separated by
2010-04-26 03:54:47 +00:00
// comma, as in JavaScript, or simply by newline.: // Assignment of properties within an object literal can be separated by
2010-03-07 16:41:56 +00:00
// comma, as in JavaScript, or simply by newline.
2010-02-11 04:24:05 +00:00
AssignList : [ o ( "" , function ( ) {
return [ ] ;
} ) , o ( "AssignObj" , function ( ) {
return [ $1 ] ;
} ) , o ( "AssignList , AssignObj" , function ( ) {
return $1 . concat ( [ $3 ] ) ;
} ) , o ( "AssignList TERMINATOR AssignObj" , function ( ) {
return $1 . concat ( [ $3 ] ) ;
} ) , o ( "AssignList , TERMINATOR AssignObj" , function ( ) {
return $1 . concat ( [ $4 ] ) ;
2010-04-26 01:22:29 +00:00
} ) , o ( "INDENT AssignList OptComma OUTDENT" , function ( ) {
2010-03-26 18:11:34 +00:00
return $2 ;
2010-02-11 04:24:05 +00:00
} )
2010-04-03 16:18:29 +00:00
] ,
// Class definitions have optional bodies of prototype property assignments,
2010-04-26 03:54:47 +00:00
// and optional references to the superclass.: // Class definitions have optional bodies of prototype property assignments,
2010-04-03 16:18:29 +00:00
// and optional references to the superclass.
Class : [ o ( "CLASS SimpleAssignable" , function ( ) {
return new ClassNode ( $2 ) ;
} ) , o ( "CLASS SimpleAssignable EXTENDS Value" , function ( ) {
return new ClassNode ( $2 , $4 ) ;
} ) , o ( "CLASS SimpleAssignable INDENT ClassBody OUTDENT" , function ( ) {
return new ClassNode ( $2 , null , $4 ) ;
} ) , o ( "CLASS SimpleAssignable EXTENDS Value INDENT ClassBody OUTDENT" , function ( ) {
return new ClassNode ( $2 , $4 , $6 ) ;
} )
] ,
2010-04-26 03:54:47 +00:00
// Assignments that can happen directly inside a class declaration.: // Assignments that can happen directly inside a class declaration.
2010-04-03 16:18:29 +00:00
ClassAssign : [ o ( "AssignObj" , function ( ) {
return $1 ;
} ) , o ( "ThisProperty ASSIGN Expression" , function ( ) {
return new AssignNode ( new ValueNode ( $1 ) , $3 , 'this' ) ;
} )
] ,
2010-04-26 03:54:47 +00:00
// A list of assignments to a class.: // A list of assignments to a class.
2010-04-03 16:18:29 +00:00
ClassBody : [ o ( "" , function ( ) {
return [ ] ;
} ) , o ( "ClassAssign" , function ( ) {
return [ $1 ] ;
} ) , o ( "ClassBody TERMINATOR ClassAssign" , function ( ) {
return $1 . concat ( $3 ) ;
} )
2010-02-11 04:24:05 +00:00
] ,
2010-03-07 16:41:56 +00:00
// The three flavors of function call: normal, object instantiation with `new`,
2010-04-26 03:54:47 +00:00
// and calling `super()`: // The three flavors of function call: normal, object instantiation with `new`,
2010-03-07 16:41:56 +00:00
// and calling `super()`
Call : [ o ( "Invocation" ) , o ( "NEW Invocation" , function ( ) {
2010-02-11 04:24:05 +00:00
return $2 . new _instance ( ) ;
2010-03-07 16:41:56 +00:00
} ) , o ( "Super" )
2010-02-11 04:24:05 +00:00
] ,
2010-04-26 03:54:47 +00:00
// Binds a function call to a context and/or arguments.: // Binds a function call to a context and/or arguments.
2010-03-18 04:42:26 +00:00
Curry : [ o ( "Value <- Arguments" , function ( ) {
2010-03-17 07:11:10 +00:00
return new CurryNode ( $1 , $3 ) ;
} )
] ,
2010-03-07 16:41:56 +00:00
// Extending an object by setting its prototype chain to reference a parent
2010-04-26 03:54:47 +00:00
// object.: // Extending an object by setting its prototype chain to reference a parent
2010-03-07 16:41:56 +00:00
// object.
2010-03-28 17:14:35 +00:00
Extends : [ o ( "SimpleAssignable EXTENDS Value" , function ( ) {
2010-02-11 04:24:05 +00:00
return new ExtendsNode ( $1 , $3 ) ;
} )
] ,
2010-04-26 03:54:47 +00:00
// Ordinary function invocation, or a chained series of calls.: // Ordinary function invocation, or a chained series of calls.
2010-02-11 04:24:05 +00:00
Invocation : [ o ( "Value Arguments" , function ( ) {
return new CallNode ( $1 , $2 ) ;
} ) , o ( "Invocation Arguments" , function ( ) {
return new CallNode ( $1 , $2 ) ;
} )
] ,
2010-04-26 03:54:47 +00:00
// The list of arguments to a function call.: // The list of arguments to a function call.
2010-04-26 01:17:46 +00:00
Arguments : [ o ( "CALL_START ArgList OptComma CALL_END" , function ( ) {
2010-03-26 15:44:25 +00:00
return $2 ;
2010-02-11 04:24:05 +00:00
} )
] ,
2010-04-26 03:54:47 +00:00
// Calling super.: // Calling super.
2010-04-26 01:17:46 +00:00
Super : [ o ( "SUPER CALL_START ArgList OptComma CALL_END" , function ( ) {
2010-03-26 15:44:25 +00:00
return new CallNode ( 'super' , $3 ) ;
2010-02-11 04:24:05 +00:00
} )
] ,
2010-04-26 03:54:47 +00:00
// A reference to the *this* current object.: // A reference to the *this* current object.
2010-03-28 17:06:16 +00:00
This : [ o ( "THIS" , function ( ) {
return new ValueNode ( new LiteralNode ( 'this' ) ) ;
} ) , o ( "@" , function ( ) {
2010-02-19 12:51:52 +00:00
return new ValueNode ( new LiteralNode ( 'this' ) ) ;
2010-03-28 17:06:16 +00:00
} )
] ,
2010-04-26 03:54:47 +00:00
// A reference to a property on *this*.: // A reference to a property on *this*.
2010-03-28 17:06:16 +00:00
ThisProperty : [ o ( "@ Identifier" , function ( ) {
2010-02-19 12:51:52 +00:00
return new ValueNode ( new LiteralNode ( 'this' ) , [ new AccessorNode ( $2 ) ] ) ;
2010-02-11 04:24:05 +00:00
} )
] ,
2010-04-26 03:54:47 +00:00
// The CoffeeScript range literal.: // The CoffeeScript range literal.
2010-02-11 04:24:05 +00:00
Range : [ o ( "[ Expression . . Expression ]" , function ( ) {
return new RangeNode ( $2 , $5 ) ;
} ) , o ( "[ Expression . . . Expression ]" , function ( ) {
return new RangeNode ( $2 , $6 , true ) ;
} )
] ,
2010-04-26 03:54:47 +00:00
// The slice literal.: // The slice literal.
2010-03-31 00:11:40 +00:00
Slice : [ o ( "INDEX_START Expression . . Expression INDEX_END" , function ( ) {
2010-02-11 04:24:05 +00:00
return new RangeNode ( $2 , $5 ) ;
} ) , o ( "INDEX_START Expression . . . Expression INDEX_END" , function ( ) {
return new RangeNode ( $2 , $6 , true ) ;
} )
] ,
2010-04-26 03:54:47 +00:00
// The array literal.: // The array literal.
2010-04-26 01:17:46 +00:00
Array : [ o ( "[ ArgList OptComma ]" , function ( ) {
2010-03-26 15:44:25 +00:00
return new ArrayNode ( $2 ) ;
2010-02-11 04:24:05 +00:00
} )
] ,
2010-03-07 16:41:56 +00:00
// The **ArgList** is both the list of objects passed into a function call,
// as well as the contents of an array literal
2010-04-26 03:54:47 +00:00
// (i.e. comma-separated expressions). Newlines work as well.: // The **ArgList** is both the list of objects passed into a function call,
// as well as the contents of an array literal
2010-03-07 16:41:56 +00:00
// (i.e. comma-separated expressions). Newlines work as well.
2010-02-11 04:24:05 +00:00
ArgList : [ o ( "" , function ( ) {
return [ ] ;
} ) , o ( "Expression" , function ( ) {
return [ $1 ] ;
} ) , o ( "INDENT Expression" , function ( ) {
return [ $2 ] ;
} ) , o ( "ArgList , Expression" , function ( ) {
return $1 . concat ( [ $3 ] ) ;
} ) , o ( "ArgList TERMINATOR Expression" , function ( ) {
return $1 . concat ( [ $3 ] ) ;
} ) , o ( "ArgList , TERMINATOR Expression" , function ( ) {
return $1 . concat ( [ $4 ] ) ;
} ) , o ( "ArgList , INDENT Expression" , function ( ) {
return $1 . concat ( [ $4 ] ) ;
2010-04-26 01:17:46 +00:00
} ) , o ( "ArgList OptComma OUTDENT" )
2010-02-11 04:24:05 +00:00
] ,
2010-03-07 16:41:56 +00:00
// Just simple, comma-separated, required arguments (no fancy syntax). We need
// this to be separate from the **ArgList** for use in **Switch** blocks, where
2010-04-26 03:54:47 +00:00
// having the newlines wouldn't make sense.: // Just simple, comma-separated, required arguments (no fancy syntax). We need
// this to be separate from the **ArgList** for use in **Switch** blocks, where
2010-03-07 16:41:56 +00:00
// having the newlines wouldn't make sense.
SimpleArgs : [ o ( "Expression" ) , o ( "SimpleArgs , Expression" , function ( ) {
2010-03-21 11:17:58 +00:00
if ( $1 instanceof Array ) {
return $1 . concat ( [ $3 ] ) ;
} else {
return [ $1 ] . concat ( [ $3 ] ) ;
}
2010-02-11 04:24:05 +00:00
} )
] ,
2010-04-26 03:54:47 +00:00
// The variants of *try/catch/finally* exception handling blocks.: // The variants of *try/catch/finally* exception handling blocks.
2010-02-11 04:24:05 +00:00
Try : [ o ( "TRY Block Catch" , function ( ) {
return new TryNode ( $2 , $3 [ 0 ] , $3 [ 1 ] ) ;
} ) , o ( "TRY Block FINALLY Block" , function ( ) {
return new TryNode ( $2 , null , null , $4 ) ;
} ) , o ( "TRY Block Catch FINALLY Block" , function ( ) {
return new TryNode ( $2 , $3 [ 0 ] , $3 [ 1 ] , $5 ) ;
} )
] ,
2010-04-26 03:54:47 +00:00
// A catch clause names its error and runs a block of code.: // A catch clause names its error and runs a block of code.
2010-02-11 04:24:05 +00:00
Catch : [ o ( "CATCH Identifier Block" , function ( ) {
return [ $2 , $3 ] ;
} )
] ,
2010-04-26 03:54:47 +00:00
// Throw an exception object.: // Throw an exception object.
2010-02-11 04:24:05 +00:00
Throw : [ o ( "THROW Expression" , function ( ) {
return new ThrowNode ( $2 ) ;
} )
] ,
2010-03-07 16:41:56 +00:00
// Parenthetical expressions. Note that the **Parenthetical** is a **Value**,
// not an **Expression**, so if you need to use an expression in a place
// where only values are accepted, wrapping it in parentheses will always do
2010-04-26 03:54:47 +00:00
// the trick.: // Parenthetical expressions. Note that the **Parenthetical** is a **Value**,
// not an **Expression**, so if you need to use an expression in a place
// where only values are accepted, wrapping it in parentheses will always do
2010-03-07 16:41:56 +00:00
// the trick.
2010-04-05 14:26:23 +00:00
Parenthetical : [ o ( "( Line )" , function ( ) {
2010-02-11 04:24:05 +00:00
return new ParentheticalNode ( $2 ) ;
} )
] ,
2010-03-10 04:04:16 +00:00
// A language extension to CoffeeScript from the outside. We simply pass
2010-04-26 03:54:47 +00:00
// it through unaltered.: // A language extension to CoffeeScript from the outside. We simply pass
2010-03-10 04:04:16 +00:00
// it through unaltered.
2010-04-22 03:21:48 +00:00
Extension : [ o ( "EXTENSION" ) ] ,
2010-04-26 03:54:47 +00:00
// The condition portion of a while loop.: // The condition portion of a while loop.
2010-02-24 03:53:43 +00:00
WhileSource : [ o ( "WHILE Expression" , function ( ) {
return new WhileNode ( $2 ) ;
} ) , o ( "WHILE Expression WHEN Expression" , function ( ) {
return new WhileNode ( $2 , {
filter : $4
} ) ;
} )
] ,
2010-03-07 16:41:56 +00:00
// The while loop can either be normal, with a block of expressions to execute,
2010-04-26 03:54:47 +00:00
// or postfix, with a single expression. There is no do..while.: // The while loop can either be normal, with a block of expressions to execute,
2010-03-07 16:41:56 +00:00
// or postfix, with a single expression. There is no do..while.
2010-02-24 03:53:43 +00:00
While : [ o ( "WhileSource Block" , function ( ) {
return $1 . add _body ( $2 ) ;
2010-04-05 14:26:23 +00:00
} ) , o ( "Statement WhileSource" , function ( ) {
return $2 . add _body ( Expressions . wrap ( [ $1 ] ) ) ;
2010-02-24 03:53:43 +00:00
} ) , o ( "Expression WhileSource" , function ( ) {
2010-03-11 01:15:12 +00:00
return $2 . add _body ( Expressions . wrap ( [ $1 ] ) ) ;
2010-02-11 04:24:05 +00:00
} )
] ,
2010-03-07 16:41:56 +00:00
// Array, object, and range comprehensions, at the most generic level.
// Comprehensions can either be normal, with a block of expressions to execute,
2010-04-26 03:54:47 +00:00
// or postfix, with a single expression.: // Array, object, and range comprehensions, at the most generic level.
// Comprehensions can either be normal, with a block of expressions to execute,
2010-03-07 16:41:56 +00:00
// or postfix, with a single expression.
2010-04-05 14:26:23 +00:00
For : [ o ( "Statement FOR ForVariables ForSource" , function ( ) {
return new ForNode ( $1 , $4 , $3 [ 0 ] , $3 [ 1 ] ) ;
} ) , o ( "Expression FOR ForVariables ForSource" , function ( ) {
2010-02-11 04:24:05 +00:00
return new ForNode ( $1 , $4 , $3 [ 0 ] , $3 [ 1 ] ) ;
} ) , o ( "FOR ForVariables ForSource Block" , function ( ) {
return new ForNode ( $4 , $3 , $2 [ 0 ] , $2 [ 1 ] ) ;
} )
] ,
2010-03-07 16:41:56 +00:00
// An array or range comprehension has variables for the current element and
// (optional) reference to the current index. Or, *key, value*, in the case
2010-04-26 03:54:47 +00:00
// of object comprehensions.: // An array or range comprehension has variables for the current element and
// (optional) reference to the current index. Or, *key, value*, in the case
2010-03-07 16:41:56 +00:00
// of object comprehensions.
2010-02-11 04:24:05 +00:00
ForVariables : [ o ( "Identifier" , function ( ) {
return [ $1 ] ;
} ) , o ( "Identifier , Identifier" , function ( ) {
return [ $1 , $3 ] ;
} )
] ,
2010-03-07 16:41:56 +00:00
// The source of a comprehension is an array or object with an optional filter
2010-03-28 18:32:01 +00:00
// clause. If it's an array comprehension, you can also choose to step through
2010-04-26 03:54:47 +00:00
// in fixed-size increments.: // The source of a comprehension is an array or object with an optional filter
// clause. If it's an array comprehension, you can also choose to step through
2010-03-07 16:41:56 +00:00
// in fixed-size increments.
2010-02-11 04:24:05 +00:00
ForSource : [ o ( "IN Expression" , function ( ) {
return {
source : $2
} ;
} ) , o ( "OF Expression" , function ( ) {
return {
source : $2 ,
object : true
} ;
2010-03-28 18:32:01 +00:00
} ) , o ( "IN Expression WHEN Expression" , function ( ) {
return {
source : $2 ,
filter : $4
} ;
} ) , o ( "OF Expression WHEN Expression" , function ( ) {
return {
source : $2 ,
filter : $4 ,
object : true
} ;
} ) , o ( "IN Expression BY Expression" , function ( ) {
return {
source : $2 ,
step : $4
} ;
} ) , o ( "IN Expression WHEN Expression BY Expression" , function ( ) {
return {
source : $2 ,
filter : $4 ,
step : $6
} ;
} ) , o ( "IN Expression BY Expression WHEN Expression" , function ( ) {
return {
source : $2 ,
step : $4 ,
filter : $6
} ;
2010-02-11 04:24:05 +00:00
} )
] ,
2010-03-07 16:41:56 +00:00
// The CoffeeScript switch/when/else block replaces the JavaScript
2010-04-26 03:54:47 +00:00
// switch/case/default by compiling into an if-else chain.: // The CoffeeScript switch/when/else block replaces the JavaScript
2010-03-07 16:41:56 +00:00
// switch/case/default by compiling into an if-else chain.
2010-02-11 04:24:05 +00:00
Switch : [ o ( "SWITCH Expression INDENT Whens OUTDENT" , function ( ) {
return $4 . rewrite _condition ( $2 ) ;
} ) , o ( "SWITCH Expression INDENT Whens ELSE Block OUTDENT" , function ( ) {
2010-02-23 00:22:09 +00:00
return $4 . rewrite _condition ( $2 ) . add _else ( $6 , true ) ;
2010-02-11 04:24:05 +00:00
} )
] ,
2010-03-07 16:41:56 +00:00
// The inner list of whens is left recursive. At code-generation time, the
2010-04-26 03:54:47 +00:00
// IfNode will rewrite them into a proper chain.: // The inner list of whens is left recursive. At code-generation time, the
2010-03-07 16:41:56 +00:00
// IfNode will rewrite them into a proper chain.
Whens : [ o ( "When" ) , o ( "Whens When" , function ( ) {
2010-02-11 04:24:05 +00:00
return $1 . push ( $2 ) ;
} )
] ,
2010-04-26 03:54:47 +00:00
// An individual **When** clause, with action.: // An individual **When** clause, with action.
2010-02-11 04:24:05 +00:00
When : [ o ( "LEADING_WHEN SimpleArgs Block" , function ( ) {
return new IfNode ( $2 , $3 , null , {
statement : true
} ) ;
} ) , o ( "LEADING_WHEN SimpleArgs Block TERMINATOR" , function ( ) {
return new IfNode ( $2 , $3 , null , {
statement : true
} ) ;
} ) , o ( "Comment TERMINATOR When" , function ( ) {
2010-02-12 21:26:28 +00:00
$3 . comment = $1 ;
return $3 ;
2010-02-11 04:24:05 +00:00
} )
] ,
2010-03-07 16:41:56 +00:00
// The most basic form of *if* is a condition and an action. The following
// if-related rules are broken up along these lines in order to avoid
2010-04-26 03:54:47 +00:00
// ambiguity.: // The most basic form of *if* is a condition and an action. The following
// if-related rules are broken up along these lines in order to avoid
2010-03-07 16:41:56 +00:00
// ambiguity.
2010-02-13 06:02:10 +00:00
IfStart : [ o ( "IF Expression Block" , function ( ) {
2010-02-11 04:24:05 +00:00
return new IfNode ( $2 , $3 ) ;
2010-03-07 16:41:56 +00:00
} ) , o ( "IfStart ElsIf" , function ( ) {
2010-02-13 06:02:10 +00:00
return $1 . add _else ( $2 ) ;
2010-02-11 04:24:05 +00:00
} )
] ,
2010-04-26 03:54:47 +00:00
// An **IfStart** can optionally be followed by an else block.: // An **IfStart** can optionally be followed by an else block.
2010-03-07 16:41:56 +00:00
IfBlock : [ o ( "IfStart" ) , o ( "IfStart ELSE Block" , function ( ) {
2010-02-13 06:02:10 +00:00
return $1 . add _else ( $3 ) ;
2010-02-11 04:24:05 +00:00
} )
] ,
2010-04-26 03:54:47 +00:00
// An *else if* continuation of the *if* expression.: // An *else if* continuation of the *if* expression.
2010-03-07 16:41:56 +00:00
ElsIf : [ o ( "ELSE IF Expression Block" , function ( ) {
2010-02-13 06:02:10 +00:00
return ( new IfNode ( $3 , $4 ) ) . force _statement ( ) ;
2010-02-11 04:24:05 +00:00
} )
] ,
2010-03-07 16:41:56 +00:00
// The full complement of *if* expressions, including postfix one-liner
2010-04-26 03:54:47 +00:00
// *if* and *unless*.: // The full complement of *if* expressions, including postfix one-liner
2010-03-07 16:41:56 +00:00
// *if* and *unless*.
2010-04-05 14:26:23 +00:00
If : [ o ( "IfBlock" ) , o ( "Statement IF Expression" , function ( ) {
return new IfNode ( $3 , Expressions . wrap ( [ $1 ] ) , null , {
statement : true
} ) ;
} ) , o ( "Expression IF Expression" , function ( ) {
2010-02-11 04:24:05 +00:00
return new IfNode ( $3 , Expressions . wrap ( [ $1 ] ) , null , {
statement : true
} ) ;
2010-04-05 14:26:23 +00:00
} ) , o ( "Statement UNLESS Expression" , function ( ) {
return new IfNode ( $3 , Expressions . wrap ( [ $1 ] ) , null , {
statement : true ,
invert : true
} ) ;
2010-02-11 04:24:05 +00:00
} ) , o ( "Expression UNLESS Expression" , function ( ) {
return new IfNode ( $3 , Expressions . wrap ( [ $1 ] ) , null , {
statement : true ,
invert : true
} ) ;
} )
2010-03-07 16:41:56 +00:00
] ,
// Arithmetic and logical operators, working on one or more operands.
// Here they are grouped by order of precedence. The actual precedence rules
// are defined at the bottom of the page. It would be shorter if we could
// combine most of these rules into a single generic *Operand OpSymbol Operand*
// -type rule, but in order to make the precedence binding possible, separate
2010-04-26 03:54:47 +00:00
// rules are necessary.: // Arithmetic and logical operators, working on one or more operands.
// Here they are grouped by order of precedence. The actual precedence rules
// are defined at the bottom of the page. It would be shorter if we could
// combine most of these rules into a single generic *Operand OpSymbol Operand*
// -type rule, but in order to make the precedence binding possible, separate
2010-03-07 16:41:56 +00:00
// rules are necessary.
Operation : [ o ( "! Expression" , function ( ) {
return new OpNode ( '!' , $2 ) ;
} ) , o ( "!! Expression" , function ( ) {
return new OpNode ( '!!' , $2 ) ;
} ) , o ( "- Expression" , ( function ( ) {
return new OpNode ( '-' , $2 ) ;
} ) , {
prec : 'UMINUS'
} ) , o ( "+ Expression" , ( function ( ) {
return new OpNode ( '+' , $2 ) ;
} ) , {
prec : 'UPLUS'
} ) , o ( "~ Expression" , function ( ) {
return new OpNode ( '~' , $2 ) ;
} ) , o ( "-- Expression" , function ( ) {
return new OpNode ( '--' , $2 ) ;
} ) , o ( "++ Expression" , function ( ) {
return new OpNode ( '++' , $2 ) ;
} ) , o ( "DELETE Expression" , function ( ) {
return new OpNode ( 'delete' , $2 ) ;
} ) , o ( "TYPEOF Expression" , function ( ) {
return new OpNode ( 'typeof' , $2 ) ;
} ) , o ( "Expression --" , function ( ) {
return new OpNode ( '--' , $1 , null , true ) ;
} ) , o ( "Expression ++" , function ( ) {
return new OpNode ( '++' , $1 , null , true ) ;
} ) , o ( "Expression * Expression" , function ( ) {
return new OpNode ( '*' , $1 , $3 ) ;
} ) , o ( "Expression / Expression" , function ( ) {
return new OpNode ( '/' , $1 , $3 ) ;
} ) , o ( "Expression % Expression" , function ( ) {
return new OpNode ( '%' , $1 , $3 ) ;
} ) , o ( "Expression + Expression" , function ( ) {
return new OpNode ( '+' , $1 , $3 ) ;
} ) , o ( "Expression - Expression" , function ( ) {
return new OpNode ( '-' , $1 , $3 ) ;
} ) , o ( "Expression << Expression" , function ( ) {
return new OpNode ( '<<' , $1 , $3 ) ;
} ) , o ( "Expression >> Expression" , function ( ) {
return new OpNode ( '>>' , $1 , $3 ) ;
} ) , o ( "Expression >>> Expression" , function ( ) {
return new OpNode ( '>>>' , $1 , $3 ) ;
} ) , o ( "Expression & Expression" , function ( ) {
return new OpNode ( '&' , $1 , $3 ) ;
2010-03-27 19:25:34 +00:00
} ) , o ( "Expression | Expression" , function ( ) {
return new OpNode ( '|' , $1 , $3 ) ;
2010-03-07 16:41:56 +00:00
} ) , o ( "Expression ^ Expression" , function ( ) {
return new OpNode ( '^' , $1 , $3 ) ;
} ) , o ( "Expression <= Expression" , function ( ) {
return new OpNode ( '<=' , $1 , $3 ) ;
} ) , o ( "Expression < Expression" , function ( ) {
return new OpNode ( '<' , $1 , $3 ) ;
} ) , o ( "Expression > Expression" , function ( ) {
return new OpNode ( '>' , $1 , $3 ) ;
} ) , o ( "Expression >= Expression" , function ( ) {
return new OpNode ( '>=' , $1 , $3 ) ;
} ) , o ( "Expression == Expression" , function ( ) {
return new OpNode ( '==' , $1 , $3 ) ;
} ) , o ( "Expression != Expression" , function ( ) {
return new OpNode ( '!=' , $1 , $3 ) ;
} ) , o ( "Expression && Expression" , function ( ) {
return new OpNode ( '&&' , $1 , $3 ) ;
} ) , o ( "Expression || Expression" , function ( ) {
return new OpNode ( '||' , $1 , $3 ) ;
} ) , o ( "Expression ? Expression" , function ( ) {
return new OpNode ( '?' , $1 , $3 ) ;
} ) , o ( "Expression -= Expression" , function ( ) {
return new OpNode ( '-=' , $1 , $3 ) ;
} ) , o ( "Expression += Expression" , function ( ) {
return new OpNode ( '+=' , $1 , $3 ) ;
} ) , o ( "Expression /= Expression" , function ( ) {
return new OpNode ( '/=' , $1 , $3 ) ;
} ) , o ( "Expression *= Expression" , function ( ) {
return new OpNode ( '*=' , $1 , $3 ) ;
} ) , o ( "Expression %= Expression" , function ( ) {
return new OpNode ( '%=' , $1 , $3 ) ;
} ) , o ( "Expression ||= Expression" , function ( ) {
return new OpNode ( '||=' , $1 , $3 ) ;
} ) , o ( "Expression &&= Expression" , function ( ) {
return new OpNode ( '&&=' , $1 , $3 ) ;
} ) , o ( "Expression ?= Expression" , function ( ) {
return new OpNode ( '?=' , $1 , $3 ) ;
} ) , o ( "Expression INSTANCEOF Expression" , function ( ) {
return new OpNode ( 'instanceof' , $1 , $3 ) ;
} ) , o ( "Expression IN Expression" , function ( ) {
return new OpNode ( 'in' , $1 , $3 ) ;
} )
2010-02-11 04:24:05 +00:00
]
} ;
2010-03-07 16:41:56 +00:00
// Precedence
// ----------
// Operators at the top of this list have higher precedence than the ones lower
// down. Following these rules is what makes `2 + 3 * 4` parse as:
// 2 + (3 * 4)
// And not:
// (2 + 3) * 4
2010-03-22 02:07:46 +00:00
operators = [ [ "left" , '?' ] , [ "nonassoc" , 'UMINUS' , 'UPLUS' , '!' , '!!' , '~' , '++' , '--' ] , [ "left" , '*' , '/' , '%' ] , [ "left" , '+' , '-' ] , [ "left" , '<<' , '>>' , '>>>' ] , [ "left" , '&' , '|' , '^' ] , [ "left" , '<=' , '<' , '>' , '>=' ] , [ "right" , 'DELETE' , 'INSTANCEOF' , 'TYPEOF' ] , [ "left" , '==' , '!=' ] , [ "left" , '&&' , '||' ] , [ "right" , '-=' , '+=' , '/=' , '*=' , '%=' , '||=' , '&&=' , '?=' ] , [ "left" , '.' ] , [ "right" , 'INDENT' ] , [ "left" , 'OUTDENT' ] , [ "right" , 'WHEN' , 'LEADING_WHEN' , 'IN' , 'OF' , 'BY' , 'THROW' ] , [ "right" , 'FOR' , 'NEW' , 'SUPER' , 'CLASS' ] , [ "left" , 'EXTENDS' ] , [ "right" , 'ASSIGN' , 'RETURN' ] , [ "right" , '->' , '=>' , '<-' , 'UNLESS' , 'IF' , 'ELSE' , 'WHILE' ] ] ;
2010-03-07 16:41:56 +00:00
// Wrapping Up
// -----------
// Finally, now what we have our **grammar** and our **operators**, we can create
// our **Jison.Parser**. We do this by processing all of our rules, recording all
// terminals (every symbol which does not appear as the name of a rule above)
// as "tokens".
2010-02-11 04:24:05 +00:00
tokens = [ ] ;
2010-02-16 23:00:40 +00:00
_a = grammar ;
2010-03-30 20:48:43 +00:00
for ( name in _a ) { if ( _ _hasProp . call ( _a , name ) ) {
2010-03-07 16:41:56 +00:00
alternatives = _a [ name ] ;
grammar [ name ] = ( function ( ) {
2010-03-27 20:04:47 +00:00
_b = [ ] ; _d = alternatives ;
for ( _c = 0 , _e = _d . length ; _c < _e ; _c ++ ) {
alt = _d [ _c ] ;
2010-02-16 23:00:40 +00:00
_b . push ( ( function ( ) {
2010-03-27 20:04:47 +00:00
_g = alt [ 0 ] . split ( ' ' ) ;
for ( _f = 0 , _h = _g . length ; _f < _h ; _f ++ ) {
token = _g [ _f ] ;
2010-03-07 16:41:56 +00:00
if ( ! ( grammar [ token ] ) ) {
tokens . push ( token ) ;
}
}
if ( name === 'Root' ) {
2010-04-04 06:59:44 +00:00
alt [ 1 ] = ( "return " + ( alt [ 1 ] ) ) ;
2010-02-14 22:35:14 +00:00
}
2010-03-07 16:41:56 +00:00
return alt ;
2010-04-10 18:40:05 +00:00
} ) ( ) ) ;
2010-02-14 22:35:14 +00:00
}
2010-02-16 23:00:40 +00:00
return _b ;
2010-04-10 18:40:05 +00:00
} ) ( ) ;
2010-02-19 01:22:53 +00:00
} }
2010-03-07 16:41:56 +00:00
// Initialize the **Parser** with our list of terminal **tokens**, our **grammar**
// rules, and the name of the root. Reverse the operators because Jison orders
// precedence from low to high, and we have it high to low
// (as in [Yacc](http://dinosaur.compilertools.net/yacc/index.html)).
2010-02-16 06:04:48 +00:00
exports . parser = new Parser ( {
2010-03-07 16:41:56 +00:00
tokens : tokens . join ( ' ' ) ,
bnf : grammar ,
2010-02-12 04:29:12 +00:00
operators : operators . reverse ( ) ,
2010-02-11 04:24:05 +00:00
startSymbol : 'Root'
} ) ;
2010-02-24 23:56:32 +00:00
} ) ( ) ;