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
|