rubypeg 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- 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
|