rubypeg 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README +67 -0
- data/bin/text-peg2ruby-peg +24 -0
- data/examples/arithmetic/arithmetic_peg.rb +57 -0
- data/examples/arithmetic/arithmetic_peg.txt +9 -0
- data/examples/arithmetic/arithmetic_peg_spec.rb +49 -0
- data/examples/arithmetic/calculator.rb +40 -0
- data/examples/arithmetic/calculator_spec.rb +26 -0
- data/examples/excel/excel_peg.txt +35 -0
- data/examples/excel/excel_peg_spec.rb +139 -0
- data/lib/rubypeg.rb +313 -0
- data/lib/textpeg.rb +159 -0
- data/lib/textpeg.txt +29 -0
- data/lib/textpeg2rubypeg.rb +182 -0
- data/spec/any_character_spec.rb +22 -0
- data/spec/lookahead_spec.rb +101 -0
- data/spec/non_terminal_spec.rb +229 -0
- data/spec/peg_leg_spec.rb +63 -0
- data/spec/repetition_spec.rb +74 -0
- data/spec/sequence_spec.rb +50 -0
- data/spec/terminal_spec.rb +118 -0
- data/spec/text_peg2ruby_peg_spec.rb +302 -0
- data/spec/text_peg_spec.rb +123 -0
- data/spec/visit_spec.rb +67 -0
- metadata +95 -0
    
        data/README
    ADDED
    
    | @@ -0,0 +1,67 @@ | |
| 1 | 
            +
            = RubyPeg
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            RubyPeg helps you to create readable Parsing Expression Grammars (PEG) in ruby.
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            This software is (c) 2010 Green on Black Ltd and distributed under the open source MIT[http://www.opensource.org/licenses/mit-license.php] licence. (See LICENCE for the wording).
         | 
| 6 | 
            +
             | 
| 7 | 
            +
            If you like this code, employ us: http://www.greenonblack.com
         | 
| 8 | 
            +
             | 
| 9 | 
            +
            = An example
         | 
| 10 | 
            +
             | 
| 11 | 
            +
            class Arithmetic < RubyPeg
         | 
| 12 | 
            +
              
         | 
| 13 | 
            +
              def root
         | 
| 14 | 
            +
                arithmetic
         | 
| 15 | 
            +
              end
         | 
| 16 | 
            +
              
         | 
| 17 | 
            +
              def arithmetic
         | 
| 18 | 
            +
                node :arithmetic do
         | 
| 19 | 
            +
                  one_or_more { expression } && ignore { terminal(/\z/) }
         | 
| 20 | 
            +
                end
         | 
| 21 | 
            +
              end
         | 
| 22 | 
            +
              
         | 
| 23 | 
            +
              def expression
         | 
| 24 | 
            +
                subtraction || addition || division || multiplication || brackets || number
         | 
| 25 | 
            +
              end
         | 
| 26 | 
            +
              
         | 
| 27 | 
            +
              def brackets
         | 
| 28 | 
            +
                node :brackets do
         | 
| 29 | 
            +
                  ignore { terminal("(") } && spacing && expression && spacing && ignore { terminal(")") }
         | 
| 30 | 
            +
                end
         | 
| 31 | 
            +
              end
         | 
| 32 | 
            +
              
         | 
| 33 | 
            +
              def multiplication
         | 
| 34 | 
            +
                node :multiplication do
         | 
| 35 | 
            +
                  (brackets || number) && spacing && ignore { terminal("*") } && spacing && expression
         | 
| 36 | 
            +
                end
         | 
| 37 | 
            +
              end
         | 
| 38 | 
            +
              
         | 
| 39 | 
            +
              def division
         | 
| 40 | 
            +
                node :division do
         | 
| 41 | 
            +
                  (brackets || number) && spacing && ignore { terminal("/") } && spacing && expression
         | 
| 42 | 
            +
                end
         | 
| 43 | 
            +
              end
         | 
| 44 | 
            +
              
         | 
| 45 | 
            +
              def addition
         | 
| 46 | 
            +
                node :addition do
         | 
| 47 | 
            +
                  (brackets || number) && spacing && ignore { terminal("+") } && spacing && expression
         | 
| 48 | 
            +
                end
         | 
| 49 | 
            +
              end
         | 
| 50 | 
            +
              
         | 
| 51 | 
            +
              def subtraction
         | 
| 52 | 
            +
                node :subtraction do
         | 
| 53 | 
            +
                  (brackets || number) && spacing && ignore { terminal("-") } && spacing && expression
         | 
| 54 | 
            +
                end
         | 
| 55 | 
            +
              end
         | 
| 56 | 
            +
              
         | 
| 57 | 
            +
              def number
         | 
| 58 | 
            +
                terminal(/[-+]?[0-9]+\.?[0-9]*([eE][-+]?[0-9]+)?/)
         | 
| 59 | 
            +
              end
         | 
| 60 | 
            +
              
         | 
| 61 | 
            +
              def spacing
         | 
| 62 | 
            +
                ignore { terminal(/[ \t]*/) }
         | 
| 63 | 
            +
              end
         | 
| 64 | 
            +
              
         | 
| 65 | 
            +
            end
         | 
| 66 | 
            +
             | 
| 67 | 
            +
            Arithmetic.parse("(1+1)+2").to_ast # [:arithmetic,[:addition,[:brackets,[:addition,'1','1']],'2']]
         | 
| @@ -0,0 +1,24 @@ | |
| 1 | 
            +
            #!/usr/bin/env ruby
         | 
| 2 | 
            +
            require 'optparse'
         | 
| 3 | 
            +
             | 
| 4 | 
            +
            $LOAD_PATH.unshift(File.expand_path(File.dirname(__FILE__) + "/../lib"))
         | 
| 5 | 
            +
            require 'textpeg2rubypeg'
         | 
| 6 | 
            +
            require 'textpeg'
         | 
| 7 | 
            +
            require 'rubypeg'
         | 
| 8 | 
            +
             | 
| 9 | 
            +
            if ARGV[0]
         | 
| 10 | 
            +
              input = IO.readlines(ARGV[0]).join
         | 
| 11 | 
            +
              ruby = TextPeg2RubyPeg.new
         | 
| 12 | 
            +
              peg = TextPeg.parse(input)
         | 
| 13 | 
            +
              peg.visit(ruby)
         | 
| 14 | 
            +
              if ARGV[1]
         | 
| 15 | 
            +
                File.open(ARGV[1],'w') { |f| f.puts ruby.to_ruby }
         | 
| 16 | 
            +
              else
         | 
| 17 | 
            +
                $stdout.puts ruby.to_ruby
         | 
| 18 | 
            +
              end
         | 
| 19 | 
            +
            else
         | 
| 20 | 
            +
              $stdout.puts "Usage:   text-peg2ruby-peg [text-peg-input-filename] [ruby-peg-output-filename]"
         | 
| 21 | 
            +
              $stdout.puts "Help:    Compiles text format parsing expression grammars into a ruby parser."
         | 
| 22 | 
            +
              $stdout.puts "         See http://github.com/tamc/ruby-peg for more information."
         | 
| 23 | 
            +
              $stdout.puts "Version: 0.0.1"
         | 
| 24 | 
            +
            end
         | 
| @@ -0,0 +1,57 @@ | |
| 1 | 
            +
            require 'rubypeg'
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            class Arithmetic < RubyPeg
         | 
| 4 | 
            +
              
         | 
| 5 | 
            +
              def root
         | 
| 6 | 
            +
                arithmetic
         | 
| 7 | 
            +
              end
         | 
| 8 | 
            +
              
         | 
| 9 | 
            +
              def arithmetic
         | 
| 10 | 
            +
                node :arithmetic do
         | 
| 11 | 
            +
                  one_or_more { expression } && ignore { terminal(/\z/) }
         | 
| 12 | 
            +
                end
         | 
| 13 | 
            +
              end
         | 
| 14 | 
            +
              
         | 
| 15 | 
            +
              def expression
         | 
| 16 | 
            +
                subtraction || addition || division || multiplication || brackets || number
         | 
| 17 | 
            +
              end
         | 
| 18 | 
            +
              
         | 
| 19 | 
            +
              def brackets
         | 
| 20 | 
            +
                node :brackets do
         | 
| 21 | 
            +
                  ignore { terminal("(") } && spacing && expression && spacing && ignore { terminal(")") }
         | 
| 22 | 
            +
                end
         | 
| 23 | 
            +
              end
         | 
| 24 | 
            +
              
         | 
| 25 | 
            +
              def multiplication
         | 
| 26 | 
            +
                node :multiplication do
         | 
| 27 | 
            +
                  (brackets || number) && spacing && ignore { terminal("*") } && spacing && expression
         | 
| 28 | 
            +
                end
         | 
| 29 | 
            +
              end
         | 
| 30 | 
            +
              
         | 
| 31 | 
            +
              def division
         | 
| 32 | 
            +
                node :division do
         | 
| 33 | 
            +
                  (brackets || number) && spacing && ignore { terminal("/") } && spacing && expression
         | 
| 34 | 
            +
                end
         | 
| 35 | 
            +
              end
         | 
| 36 | 
            +
              
         | 
| 37 | 
            +
              def addition
         | 
| 38 | 
            +
                node :addition do
         | 
| 39 | 
            +
                  (brackets || number) && spacing && ignore { terminal("+") } && spacing && expression
         | 
| 40 | 
            +
                end
         | 
| 41 | 
            +
              end
         | 
| 42 | 
            +
              
         | 
| 43 | 
            +
              def subtraction
         | 
| 44 | 
            +
                node :subtraction do
         | 
| 45 | 
            +
                  (brackets || number) && spacing && ignore { terminal("-") } && spacing && expression
         | 
| 46 | 
            +
                end
         | 
| 47 | 
            +
              end
         | 
| 48 | 
            +
              
         | 
| 49 | 
            +
              def number
         | 
| 50 | 
            +
                terminal(/[-+]?[0-9]+\.?[0-9]*([eE][-+]?[0-9]+)?/)
         | 
| 51 | 
            +
              end
         | 
| 52 | 
            +
              
         | 
| 53 | 
            +
              def spacing
         | 
| 54 | 
            +
                ignore { terminal(/[ \t]*/) }
         | 
| 55 | 
            +
              end
         | 
| 56 | 
            +
              
         | 
| 57 | 
            +
            end
         | 
| @@ -0,0 +1,9 @@ | |
| 1 | 
            +
            arithmetic      := expression+ `/\z/
         | 
| 2 | 
            +
            expression       = subtraction | addition | division | multiplication | brackets | number
         | 
| 3 | 
            +
            brackets        := `"(" spacing expression spacing `")"
         | 
| 4 | 
            +
            multiplication  := (brackets | number ) spacing `'*' spacing expression
         | 
| 5 | 
            +
            division        := (brackets | number ) spacing `'/' spacing expression
         | 
| 6 | 
            +
            addition        := (brackets | number ) spacing `'+' spacing expression
         | 
| 7 | 
            +
            subtraction     := (brackets | number ) spacing `'-' spacing expression
         | 
| 8 | 
            +
            number           = /[-+]?[0-9]+\.?[0-9]*([eE][-+]?[0-9]+)?/
         | 
| 9 | 
            +
            spacing          = `/[ \t]*/
         | 
| @@ -0,0 +1,49 @@ | |
| 1 | 
            +
            $:.unshift File.join(File.dirname(__FILE__), *%w[.])
         | 
| 2 | 
            +
            $:.unshift File.join(File.dirname(__FILE__), *%w[.. .. lib])
         | 
| 3 | 
            +
            require 'rubypeg'
         | 
| 4 | 
            +
            require 'arithmetic_peg'
         | 
| 5 | 
            +
             | 
| 6 | 
            +
            describe Arithmetic do
         | 
| 7 | 
            +
              
         | 
| 8 | 
            +
              def check(text)
         | 
| 9 | 
            +
                puts
         | 
| 10 | 
            +
                e = Arithmetic.new
         | 
| 11 | 
            +
                e.parse(text)
         | 
| 12 | 
            +
                e.pretty_print_cache
         | 
| 13 | 
            +
                puts
         | 
| 14 | 
            +
              end
         | 
| 15 | 
            +
              
         | 
| 16 | 
            +
              it "parses decimal numbers, including those in scientific notation" do
         | 
| 17 | 
            +
                Arithmetic.parse("1").to_ast.should == [:arithmetic,'1']
         | 
| 18 | 
            +
                Arithmetic.parse("103.287").to_ast.should == [:arithmetic,'103.287']
         | 
| 19 | 
            +
                Arithmetic.parse("-1.0E-27").to_ast.should == [:arithmetic,'-1.0E-27']
         | 
| 20 | 
            +
              end
         | 
| 21 | 
            +
              
         | 
| 22 | 
            +
              it "parses sums of decimal numbers" do
         | 
| 23 | 
            +
                Arithmetic.parse("1+1").to_ast.should == [:arithmetic,[:addition,'1','1']]
         | 
| 24 | 
            +
              end
         | 
| 25 | 
            +
              
         | 
| 26 | 
            +
              it "parses series of sums" do
         | 
| 27 | 
            +
                Arithmetic.parse("1+1+2").to_ast.should == [:arithmetic,[:addition,'1',[:addition,'1','2']]]
         | 
| 28 | 
            +
              end
         | 
| 29 | 
            +
              
         | 
| 30 | 
            +
              it "parses a series of sums with brackets" do
         | 
| 31 | 
            +
                Arithmetic.parse("(1+1)+2").to_ast.should == [:arithmetic,[:addition,[:brackets,[:addition,'1','1']],'2']]
         | 
| 32 | 
            +
                Arithmetic.parse("1+(1+2)").to_ast.should == [:arithmetic,[:addition,'1',[:brackets,[:addition,'1','2']]]]
         | 
| 33 | 
            +
                Arithmetic.parse("(1+1)+(1+2)").to_ast.should == [:arithmetic,[:addition,[:brackets,[:addition,'1','1']],[:brackets,[:addition,'1','2']]]]
         | 
| 34 | 
            +
                Arithmetic.parse("((1+1)+(1+2))").to_ast.should == [:arithmetic,[:brackets,[:addition,[:brackets,[:addition,'1','1']],[:brackets,[:addition,'1','2']]]]]
         | 
| 35 | 
            +
              end
         | 
| 36 | 
            +
              
         | 
| 37 | 
            +
              it "parses subtractions" do
         | 
| 38 | 
            +
                Arithmetic.parse("1-1").to_ast.should == [:arithmetic,[:subtraction,'1','1']]
         | 
| 39 | 
            +
              end
         | 
| 40 | 
            +
              
         | 
| 41 | 
            +
              it "parses multiplication" do
         | 
| 42 | 
            +
                Arithmetic.parse("1*1").to_ast.should == [:arithmetic,[:multiplication,'1','1']]
         | 
| 43 | 
            +
              end
         | 
| 44 | 
            +
              
         | 
| 45 | 
            +
              it "parses division" do
         | 
| 46 | 
            +
                Arithmetic.parse("1/1").to_ast.should == [:arithmetic,[:division,'1','1']]
         | 
| 47 | 
            +
              end
         | 
| 48 | 
            +
             | 
| 49 | 
            +
            end
         | 
| @@ -0,0 +1,40 @@ | |
| 1 | 
            +
            $:.unshift File.join(File.dirname(__FILE__), *%w[.. .. lib])
         | 
| 2 | 
            +
            $:.unshift File.join(File.dirname(__FILE__), *%w[.])
         | 
| 3 | 
            +
            require 'rubypeg'
         | 
| 4 | 
            +
            require 'arithmetic_peg'
         | 
| 5 | 
            +
             | 
| 6 | 
            +
            module TerminalNode
         | 
| 7 | 
            +
              def build(builder)
         | 
| 8 | 
            +
                self.to_f
         | 
| 9 | 
            +
              end
         | 
| 10 | 
            +
            end
         | 
| 11 | 
            +
             | 
| 12 | 
            +
            class CalculationEngine
         | 
| 13 | 
            +
              
         | 
| 14 | 
            +
              def addition(left,right)
         | 
| 15 | 
            +
                left.build(self) + right.build(self)
         | 
| 16 | 
            +
              end
         | 
| 17 | 
            +
              
         | 
| 18 | 
            +
              def subtraction(left,right)
         | 
| 19 | 
            +
                left.build(self) - right.build(self)
         | 
| 20 | 
            +
              end
         | 
| 21 | 
            +
              
         | 
| 22 | 
            +
              def multiplication(left,right)
         | 
| 23 | 
            +
                left.build(self) * right.build(self)
         | 
| 24 | 
            +
              end
         | 
| 25 | 
            +
              
         | 
| 26 | 
            +
              def division(left,right)
         | 
| 27 | 
            +
                left.build(self) / right.build(self)    
         | 
| 28 | 
            +
              end
         | 
| 29 | 
            +
              
         | 
| 30 | 
            +
            end
         | 
| 31 | 
            +
             | 
| 32 | 
            +
            class Calculator
         | 
| 33 | 
            +
              
         | 
| 34 | 
            +
              def self.calculate(sum)
         | 
| 35 | 
            +
                ast = Arithmetic.parse(sum)
         | 
| 36 | 
            +
                answer = ast.build(CalculationEngine.new)
         | 
| 37 | 
            +
                answer
         | 
| 38 | 
            +
              end
         | 
| 39 | 
            +
              
         | 
| 40 | 
            +
            end
         | 
| @@ -0,0 +1,26 @@ | |
| 1 | 
            +
            $:.unshift File.join(File.dirname(__FILE__), *%w[.])
         | 
| 2 | 
            +
            require 'calculator'
         | 
| 3 | 
            +
             | 
| 4 | 
            +
            describe Calculator do
         | 
| 5 | 
            +
             | 
| 6 | 
            +
              it "should know that 1 + 1 = 2.0" do
         | 
| 7 | 
            +
                Calculator.calculate("1+1").should == 2.0
         | 
| 8 | 
            +
              end
         | 
| 9 | 
            +
              
         | 
| 10 | 
            +
              it "should know that 5.0 - 1.3 = 3.7" do
         | 
| 11 | 
            +
                Calculator.calculate("5.0 - 1.3").should == 3.7
         | 
| 12 | 
            +
              end
         | 
| 13 | 
            +
             | 
| 14 | 
            +
              it "should know that -12.3e-27 * 5 =  6.15e-26" do
         | 
| 15 | 
            +
                Calculator.calculate("-12.3e-27*5").should == -6.15e-26
         | 
| 16 | 
            +
              end
         | 
| 17 | 
            +
             | 
| 18 | 
            +
              it "should know that 1000/10 =  100" do
         | 
| 19 | 
            +
                Calculator.calculate("1000/10").should == 100
         | 
| 20 | 
            +
              end
         | 
| 21 | 
            +
              
         | 
| 22 | 
            +
              it "should know that (1+3)*(8*2) = 64" do
         | 
| 23 | 
            +
                Calculator.calculate("(1+3)*(8*2)").should == 64
         | 
| 24 | 
            +
              end
         | 
| 25 | 
            +
              
         | 
| 26 | 
            +
            end
         | 
| @@ -0,0 +1,35 @@ | |
| 1 | 
            +
            formula                         := expression+
         | 
| 2 | 
            +
            expression                       = string_join | arithmetic | comparison | thing
         | 
| 3 | 
            +
            thing                            = function | brackets | string | any_reference | percentage | number | boolean | named_reference | prefix
         | 
| 4 | 
            +
            function                        := /[A-Z]+/ `'(' expression? (`',' expression)* `')'
         | 
| 5 | 
            +
            brackets                        := `'(' expression `')'
         | 
| 6 | 
            +
            string_join                     := thing (`"&" thing)+
         | 
| 7 | 
            +
            arithmetic                      := thing (operator thing)+
         | 
| 8 | 
            +
            comparison                      := thing comparator thing
         | 
| 9 | 
            +
            comparator                      := '>=' | '<=' | '<>' | '>' | '<' | '='
         | 
| 10 | 
            +
            string                          := `'"' /[^"]*/ `'"'
         | 
| 11 | 
            +
            any_reference                    =  table_reference | quoted_sheet_reference | sheet_reference | sheetless_reference
         | 
| 12 | 
            +
            percentage                      := /[-+]?[0-9]+\.?[0-9]*/ `'%'
         | 
| 13 | 
            +
            number                          := /[-+]?[0-9]+\.?[0-9]*([eE][-+]?[0-9]+)?/
         | 
| 14 | 
            +
            operator                        := '+' | '-' | '/' | '*' | '^'
         | 
| 15 | 
            +
            table_reference                  = qualified_table_reference | local_table_reference
         | 
| 16 | 
            +
            qualified_table_reference       := /[a-zA-Z0-9]+/ table_column
         | 
| 17 | 
            +
            local_table_reference           := table_column
         | 
| 18 | 
            +
            table_column                     = `'[' /[^\u005d]*/ `']'
         | 
| 19 | 
            +
            named_reference                 := /[a-zA-Z][\w_.]+/
         | 
| 20 | 
            +
            quoted_sheet_reference          := single_quoted_string `'!' sheetless_reference
         | 
| 21 | 
            +
            sheet_reference                 := /[a-zA-Z][\w_]+/ `'!' sheetless_reference
         | 
| 22 | 
            +
            single_quoted_string             = `"'" /[^']*/ `"'"
         | 
| 23 | 
            +
            sheetless_reference              = column_range | row_range | area | cell
         | 
| 24 | 
            +
            column_range                    := column `':' column
         | 
| 25 | 
            +
            row_range                       := row `':' row
         | 
| 26 | 
            +
            area                            := reference `':' reference
         | 
| 27 | 
            +
            cell                            := reference
         | 
| 28 | 
            +
            row                              = /\$?\d+/
         | 
| 29 | 
            +
            column                           = /\$?[A-Z]+/
         | 
| 30 | 
            +
            reference                        = /\$?[A-Z]+\$?[0-9]+/
         | 
| 31 | 
            +
            boolean                          = boolean_true | boolean_false
         | 
| 32 | 
            +
            boolean_true                    := `'TRUE'
         | 
| 33 | 
            +
            boolean_false                   := `'FALSE'
         | 
| 34 | 
            +
            prefix                          := /[-+]/
         | 
| 35 | 
            +
             | 
| @@ -0,0 +1,139 @@ | |
| 1 | 
            +
            $:.unshift File.join(File.dirname(__FILE__), *%w[.])
         | 
| 2 | 
            +
            $:.unshift File.join(File.dirname(__FILE__), *%w[.. .. lib])
         | 
| 3 | 
            +
            require 'textpeg2rubypeg'
         | 
| 4 | 
            +
            text_peg = IO.readlines(File.join(File.dirname(__FILE__),'excel_peg.txt')).join
         | 
| 5 | 
            +
            ast = TextPeg.parse(text_peg)
         | 
| 6 | 
            +
            # puts ast.to_ast
         | 
| 7 | 
            +
            # exit
         | 
| 8 | 
            +
            builder = TextPeg2RubyPeg.new
         | 
| 9 | 
            +
            ruby = ast.build(builder)
         | 
| 10 | 
            +
            Kernel.eval(ruby)
         | 
| 11 | 
            +
             | 
| 12 | 
            +
            describe Formula do
         | 
| 13 | 
            +
              
         | 
| 14 | 
            +
              def check(text)
         | 
| 15 | 
            +
                puts
         | 
| 16 | 
            +
                e = Formula.new
         | 
| 17 | 
            +
                e.parse(text)
         | 
| 18 | 
            +
                e.pretty_print_cache
         | 
| 19 | 
            +
                puts
         | 
| 20 | 
            +
              end
         | 
| 21 | 
            +
              
         | 
| 22 | 
            +
              it "returns formulas" do
         | 
| 23 | 
            +
                Formula.parse('1+1').to_ast.first.should == :formula
         | 
| 24 | 
            +
              end
         | 
| 25 | 
            +
              
         | 
| 26 | 
            +
              it "returns cells" do
         | 
| 27 | 
            +
                Formula.parse('$A$1').to_ast.should == [:formula,[:cell,'$A$1']]
         | 
| 28 | 
            +
                Formula.parse('A1').to_ast.should == [:formula,[:cell,'A1']]    
         | 
| 29 | 
            +
                Formula.parse('$A1').to_ast.should == [:formula,[:cell,'$A1']]    
         | 
| 30 | 
            +
                Formula.parse('A$1').to_ast.should == [:formula,[:cell,'A$1']]    
         | 
| 31 | 
            +
                Formula.parse('AAA1123').to_ast.should == [:formula,[:cell,'AAA1123']]
         | 
| 32 | 
            +
              end
         | 
| 33 | 
            +
              
         | 
| 34 | 
            +
              it "returns areas" do
         | 
| 35 | 
            +
                Formula.parse('$A$1:$Z$1').to_ast.should == [:formula,[:area,'$A$1','$Z$1']]
         | 
| 36 | 
            +
                Formula.parse('A1:$Z$1').to_ast.should == [:formula,[:area,'A1','$Z$1']]    
         | 
| 37 | 
            +
              end
         | 
| 38 | 
            +
              
         | 
| 39 | 
            +
              it "returns row ranges" do
         | 
| 40 | 
            +
                Formula.parse('$1:$1000').to_ast.should == [:formula,[:row_range,'$1','$1000']]
         | 
| 41 | 
            +
                Formula.parse('1000:1').to_ast.should == [:formula,[:row_range,'1000','1']]    
         | 
| 42 | 
            +
              end
         | 
| 43 | 
            +
              
         | 
| 44 | 
            +
              it "returns column ranges" do
         | 
| 45 | 
            +
                Formula.parse('$C:$AZ').to_ast.should == [:formula,[:column_range,'$C','$AZ']]
         | 
| 46 | 
            +
                Formula.parse('C:AZ').to_ast.should == [:formula,[:column_range,'C','AZ']]    
         | 
| 47 | 
            +
              end
         | 
| 48 | 
            +
              
         | 
| 49 | 
            +
              it "returns references to other sheets" do
         | 
| 50 | 
            +
                Formula.parse('sheet1!$A$1').to_ast.should == [:formula,[:sheet_reference,'sheet1',[:cell,'$A$1']]]    
         | 
| 51 | 
            +
                Formula.parse('sheet1!$A$1:$Z$1').to_ast.should == [:formula,[:sheet_reference,'sheet1',[:area,'$A$1','$Z$1']]]
         | 
| 52 | 
            +
                Formula.parse('sheet1!$1:$1000').to_ast.should == [:formula,[:sheet_reference,'sheet1',[:row_range,'$1','$1000']]]
         | 
| 53 | 
            +
                Formula.parse('sheet1!$C:$AZ').to_ast.should == [:formula,[:sheet_reference,'sheet1',[:column_range,'$C','$AZ']]]
         | 
| 54 | 
            +
              end
         | 
| 55 | 
            +
              
         | 
| 56 | 
            +
              it "returns references to other sheets with extended names" do
         | 
| 57 | 
            +
                Formula.parse("'sheet 1'!$A$1").to_ast.should == [:formula,[:quoted_sheet_reference,'sheet 1',[:cell,'$A$1']]]    
         | 
| 58 | 
            +
                Formula.parse("'sheet 1'!$A$1:$Z$1").to_ast.should == [:formula,[:quoted_sheet_reference,'sheet 1',[:area,'$A$1','$Z$1']]]
         | 
| 59 | 
            +
                Formula.parse("'sheet 1'!$1:$1000").to_ast.should == [:formula,[:quoted_sheet_reference,'sheet 1',[:row_range,'$1','$1000']]]
         | 
| 60 | 
            +
                Formula.parse("'sheet 1'!$C:$AZ").to_ast.should == [:formula,[:quoted_sheet_reference,'sheet 1',[:column_range,'$C','$AZ']]]
         | 
| 61 | 
            +
              end
         | 
| 62 | 
            +
              
         | 
| 63 | 
            +
              it "returns numbers" do
         | 
| 64 | 
            +
                Formula.parse("1").to_ast.should == [:formula,[:number,'1']]
         | 
| 65 | 
            +
                Formula.parse("103.287").to_ast.should == [:formula,[:number,'103.287']]
         | 
| 66 | 
            +
                Formula.parse("-1.0E-27").to_ast.should == [:formula,[:number,'-1.0E-27']]
         | 
| 67 | 
            +
              end
         | 
| 68 | 
            +
             | 
| 69 | 
            +
              it "returns percentages" do
         | 
| 70 | 
            +
                Formula.parse("1%").to_ast.should == [:formula,[:percentage,'1']]
         | 
| 71 | 
            +
                Formula.parse("103.287%").to_ast.should == [:formula,[:percentage,'103.287']]
         | 
| 72 | 
            +
                Formula.parse("-1.0%").to_ast.should == [:formula,[:percentage,'-1.0']]
         | 
| 73 | 
            +
              end
         | 
| 74 | 
            +
              
         | 
| 75 | 
            +
              it "returns strings" do
         | 
| 76 | 
            +
                Formula.parse('"A handy string"').to_ast.should == [:formula,[:string,"A handy string"]]
         | 
| 77 | 
            +
                Formula.parse('"$A$1"').to_ast.should == [:formula,[:string,"$A$1"]]  
         | 
| 78 | 
            +
              end
         | 
| 79 | 
            +
              
         | 
| 80 | 
            +
              it "returns string joins" do
         | 
| 81 | 
            +
                Formula.parse('"A handy string"&$A$1').to_ast.should == [:formula,[:string_join,[:string,"A handy string"],[:cell,'$A$1']]]
         | 
| 82 | 
            +
                Formula.parse('$A$1&"A handy string"').to_ast.should == [:formula,[:string_join,[:cell,'$A$1'],[:string,"A handy string"]]]
         | 
| 83 | 
            +
                Formula.parse('$A$1&"A handy string"&$A$1').to_ast.should == [:formula,[:string_join,[:cell,'$A$1'],[:string,"A handy string"],[:cell,'$A$1'],]]
         | 
| 84 | 
            +
                Formula.parse('$A$1&$A$1&$A$1').to_ast.should == [:formula,[:string_join,[:cell,'$A$1'],[:cell,'$A$1'],[:cell,'$A$1'],]]
         | 
| 85 | 
            +
                Formula.parse('"GW"&ISERR($AA$1)').to_ast.should == [:formula,[:string_join,[:string,'GW'],[:function,'ISERR',[:cell,'$AA$1']]]]
         | 
| 86 | 
            +
              end
         | 
| 87 | 
            +
              
         | 
| 88 | 
            +
              it "returns numeric operations" do
         | 
| 89 | 
            +
                Formula.parse('$A$1+$A$2+1').to_ast.should == [:formula,[:arithmetic,[:cell,'$A$1'],[:operator,"+"],[:cell,'$A$2'],[:operator,"+"],[:number,'1']]]
         | 
| 90 | 
            +
                Formula.parse('$A$1-$A$2-1').to_ast.should == [:formula,[:arithmetic,[:cell,'$A$1'],[:operator,"-"],[:cell,'$A$2'],[:operator,"-"],[:number,'1']]]
         | 
| 91 | 
            +
                Formula.parse('$A$1*$A$2*1').to_ast.should == [:formula,[:arithmetic,[:cell,'$A$1'],[:operator,"*"],[:cell,'$A$2'],[:operator,"*"],[:number,'1']]]
         | 
| 92 | 
            +
                Formula.parse('$A$1/$A$2/1').to_ast.should == [:formula,[:arithmetic,[:cell,'$A$1'],[:operator,"/"],[:cell,'$A$2'],[:operator,"/"],[:number,'1']]            ]
         | 
| 93 | 
            +
                Formula.parse('$A$1^$A$2^1').to_ast.should == [:formula,[:arithmetic,[:cell,'$A$1'],[:operator,"^"],[:cell,'$A$2'],[:operator,"^"],[:number,'1']]]
         | 
| 94 | 
            +
              end
         | 
| 95 | 
            +
              
         | 
| 96 | 
            +
              it "returns expressions in brackets" do
         | 
| 97 | 
            +
                Formula.parse('($A$1+$A$2)').to_ast.should == [:formula,[:brackets,[:arithmetic,[:cell,'$A$1'],[:operator,"+"],[:cell,'$A$2']]]]
         | 
| 98 | 
            +
                Formula.parse('($A$1+$A$2)+2').to_ast.should == [:formula, [:arithmetic, [:brackets, [:arithmetic, [:cell,'$A$1'], [:operator,"+"], [:cell,'$A$2']]], [:operator,"+"], [:number,'2']]]
         | 
| 99 | 
            +
                Formula.parse('($A$1+$A$2)+(2+(1*2))').to_ast.should == [:formula, [:arithmetic, [:brackets, [:arithmetic, [:cell,'$A$1'], [:operator,"+"], [:cell,'$A$2']]], [:operator,"+"], [:brackets, [:arithmetic, [:number,'2'], [:operator,'+'] ,[:brackets, [:arithmetic, [:number,'1'], [:operator,'*'], [:number,'2']]]]]]]  
         | 
| 100 | 
            +
              end
         | 
| 101 | 
            +
              
         | 
| 102 | 
            +
              it "returns comparisons" do
         | 
| 103 | 
            +
                Formula.parse('$A$1>$A$2').to_ast.should  == [:formula,[:comparison,[:cell,'$A$1'],[:comparator,">"],[:cell,'$A$2']]]
         | 
| 104 | 
            +
                Formula.parse('$A$1<$A$2').to_ast.should  == [:formula,[:comparison,[:cell,'$A$1'],[:comparator,"<"],[:cell,'$A$2']]]
         | 
| 105 | 
            +
                Formula.parse('$A$1=$A$2').to_ast.should  == [:formula,[:comparison,[:cell,'$A$1'],[:comparator,"="],[:cell,'$A$2']]]
         | 
| 106 | 
            +
                Formula.parse('$A$1>=$A$2').to_ast.should == [:formula,[:comparison,[:cell,'$A$1'],[:comparator,">="],[:cell,'$A$2']]]
         | 
| 107 | 
            +
                Formula.parse('$A$1<=$A$2').to_ast.should == [:formula,[:comparison,[:cell,'$A$1'],[:comparator,"<="],[:cell,'$A$2']]]
         | 
| 108 | 
            +
                Formula.parse('$A$1<>$A$2').to_ast.should == [:formula,[:comparison,[:cell,'$A$1'],[:comparator,"<>"],[:cell,'$A$2']]]
         | 
| 109 | 
            +
              end
         | 
| 110 | 
            +
              
         | 
| 111 | 
            +
              it "returns functions" do
         | 
| 112 | 
            +
                Formula.parse('PI()').to_ast.should  == [:formula,[:function,'PI']]
         | 
| 113 | 
            +
                Formula.parse('ERR($A$1)').to_ast.should  == [:formula,[:function,'ERR',[:cell,'$A$1']]]
         | 
| 114 | 
            +
                Formula.parse('SUM($A$1,sheet1!$1:$1000,1)').to_ast.should  == [:formula,[:function,'SUM',[:cell,'$A$1'],[:sheet_reference,'sheet1',[:row_range,'$1','$1000']],[:number,'1']]]
         | 
| 115 | 
            +
              end
         | 
| 116 | 
            +
              
         | 
| 117 | 
            +
              it "returns fully qualified structured references (i.e., Table[column])" do
         | 
| 118 | 
            +
                Formula.parse('DeptSales[Sale Amount]').to_ast.should  == [:formula,[:qualified_table_reference,'DeptSales','Sale Amount']]
         | 
| 119 | 
            +
                #Formula.parse("DeptSales[Sale'] Amount]").to_ast.should  == [:formula,[:qualified_table_reference,'DeptSales','Sale Amount']]
         | 
| 120 | 
            +
              end
         | 
| 121 | 
            +
              
         | 
| 122 | 
            +
              it "returns booleans" do
         | 
| 123 | 
            +
                Formula.parse("TRUE*FALSE").to_ast.should == [:formula,[:arithmetic,[:boolean_true],[:operator,'*'],[:boolean_false]]]
         | 
| 124 | 
            +
              end
         | 
| 125 | 
            +
              
         | 
| 126 | 
            +
              it "returns prefixes (+/-)" do
         | 
| 127 | 
            +
                Formula.parse("-(3-1)").to_ast.should == [:formula,[:prefix,'-'],[:brackets,[:arithmetic,[:number,'3'],[:operator,'-'],[:number,'1']]]]
         | 
| 128 | 
            +
              end
         | 
| 129 | 
            +
              
         | 
| 130 | 
            +
              it "returns local structured references (i.e., [column])" do
         | 
| 131 | 
            +
                Formula.parse('[Sale Amount]').to_ast.should  == [:formula,[:local_table_reference,'Sale Amount']]
         | 
| 132 | 
            +
                #Formula.parse("DeptSales[Sale'] Amount]").to_ast.should  == [:formula,[:qualified_table_reference,'DeptSales','Sale Amount']]
         | 
| 133 | 
            +
              end
         | 
| 134 | 
            +
              
         | 
| 135 | 
            +
              it "returns named references" do
         | 
| 136 | 
            +
                Formula.parse('EF.NaturalGas.N2O').to_ast.should == [:formula,[:named_reference,'EF.NaturalGas.N2O']]
         | 
| 137 | 
            +
              end
         | 
| 138 | 
            +
              
         | 
| 139 | 
            +
            end
         |