Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

initial commit of the mystery language

  • Loading branch information...
commit 8e9d637985d2dc9b44922076ad54ffef7fa8e9c2 0 parents
Jeremy Ashkenas authored
30 SYNTAX
@@ -0,0 +1,30 @@
+Every line is an expression. Multiple expressions on a single line can be
+separated by a ";" character.
+
+NUM: 1
+ 1.0
+
+STRING: "hello"
+ 'hello'
+
+OBJECT: {one : 1, two : 2}
+
+ARRAY: [1, 2, 3]
+
+CODE: a, b => a * b.
+
+IF: return x if x > 1
+
+ if (x > 1) return x
+
+ASSIGN: a : b
+
+LOGICAL: x && y
+ x and y
+ x || y
+ x or y
+
+
+
+
+
40 code.jaa
@@ -0,0 +1,40 @@
+# I'm a comment and I'm ok.
+# Return
+# Case
+
+square: x => x * x.
+
+sum: x, y => x + y.
+
+odd: x => x % 2 is 0.
+
+even: x => x % 2 aint 0.
+
+object_literal: {one: 1, two: 2, three: 3}
+
+multiline_object: {
+ pi: 3.14159
+ list: [1, 2, 3, 4]
+ three: 3
+ inner_obj: {
+ freedom: => _.freedom().
+ }
+}
+
+run_loop: =>
+ fire_events(e => e.stopPropagation().)
+ listen()
+ wait().
+
+if submarine.shields_up
+ full_speed_ahead()
+ weapons.fire_torpedos()
+else
+ run_away().
+
+eldest: if 25 > 21 then liz else marge.
+
+
+
+
+
76 documents.jaa
@@ -0,0 +1,76 @@
+# Document Model
+dc.model.Document: dc.Model.extend({
+
+ constructor : attributes => this.base(attributes).
+
+ # For display, show either the highlighted search results, or the summary,
+ # if no highlights are available.
+ # The import process will take care of this in the future, but the inline
+ # version of the summary has all runs of whitespace squeezed out.
+ displaySummary : =>
+ text: this.get('highlight') or this.get('summary')
+ text ? text.replace(/\s+/g, ' ') else ''
+
+ # Return a list of the document's metadata. Think about caching this on the
+ # document by binding to Metadata, instead of on-the-fly.
+ metadata : =>
+ docId : this.id
+ _.select(Metadata.models(), (m =>
+ _.any(m.get('instances'), (i =>
+ i.document_id == docId
+ ))
+ ))
+
+ bookmark : pageNumber =>
+ bookmark : new dc.model.Bookmark({title : this.get('title'), page_number : pageNumber, document_id : this.id})
+ Bookmarks.create(bookmark)
+
+ # Inspect.
+ toString : =>
+ 'Document ' + this.id + ' "' + this.get('title') + '"'
+
+})
+
+# Document Set
+dc.model.DocumentSet : dc.model.RESTfulSet.extend({
+
+ resource : 'documents'
+
+ SELECTION_CHANGED : 'documents:selection_changed'
+
+ constructor : options =>
+ this.base(options)
+ _.bindAll(this, 'downloadSelectedViewers', 'downloadSelectedPDF', 'downloadSelectedFullText')
+
+ selected : => _.select(this.models(), m => m.get('selected'))
+
+ selectedIds : => _.pluck(this.selected(), 'id')
+
+ countSelected : => this.selected().length
+
+ downloadSelectedViewers : =>
+ dc.app.download('/download/' + this.selectedIds().join('/') + '/document_viewer.zip');
+
+ downloadSelectedPDF : =>
+ return window.open(this.selected()[0].get('pdf_url')) if this.countSelected() <= 1
+ dc.app.download('/download/' + this.selectedIds().join('/') + '/document_pdfs.zip')
+
+ downloadSelectedFullText : =>
+ return window.open(this.selected()[0].get('full_text_url')) if this.countSelected() <= 1
+ dc.app.download('/download/' + this.selectedIds().join('/') + '/document_text.zip')
+
+ # We override "_onModelEvent" to fire selection changed events when documents
+ # change their selected state.
+ _onModelEvent : e, model =>
+ this.base(e, model)
+ fire : (e == dc.Model.CHANGED and model.hasChanged('selected'))
+ _.defer(_(this.fire).bind(this, this.SELECTION_CHANGED, this)) if fire
+ }
+
+})
+
+# The main set of Documents, used by the search tab.
+window.Documents : new dc.model.DocumentSet()
+
+# The set of documents that is used to look at a particular label.
+dc.app.LabeledDocuments : new dc.model.DocumentSet()
206 grammar.y
@@ -0,0 +1,206 @@
+class Parser
+
+# Declare tokens produced by the lexer
+token IF ELSE THEN
+token NEWLINE
+token NUMBER
+token STRING
+token TRUE FALSE NULL
+token IDENTIFIER PROPERTY_ACCESS
+token CODE
+
+prechigh
+ nonassoc UMINUS NOT '!'
+ left '*' '/' '%'
+ left '+' '-'
+ left '<=' '<' '>' '>='
+ right '==' '!=' IS AINT
+ left '&&' '||' AND OR
+ right '-=' '+=' '/=' '*='
+preclow
+
+rule
+ # All rules are declared in this format:
+ #
+ # RuleName:
+ # OtherRule TOKEN AnotherRule { code to run when this matches }
+ # | OtherRule { ... }
+ # ;
+ #
+ # In the code section (inside the {...} on the right):
+ # - Assign to "result" the value returned by the rule.
+ # - Use val[index of expression] to reference expressions on the left.
+
+
+ # All parsing will end in this rule, being the trunk of the AST.
+ Root:
+ /* nothing */ { result = Nodes.new([]) }
+ | Expressions { result = val[0] }
+ ;
+
+ # Any list of expressions or method body, seperated by line breaks.
+ Expressions:
+ Expression { result = Nodes.new(val) }
+ | Expressions Terminator Expression { result = val[0] << val[2] }
+ | Expressions Terminator { result = Nodes.new([val[0]]) }
+ | Terminator Expressions { result = Nodes.new([val[1]]) }
+ ;
+
+ # All types of expressions in our language
+ Expression:
+ Literal
+ | Variable
+ | Call
+ | Assign
+ | Object
+ | Code
+ | Operation
+ | Array
+ | If
+ ;
+
+ # All tokens that can terminate an expression
+ Terminator:
+ "\n"
+ | ";"
+ ;
+
+ # All hard-coded values
+ Literal:
+ NUMBER { result = LiteralNode.new(val[0]) }
+ | STRING { result = LiteralNode.new(val[0]) }
+ | TRUE { result = LiteralNode.new(true) }
+ | FALSE { result = LiteralNode.new(false) }
+ | NULL { result = LiteralNode.new(nil) }
+ ;
+
+ # Assign to a variable
+ Assign:
+ Variable ":" Expression { result = AssignNode.new(val[0], val[2]) }
+ ;
+
+ # Assignment within an object literal.
+ AssignObj:
+ IDENTIFIER ":" Expression { result = AssignNode.new(val[0], val[2], :object) }
+ ;
+
+ # Arithmetic and logical operators
+ # For Ruby's Operator precedence, see:
+ # https://www.cs.auckland.ac.nz/references/ruby/ProgrammingRuby/language.html
+ Operation:
+ '!' Expression { result = OpNode.new(val[0], val[1]) }
+ | '-' Expression = UMINUS { result = OpNode.new(val[0], val[1]) }
+ | NOT Expression { result = OpNode.new(val[0], val[1]) }
+
+
+ | Expression '*' Expression { result = OpNode.new(val[1], val[0], val[2]) }
+ | Expression '/' Expression { result = OpNode.new(val[1], val[0], val[2]) }
+ | Expression '%' Expression { result = OpNode.new(val[1], val[0], val[2]) }
+
+ | Expression '+' Expression { result = OpNode.new(val[1], val[0], val[2]) }
+ | Expression '-' Expression { result = OpNode.new(val[1], val[0], val[2]) }
+
+ | Expression '<=' Expression { result = OpNode.new(val[1], val[0], val[2]) }
+ | Expression '<' Expression { result = OpNode.new(val[1], val[0], val[2]) }
+ | Expression '>' Expression { result = OpNode.new(val[1], val[0], val[2]) }
+ | Expression '>=' Expression { result = OpNode.new(val[1], val[0], val[2]) }
+
+ | Expression '==' Expression { result = OpNode.new(val[1], val[0], val[2]) }
+ | Expression '!=' Expression { result = OpNode.new(val[1], val[0], val[2]) }
+ | Expression IS Expression { result = OpNode.new(val[1], val[0], val[2]) }
+ | Expression AINT Expression { result = OpNode.new(val[1], val[0], val[2]) }
+
+ | Expression '&&' Expression { result = OpNode.new(val[1], val[0], val[2]) }
+ | Expression '||' Expression { result = OpNode.new(val[1], val[0], val[2]) }
+ | Expression AND Expression { result = OpNode.new(val[1], val[0], val[2]) }
+ | Expression OR Expression { result = OpNode.new(val[1], val[0], val[2]) }
+
+ # Add ternary?
+
+ | Expression '-=' Expression { result = OpNode.new(val[1], val[0], val[2]) }
+ | Expression '+=' Expression { result = OpNode.new(val[1], val[0], val[2]) }
+ | Expression '/=' Expression { result = OpNode.new(val[1], val[0], val[2]) }
+ | Expression '*=' Expression { result = OpNode.new(val[1], val[0], val[2]) }
+ # Add ||= &&=
+ ;
+
+
+ # Method definition
+ Code:
+ "=>" Expressions "." { result = CodeNode.new([], val[1]) }
+ | ParamList
+ "=>" Expressions "." { result = CodeNode.new(val[0], val[2]) }
+ ;
+
+ ParamList:
+ /* nothing */ { result = [] }
+ | IDENTIFIER { result = val }
+ | ParamList "," IDENTIFIER { result = val[0] << val[2] }
+ ;
+
+ Variable:
+ IDENTIFIER { result = VariableNode.new(val) }
+ | Variable PROPERTY_ACCESS IDENTIFIER { result = val[0] << val[2] }
+ ;
+
+ Object:
+ "{" "}" { result = ObjectNode.new([]) }
+ | "{" AssignList "}" { result = ObjectNode.new(val[1]) }
+ | "{" Terminator AssignList
+ Terminator "}" { result = ObjectNode.new(val[2]) }
+ ;
+
+ AssignList:
+ /* nothing */ { result = []}
+ | AssignObj { result = val }
+ | AssignList "," AssignObj { result = val[0] << val[2] }
+ | AssignList Terminator AssignObj { result = val[0] << val[2] }
+ ;
+
+ # A method call.
+ Call:
+ Variable "(" ArgList ")" { result = CallNode.new(val[0], val[2]) }
+ ;
+
+ # An Array.
+ Array:
+ "[" ArgList "]" { result = ArrayNode.new(val[1]) }
+ ;
+
+ # A list of arguments to a method call.
+ ArgList:
+ /* nothing */ { result = [] }
+ | Expression { result = val }
+ | ArgList "," Expression { result = val[0] << val[2] }
+ ;
+
+ If:
+ IF Expression
+ THEN Expression "." { result = TernaryNode.new(val[1], val[3]) }
+ | IF Expression Terminator
+ Expressions "." { result = IfNode.new(val[1], val[3]) }
+ | IF Expression
+ THEN Expression
+ ELSE Expression "." { result = TernaryNode.new(val[1], val[3], val[5]) }
+ | IF Expression Terminator
+ Expressions Terminator
+ ELSE Expressions "." { result = IfNode.new(val[1], val[3], val[6]) }
+ ;
+
+end
+
+---- header
+ require "lexer"
+ require "nodes"
+
+---- inner
+ def parse(code, show_tokens=false)
+ # @yydebug = true
+ @tokens = Lexer.new.tokenize(code)
+ puts @tokens.inspect if show_tokens
+ do_parse
+ end
+
+ def next_token
+ @tokens.shift
+ end
90 lexer.rb
@@ -0,0 +1,90 @@
+class Lexer
+
+ KEYWORDS = ["if", "else", "then",
+ "true", "false", "null",
+ "and", "or", "is", "aint", "not"]
+
+ IDENTIFIER = /\A([a-zA-Z$_]\w*)/
+ NUMBER = /\A([0-9]+(\.[0-9]+)?)/
+ STRING = /\A["'](.*?)["']/
+ OPERATOR = /\A([+\*&|\/\-%=<>]+)/
+ WHITESPACE = /\A([ \t\r]+)/
+ NEWLINE = /\A([\r\n]+)/
+ COMMENT = /\A(#[^\r\n]*)/
+ CODE = /\A(=>)/
+
+ # This is how to implement a very simple scanner.
+ # Scan one caracter at the time until you find something to parse.
+ def tokenize(code)
+ @code = code.chomp # Cleanup code by remove extra line breaks
+ @i = 0 # Current character position we're parsing
+ @tokens = [] # Collection of all parsed tokens in the form [:TOKEN_TYPE, value]
+ while @i < @code.length
+ @chunk = @code[@i..-1]
+ extract_next_token
+ end
+ @tokens
+ end
+
+ def extract_next_token
+ return if identifier_token
+ return if number_token
+ return if string_token
+ return if remove_comment
+ return if whitespace_token
+ return literal_token
+ end
+
+ # Matching if, print, method names, etc.
+ def identifier_token
+ return false unless identifier = @chunk[IDENTIFIER, 1]
+ # Keywords are special identifiers tagged with their own name, 'if' will result
+ # in an [:IF, "if"] token
+ tag = KEYWORDS.include?(identifier) ? identifier.upcase.to_sym : :IDENTIFIER
+ if tag == :IDENTIFIER && @tokens[-1] && @tokens[-1][1] == '.'
+ @tokens[-1] = [:PROPERTY_ACCESS, '.']
+ end
+ @tokens << [tag, identifier]
+ @i += identifier.length
+ end
+
+ def number_token
+ return false unless number = @chunk[NUMBER, 1]
+ float = number.include?('.')
+ @tokens << [:NUMBER, float ? number.to_f : number.to_i]
+ @i += number.length
+ end
+
+ def string_token
+ return false unless string = @chunk[STRING, 1]
+ @tokens << [:STRING, string]
+ @i += string.length + 2
+ end
+
+ def remove_comment
+ return false unless comment = @chunk[COMMENT, 1]
+ @i += comment.length
+ end
+
+ # Ignore whitespace
+ def whitespace_token
+ return false unless whitespace = @chunk[WHITESPACE, 1]
+ @i += whitespace.length
+ end
+
+ # We treat all other single characters as a token. Eg.: ( ) , . !
+ # Multi-character operators are also literal tokens, so that Racc can assign
+ # the proper order of operations. Multiple newlines get merged.
+ def literal_token
+ value = @chunk[NEWLINE, 1]
+ if value
+ @tokens << ["\n", "\n"] unless @tokens.last && @tokens.last[0] == "\n"
+ return @i += value.length
+ end
+ value = @chunk[OPERATOR, 1]
+ value ||= @chunk[0,1]
+ @tokens << [value, value]
+ @i += value.length
+ end
+
+end
2  lexer_test.rb
@@ -0,0 +1,2 @@
+require "lexer"
+p Lexer.new.tokenize(File.read('code.jaa'))
176 nodes.rb
@@ -0,0 +1,176 @@
+# Tabs are two spaces for pretty-printing.
+TAB = ' '
+
+# Collection of nodes each one representing an expression.
+class Nodes
+ attr_reader :nodes
+ def initialize(nodes)
+ @nodes = nodes
+ end
+
+ def <<(node)
+ @nodes << node
+ self
+ end
+
+ # Flatten redundant nested node lists until we have multiple nodes on the
+ # same level to work with.
+ def reduce
+ return nodes.first.reduce if nodes.length == 1 && nodes.first.is_a?(Nodes)
+ nodes
+ end
+
+ def compile(indent='')
+ reduce.map { |node|
+ indent + node.compile(indent) + (node.is_a?(IfNode) ? '' : ';')
+ }.join("\n")
+ end
+end
+
+# Literals are static values that have a Ruby representation, eg.: a string, a number,
+# true, false, nil, etc.
+class LiteralNode
+ def initialize(value)
+ @value = value
+ end
+
+ def compile(indent)
+ @value.to_s
+ end
+end
+
+# Node of a method call or local variable access, can take any of these forms:
+#
+# method # this form can also be a local variable
+# method(argument1, argument2)
+# receiver.method
+# receiver.method(argument1, argument2)
+#
+class CallNode
+ def initialize(variable, arguments=[])
+ @variable, @arguments = variable, arguments
+ end
+
+ def compile(indent)
+ args = @arguments.map{|a| a.compile(indent) }.join(', ')
+ "#{@variable.compile(indent)}(#{args})"
+ end
+end
+
+class VariableNode
+ def initialize(name)
+ @name = name
+ @properties = []
+ end
+
+ def <<(other)
+ @properties << other
+ self
+ end
+
+ def compile(indent)
+ [@name, @properties].flatten.join('.')
+ end
+end
+
+# Setting the value of a local variable.
+class AssignNode
+ def initialize(variable, value, context=nil)
+ @variable, @value, @context = variable, value, context
+ end
+
+ def compile(indent)
+ return "#{@variable}: #{@value.compile(indent + TAB)}" if @context == :object
+ "var #{@variable.compile(indent)} = #{@value.compile(indent)}"
+ end
+end
+
+# Simple Arithmetic and logical operations
+class OpNode
+ CONVERSIONS = {
+ "==" => "===",
+ "!=" => "!==",
+ 'and' => '&&',
+ 'or' => '||',
+ 'is' => '===',
+ "aint" => "!==",
+ 'not' => '!',
+ }
+
+ def initialize(operator, first, second=nil)
+ @first, @second = first, second
+ @operator = CONVERSIONS[operator] || operator
+ end
+
+ def unary?
+ @second.nil?
+ end
+
+ def compile(indent)
+ "(#{@first.compile(indent)} #{@operator} #{@second.compile(indent)})"
+ end
+end
+
+# Method definition.
+class CodeNode
+ def initialize(params, body)
+ @params = params
+ @body = body
+ end
+
+ def compile(indent)
+ nodes = @body.reduce
+ exprs = nodes.map {|n| n.compile(indent + TAB) }
+ exprs[-1] = "return #{exprs[-1]};"
+ exprs = exprs.map {|e| indent + TAB + e }
+ "function(#{@params.join(', ')}) {\n#{exprs.join(";\n")}\n#{indent}}"
+ end
+end
+
+class ObjectNode
+ def initialize(properties = [])
+ @properties = properties
+ end
+
+ def compile(indent)
+ props = @properties.map {|p| indent + TAB + p.compile(indent) }.join(",\n")
+ "{\n#{props}\n#{indent}}"
+ end
+end
+
+class ArrayNode
+ def initialize(objects=[])
+ @objects = objects
+ end
+
+ def compile(indent)
+ objects = @objects.map {|o| o.compile(indent) }.join(', ')
+ "[#{objects}]"
+ end
+end
+
+# "if-else" control structure. Look at this node if you want to implement other control
+# structures like while, for, loop, etc.
+class IfNode
+ def initialize(condition, body, else_body=nil)
+ @condition, @body, @else_body = condition, body, else_body
+ end
+
+ def compile(indent)
+ if_part = "if (#{@condition.compile(indent)}) {\n#{@body.compile(indent + TAB)}\n#{indent}}"
+ else_part = @else_body ? " else {\n#{@else_body.compile(indent + TAB)}\n#{indent}}" : ''
+ if_part + else_part
+ end
+end
+
+class TernaryNode
+ def initialize(condition, body, else_body=nil)
+ @condition, @body, @else_body = condition, body, else_body
+ end
+
+ def compile(indent)
+ if_part = "#{@condition.compile(indent)} ? #{@body.compile(indent)}"
+ else_part = @else_body ? "#{@else_body.compile(indent)}" : 'null'
+ "#{if_part} : #{else_part}"
+ end
+end
1,090 parser.rb
@@ -0,0 +1,1090 @@
+#
+# DO NOT MODIFY!!!!
+# This file is automatically generated by Racc 1.4.6
+# from Racc grammer file "".
+#
+
+require 'racc/parser.rb'
+
+ require "lexer"
+ require "nodes"
+
+class Parser < Racc::Parser
+
+module_eval(<<'...end grammar.y/module_eval...', 'grammar.y', 197)
+ def parse(code, show_tokens=false)
+ # @yydebug = true
+ @tokens = Lexer.new.tokenize(code)
+ puts @tokens.inspect if show_tokens
+ do_parse
+ end
+
+ def next_token
+ @tokens.shift
+ end
+...end grammar.y/module_eval...
+##### State transition tables begin ###
+
+racc_action_table = [
+ 5, 83, 31, 35, 14, 17, 21, 24, 28, 2,
+ 12, 15, 82, 9, 11, 73, 5, 31, 81, 27,
+ 14, 17, 21, 24, 28, 2, 74, 12, 15, 9,
+ 11, 37, 73, 31, 71, 27, 118, 36, -52, 20,
+ -52, 67, 1, 68, 12, 15, 8, -65, 82, 12,
+ 15, 32, 113, 84, 31, 20, 12, 15, 1, 5,
+ 127, -65, 8, 14, 17, 21, 24, 28, 2, 76,
+ 12, 15, 9, 11, 121, 5, 12, 15, 27, 14,
+ 17, 21, 24, 28, 2, 43, 12, 15, 9, 11,
+ 117, 58, 60, 62, 27, 12, 15, 31, 20, 12,
+ 15, 1, 58, 60, 62, 8, 58, 60, 62, 64,
+ 66, 108, nil, nil, 20, nil, nil, 1, 5, nil,
+ nil, 8, 14, 17, 21, 24, 28, 2, nil, nil,
+ nil, 9, 11, nil, 5, nil, nil, 27, 14, 17,
+ 21, 24, 28, 2, nil, nil, nil, 9, 11, nil,
+ nil, nil, nil, 27, nil, nil, nil, 20, nil, nil,
+ 1, nil, nil, nil, 8, 58, 60, 62, 64, 66,
+ 12, 15, nil, 20, nil, -51, 1, 5, nil, nil,
+ 8, 14, 17, 21, 24, 28, 2, nil, nil, nil,
+ 9, 11, nil, 5, nil, nil, 27, 14, 17, 21,
+ 24, 28, 2, nil, nil, nil, 9, 11, nil, nil,
+ nil, nil, 27, nil, nil, nil, 20, nil, nil, 1,
+ nil, nil, nil, 8, 58, 60, 62, 64, 66, nil,
+ nil, nil, 20, nil, nil, 1, 5, nil, nil, 8,
+ 14, 17, 21, 24, 28, 2, nil, nil, nil, 9,
+ 11, nil, 5, nil, nil, 27, 14, 17, 21, 24,
+ 28, 2, nil, nil, nil, 9, 11, nil, nil, nil,
+ nil, 27, 12, 15, nil, 20, nil, nil, 1, nil,
+ nil, nil, 8, 58, 60, 62, 64, 66, 12, 15,
+ nil, 20, nil, nil, 1, 5, 124, nil, 8, 14,
+ 17, 21, 24, 28, 2, nil, nil, nil, 9, 11,
+ nil, 5, nil, nil, 27, 14, 17, 21, 24, 28,
+ 2, nil, nil, nil, 9, 11, nil, nil, nil, nil,
+ 27, nil, nil, nil, 20, nil, -51, 1, nil, nil,
+ nil, 8, nil, nil, nil, nil, nil, nil, nil, nil,
+ 20, nil, nil, 1, 5, nil, nil, 8, 14, 17,
+ 21, 24, 28, 2, nil, nil, nil, 9, 11, nil,
+ 5, nil, nil, 27, 14, 17, 21, 24, 28, 2,
+ nil, nil, nil, 9, 11, nil, nil, nil, nil, 27,
+ nil, nil, nil, 20, nil, nil, 1, nil, nil, nil,
+ 8, nil, nil, nil, nil, nil, nil, nil, nil, 20,
+ nil, nil, 1, 5, nil, nil, 8, 14, 17, 21,
+ 24, 28, 2, nil, nil, nil, 9, 11, nil, 5,
+ nil, nil, 27, 14, 17, 21, 24, 28, 2, nil,
+ nil, nil, 9, 11, nil, nil, nil, nil, 27, 12,
+ 15, nil, 20, nil, nil, 1, nil, nil, nil, 8,
+ nil, nil, nil, nil, nil, 12, 15, nil, 20, nil,
+ nil, 1, 5, nil, nil, 8, 14, 17, 21, 24,
+ 28, 2, nil, nil, nil, 9, 11, nil, 5, nil,
+ nil, 27, 14, 17, 21, 24, 28, 2, nil, nil,
+ nil, 9, 11, nil, nil, nil, nil, 27, nil, nil,
+ nil, 20, nil, nil, 1, nil, nil, nil, 8, nil,
+ nil, nil, nil, nil, nil, nil, nil, 20, nil, nil,
+ 1, 5, nil, nil, 8, 14, 17, 21, 24, 28,
+ 2, nil, nil, nil, 9, 11, nil, 5, nil, nil,
+ 27, 14, 17, 21, 24, 28, 2, nil, nil, nil,
+ 9, 11, nil, nil, nil, nil, 27, nil, nil, nil,
+ 20, nil, nil, 1, nil, nil, nil, 8, nil, nil,
+ nil, nil, nil, nil, nil, nil, 20, nil, nil, 1,
+ 5, nil, nil, 8, 14, 17, 21, 24, 28, 2,
+ nil, nil, nil, 9, 11, nil, 5, nil, nil, 27,
+ 14, 17, 21, 24, 28, 2, nil, nil, nil, 9,
+ 11, nil, nil, nil, nil, 27, nil, nil, nil, 20,
+ nil, nil, 1, nil, nil, nil, 8, nil, nil, nil,
+ nil, nil, nil, nil, nil, 20, nil, nil, 1, 5,
+ nil, nil, 8, 14, 17, 21, 24, 28, 2, nil,
+ nil, nil, 9, 11, nil, 5, nil, nil, 27, 14,
+ 17, 21, 24, 28, 2, nil, nil, nil, 9, 11,
+ nil, nil, nil, nil, 27, nil, nil, nil, 20, nil,
+ nil, 1, nil, nil, nil, 8, nil, nil, nil, nil,
+ nil, nil, nil, nil, 20, nil, nil, 1, 5, nil,
+ nil, 8, 14, 17, 21, 24, 28, 2, nil, nil,
+ nil, 9, 11, nil, 5, nil, nil, 27, 14, 17,
+ 21, 24, 28, 2, nil, nil, nil, 9, 11, nil,
+ nil, nil, nil, 27, nil, nil, nil, 20, nil, nil,
+ 1, nil, nil, nil, 8, nil, nil, nil, nil, nil,
+ nil, nil, nil, 20, nil, nil, 1, 5, nil, nil,
+ 8, 14, 17, 21, 24, 28, 2, nil, nil, nil,
+ 9, 11, nil, 5, nil, nil, 27, 14, 17, 21,
+ 24, 28, 2, nil, nil, nil, 9, 11, nil, nil,
+ nil, nil, 27, nil, nil, nil, 20, nil, -51, 1,
+ nil, nil, nil, 8, nil, nil, nil, nil, nil, nil,
+ nil, nil, 20, nil, nil, 1, 5, nil, nil, 8,
+ 14, 17, 21, 24, 28, 2, nil, nil, nil, 9,
+ 11, nil, 5, nil, nil, 27, 14, 17, 21, 24,
+ 28, 2, nil, nil, nil, 9, 11, nil, nil, nil,
+ nil, 27, nil, nil, nil, 20, nil, nil, 1, nil,
+ nil, nil, 8, nil, nil, nil, nil, nil, nil, nil,
+ nil, 20, nil, nil, 1, 5, nil, nil, 8, 14,
+ 17, 21, 24, 28, 2, nil, nil, nil, 9, 11,
+ nil, 5, nil, nil, 27, 14, 17, 21, 24, 28,
+ 2, nil, nil, nil, 9, 11, nil, nil, nil, nil,
+ 27, nil, nil, nil, 20, nil, nil, 1, nil, nil,
+ nil, 8, nil, nil, nil, nil, nil, nil, nil, nil,
+ 20, nil, nil, 1, 5, nil, nil, 8, 14, 17,
+ 21, 24, 28, 2, nil, nil, nil, 9, 11, nil,
+ 5, nil, nil, 27, 14, 17, 21, 24, 28, 2,
+ nil, nil, nil, 9, 11, nil, nil, nil, nil, 27,
+ nil, nil, nil, 20, nil, nil, 1, nil, nil, nil,
+ 8, nil, nil, nil, nil, nil, nil, nil, nil, 20,
+ nil, nil, 1, 5, nil, nil, 8, 14, 17, 21,
+ 24, 28, 2, nil, nil, nil, 9, 11, nil, 5,
+ nil, nil, 27, 14, 17, 21, 24, 28, 2, nil,
+ nil, nil, 9, 11, nil, nil, nil, nil, 27, nil,
+ nil, nil, 20, nil, nil, 1, nil, nil, nil, 8,
+ nil, nil, nil, nil, nil, nil, nil, nil, 20, nil,
+ nil, 1, 5, nil, nil, 8, 14, 17, 21, 24,
+ 28, 2, nil, nil, nil, 9, 11, nil, 5, nil,
+ nil, 27, 14, 17, 21, 24, 28, 2, nil, nil,
+ nil, 9, 11, nil, nil, nil, nil, 27, nil, nil,
+ nil, 20, nil, nil, 1, nil, nil, nil, 8, nil,
+ nil, nil, nil, nil, nil, nil, nil, 20, nil, nil,
+ 1, 5, nil, nil, 8, 14, 17, 21, 24, 28,
+ 2, nil, nil, nil, 9, 11, nil, 5, nil, nil,
+ 27, 14, 17, 21, 24, 28, 2, nil, nil, nil,
+ 9, 11, nil, nil, nil, nil, 27, nil, nil, nil,
+ 20, nil, nil, 1, nil, nil, nil, 8, nil, nil,
+ 119, nil, nil, nil, nil, nil, 20, nil, nil, 1,
+ nil, nil, nil, 8, 58, 60, 62, 64, 66, 47,
+ 49, 51, 53, 55, 56, 57, 59, 61, 63, 65,
+ 46, 48, 50, 52, 54, 79, nil, nil, nil, 120,
+ nil, nil, nil, nil, nil, nil, nil, nil, 58, 60,
+ 62, 64, 66, 47, 49, 51, 53, 55, 56, 57,
+ 59, 61, 63, 65, 46, 48, 50, 52, 54, 12,
+ 15, 58, 60, 62, 64, 66, 47, 49, 51, 53,
+ 55, 56, 57, 59, 61, 63, 65, 46, 48, 50,
+ 52, 54, nil, nil, nil, nil, 125, 58, 60, 62,
+ 64, 66, 47, 49, 51, 53, 55, 56, 57, 59,
+ 61, 63, 65, 46, 48, 50, 52, 54, 58, 60,
+ 62, 64, 66, 47, 49, 51, 53, 55, 56, 57,
+ 59, 61, 63, 65, 46, 48, 50, 52, 54, 58,
+ 60, 62, 64, 66, 47, 49, 51, 53, 55, 56,
+ 57, 59, 61, 63, 65, 46, 48, 50, 52, 54,
+ 58, 60, 62, 64, 66, 47, 49, 51, 53, 55,
+ 56, 57, 59, 61, 63, 65, 46, 48, 50, 52,
+ 54, 58, 60, 62, 64, 66, 47, 49, 51, 53,
+ 55, 56, 57, 59, 61, 63, 65, 46, 48, 50,
+ 52, 54, 58, 60, 62, 64, 66, 47, 49, 51,
+ 53, 55, 56, 57, 59, 61, 63, 65, 46, 48,
+ 50, 52, 54, 58, 60, 62, 64, 66, 47, 49,
+ 51, 53, 55, 56, 57, 59, 61, 63, 65, 46,
+ 48, 50, 52, 54, 58, 60, 62, 64, 66, 47,
+ 49, 51, 53, 55, 56, 57, 59, 61, 63, 65,
+ 46, 48, 50, 52, 54, 58, 60, 62, 64, 66,
+ 47, 49, 51, 53, 55, 56, 57, 59, 61, 63,
+ 65, 46, 48, 50, 52, 54, 58, 60, 62, 64,
+ 66, 47, 49, 51, 53, 55, 56, 57, 59, 61,
+ 63, 65, 46, 48, 50, 52, 54, 58, 60, 62,
+ 64, 66, 47, 49, 51, 53, 55, 56, 57, 59,
+ 58, 60, 62, 64, 66, 47, 49, 51, 53, 55,
+ 56, 57, 59, 58, 60, 62, 64, 66, 47, 49,
+ 51, 53, 55, 56, 57, 59, 58, 60, 62, 64,
+ 66, 47, 49, 51, 53, 55, 56, 57, 59, 58,
+ 60, 62, 64, 66, 47, 49, 51, 53, 55, 56,
+ 57, 59, 58, 60, 62, 64, 66, 47, 49, 51,
+ 53, 55, 56, 57, 59, 58, 60, 62, 64, 66,
+ 47, 49, 51, 53, 55, 56, 57, 59, 58, 60,
+ 62, 64, 66, 47, 49, 51, 53, 55, 56, 57,
+ 59 ]
+
+racc_action_check = [
+ 8, 43, 112, 4, 8, 8, 8, 8, 8, 8,
+ 75, 75, 39, 8, 8, 75, 36, 1, 39, 8,
+ 36, 36, 36, 36, 36, 36, 31, 30, 30, 36,
+ 36, 4, 30, 73, 30, 36, 112, 4, 2, 8,
+ 2, 26, 8, 26, 1, 1, 8, 8, 77, 44,
+ 44, 1, 77, 44, 34, 36, 126, 126, 36, 124,
+ 126, 36, 36, 124, 124, 124, 124, 124, 124, 35,
+ 115, 115, 124, 124, 115, 74, 23, 23, 124, 74,
+ 74, 74, 74, 74, 74, 19, 107, 107, 74, 74,
+ 107, 104, 104, 104, 74, 124, 124, 72, 124, 70,
+ 70, 124, 106, 106, 106, 124, 93, 93, 93, 93,
+ 93, 68, nil, nil, 74, nil, nil, 74, 5, nil,
+ nil, 74, 5, 5, 5, 5, 5, 5, nil, nil,
+ nil, 5, 5, nil, 0, nil, nil, 5, 0, 0,
+ 0, 0, 0, 0, nil, nil, nil, 0, 0, nil,
+ nil, nil, nil, 0, nil, nil, nil, 5, nil, nil,
+ 5, nil, nil, nil, 5, 91, 91, 91, 91, 91,
+ 0, 0, nil, 0, nil, 0, 0, 9, nil, nil,
+ 0, 9, 9, 9, 9, 9, 9, nil, nil, nil,
+ 9, 9, nil, 11, nil, nil, 9, 11, 11, 11,
+ 11, 11, 11, nil, nil, nil, 11, 11, nil, nil,
+ nil, nil, 11, nil, nil, nil, 9, nil, nil, 9,
+ nil, nil, nil, 9, 89, 89, 89, 89, 89, nil,
+ nil, nil, 11, nil, nil, 11, 80, nil, nil, 11,
+ 80, 80, 80, 80, 80, 80, nil, nil, nil, 80,
+ 80, nil, 20, nil, nil, 80, 20, 20, 20, 20,
+ 20, 20, nil, nil, nil, 20, 20, nil, nil, nil,
+ nil, 20, 80, 80, nil, 80, nil, nil, 80, nil,
+ nil, nil, 80, 87, 87, 87, 87, 87, 20, 20,
+ nil, 20, nil, nil, 20, 122, 122, nil, 20, 122,
+ 122, 122, 122, 122, 122, nil, nil, nil, 122, 122,
+ nil, 82, nil, nil, 122, 82, 82, 82, 82, 82,
+ 82, nil, nil, nil, 82, 82, nil, nil, nil, nil,
+ 82, nil, nil, nil, 122, nil, 122, 122, nil, nil,
+ nil, 122, nil, nil, nil, nil, nil, nil, nil, nil,
+ 82, nil, nil, 82, 119, nil, nil, 82, 119, 119,
+ 119, 119, 119, 119, nil, nil, nil, 119, 119, nil,
+ 27, nil, nil, 119, 27, 27, 27, 27, 27, 27,
+ nil, nil, nil, 27, 27, nil, nil, nil, nil, 27,
+ nil, nil, nil, 119, nil, nil, 119, nil, nil, nil,
+ 119, nil, nil, nil, nil, nil, nil, nil, nil, 27,
+ nil, nil, 27, 29, nil, nil, 27, 29, 29, 29,
+ 29, 29, 29, nil, nil, nil, 29, 29, nil, 67,
+ nil, nil, 29, 67, 67, 67, 67, 67, 67, nil,
+ nil, nil, 67, 67, nil, nil, nil, nil, 67, 29,
+ 29, nil, 29, nil, nil, 29, nil, nil, nil, 29,
+ nil, nil, nil, nil, nil, 67, 67, nil, 67, nil,
+ nil, 67, 66, nil, nil, 67, 66, 66, 66, 66,
+ 66, 66, nil, nil, nil, 66, 66, nil, 65, nil,
+ nil, 66, 65, 65, 65, 65, 65, 65, nil, nil,
+ nil, 65, 65, nil, nil, nil, nil, 65, nil, nil,
+ nil, 66, nil, nil, 66, nil, nil, nil, 66, nil,
+ nil, nil, nil, nil, nil, nil, nil, 65, nil, nil,
+ 65, 64, nil, nil, 65, 64, 64, 64, 64, 64,
+ 64, nil, nil, nil, 64, 64, nil, 79, nil, nil,
+ 64, 79, 79, 79, 79, 79, 79, nil, nil, nil,
+ 79, 79, nil, nil, nil, nil, 79, nil, nil, nil,
+ 64, nil, nil, 64, nil, nil, nil, 64, nil, nil,
+ nil, nil, nil, nil, nil, nil, 79, nil, nil, 79,
+ 37, nil, nil, 79, 37, 37, 37, 37, 37, 37,
+ nil, nil, nil, 37, 37, nil, 63, nil, nil, 37,
+ 63, 63, 63, 63, 63, 63, nil, nil, nil, 63,
+ 63, nil, nil, nil, nil, 63, nil, nil, nil, 37,
+ nil, nil, 37, nil, nil, nil, 37, nil, nil, nil,
+ nil, nil, nil, nil, nil, 63, nil, nil, 63, 62,
+ nil, nil, 63, 62, 62, 62, 62, 62, 62, nil,
+ nil, nil, 62, 62, nil, 61, nil, nil, 62, 61,
+ 61, 61, 61, 61, 61, nil, nil, nil, 61, 61,
+ nil, nil, nil, nil, 61, nil, nil, nil, 62, nil,
+ nil, 62, nil, nil, nil, 62, nil, nil, nil, nil,
+ nil, nil, nil, nil, 61, nil, nil, 61, 60, nil,
+ nil, 61, 60, 60, 60, 60, 60, 60, nil, nil,
+ nil, 60, 60, nil, 59, nil, nil, 60, 59, 59,
+ 59, 59, 59, 59, nil, nil, nil, 59, 59, nil,
+ nil, nil, nil, 59, nil, nil, nil, 60, nil, nil,
+ 60, nil, nil, nil, 60, nil, nil, nil, nil, nil,
+ nil, nil, nil, 59, nil, nil, 59, 45, nil, nil,
+ 59, 45, 45, 45, 45, 45, 45, nil, nil, nil,
+ 45, 45, nil, 58, nil, nil, 45, 58, 58, 58,
+ 58, 58, 58, nil, nil, nil, 58, 58, nil, nil,
+ nil, nil, 58, nil, nil, nil, 45, nil, 45, 45,
+ nil, nil, nil, 45, nil, nil, nil, nil, nil, nil,
+ nil, nil, 58, nil, nil, 58, 47, nil, nil, 58,
+ 47, 47, 47, 47, 47, 47, nil, nil, nil, 47,
+ 47, nil, 48, nil, nil, 47, 48, 48, 48, 48,
+ 48, 48, nil, nil, nil, 48, 48, nil, nil, nil,
+ nil, 48, nil, nil, nil, 47, nil, nil, 47, nil,
+ nil, nil, 47, nil, nil, nil, nil, nil, nil, nil,
+ nil, 48, nil, nil, 48, 49, nil, nil, 48, 49,
+ 49, 49, 49, 49, 49, nil, nil, nil, 49, 49,
+ nil, 50, nil, nil, 49, 50, 50, 50, 50, 50,
+ 50, nil, nil, nil, 50, 50, nil, nil, nil, nil,
+ 50, nil, nil, nil, 49, nil, nil, 49, nil, nil,
+ nil, 49, nil, nil, nil, nil, nil, nil, nil, nil,
+ 50, nil, nil, 50, 51, nil, nil, 50, 51, 51,
+ 51, 51, 51, 51, nil, nil, nil, 51, 51, nil,
+ 52, nil, nil, 51, 52, 52, 52, 52, 52, 52,
+ nil, nil, nil, 52, 52, nil, nil, nil, nil, 52,
+ nil, nil, nil, 51, nil, nil, 51, nil, nil, nil,
+ 51, nil, nil, nil, nil, nil, nil, nil, nil, 52,
+ nil, nil, 52, 53, nil, nil, 52, 53, 53, 53,
+ 53, 53, 53, nil, nil, nil, 53, 53, nil, 54,
+ nil, nil, 53, 54, 54, 54, 54, 54, 54, nil,
+ nil, nil, 54, 54, nil, nil, nil, nil, 54, nil,
+ nil, nil, 53, nil, nil, 53, nil, nil, nil, 53,
+ nil, nil, nil, nil, nil, nil, nil, nil, 54, nil,
+ nil, 54, 55, nil, nil, 54, 55, 55, 55, 55,
+ 55, 55, nil, nil, nil, 55, 55, nil, 56, nil,
+ nil, 55, 56, 56, 56, 56, 56, 56, nil, nil,
+ nil, 56, 56, nil, nil, nil, nil, 56, nil, nil,
+ nil, 55, nil, nil, 55, nil, nil, nil, 55, nil,
+ nil, nil, nil, nil, nil, nil, nil, 56, nil, nil,
+ 56, 57, nil, nil, 56, 57, 57, 57, 57, 57,
+ 57, nil, nil, nil, 57, 57, nil, 46, nil, nil,
+ 57, 46, 46, 46, 46, 46, 46, nil, nil, nil,
+ 46, 46, nil, nil, nil, nil, 46, nil, nil, nil,
+ 57, nil, nil, 57, nil, nil, nil, 57, nil, nil,
+ 114, nil, nil, nil, nil, nil, 46, nil, nil, 46,
+ nil, nil, nil, 46, 114, 114, 114, 114, 114, 114,
+ 114, 114, 114, 114, 114, 114, 114, 114, 114, 114,
+ 114, 114, 114, 114, 114, 38, nil, nil, nil, 114,
+ nil, nil, nil, nil, nil, nil, nil, nil, 38, 38,
+ 38, 38, 38, 38, 38, 38, 38, 38, 38, 38,
+ 38, 38, 38, 38, 38, 38, 38, 38, 38, 38,
+ 38, 123, 123, 123, 123, 123, 123, 123, 123, 123,
+ 123, 123, 123, 123, 123, 123, 123, 123, 123, 123,
+ 123, 123, nil, nil, nil, nil, 123, 85, 85, 85,
+ 85, 85, 85, 85, 85, 85, 85, 85, 85, 85,
+ 85, 85, 85, 85, 85, 85, 85, 85, 40, 40,
+ 40, 40, 40, 40, 40, 40, 40, 40, 40, 40,
+ 40, 40, 40, 40, 40, 40, 40, 40, 40, 116,
+ 116, 116, 116, 116, 116, 116, 116, 116, 116, 116,
+ 116, 116, 116, 116, 116, 116, 116, 116, 116, 116,
+ 88, 88, 88, 88, 88, 88, 88, 88, 88, 88,
+ 88, 88, 88, 88, 88, 88, 88, 88, 88, 88,
+ 88, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94, 25, 25, 25, 25, 25, 25, 25, 25,
+ 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+ 25, 25, 25, 111, 111, 111, 111, 111, 111, 111,
+ 111, 111, 111, 111, 111, 111, 111, 111, 111, 111,
+ 111, 111, 111, 111, 78, 78, 78, 78, 78, 78,
+ 78, 78, 78, 78, 78, 78, 78, 78, 78, 78,
+ 78, 78, 78, 78, 78, 90, 90, 90, 90, 90,
+ 90, 90, 90, 90, 90, 90, 90, 90, 90, 90,
+ 90, 90, 90, 90, 90, 90, 92, 92, 92, 92,
+ 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
+ 92, 92, 92, 92, 92, 92, 92, 99, 99, 99,
+ 99, 99, 99, 99, 99, 99, 99, 99, 99, 99,
+ 95, 95, 95, 95, 95, 95, 95, 95, 95, 95,
+ 95, 95, 95, 96, 96, 96, 96, 96, 96, 96,
+ 96, 96, 96, 96, 96, 96, 105, 105, 105, 105,
+ 105, 105, 105, 105, 105, 105, 105, 105, 105, 103,
+ 103, 103, 103, 103, 103, 103, 103, 103, 103, 103,
+ 103, 103, 97, 97, 97, 97, 97, 97, 97, 97,
+ 97, 97, 97, 97, 97, 101, 101, 101, 101, 101,
+ 101, 101, 101, 101, 101, 101, 101, 101, 86, 86,
+ 86, 86, 86, 86, 86, 86, 86, 86, 86, 86,
+ 86 ]
+
+racc_action_pointer = [
+ 132, 6, -3, nil, -9, 116, nil, nil, -2, 175,
+ nil, 191, nil, nil, nil, nil, nil, nil, nil, 85,
+ 250, nil, nil, 38, nil, 1355, 0, 368, nil, 411,
+ -11, -14, nil, nil, 43, 58, 14, 588, 1201, -31,
+ 1271, nil, nil, 1, 11, 765, 1135, 824, 840, 883,
+ 899, 942, 958, 1001, 1017, 1060, 1076, 1119, 781, 722,
+ 706, 663, 647, 604, 529, 486, 470, 427, 100, nil,
+ 61, nil, 86, 22, 73, -28, nil, 5, 1397, 545,
+ 234, nil, 309, nil, nil, 1250, 1551, 266, 1313, 207,
+ 1418, 148, 1439, 89, 1334, 1473, 1486, 1525, nil, 1460,
+ nil, 1538, nil, 1512, 74, 1499, 85, 48, nil, nil,
+ nil, 1376, -9, nil, 1167, 32, 1292, nil, nil, 352,
+ nil, nil, 293, 1224, 57, nil, 18, nil ]
+
+racc_action_default = [
+ -1, -59, -54, -7, -8, -51, -9, -10, -51, -51,
+ -11, -51, -16, -12, -18, -17, -13, -19, -14, -72,
+ -51, -20, -15, -2, -21, -3, -72, -51, -22, -51,
+ -72, -72, -56, -60, -59, -72, -51, -51, -72, -72,
+ -66, -27, -25, -72, -72, -5, -51, -51, -51, -51,
+ -51, -51, -51, -51, -51, -51, -51, -51, -51, -51,
+ -51, -51, -51, -51, -51, -51, -51, -51, -72, -26,
+ -6, -57, -72, -72, -51, -72, -55, -72, -23, -51,
+ -51, -64, -51, 128, -49, -4, -44, -33, -45, -34,
+ -46, -35, -47, -36, -48, -37, -38, -39, -28, -40,
+ -29, -41, -30, -42, -31, -43, -32, -72, -53, -62,
+ -61, -24, -72, -63, -72, -72, -67, -50, -58, -51,
+ -68, -69, -5, -72, -51, -70, -72, -71 ]
+
+racc_goto_table = [
+ 34, 109, 110, 23, 38, 30, 39, 40, 41, 19,
+ 42, nil, nil, nil, nil, nil, nil, nil, nil, nil,
+ nil, nil, 45, 44, nil, nil, 69, nil, nil, 72,
+ nil, nil, 70, nil, 77, 40, 78, 80, 75, nil,
+ nil, 109, nil, 45, 85, 86, 87, 88, 89, 90,
+ 91, 92, 93, 94, 95, 96, 97, 98, 99, 100,
+ 101, 102, 103, 104, 105, 106, nil, nil, nil, 45,
+ 107, nil, nil, 111, 112, nil, nil, nil, 114, nil,
+ nil, 116, nil, 115, nil, nil, nil, nil, nil, nil,
+ nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
+ nil, nil, nil, nil, nil, nil, 45, nil, nil, nil,
+ nil, nil, nil, nil, 122, nil, nil, nil, 123, nil,
+ nil, 85, nil, nil, nil, 45, nil, 126 ]
+
+racc_goto_check = [
+ 4, 14, 14, 2, 3, 16, 17, 3, 3, 1,
+ 3, nil, nil, nil, nil, nil, nil, nil, nil, nil,
+ nil, nil, 4, 2, nil, nil, 3, nil, nil, 4,
+ nil, nil, 2, nil, 17, 3, 3, 4, 16, nil,
+ nil, 14, nil, 4, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, nil, nil, nil, 4,
+ 2, nil, nil, 3, 4, nil, nil, nil, 3, nil,
+ nil, 3, nil, 2, nil, nil, nil, nil, nil, nil,
+ nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
+ nil, nil, nil, nil, nil, nil, 4, nil, nil, nil,
+ nil, nil, nil, nil, 4, nil, nil, nil, 3, nil,
+ nil, 3, nil, nil, nil, 4, nil, 2 ]
+
+racc_goto_pointer = [
+ nil, 9, 3, -1, -1, nil, nil, nil, nil, nil,
+ nil, nil, nil, nil, -71, nil, 4, -2 ]
+
+racc_goto_default = [
+ nil, nil, nil, 25, 29, 3, 4, 6, 7, 10,
+ 13, 16, 18, 22, 33, 26, nil, nil ]
+
+racc_reduce_table = [
+ 0, 0, :racc_error,
+ 0, 51, :_reduce_1,
+ 1, 51, :_reduce_2,
+ 1, 52, :_reduce_3,
+ 3, 52, :_reduce_4,
+ 2, 52, :_reduce_5,
+ 2, 52, :_reduce_6,
+ 1, 53, :_reduce_none,
+ 1, 53, :_reduce_none,
+ 1, 53, :_reduce_none,
+ 1, 53, :_reduce_none,
+ 1, 53, :_reduce_none,
+ 1, 53, :_reduce_none,
+ 1, 53, :_reduce_none,
+ 1, 53, :_reduce_none,
+ 1, 53, :_reduce_none,
+ 1, 54, :_reduce_none,
+ 1, 54, :_reduce_none,
+ 1, 55, :_reduce_18,
+ 1, 55, :_reduce_19,
+ 1, 55, :_reduce_20,
+ 1, 55, :_reduce_21,
+ 1, 55, :_reduce_22,
+ 3, 58, :_reduce_23,
+ 3, 64, :_reduce_24,
+ 2, 61, :_reduce_25,
+ 2, 61, :_reduce_26,
+ 2, 61, :_reduce_27,
+ 3, 61, :_reduce_28,
+ 3, 61, :_reduce_29,
+ 3, 61, :_reduce_30,
+ 3, 61, :_reduce_31,
+ 3, 61, :_reduce_32,
+ 3, 61, :_reduce_33,
+ 3, 61, :_reduce_34,
+ 3, 61, :_reduce_35,
+ 3, 61, :_reduce_36,
+ 3, 61, :_reduce_37,
+ 3, 61, :_reduce_38,
+ 3, 61, :_reduce_39,
+ 3, 61, :_reduce_40,
+ 3, 61, :_reduce_41,
+ 3, 61, :_reduce_42,
+ 3, 61, :_reduce_43,
+ 3, 61, :_reduce_44,
+ 3, 61, :_reduce_45,
+ 3, 61, :_reduce_46,
+ 3, 61, :_reduce_47,
+ 3, 61, :_reduce_48,
+ 3, 60, :_reduce_49,
+ 4, 60, :_reduce_50,
+ 0, 65, :_reduce_51,
+ 1, 65, :_reduce_52,
+ 3, 65, :_reduce_53,
+ 1, 56, :_reduce_54,
+ 3, 56, :_reduce_55,
+ 2, 59, :_reduce_56,
+ 3, 59, :_reduce_57,
+ 5, 59, :_reduce_58,
+ 0, 66, :_reduce_59,
+ 1, 66, :_reduce_60,
+ 3, 66, :_reduce_61,
+ 3, 66, :_reduce_62,
+ 4, 57, :_reduce_63,
+ 3, 62, :_reduce_64,
+ 0, 67, :_reduce_65,
+ 1, 67, :_reduce_66,
+ 3, 67, :_reduce_67,
+ 5, 63, :_reduce_68,
+ 5, 63, :_reduce_69,
+ 7, 63, :_reduce_70,
+ 8, 63, :_reduce_71 ]
+
+racc_reduce_n = 72
+
+racc_shift_n = 128
+
+racc_token_table = {
+ false => 0,
+ :error => 1,
+ :IF => 2,
+ :ELSE => 3,
+ :THEN => 4,
+ :NEWLINE => 5,
+ :NUMBER => 6,
+ :STRING => 7,
+ :TRUE => 8,
+ :FALSE => 9,
+ :NULL => 10,
+ :IDENTIFIER => 11,
+ :PROPERTY_ACCESS => 12,
+ :CODE => 13,
+ :UMINUS => 14,
+ :NOT => 15,
+ "!" => 16,
+ "*" => 17,
+ "/" => 18,
+ "%" => 19,
+ "+" => 20,
+ "-" => 21,
+ "<=" => 22,
+ "<" => 23,
+ ">" => 24,
+ ">=" => 25,
+ "==" => 26,
+ "!=" => 27,
+ :IS => 28,
+ :AINT => 29,
+ "&&" => 30,
+ "||" => 31,
+ :AND => 32,
+ :OR => 33,
+ "-=" => 34,
+ "+=" => 35,
+ "/=" => 36,
+ "*=" => 37,
+ "\n" => 38,
+ ";" => 39,
+ ":" => 40,
+ "=>" => 41,
+ "." => 42,
+ "," => 43,
+ "{" => 44,
+ "}" => 45,
+ "(" => 46,
+ ")" => 47,
+ "[" => 48,
+ "]" => 49 }
+
+racc_nt_base = 50
+
+racc_use_result_var = true
+
+Racc_arg = [
+ racc_action_table,
+ racc_action_check,
+ racc_action_default,
+ racc_action_pointer,
+ racc_goto_table,
+ racc_goto_check,
+ racc_goto_default,
+ racc_goto_pointer,
+ racc_nt_base,
+ racc_reduce_table,
+ racc_token_table,
+ racc_shift_n,
+ racc_reduce_n,
+ racc_use_result_var ]
+
+Racc_token_to_s_table = [
+ "$end",
+ "error",
+ "IF",
+ "ELSE",
+ "THEN",
+ "NEWLINE",
+ "NUMBER",
+ "STRING",
+ "TRUE",
+ "FALSE",
+ "NULL",
+ "IDENTIFIER",
+ "PROPERTY_ACCESS",
+ "CODE",
+ "UMINUS",
+ "NOT",
+ "\"!\"",
+ "\"*\"",
+ "\"/\"",
+ "\"%\"",
+ "\"+\"",
+ "\"-\"",
+ "\"<=\"",
+ "\"<\"",
+ "\">\"",
+ "\">=\"",
+ "\"==\"",
+ "\"!=\"",
+ "IS",
+ "AINT",
+ "\"&&\"",
+ "\"||\"",
+ "AND",
+ "OR",
+ "\"-=\"",
+ "\"+=\"",
+ "\"/=\"",
+ "\"*=\"",
+ "\"\\n\"",
+ "\";\"",
+ "\":\"",
+ "\"=>\"",
+ "\".\"",
+ "\",\"",
+ "\"{\"",
+ "\"}\"",
+ "\"(\"",
+ "\")\"",
+ "\"[\"",
+ "\"]\"",
+ "$start",
+ "Root",
+ "Expressions",
+ "Expression",
+ "Terminator",
+ "Literal",
+ "Variable",
+ "Call",
+ "Assign",
+ "Object",
+ "Code",
+ "Operation",
+ "Array",
+ "If",
+ "AssignObj",
+ "ParamList",
+ "AssignList",
+ "ArgList" ]
+
+Racc_debug_parser = false
+
+##### State transition tables end #####
+
+# reduce 0 omitted
+
+module_eval(<<'.,.,', 'grammar.y', 36)
+ def _reduce_1(val, _values, result)
+ result = Nodes.new([])
+ result
+ end
+.,.,
+
+module_eval(<<'.,.,', 'grammar.y', 37)
+ def _reduce_2(val, _values, result)
+ result = val[0]
+ result
+ end
+.,.,
+
+module_eval(<<'.,.,', 'grammar.y', 42)
+ def _reduce_3(val, _values, result)
+ result = Nodes.new(val)
+ result
+ end
+.,.,
+
+module_eval(<<'.,.,', 'grammar.y', 43)
+ def _reduce_4(val, _values, result)
+ result = val[0] << val[2]
+ result
+ end
+.,.,
+
+module_eval(<<'.,.,', 'grammar.y', 44)
+ def _reduce_5(val, _values, result)
+ result = Nodes.new([val[0]])
+ result
+ end
+.,.,
+
+module_eval(<<'.,.,', 'grammar.y', 45)
+ def _reduce_6(val, _values, result)
+ result = Nodes.new([val[1]])
+ result
+ end
+.,.,
+
+# reduce 7 omitted
+
+# reduce 8 omitted
+
+# reduce 9 omitted
+
+# reduce 10 omitted
+
+# reduce 11 omitted
+
+# reduce 12 omitted
+
+# reduce 13 omitted
+
+# reduce 14 omitted
+
+# reduce 15 omitted
+
+# reduce 16 omitted
+
+# reduce 17 omitted
+
+module_eval(<<'.,.,', 'grammar.y', 69)
+ def _reduce_18(val, _values, result)
+ result = LiteralNode.new(val[0])
+ result
+ end
+.,.,
+
+module_eval(<<'.,.,', 'grammar.y', 70)
+ def _reduce_19(val, _values, result)
+ result = LiteralNode.new(val[0])
+ result
+ end
+.,.,
+
+module_eval(<<'.,.,', 'grammar.y', 71)
+ def _reduce_20(val, _values, result)
+ result = LiteralNode.new(true)
+ result
+ end
+.,.,
+
+module_eval(<<'.,.,', 'grammar.y', 72)
+ def _reduce_21(val, _values, result)
+ result = LiteralNode.new(false)
+ result
+ end
+.,.,
+
+module_eval(<<'.,.,', 'grammar.y', 73)
+ def _reduce_22(val, _values, result)
+ result = LiteralNode.new(nil)
+ result
+ end
+.,.,
+
+module_eval(<<'.,.,', 'grammar.y', 78)
+ def _reduce_23(val, _values, result)
+ result = AssignNode.new(val[0], val[2])
+ result
+ end
+.,.,
+
+module_eval(<<'.,.,', 'grammar.y', 83)
+ def _reduce_24(val, _values, result)
+ result = AssignNode.new(val[0], val[2], :object)
+ result
+ end
+.,.,
+
+module_eval(<<'.,.,', 'grammar.y', 90)
+ def _reduce_25(val, _values, result)
+ result = OpNode.new(val[0], val[1])
+ result
+ end
+.,.,
+
+module_eval(<<'.,.,', 'grammar.y', 91)
+ def _reduce_26(val, _values, result)
+ result = OpNode.new(val[0], val[1])
+ result
+ end
+.,.,
+
+module_eval(<<'.,.,', 'grammar.y', 92)
+ def _reduce_27(val, _values, result)
+ result = OpNode.new(val[0], val[1])
+ result
+ end
+.,.,
+
+module_eval(<<'.,.,', 'grammar.y', 95)
+ def _reduce_28(val, _values, result)
+ result = OpNode.new(val[1], val[0], val[2])
+ result
+ end
+.,.,
+
+module_eval(<<'.,.,', 'grammar.y', 96)
+ def _reduce_29(val, _values, result)
+ result = OpNode.new(val[1], val[0], val[2])
+ result
+ end
+.,.,
+
+module_eval(<<'.,.,', 'grammar.y', 97)
+ def _reduce_30(val, _values, result)
+ result = OpNode.new(val[1], val[0], val[2])
+ result
+ end
+.,.,
+
+module_eval(<<'.,.,', 'grammar.y', 99)
+ def _reduce_31(val, _values, result)
+ result = OpNode.new(val[1], val[0], val[2])
+ result
+ end
+.,.,
+
+module_eval(<<'.,.,', 'grammar.y', 100)
+ def _reduce_32(val, _values, result)
+ result = OpNode.new(val[1], val[0], val[2])
+ result
+ end
+.,.,
+
+module_eval(<<'.,.,', 'grammar.y', 102)
+ def _reduce_33(val, _values, result)
+ result = OpNode.new(val[1], val[0], val[2])
+ result
+ end
+.,.,
+
+module_eval(<<'.,.,', 'grammar.y', 103)
+ def _reduce_34(val, _values, result)
+ result = OpNode.new(val[1], val[0], val[2])
+ result
+ end
+.,.,
+
+module_eval(<<'.,.,', 'grammar.y', 104)
+ def _reduce_35(val, _values, result)
+ result = OpNode.new(val[1], val[0], val[2])
+ result
+ end
+.,.,
+
+module_eval(<<'.,.,', 'grammar.y', 105)
+ def _reduce_36(val, _values, result)
+ result = OpNode.new(val[1], val[0], val[2])
+ result
+ end
+.,.,
+
+module_eval(<<'.,.,', 'grammar.y', 107)
+ def _reduce_37(val, _values, result)
+ result = OpNode.new(val[1], val[0], val[2])
+ result
+ end
+.,.,
+
+module_eval(<<'.,.,', 'grammar.y', 108)
+ def _reduce_38(val, _values, result)
+ result = OpNode.new(val[1], val[0], val[2])
+ result
+ end
+.,.,
+
+module_eval(<<'.,.,', 'grammar.y', 109)
+ def _reduce_39(val, _values, result)
+ result = OpNode.new(val[1], val[0], val[2])
+ result
+ end
+.,.,
+
+module_eval(<<'.,.,', 'grammar.y', 110)
+ def _reduce_40(val, _values, result)
+ result = OpNode.new(val[1], val[0], val[2])
+ result
+ end
+.,.,
+
+module_eval(<<'.,.,', 'grammar.y', 112)
+ def _reduce_41(val, _values, result)
+ result = OpNode.new(val[1], val[0], val[2])
+ result
+ end
+.,.,
+
+module_eval(<<'.,.,', 'grammar.y', 113)
+ def _reduce_42(val, _values, result)
+ result = OpNode.new(val[1], val[0], val[2])
+ result
+ end
+.,.,
+
+module_eval(<<'.,.,', 'grammar.y', 114)
+ def _reduce_43(val, _values, result)
+ result = OpNode.new(val[1], val[0], val[2])
+ result
+ end
+.,.,
+
+module_eval(<<'.,.,', 'grammar.y', 115)
+ def _reduce_44(val, _values, result)
+ result = OpNode.new(val[1], val[0], val[2])
+ result
+ end
+.,.,
+
+module_eval(<<'.,.,', 'grammar.y', 119)
+ def _reduce_45(val, _values, result)
+ result = OpNode.new(val[1], val[0], val[2])
+ result
+ end
+.,.,
+
+module_eval(<<'.,.,', 'grammar.y', 120)
+ def _reduce_46(val, _values, result)
+ result = OpNode.new(val[1], val[0], val[2])
+ result
+ end
+.,.,
+
+module_eval(<<'.,.,', 'grammar.y', 121)
+ def _reduce_47(val, _values, result)
+ result = OpNode.new(val[1], val[0], val[2])
+ result
+ end
+.,.,
+
+module_eval(<<'.,.,', 'grammar.y', 122)
+ def _reduce_48(val, _values, result)
+ result = OpNode.new(val[1], val[0], val[2])
+ result
+ end
+.,.,
+
+module_eval(<<'.,.,', 'grammar.y', 129)
+ def _reduce_49(val, _values, result)
+ result = CodeNode.new([], val[1])
+ result
+ end
+.,.,
+
+module_eval(<<'.,.,', 'grammar.y', 131)
+ def _reduce_50(val, _values, result)
+ result = CodeNode.new(val[0], val[2])
+ result
+ end
+.,.,
+
+module_eval(<<'.,.,', 'grammar.y', 135)
+ def _reduce_51(val, _values, result)
+ result = []
+ result
+ end
+.,.,
+
+module_eval(<<'.,.,', 'grammar.y', 136)
+ def _reduce_52(val, _values, result)
+ result = val
+ result
+ end
+.,.,
+
+module_eval(<<'.,.,', 'grammar.y', 137)
+ def _reduce_53(val, _values, result)
+ result = val[0] << val[2]
+ result
+ end
+.,.,
+
+module_eval(<<'.,.,', 'grammar.y', 141)
+ def _reduce_54(val, _values, result)
+ result = VariableNode.new(val)
+ result
+ end
+.,.,
+
+module_eval(<<'.,.,', 'grammar.y', 142)
+ def _reduce_55(val, _values, result)
+ result = val[0] << val[2]
+ result
+ end
+.,.,
+
+module_eval(<<'.,.,', 'grammar.y', 146)
+ def _reduce_56(val, _values, result)
+ result = ObjectNode.new([])
+ result
+ end
+.,.,
+
+module_eval(<<'.,.,', 'grammar.y', 147)
+ def _reduce_57(val, _values, result)
+ result = ObjectNode.new(val[1])
+ result
+ end
+.,.,
+
+module_eval(<<'.,.,', 'grammar.y', 149)
+ def _reduce_58(val, _values, result)
+ result = ObjectNode.new(val[2])
+ result
+ end
+.,.,
+
+module_eval(<<'.,.,', 'grammar.y', 153)
+ def _reduce_59(val, _values, result)
+ result = []
+ result
+ end
+.,.,
+
+module_eval(<<'.,.,', 'grammar.y', 154)
+ def _reduce_60(val, _values, result)
+ result = val
+ result
+ end
+.,.,
+
+module_eval(<<'.,.,', 'grammar.y', 155)
+ def _reduce_61(val, _values, result)
+ result = val[0] << val[2]
+ result
+ end
+.,.,
+
+module_eval(<<'.,.,', 'grammar.y', 156)
+ def _reduce_62(val, _values, result)
+ result = val[0] << val[2]
+ result
+ end
+.,.,
+
+module_eval(<<'.,.,', 'grammar.y', 161)
+ def _reduce_63(val, _values, result)
+ result = CallNode.new(val[0], val[2])
+ result
+ end
+.,.,
+
+module_eval(<<'.,.,', 'grammar.y', 166)
+ def _reduce_64(val, _values, result)
+ result = ArrayNode.new(val[1])
+ result
+ end
+.,.,
+
+module_eval(<<'.,.,', 'grammar.y', 171)
+ def _reduce_65(val, _values, result)
+ result = []
+ result
+ end
+.,.,
+
+module_eval(<<'.,.,', 'grammar.y', 172)
+ def _reduce_66(val, _values, result)
+ result = val
+ result
+ end
+.,.,
+
+module_eval(<<'.,.,', 'grammar.y', 173)
+ def _reduce_67(val, _values, result)
+ result = val[0] << val[2]
+ result
+ end
+.,.,
+
+module_eval(<<'.,.,', 'grammar.y', 178)
+ def _reduce_68(val, _values, result)
+ result = TernaryNode.new(val[1], val[3])
+ result
+ end
+.,.,
+
+module_eval(<<'.,.,', 'grammar.y', 180)
+ def _reduce_69(val, _values, result)
+ result = IfNode.new(val[1], val[3])
+ result
+ end
+.,.,
+
+module_eval(<<'.,.,', 'grammar.y', 183)
+ def _reduce_70(val, _values, result)
+ result = TernaryNode.new(val[1], val[3], val[5])
+ result
+ end
+.,.,
+
+module_eval(<<'.,.,', 'grammar.y', 186)
+ def _reduce_71(val, _values, result)
+ result = IfNode.new(val[1], val[3], val[6])
+ result
+ end
+.,.,
+
+def _reduce_none(val, _values, result)
+ val[0]
+end
+
+end # class Parser
19 parser_test.rb
@@ -0,0 +1,19 @@
+# Recompile the Parser.
+# With debugging and verbose: -v -g
+`racc -o parser.rb grammar.y`
+
+# Parse and print "code.jaa".
+require "parser.rb"
+js = Parser.new.parse(File.read('code.jaa')).compile
+puts "\n\n"
+puts js
+
+# Pipe compiled JS through JSLint.
+puts "\n\n"
+require 'open3'
+stdin, stdout, stderr = Open3.popen3('/Users/jashkenas/Library/Application\ Support/TextMate/Bundles/JavaScript\ Tools.tmbundle/Support/bin/jsl -nologo -stdin')
+stdin.write(js)
+stdin.close
+puts stdout.read
+stdout.close
+stderr.close
610 underscore.jaa
@@ -0,0 +1,610 @@
+# Underscore.js
+# (c) 2009 Jeremy Ashkenas, DocumentCloud Inc.
+# Underscore is freely distributable under the terms of the MIT license.
+# Portions of Underscore are inspired by or borrowed from Prototype.js,
+# Oliver Steele's Functional, and John Resig's Micro-Templating.
+# For all details and documentation:
+# http://documentcloud.github.com/underscore/
+
+=>
+
+ # ------------------------- Baseline setup ---------------------------------
+
+ # Establish the root object, "window" in the browser, or "global" on the server.
+ root = this
+
+ # Save the previous value of the "_" variable.
+ previousUnderscore = root._
+
+ # If Underscore is called as a function, it returns a wrapped object that
+ # can be used OO-style. This wrapper holds altered versions of all the
+ # underscore functions. Wrapped objects may be chained.
+ wrapper = (obj => this._wrapped = obj)
+
+ # Establish the object that gets thrown to break out of a loop iteration.
+ breaker = typeof StopIteration !== 'undefined' ? StopIteration : '__break__'
+
+ # Create a safe reference to the Underscore object for reference below.
+ _ = root._ = obj => new wrapper(obj)
+
+ # Export the Underscore object for CommonJS.
+ exports._ = _ if typeof exports !== 'undefined'
+
+ # Create quick reference variables for speed access to core prototypes.
+ slice = Array.prototype.slice
+ unshift = Array.prototype.unshift
+ toString = Object.prototype.toString
+ hasOwnProperty = Object.prototype.hasOwnProperty
+ propertyIsEnumerable = Object.prototype.propertyIsEnumerable
+
+ # Current version.
+ _.VERSION = '0.5.1'
+
+ # ------------------------ Collection Functions: ---------------------------
+
+ # The cornerstone, an each implementation.
+ # Handles objects implementing forEach, arrays, and raw objects.
+ _.each = obj, iterator, context =>
+ index = 0
+ try
+ return obj.forEach(iterator, context) if obj.forEach
+ canLoop = _.isArray(obj) or _.isArguments(obj)
+ return for (i=0, l=obj.length; i<l; i++) iterator.call(context, obj[i], i, obj) if canLoop
+ keys = _.keys(obj)
+ l = keys.length
+ for (var i=0; i<l; i++) iterator.call(context, obj[keys[i]], keys[i], obj)
+ catch(e)
+ throw e if (e != breaker)
+ return obj;
+
+ # Return the results of applying the iterator to each element. Use JavaScript
+ # 1.6's version of map, if possible.
+ _.map = obj, iterator, context =>
+ return obj.map(iterator, context) if (obj and _.isFunction(obj.map))
+ results = []
+ _.each(obj, (value, index, list =>
+ results.push(iterator.call(context, value, index, list))
+ ))
+ results
+
+ # Reduce builds up a single result from a list of values. Also known as
+ # inject, or foldl. Uses JavaScript 1.8's version of reduce, if possible.
+ _.reduce = obj, memo, iterator, context =>
+ return obj.reduce(_.bind(iterator, context), memo) if (obj and _.isFunction(obj.reduce))
+ _.each(obj, (value, index, list =>
+ memo = iterator.call(context, memo, value, index, list)
+ ))
+ memo
+
+ # The right-associative version of reduce, also known as foldr. Uses
+ # JavaScript 1.8's version of reduceRight, if available.
+ _.reduceRight = function(obj, memo, iterator, context) {
+ if (obj && _.isFunction(obj.reduceRight)) return obj.reduceRight(_.bind(iterator, context), memo);
+ var reversed = _.clone(_.toArray(obj)).reverse();
+ _.each(reversed, function(value, index) {
+ memo = iterator.call(context, memo, value, index, obj);
+ });
+ return memo;
+ };
+
+ # Return the first value which passes a truth test.
+ _.detect = function(obj, iterator, context) {
+ var result;
+ _.each(obj, function(value, index, list) {
+ if (iterator.call(context, value, index, list)) {
+ result = value;
+ _.breakLoop();
+ }
+ });
+ return result;
+ };
+
+ # Return all the elements that pass a truth test. Use JavaScript 1.6's
+ # filter(), if it exists.
+ _.select = function(obj, iterator, context) {
+ if (obj && _.isFunction(obj.filter)) return obj.filter(iterator, context);
+ var results = [];
+ _.each(obj, function(value, index, list) {
+ iterator.call(context, value, index, list) && results.push(value);
+ });
+ return results;
+ };
+
+ # Return all the elements for which a truth test fails.
+ _.reject = function(obj, iterator, context) {
+ var results = [];
+ _.each(obj, function(value, index, list) {
+ !iterator.call(context, value, index, list) && results.push(value);
+ });
+ return results;
+ };
+
+ # Determine whether all of the elements match a truth test. Delegate to
+ # JavaScript 1.6's every(), if it is present.
+ _.all = function(obj, iterator, context) {
+ iterator = iterator || _.identity;
+ if (obj && _.isFunction(obj.every)) return obj.every(iterator, context);
+ var result = true;
+ _.each(obj, function(value, index, list) {
+ if (!(result = result && iterator.call(context, value, index, list))) _.breakLoop();
+ });
+ return result;
+ };
+
+ # Determine if at least one element in the object matches a truth test. Use
+ # JavaScript 1.6's some(), if it exists.
+ _.any = function(obj, iterator, context) {
+ iterator = iterator || _.identity;
+ if (obj && _.isFunction(obj.some)) return obj.some(iterator, context);
+ var result = false;
+ _.each(obj, function(value, index, list) {
+ if (result = iterator.call(context, value, index, list)) _.breakLoop();
+ });
+ return result;
+ };
+
+ # Determine if a given value is included in the array or object,
+ # based on '==='.
+ _.include = function(obj, target) {
+ if (_.isArray(obj)) return _.indexOf(obj, target) != -1;
+ var found = false;
+ _.each(obj, function(value) {
+ if (found = value === target) _.breakLoop();
+ });
+ return found;
+ };
+
+ # Invoke a method with arguments on every item in a collection.
+ _.invoke = function(obj, method) {
+ var args = _.rest(arguments, 2);
+ return _.map(obj, function(value) {
+ return (method ? value[method] : value).apply(value, args);
+ });
+ };
+
+ # Convenience version of a common use case of map: fetching a property.
+ _.pluck = function(obj, key) {
+ return _.map(obj, function(value){ return value[key]; });
+ };
+
+ # Return the maximum item or (item-based computation).
+ _.max = function(obj, iterator, context) {
+ if (!iterator && _.isArray(obj)) return Math.max.apply(Math, obj);
+ var result = {computed : -Infinity};
+ _.each(obj, function(value, index, list) {
+ var computed = iterator ? iterator.call(context, value, index, list) : value;
+ computed >= result.computed && (result = {value : value, computed : computed});
+ });
+ return result.value;
+ };
+
+ # Return the minimum element (or element-based computation).
+ _.min = function(obj, iterator, context) {
+ if (!iterator && _.isArray(obj)) return Math.min.apply(Math, obj);
+ var result = {computed : Infinity};
+ _.each(obj, function(value, index, list) {
+ var computed = iterator ? iterator.call(context, value, index, list) : value;
+ computed < result.computed && (result = {value : value, computed : computed});
+ });
+ return result.value;
+ };
+
+ # Sort the object's values by a criteria produced by an iterator.
+ _.sortBy = function(obj, iterator, context) {
+ return _.pluck(_.map(obj, function(value, index, list) {
+ return {
+ value : value,
+ criteria : iterator.call(context, value, index, list)
+ };
+ }).sort(function(left, right) {
+ var a = left.criteria, b = right.criteria;
+ return a < b ? -1 : a > b ? 1 : 0;
+ }), 'value');
+ };
+
+ # Use a comparator function to figure out at what index an object should
+ # be inserted so as to maintain order. Uses binary search.
+ _.sortedIndex = function(array, obj, iterator) {
+ iterator = iterator || _.identity;
+ var low = 0, high = array.length;
+ while (low < high) {
+ var mid = (low + high) >> 1;
+ iterator(array[mid]) < iterator(obj) ? low = mid + 1 : high = mid;
+ }
+ return low;
+ };
+
+ # Convert anything iterable into a real, live array.
+ _.toArray = function(iterable) {
+ if (!iterable) return [];
+ if (iterable.toArray) return iterable.toArray();
+ if (_.isArray(iterable)) return iterable;
+ if (_.isArguments(iterable)) return slice.call(iterable);
+ return _.map(iterable, function(val){ return val; });
+ };
+
+ # Return the number of elements in an object.
+ _.size = function(obj) {
+ return _.toArray(obj).length;
+ };
+
+ /*-------------------------- Array Functions: ------------------------------*/
+
+ # Get the first element of an array. Passing "n" will return the first N
+ # values in the array. Aliased as "head". The "guard" check allows it to work
+ # with _.map.
+ _.first = function(array, n, guard) {
+ return n && !guard ? slice.call(array, 0, n) : array[0];
+ };
+
+ # Returns everything but the first entry of the array. Aliased as "tail".
+ # Especially useful on the arguments object. Passing an "index" will return
+ # the rest of the values in the array from that index onward. The "guard"
+ //check allows it to work with _.map.
+ _.rest = function(array, index, guard) {
+ return slice.call(array, _.isUndefined(index) || guard ? 1 : index);
+ };
+
+ # Get the last element of an array.
+ _.last = function(array) {
+ return array[array.length - 1];
+ };
+
+ # Trim out all falsy values from an array.
+ _.compact = function(array) {
+ return _.select(array, function(value){ return !!value; });
+ };
+
+ # Return a completely flattened version of an array.
+ _.flatten = function(array) {
+ return _.reduce(array, [], function(memo, value) {
+ if (_.isArray(value)) return memo.concat(_.flatten(value));
+ memo.push(value);
+ return memo;
+ });
+ };
+
+ # Return a version of the array that does not contain the specified value(s).
+ _.without = function(array) {
+ var values = _.rest(arguments);
+ return _.select(array, function(value){ return !_.include(values, value); });
+ };
+
+ # Produce a duplicate-free version of the array. If the array has already
+ # been sorted, you have the option of using a faster algorithm.
+ _.uniq = function(array, isSorted) {
+ return _.reduce(array, [], function(memo, el, i) {
+ if (0 == i || (isSorted === true ? _.last(memo) != el : !_.include(memo, el))) memo.push(el);
+ return memo;
+ });
+ };
+
+ # Produce an array that contains every item shared between all the
+ # passed-in arrays.
+ _.intersect = function(array) {
+ var rest = _.rest(arguments);
+ return _.select(_.uniq(array), function(item) {
+ return _.all(rest, function(other) {
+ return _.indexOf(other, item) >= 0;
+ });
+ });
+ };
+
+ # Zip together multiple lists into a single array -- elements that share
+ # an index go together.
+ _.zip = function() {
+ var args = _.toArray(arguments);
+ var length = _.max(_.pluck(args, 'length'));
+ var results = new Array(length);
+ for (var i=0; i<length; i++) results[i] = _.pluck(args, String(i));
+ return results;
+ };
+
+ # If the browser doesn't supply us with indexOf (I'm looking at you, MSIE),
+ # we need this function. Return the position of the first occurence of an
+ # item in an array, or -1 if the item is not included in the array.
+ _.indexOf = function(array, item) {
+ if (array.indexOf) return array.indexOf(item);
+ for (var i=0, l=array.length; i<l; i++) if (array[i] === item) return i;
+ return -1;
+ };
+
+ # Provide JavaScript 1.6's lastIndexOf, delegating to the native function,
+ # if possible.
+ _.lastIndexOf = function(array, item) {
+ if (array.lastIndexOf) return array.lastIndexOf(item);
+ var i = array.length;
+ while (i--) if (array[i] === item) return i;
+ return -1;
+ };
+
+ # Generate an integer Array containing an arithmetic progression. A port of
+ # the native Python range() function. See:
+ # http://docs.python.org/library/functions.html#range
+ _.range = function(start, stop, step) {
+ var a = _.toArray(arguments);
+ var solo = a.length <= 1;
+ var start = solo ? 0 : a[0], stop = solo ? a[0] : a[1], step = a[2] || 1;
+ var len = Math.ceil((stop - start) / step);
+ if (len <= 0) return [];
+ var range = new Array(len);
+ for (var i = start, idx = 0; true; i += step) {
+ if ((step > 0 ? i - stop : stop - i) >= 0) return range;
+ range[idx++] = i;
+ }
+ };
+
+ /* ----------------------- Function Functions: -----------------------------*/
+
+ # Create a function bound to a given object (assigning 'this', and arguments,
+ # optionally). Binding with arguments is also known as 'curry'.
+ _.bind = function(func, obj) {
+ var args = _.rest(arguments, 2);
+ return function() {
+ return func.apply(obj || root, args.concat(_.toArray(arguments)));
+ };
+ };
+
+ # Bind all of an object's methods to that object. Useful for ensuring that
+ # all callbacks defined on an object belong to it.
+ _.bindAll = function(obj) {
+ var funcs = _.rest(arguments);
+ if (funcs.length == 0) funcs = _.functions(obj);
+ _.each(funcs, function(f) { obj[f] = _.bind(obj[f], obj); });
+ return obj;
+ };
+
+ # Delays a function for the given number of milliseconds, and then calls
+ # it with the arguments supplied.
+ _.delay = function(func, wait) {
+ var args = _.rest(arguments, 2);
+ return setTimeout(function(){ return func.apply(func, args); }, wait);
+ };
+
+ # Defers a function, scheduling it to run after the current call stack has
+ # cleared.
+ _.defer = function(func) {
+ return _.delay.apply(_, [func, 1].concat(_.rest(arguments)));
+ };
+
+ # Returns the first function passed as an argument to the second,
+ # allowing you to adjust arguments, run code before and after, and
+ # conditionally execute the original function.
+ _.wrap = function(func, wrapper) {
+ return function() {
+ var args = [func].concat(_.toArray(arguments));
+ return wrapper.apply(wrapper, args);
+ };
+ };
+
+ # Returns a function that is the composition of a list of functions, each
+ # consuming the return value of the function that follows.
+ _.compose = function() {
+ var funcs = _.toArray(arguments);
+ return function() {
+ var args = _.toArray(arguments);
+ for (var i=funcs.length-1; i >= 0; i--) {
+ args = [funcs[i].apply(this, args)];
+ }
+ return args[0];
+ };
+ };
+
+ /* ------------------------- Object Functions: ---------------------------- */
+
+ # Retrieve the names of an object's properties.
+ _.keys = function(obj) {
+ if(_.isArray(obj)) return _.range(0, obj.length);
+ var keys = [];
+ for (var key in obj) if (hasOwnProperty.call(obj, key)) keys.push(key);
+ return keys;
+ };
+
+ # Retrieve the values of an object's properties.
+ _.values = function(obj) {
+ return _.map(obj, _.identity);
+ };
+
+ # Return a sorted list of the function names available in Underscore.
+ _.functions = function(obj) {
+ return _.select(_.keys(obj), function(key){ return _.isFunction(obj[key]); }).sort();
+ };
+
+ # Extend a given object with all of the properties in a source object.
+ _.extend = function(destination, source) {
+ for (var property in source) destination[property] = source[property];
+ return destination;
+ };
+
+ # Create a (shallow-cloned) duplicate of an object.
+ _.clone = function(obj) {
+ if (_.isArray(obj)) return obj.slice(0);
+ return _.extend({}, obj);
+ };
+
+ # Perform a deep comparison to check if two objects are equal.
+ _.isEqual = function(a, b) {
+ # Check object identity.
+ if (a === b) return true;
+ # Different types?
+ var atype = typeof(a), btype = typeof(b);
+ if (atype != btype) return false;
+ # Basic equality test (watch out for coercions).
+ if (a == b) return true;
+ # One is falsy and the other truthy.
+ if ((!a && b) || (a && !b)) return false;
+ # One of them implements an isEqual()?
+ if (a.isEqual) return a.isEqual(b);
+ # Check dates' integer values.
+ if (_.isDate(a) && _.isDate(b)) return a.getTime() === b.getTime();
+ # Both are NaN?
+ if (_.isNaN(a) && _.isNaN(b)) return true;
+ # Compare regular expressions.
+ if (_.isRegExp(a) && _.isRegExp(b))
+ return a.source === b.source &&
+ a.global === b.global &&
+ a.ignoreCase === b.ignoreCase &&
+ a.multiline === b.multiline;
+ # If a is not an object by this point, we can't handle it.
+ if (atype !== 'object') return false;
+ # Check for different array lengths before comparing contents.
+ if (a.length && (a.length !== b.length)) return false;
+ # Nothing else worked, deep compare the contents.
+ var aKeys = _.keys(a), bKeys = _.keys(b);
+ # Different object sizes?
+ if (aKeys.length != bKeys.length) return false;
+ # Recursive comparison of contents.
+ for (var key in a) if (!_.isEqual(a[key], b[key])) return false;
+ return true;
+ };
+
+ # Is a given array or object empty?
+ _.isEmpty = function(obj) {
+ return _.keys(obj).length == 0;
+ };
+
+ # Is a given value a DOM element?
+ _.isElement = function(obj) {
+ return !!(obj && obj.nodeType == 1);
+ };
+
+ # Is a given variable an arguments object?
+ _.isArguments = function(obj) {
+ return obj && _.isNumber(obj.length) && !_.isArray(obj) && !propertyIsEnumerable.call(obj, 'length');
+ };
+
+ # Is the given value NaN -- this one is interesting. NaN != NaN, and
+ # isNaN(undefined) == true, so we make sure it's a number first.
+ _.isNaN = function(obj) {
+ return _.isNumber(obj) && isNaN(obj);
+ };
+
+ # Is a given value equal to null?
+ _.isNull = function(obj) {
+ return obj === null;
+ };
+
+ # Is a given variable undefined?
+ _.isUndefined = function(obj) {
+ return typeof obj == 'undefined';
+ };
+
+ # Invokes interceptor with the obj, and then returns obj.
+ # The primary purpose of this method is to "tap into" a method chain, in order to perform operations on intermediate results within the chain.
+ _.tap = function(obj, interceptor) {
+ interceptor(obj);
+ return obj;
+ }
+
+ # Define the isArray, isDate, isFunction, isNumber, isRegExp, and isString
+ # functions based on their toString identifiers.
+ var types = ['Array', 'Date', 'Function', 'Number', 'RegExp', 'String'];
+ for (var i=0, l=types.length; i<l; i++) {
+ (function() {
+ var identifier = '[object ' + types[i] + ']';
+ _['is' + types[i]] = function(obj) { return toString.call(obj) == identifier; };
+ })();
+ }
+
+ /* -------------------------- Utility Functions: -------------------------- */
+
+ # Run Underscore.js in noConflict mode, returning the '_' variable to its
+ # previous owner. Returns a reference to the Underscore object.
+ _.noConflict = function() {
+ root._ = previousUnderscore;
+ return this;
+ };
+
+ # Keep the identity function around for default iterators.
+ _.identity = function(value) {
+ return value;
+ };
+
+ # Break out of the middle of an iteration.
+ _.breakLoop = function() {
+ throw breaker;
+ };
+
+ # Generate a unique integer id (unique within the entire client session).
+ # Useful for temporary DOM ids.
+ var idCounter = 0;
+ _.uniqueId = function(prefix) {
+ var id = idCounter++;
+ return prefix ? prefix + id : id;
+ };
+
+ # JavaScript templating a-la ERB, pilfered from John Resig's
+ # "Secrets of the JavaScript Ninja", page 83.
+ _.template = function(str, data) {
+ var fn = new Function('obj',
+ 'var p=[],print=function(){p.push.apply(p,arguments);};' +
+ 'with(obj){p.push(\'' +
+ str
+ .replace(/[\r\t\n]/g, " ")
+ .split("<%").join("\t")
+ .replace(/((^|%>)[^\t]*)'/g, "$1\r")
+ .replace(/\t=(.*?)%>/g, "',$1,'")
+ .split("\t").join("');")
+ .split("%>").join("p.push('")
+ .split("\r").join("\\'")
+ + "');}return p.join('');");
+ return data ? fn(data) : fn;
+ };
+
+ /*------------------------------- Aliases ----------------------------------*/
+
+ _.forEach = _.each;
+ _.foldl = _.inject = _.reduce;
+ _.foldr = _.reduceRight;
+ _.filter = _.select;
+ _.every = _.all;
+ _.some = _.any;
+ _.head = _.first;
+ _.tail = _.rest;
+ _.methods = _.functions;
+
+ /*------------------------ Setup the OOP Wrapper: --------------------------*/
+
+ # Helper function to continue chaining intermediate results.
+ var result = function(obj, chain) {
+ return chain ? _(obj).chain() : obj;
+ };
+
+ # Add all of the Underscore functions to the wrapper object.
+ _.each(_.functions(_), function(name) {
+ var method = _[name];
+ wrapper.prototype[name] = function() {
+ unshift.call(arguments, this._wrapped);
+ return result(method.apply(_, arguments), this._chain);
+ };
+ });
+
+ # Add all mutator Array functions to the wrapper.
+ _.each(['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'], function(name) {
+ var method = Array.prototype[name];
+ wrapper.prototype[name] = function() {
+ method.apply(this._wrapped, arguments);
+ return result(this._wrapped, this._chain);
+ };
+ });
+
+ # Add all accessor Array functions to the wrapper.
+ _.each(['concat', 'join', 'slice'], function(name) {
+ var method = Array.prototype[name];
+ wrapper.prototype[name] = function() {
+ return result(method.apply(this._wrapped, arguments), this._chain);
+ };
+ });
+
+ # Start chaining a wrapped Underscore object.
+ wrapper.prototype.chain = function() {
+ this._chain = true;
+ return this;
+ };
+
+ # Extracts the result from a wrapped and chained object.
+ wrapper.prototype.value = function() {
+ return this._wrapped;
+ };
+
+()

7 comments on commit 8e9d637

Amr Tamimi

Oh my god! this is an epic commit!!
I know coffee was built initially on Ruby — but didn't know that the extension was .jaa! :laughing:

Jeremy Ashkenas
Owner

I know, so embarrassing ;) Didn't have any sort of name for the language, and the first three letters that popped into my head were initials.

ven
Collaborator

I knew about the ruby part, the syntax part, but I certainly didn't know about that extension either !

Michael Ficarra
Collaborator

I'm pretty glad we don't have an aint operator any longer.

题叶

Couldn't believe it was CoffeeScript:

sum: x, y => x + y.
David Chambers

I'm pretty glad we don't have an aint operator any longer.

say it aint so
Amr Tamimi

@jashkenas: here's a good guess for .jaa :wink:

%w(awesome artistic javascript).collect{|s| s[0]}.join.reverse
Please sign in to comment.
Something went wrong with that request. Please try again.