activefacts 0.8.9 → 0.8.10
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/.gemtest +0 -0
- data/Manifest.txt +28 -33
- data/Rakefile +11 -12
- data/bin/cql +90 -46
- data/examples/CQL/Blog.cql +2 -1
- data/examples/CQL/CompanyDirectorEmployee.cql +2 -2
- data/examples/CQL/Death.cql +1 -1
- data/examples/CQL/Diplomacy.cql +9 -9
- data/examples/CQL/Genealogy.cql +3 -2
- data/examples/CQL/Insurance.cql +10 -7
- data/examples/CQL/JoinEquality.cql +2 -2
- data/examples/CQL/Marriage.cql +1 -1
- data/examples/CQL/Metamodel.cql +73 -53
- data/examples/CQL/MetamodelNext.cql +89 -67
- data/examples/CQL/OneToOnes.cql +2 -2
- data/examples/CQL/ServiceDirector.cql +10 -5
- data/examples/CQL/Supervision.cql +3 -3
- data/examples/CQL/Tests.Test5.Load.cql +1 -1
- data/examples/CQL/Warehousing.cql +4 -2
- data/lib/activefacts/cql/CQLParser.treetop +26 -60
- data/lib/activefacts/cql/Context.treetop +12 -2
- data/lib/activefacts/cql/Expressions.treetop +14 -30
- data/lib/activefacts/cql/FactTypes.treetop +165 -110
- data/lib/activefacts/cql/Language/English.treetop +167 -54
- data/lib/activefacts/cql/LexicalRules.treetop +16 -2
- data/lib/activefacts/cql/{Concepts.treetop → ObjectTypes.treetop} +36 -37
- data/lib/activefacts/cql/Terms.treetop +57 -27
- data/lib/activefacts/cql/ValueTypes.treetop +39 -13
- data/lib/activefacts/cql/compiler.rb +5 -3
- data/lib/activefacts/cql/compiler/{reading.rb → clause.rb} +407 -285
- data/lib/activefacts/cql/compiler/constraint.rb +178 -275
- data/lib/activefacts/cql/compiler/entity_type.rb +73 -64
- data/lib/activefacts/cql/compiler/expression.rb +418 -0
- data/lib/activefacts/cql/compiler/fact.rb +146 -145
- data/lib/activefacts/cql/compiler/fact_type.rb +197 -80
- data/lib/activefacts/cql/compiler/join.rb +159 -0
- data/lib/activefacts/cql/compiler/shared.rb +51 -23
- data/lib/activefacts/cql/compiler/value_type.rb +56 -2
- data/lib/activefacts/cql/parser.rb +15 -4
- data/lib/activefacts/generate/absorption.rb +7 -7
- data/lib/activefacts/generate/cql.rb +100 -37
- data/lib/activefacts/generate/oo.rb +28 -51
- data/lib/activefacts/generate/ordered.rb +60 -36
- data/lib/activefacts/generate/ruby.rb +6 -6
- data/lib/activefacts/generate/sql/server.rb +4 -4
- data/lib/activefacts/input/orm.rb +71 -53
- data/lib/activefacts/persistence.rb +1 -1
- data/lib/activefacts/persistence/columns.rb +27 -23
- data/lib/activefacts/persistence/foreignkey.rb +6 -6
- data/lib/activefacts/persistence/index.rb +17 -17
- data/lib/activefacts/persistence/{concept.rb → object_type.rb} +9 -9
- data/lib/activefacts/persistence/reference.rb +61 -36
- data/lib/activefacts/persistence/tables.rb +61 -59
- data/lib/activefacts/support.rb +54 -29
- data/lib/activefacts/version.rb +1 -1
- data/lib/activefacts/vocabulary/extensions.rb +99 -54
- data/lib/activefacts/vocabulary/metamodel.rb +43 -37
- data/lib/activefacts/vocabulary/verbaliser.rb +134 -109
- data/spec/absorption_spec.rb +8 -8
- data/spec/cql/comparison_spec.rb +91 -0
- data/spec/cql/contractions_spec.rb +251 -0
- data/spec/cql/entity_type_spec.rb +319 -0
- data/spec/cql/expressions_spec.rb +63 -0
- data/spec/cql/fact_type_matching_spec.rb +283 -0
- data/spec/cql/french_spec.rb +21 -0
- data/spec/cql/parser/bad_literals_spec.rb +86 -0
- data/spec/cql/parser/constraints_spec.rb +19 -0
- data/spec/cql/parser/entity_types_spec.rb +106 -0
- data/spec/cql/parser/expressions_spec.rb +179 -0
- data/spec/cql/parser/fact_types_spec.rb +41 -0
- data/spec/cql/parser/literals_spec.rb +312 -0
- data/spec/cql/parser/pragmas_spec.rb +89 -0
- data/spec/cql/parser/value_types_spec.rb +42 -0
- data/spec/cql/role_matching_spec.rb +147 -0
- data/spec/cql/samples_spec.rb +9 -9
- data/spec/cql_cql_spec.rb +1 -1
- data/spec/cql_dm_spec.rb +116 -0
- data/spec/cql_mysql_spec.rb +1 -1
- data/spec/cql_ruby_spec.rb +1 -1
- data/spec/cql_sql_spec.rb +3 -3
- data/spec/cql_symbol_tables_spec.rb +30 -30
- data/spec/cqldump_spec.rb +4 -4
- data/spec/helpers/array_matcher.rb +32 -27
- data/spec/helpers/diff_matcher.rb +6 -26
- data/spec/helpers/file_matcher.rb +41 -32
- data/spec/helpers/parse_to_ast_matcher.rb +76 -0
- data/spec/helpers/string_matcher.rb +32 -31
- data/spec/norma_cql_spec.rb +1 -1
- data/spec/norma_ruby_spec.rb +1 -1
- data/spec/norma_ruby_sql_spec.rb +1 -1
- data/spec/norma_sql_spec.rb +3 -1
- data/spec/norma_tables_spec.rb +1 -1
- data/spec/ruby_api_spec.rb +23 -0
- data/spec/spec_helper.rb +5 -4
- metadata +66 -66
- data/examples/CQL/OrienteeringER.cql +0 -58
- data/lib/activefacts/api.rb +0 -44
- data/lib/activefacts/api/concept.rb +0 -410
- data/lib/activefacts/api/constellation.rb +0 -128
- data/lib/activefacts/api/entity.rb +0 -256
- data/lib/activefacts/api/instance.rb +0 -60
- data/lib/activefacts/api/instance_index.rb +0 -80
- data/lib/activefacts/api/numeric.rb +0 -167
- data/lib/activefacts/api/role.rb +0 -80
- data/lib/activefacts/api/role_proxy.rb +0 -70
- data/lib/activefacts/api/role_values.rb +0 -117
- data/lib/activefacts/api/standard_types.rb +0 -87
- data/lib/activefacts/api/support.rb +0 -65
- data/lib/activefacts/api/value.rb +0 -135
- data/lib/activefacts/api/vocabulary.rb +0 -82
- data/spec/api/autocounter.rb +0 -82
- data/spec/api/constellation.rb +0 -130
- data/spec/api/entity_type.rb +0 -103
- data/spec/api/instance.rb +0 -461
- data/spec/api/roles.rb +0 -124
- data/spec/api/value_type.rb +0 -112
- data/spec/api_spec.rb +0 -13
- data/spec/cql/matching_spec.rb +0 -517
- data/spec/cql/unit_spec.rb +0 -394
- data/spec/spec.opts +0 -1
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
#
|
|
2
|
+
# ActiveFacts tests: Test the CQL parser by looking at its parse trees.
|
|
3
|
+
# Copyright (c) 2008 Clifford Heath. Read the LICENSE file.
|
|
4
|
+
#
|
|
5
|
+
|
|
6
|
+
require 'activefacts/cql'
|
|
7
|
+
require 'activefacts/support'
|
|
8
|
+
require 'activefacts/api/support'
|
|
9
|
+
require 'spec_helper'
|
|
10
|
+
require 'helpers/test_parser'
|
|
11
|
+
|
|
12
|
+
describe "ASTs from Derived Fact Types with expressions" do
|
|
13
|
+
it "should parse a simple comparison clause" do
|
|
14
|
+
%q{
|
|
15
|
+
each combination FamilyName, GivenName occurs at most one time in Competitor has FamilyName, Competitor has GivenName;
|
|
16
|
+
}.should parse_to_ast \
|
|
17
|
+
"PresenceConstraint over [[{Competitor} \"has\" {FamilyName}], [{Competitor} \"has\" {GivenName}]] -1 over ({FamilyName}, {GivenName})"
|
|
18
|
+
end
|
|
19
|
+
end
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
#
|
|
2
|
+
# ActiveFacts tests: Test the CQL parser by looking at its parse trees.
|
|
3
|
+
# Copyright (c) 2008 Clifford Heath. Read the LICENSE file.
|
|
4
|
+
#
|
|
5
|
+
|
|
6
|
+
require 'activefacts/cql'
|
|
7
|
+
require 'activefacts/support'
|
|
8
|
+
require 'activefacts/api/support'
|
|
9
|
+
require 'helpers/test_parser'
|
|
10
|
+
|
|
11
|
+
describe "Entity Types" do
|
|
12
|
+
EntityTypes_RefMode = [
|
|
13
|
+
[ "a is identified by its id;", # Entity type declaration with reference mode
|
|
14
|
+
["EntityType: a identified by its id;"]
|
|
15
|
+
],
|
|
16
|
+
[ "a is identified by its number(12);", # Entity type declaration with reference mode
|
|
17
|
+
["EntityType: a identified by its number(12);"]
|
|
18
|
+
],
|
|
19
|
+
[ "a is identified by its id where c;", # Entity type declaration with reference mode and fact type(s)
|
|
20
|
+
["EntityType: a identified by its id where [{c}];"]
|
|
21
|
+
],
|
|
22
|
+
[ "a is identified by its id where c;", # Entity type declaration with reference mode and where
|
|
23
|
+
["EntityType: a identified by its id where [{c}];"]
|
|
24
|
+
],
|
|
25
|
+
]
|
|
26
|
+
|
|
27
|
+
EntityTypes_Simple = [
|
|
28
|
+
[ "a is identified by b where c;", # Entity type declaration
|
|
29
|
+
["EntityType: a [{b}] where [{c}];"]
|
|
30
|
+
],
|
|
31
|
+
[ "a is identified by b where c;", # Entity type declaration with where
|
|
32
|
+
["EntityType: a [{b}] where [{c}];"]
|
|
33
|
+
],
|
|
34
|
+
[ "a is identified by b and c where d;", # Entity type declaration with two-part identifier
|
|
35
|
+
["EntityType: a [{b}, {c}] where [\"d\"];"]
|
|
36
|
+
],
|
|
37
|
+
[ "a is identified by b, c where d;", # Entity type declaration with two-part identifier
|
|
38
|
+
["EntityType: a [{b}, {c}] where [\"d\"];"]
|
|
39
|
+
],
|
|
40
|
+
[ "a is written as b(); e is identified by a where d;",
|
|
41
|
+
["ValueType: a is written as b;", "EntityType: e [{a}] where [\"d\"];"]
|
|
42
|
+
],
|
|
43
|
+
[ " a is written as b ( ) ; e is identified by a where d ; ",
|
|
44
|
+
["ValueType: a is written as b;", "EntityType: e [{a}] where [\"d\"];"]
|
|
45
|
+
],
|
|
46
|
+
[ "e is written as b; a is identified by e where maybe d;",
|
|
47
|
+
["ValueType: e is written as b;", "EntityType: a [{e}] where [[\"maybe\"] \"d\"];"]
|
|
48
|
+
],
|
|
49
|
+
]
|
|
50
|
+
|
|
51
|
+
EntityTypes_Objectified = [
|
|
52
|
+
[ "Director is where b directs c, c is directed by b;",
|
|
53
|
+
["FactType: Director [{b} \"directs\" {c}, {c} \"is directed by\" {b}]"]
|
|
54
|
+
],
|
|
55
|
+
]
|
|
56
|
+
|
|
57
|
+
EntityTypes_Subtypes = [
|
|
58
|
+
[ "Employee is a kind of Person;",
|
|
59
|
+
["EntityType: Employee < Person nil;"]
|
|
60
|
+
],
|
|
61
|
+
[ "Employee is a subtype of Person;",
|
|
62
|
+
["EntityType: Employee < Person nil;"]
|
|
63
|
+
],
|
|
64
|
+
[ "AustralianEmployee is a subtype of Employee, Australian;",
|
|
65
|
+
["EntityType: AustralianEmployee < Employee,Australian nil;"]
|
|
66
|
+
],
|
|
67
|
+
[ "Employee is a kind of Person identified by EmployeeNumber;",
|
|
68
|
+
["EntityType: Employee < Person [{EmployeeNumber}];"]
|
|
69
|
+
],
|
|
70
|
+
[ "Employee is a subtype of Person identified by EmployeeNumber;",
|
|
71
|
+
["EntityType: Employee < Person [{EmployeeNumber}];"]
|
|
72
|
+
],
|
|
73
|
+
[ "AustralianEmployee is a subtype of Employee, Australian identified by TaxFileNumber;",
|
|
74
|
+
["EntityType: AustralianEmployee < Employee,Australian [{TaxFileNumber}];"]
|
|
75
|
+
],
|
|
76
|
+
]
|
|
77
|
+
|
|
78
|
+
EntityTypes =
|
|
79
|
+
EntityTypes_RefMode +
|
|
80
|
+
EntityTypes_Simple +
|
|
81
|
+
EntityTypes_Objectified +
|
|
82
|
+
EntityTypes_Subtypes
|
|
83
|
+
|
|
84
|
+
before :each do
|
|
85
|
+
@parser = TestParser.new
|
|
86
|
+
@parser.parse_all("c is written as b;", :definition)
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
EntityTypes.each do |c|
|
|
90
|
+
source, ast = *c
|
|
91
|
+
it "should parse #{source.inspect}" do
|
|
92
|
+
result = @parser.parse_all(source, :definition)
|
|
93
|
+
|
|
94
|
+
puts @parser.failure_reason unless result
|
|
95
|
+
result.should_not be_nil
|
|
96
|
+
|
|
97
|
+
canonical_form = result.map{|d| d.ast.to_s}
|
|
98
|
+
if ast
|
|
99
|
+
canonical_form.should == ast
|
|
100
|
+
else
|
|
101
|
+
puts "#{source.inspect} should compile to"
|
|
102
|
+
puts "\t#{canonical_form}"
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
end
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
#
|
|
2
|
+
# ActiveFacts tests: Test the CQL parser by looking at its parse trees.
|
|
3
|
+
# Copyright (c) 2008 Clifford Heath. Read the LICENSE file.
|
|
4
|
+
#
|
|
5
|
+
|
|
6
|
+
require 'activefacts/cql'
|
|
7
|
+
require 'activefacts/support'
|
|
8
|
+
require 'activefacts/api/support'
|
|
9
|
+
require 'spec_helper'
|
|
10
|
+
require 'helpers/test_parser'
|
|
11
|
+
|
|
12
|
+
describe "ASTs from Derived Fact Types with expressions" do
|
|
13
|
+
it "should parse a simple comparison clause" do
|
|
14
|
+
# Director is old: Company is directed by Person who is of Age > 60;
|
|
15
|
+
%q{
|
|
16
|
+
Director is old: Person directs Company, Person is of Age, Age > 60;
|
|
17
|
+
}.should parse_to_ast \
|
|
18
|
+
%q{FactType: [{Director} "is old"] where {Person} "directs" {Company} ,
|
|
19
|
+
{Person} "is of" {Age} ,
|
|
20
|
+
compare>({Age} 60)}
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
it "should parse a comparison clause with subscripts" do
|
|
24
|
+
%q{
|
|
25
|
+
Director is old: Person directs Company, Person has Salary(2), Person is of Age(1), Age(1) > Salary(2);
|
|
26
|
+
}.should parse_to_ast \
|
|
27
|
+
%q{
|
|
28
|
+
FactType: [{Director} "is old"]
|
|
29
|
+
where {Person} "directs" {Company} ,
|
|
30
|
+
{Person} "has" {Salary(2)} ,
|
|
31
|
+
{Person} "is of" {Age(1)} ,
|
|
32
|
+
compare>({Age(1)} {Salary(2)})
|
|
33
|
+
}
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
it "should parse simple comparison clause having an unmarked adjective" do
|
|
37
|
+
%q{
|
|
38
|
+
Person is independent: Person has taxable- Income and taxable Income >= 20000 dollars or Person has sugar-Daddy;
|
|
39
|
+
}.should parse_to_ast \
|
|
40
|
+
%q{FactType: [{Person} "is independent"] where {Person} "has" {taxable- Income} and
|
|
41
|
+
compare>=({taxable- Income} (20000 in dollars)) or {Person} "has" {sugar- Daddy}}
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
it "should parse a reading with a contracted comparison expression" do
|
|
45
|
+
%q{
|
|
46
|
+
Director is old: Person directs company, Person is of Age > 20+2*20;
|
|
47
|
+
}.should parse_to_ast \
|
|
48
|
+
%q{FactType: [{Director} "is old"] where {Person} "directs company" ,
|
|
49
|
+
{Person} "is of" {Age}
|
|
50
|
+
> compare>({Age} sum(20 product(2 20)))}
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
it "should parse a right-contracted comparison clause after a right-contracted clause" do
|
|
54
|
+
%q{
|
|
55
|
+
Director is old: Company is directed by Person who is of Age > 60;
|
|
56
|
+
}.should parse_to_ast \
|
|
57
|
+
%q{FactType: [{Director} "is old"] where {Company} "is directed by" {Person} who
|
|
58
|
+
{Person} "is of" {Age} >
|
|
59
|
+
compare>({Age} 60)}
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
it "should parse a simple reading with qualifiers" do
|
|
63
|
+
%q{
|
|
64
|
+
Person(1) is ancestor of Person(2): maybe Person(1) is parent of Person(2) [transitive];
|
|
65
|
+
}.should parse_to_ast \
|
|
66
|
+
%q{FactType: [{Person(1)} "is ancestor of" {Person(2)}] where
|
|
67
|
+
["maybe", "transitive"] {Person(1)} "is parent of" {Person(2)}}
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
it "should parse a contracted reading with qualifiers" do
|
|
71
|
+
%q{
|
|
72
|
+
Person(1) provides lineage of Person(2): maybe Person(2) is child of Person(1) [transitive] who is male;
|
|
73
|
+
}.should parse_to_ast \
|
|
74
|
+
%q{FactType: [{Person(1)} "provides lineage of" {Person(2)}] where
|
|
75
|
+
["maybe", "transitive"] {Person(2)} "is child of" {Person(1)}
|
|
76
|
+
who {Person(1)} "is male"}
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
it "should parse a contracted readings and comparisons with qualifiers" do
|
|
80
|
+
%q{
|
|
81
|
+
Person(1) is ancestor of adult Person(2):
|
|
82
|
+
maybe Person(1) is parent of Person(2) [transitive]
|
|
83
|
+
who maybe is of Age [static]
|
|
84
|
+
definitely >= 21;
|
|
85
|
+
}.should parse_to_ast \
|
|
86
|
+
%q{FactType: [{Person(1)} "is ancestor of adult" {Person(2)}] where
|
|
87
|
+
["maybe", "transitive"] {Person(1)} "is parent of" {Person(2)}
|
|
88
|
+
who ["maybe", "static"] {Person(2)} "is of" {Age}
|
|
89
|
+
>= compare>=({Age} 21, [definitely])}
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
it "should parse a comparison expression with a contracted reading" do
|
|
93
|
+
%q{
|
|
94
|
+
Director is old: Person directs company, 3*30 >= Age that is of Person;
|
|
95
|
+
}.should parse_to_ast \
|
|
96
|
+
%q{FactType: [{Director} "is old"] where {Person} "directs company" ,
|
|
97
|
+
compare>=(product(3 30) {Age})
|
|
98
|
+
that {Age} "is of" {Person}}
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
it "should parse a comparison expression with a contracted comparison" do
|
|
102
|
+
%q{
|
|
103
|
+
Director is old: Person directs company, Person is of Age, maybe 20 <= Age definitely < 60;
|
|
104
|
+
}.should parse_to_ast \
|
|
105
|
+
%q{FactType: [{Director} "is old"] where {Person} "directs company" ,
|
|
106
|
+
{Person} "is of" {Age} ,
|
|
107
|
+
compare<=(20 {Age}, [maybe])
|
|
108
|
+
< compare<({Age} 60, [definitely])}
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
it "should parse a comparison expression with right-contracted then left-contracted comparisons"
|
|
112
|
+
# Director is probably adult: Person directs company, Person is of Age maybe >= 21 and definitely < 60;
|
|
113
|
+
# end
|
|
114
|
+
|
|
115
|
+
it "should fail to parse a contracted comparison that doesn't follow a role" do
|
|
116
|
+
%q{
|
|
117
|
+
Director is old: Person directs company, Person is of Age considerable > 3*20;
|
|
118
|
+
}.should fail_to_parse /Expected (.|\n)* after (.|\n)* Age considerable $/
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
it "should parse pre and post-qualifiers and leading and trailing adjectives with contracted comparisons" do
|
|
122
|
+
%q{
|
|
123
|
+
A is a farce: maybe A has completely- B [transitive, acyclic] < 5, B -c = 2;
|
|
124
|
+
}.should parse_to_ast \
|
|
125
|
+
%q{FactType: [{A} "is a farce"] where ["acyclic", "maybe", "transitive"] {A} "has" {completely- B}
|
|
126
|
+
< compare<({completely- B} 5)
|
|
127
|
+
, compare=({B -c} 2)}
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
it "should parse multiple leading and trailing adjectives with contracted comparisons" do
|
|
131
|
+
%q{
|
|
132
|
+
A is a farce: maybe A has completely- green B [transitive, acyclic] < 9, B c -d = 2;
|
|
133
|
+
}.should parse_to_ast \
|
|
134
|
+
%q{FactType: [{A} "is a farce"] where ["acyclic", "maybe", "transitive"] {A} "has" {completely- green B}
|
|
135
|
+
< compare<({completely- green B} 9)
|
|
136
|
+
, compare=({B c -d} 2)}
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
it "should parse a comparison clause containing units" do
|
|
140
|
+
%q{
|
|
141
|
+
254 mm converts to foot/feet;
|
|
142
|
+
Width is written as Integer mm;
|
|
143
|
+
Window requires toughening where
|
|
144
|
+
Window has Width,
|
|
145
|
+
Window has Height,
|
|
146
|
+
Width * Height >= 10 feet^2;
|
|
147
|
+
}.should parse_to_ast \
|
|
148
|
+
%q{Unit(foot/feet) is 254/1+0 mm^1},
|
|
149
|
+
%q{ValueType: Width is written as Integer in [["mm", 1]];},
|
|
150
|
+
%q{FactType: [{Window} "requires toughening"] where {Window} "has" {Width} ,
|
|
151
|
+
{Window} "has" {Height}
|
|
152
|
+
, compare>=(product({Width} {Height}) (10 in feet^2))}
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
it "should parse nested expressions" do
|
|
156
|
+
%q{
|
|
157
|
+
A is written as B;
|
|
158
|
+
A > B+3*(4+5)?
|
|
159
|
+
}.should parse_to_ast \
|
|
160
|
+
%q{ValueType: A is written as B;},
|
|
161
|
+
%q{FactType: [] where compare>({A} sum({B} product(3 sum(4 5))))}
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
it "should parse a fact type containing an expression with subscripts"
|
|
165
|
+
|
|
166
|
+
it "should parse a fact type containing objectification joins and contractions" do
|
|
167
|
+
%q{
|
|
168
|
+
Driving was negligent where
|
|
169
|
+
Driving (where maybe Driver drove in Incident [acyclic] that definitely is of Claim [intransitive]) followed Intoxication [static];
|
|
170
|
+
}.should parse_to_ast \
|
|
171
|
+
%q{
|
|
172
|
+
FactType: [{Driving} "was negligent"] where ["static"] {Driving}
|
|
173
|
+
(where ["acyclic", "maybe"] {Driver} "drove in" {Incident}
|
|
174
|
+
that ["definitely", "intransitive"] {Incident} "is of" {Claim})
|
|
175
|
+
"followed" {Intoxication}
|
|
176
|
+
}
|
|
177
|
+
end
|
|
178
|
+
|
|
179
|
+
end
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
#
|
|
2
|
+
# ActiveFacts tests: Test the CQL parser by looking at its parse trees.
|
|
3
|
+
# Copyright (c) 2008 Clifford Heath. Read the LICENSE file.
|
|
4
|
+
#
|
|
5
|
+
|
|
6
|
+
require 'activefacts/cql'
|
|
7
|
+
require 'activefacts/support'
|
|
8
|
+
require 'activefacts/api/support'
|
|
9
|
+
require 'spec_helper'
|
|
10
|
+
require 'helpers/test_parser'
|
|
11
|
+
|
|
12
|
+
describe "Fact Types" do
|
|
13
|
+
FactTypes = [
|
|
14
|
+
[ "Foo has at most one Bar, Bar is of one Foo restricted to {1..10};",
|
|
15
|
+
["FactType: [{Foo} \"has\" {[..1] Bar}, {Bar} \"is of\" {[1..1] Foo ValueConstraint to ([1..10])}]"]
|
|
16
|
+
],
|
|
17
|
+
[ "Bar(1) is related to Bar(2), primary-Bar(1) has secondary-Bar(2);",
|
|
18
|
+
["FactType: [{Bar(1)} \"is related to\" {Bar(2)}, {primary- Bar(1)} \"has\" {secondary- Bar(2)}]"]
|
|
19
|
+
],
|
|
20
|
+
# REVISIT: Test all quantifiers
|
|
21
|
+
# REVISIT: Test all post-qualifiers
|
|
22
|
+
# [ "AnnualIncome is where Person has total- Income in Year: Person has total- Income.sum(), Income was earned in current- Time.Year() (as Year);",
|
|
23
|
+
# [%q{FactType: AnnualIncome [{Person} "has" {total- Income} "in" {Year}] where {Person} "has" {total- Income}.sum() , {Income} "was earned in" {current- Time (as Year)}.Year()}]
|
|
24
|
+
# ],
|
|
25
|
+
[ "A is interesting : b- C has F -g;",
|
|
26
|
+
["FactType: [{A} \"is interesting\"] where {b- C} \"has\" {F -g}"]
|
|
27
|
+
]
|
|
28
|
+
# REVISIT: Test all quantifiers
|
|
29
|
+
]
|
|
30
|
+
|
|
31
|
+
before :each do
|
|
32
|
+
@parser = TestParser.new
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
FactTypes.each do |c|
|
|
36
|
+
source, ast, definition = *c
|
|
37
|
+
it "should parse #{source.inspect}" do
|
|
38
|
+
source.should parse_to_ast *ast
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
@@ -0,0 +1,312 @@
|
|
|
1
|
+
#
|
|
2
|
+
# ActiveFacts tests: Test the CQL parser by looking at its parse trees.
|
|
3
|
+
# Copyright (c) 2008 Clifford Heath. Read the LICENSE file.
|
|
4
|
+
#
|
|
5
|
+
|
|
6
|
+
require 'activefacts/cql'
|
|
7
|
+
require 'activefacts/support'
|
|
8
|
+
require 'activefacts/api/support'
|
|
9
|
+
require 'helpers/test_parser'
|
|
10
|
+
|
|
11
|
+
describe "Valid Numbers, Strings and Ranges" do
|
|
12
|
+
ValidNumbersEtc = [
|
|
13
|
+
[ "a is written as b;", # Value type declaration, no params, minimal whitespace
|
|
14
|
+
['ValueType: a is written as b;']
|
|
15
|
+
],
|
|
16
|
+
[ "a is written as B;", # Value type declaration, no params, minimal whitespace
|
|
17
|
+
['ValueType: a is written as B;']
|
|
18
|
+
],
|
|
19
|
+
[ "a is written as b();", # Value type declaration, minimal whitespace
|
|
20
|
+
['ValueType: a is written as b;']
|
|
21
|
+
],
|
|
22
|
+
[ "a is written as b ;", # Value type declaration, no params, trailing whitespace
|
|
23
|
+
['ValueType: a is written as b;']
|
|
24
|
+
],
|
|
25
|
+
[ "a is written as b ( ) ; ", # Value type declaration, maximal whitespace
|
|
26
|
+
['ValueType: a is written as b;']
|
|
27
|
+
],
|
|
28
|
+
|
|
29
|
+
# Comments and newlines, etc as whitespace
|
|
30
|
+
[ "\na\nis written as \nb\n(\n)\n;\n", # Basic value type declaration, newlines for whitespace
|
|
31
|
+
['ValueType: a is written as b;']
|
|
32
|
+
],
|
|
33
|
+
[ "\ra\ris written as\rb\r(\r)\r;\r", # Basic value type declaration, returns for whitespace
|
|
34
|
+
['ValueType: a is written as b;']
|
|
35
|
+
],
|
|
36
|
+
[ "\ta\tis written as\tb\t(\t)\t;\t", # Basic value type declaration, tabs for whitespace
|
|
37
|
+
['ValueType: a is written as b;']
|
|
38
|
+
],
|
|
39
|
+
[ " /* Plugh */ a /* Plugh */ is written as\n b /* *Plugh* / */ ( /* *Plugh* / */ ) /* *Plugh* / */ ; /* *Plugh* / */ ",
|
|
40
|
+
['ValueType: a is written as b;']
|
|
41
|
+
],
|
|
42
|
+
[ "//Plugh\na // Plugh\n is written as // Plugh\n b // Plugh\n ( // Plugh\n ) // Plugh\n ; // Plugh\n ",
|
|
43
|
+
['ValueType: a is written as b;']
|
|
44
|
+
],
|
|
45
|
+
|
|
46
|
+
# Integers
|
|
47
|
+
[ "a is written as b(0);", # Integer zero
|
|
48
|
+
['ValueType: a is written as b(0);']
|
|
49
|
+
],
|
|
50
|
+
[ "a is written as b( 0 ) ; ", # Integer zero, maximal whitespace
|
|
51
|
+
['ValueType: a is written as b(0);']
|
|
52
|
+
],
|
|
53
|
+
[ "a is written as b(1);", # Integer one
|
|
54
|
+
['ValueType: a is written as b(1);']
|
|
55
|
+
],
|
|
56
|
+
[ "a is written as b(-1);", # Integer negative one
|
|
57
|
+
['ValueType: a is written as b(-1);']
|
|
58
|
+
],
|
|
59
|
+
[ "a is written as b(+1);", # Positive integer
|
|
60
|
+
['ValueType: a is written as b(1);']
|
|
61
|
+
],
|
|
62
|
+
[ "a is written as b(1e4);", # Integer with exponent
|
|
63
|
+
['ValueType: a is written as b(10000.0);']
|
|
64
|
+
],
|
|
65
|
+
[ "a is written as b(1e-4);", # Integer with negative exponent
|
|
66
|
+
['ValueType: a is written as b(0.0001);']
|
|
67
|
+
],
|
|
68
|
+
[ "a is written as b(-1e-4);", # Negative integer with negative exponent
|
|
69
|
+
['ValueType: a is written as b(-0.0001);']
|
|
70
|
+
],
|
|
71
|
+
[ "a is written as b(077);", # Octal integer
|
|
72
|
+
['ValueType: a is written as b(63);']
|
|
73
|
+
],
|
|
74
|
+
[ "a is written as b(0xFace8);", # Hexadecimal integer
|
|
75
|
+
['ValueType: a is written as b(1027304);']
|
|
76
|
+
],
|
|
77
|
+
[ "a is written as b(0,1);", # Two parameters
|
|
78
|
+
['ValueType: a is written as b(0, 1);']
|
|
79
|
+
],
|
|
80
|
+
[ "a is written as b( 0 , 1 );",
|
|
81
|
+
['ValueType: a is written as b(0, 1);']
|
|
82
|
+
],
|
|
83
|
+
[ "a is written as b(0,1,2) ;", # Three parameters now allowed
|
|
84
|
+
['ValueType: a is written as b(0, 1, 2);']
|
|
85
|
+
],
|
|
86
|
+
|
|
87
|
+
# Reals
|
|
88
|
+
[ "a is written as b(1.0);",
|
|
89
|
+
['ValueType: a is written as b(1.0);']
|
|
90
|
+
],
|
|
91
|
+
[ "a is written as b(-1.0);",
|
|
92
|
+
['ValueType: a is written as b(-1.0);']
|
|
93
|
+
],
|
|
94
|
+
[ "a is written as b(+1.0);",
|
|
95
|
+
['ValueType: a is written as b(1.0);']
|
|
96
|
+
],
|
|
97
|
+
[ "a is written as b(0.1);",
|
|
98
|
+
['ValueType: a is written as b(0.1);']
|
|
99
|
+
],
|
|
100
|
+
[ "a is written as b(-0.1);",
|
|
101
|
+
['ValueType: a is written as b(-0.1);']
|
|
102
|
+
],
|
|
103
|
+
[ "a is written as b(+0.1);",
|
|
104
|
+
['ValueType: a is written as b(0.1);']
|
|
105
|
+
],
|
|
106
|
+
[ "a is written as b(0.0);",
|
|
107
|
+
['ValueType: a is written as b(0.0);']
|
|
108
|
+
],
|
|
109
|
+
[ "a is written as b(-0.0);",
|
|
110
|
+
['ValueType: a is written as b(-0.0);']
|
|
111
|
+
],
|
|
112
|
+
[ "a is written as b(+0.0);",
|
|
113
|
+
['ValueType: a is written as b(0.0);']
|
|
114
|
+
],
|
|
115
|
+
|
|
116
|
+
# Value types with units
|
|
117
|
+
[ "a is written as b inch;", # Value type declaration with unit
|
|
118
|
+
['ValueType: a is written as b in [["inch", 1]];']
|
|
119
|
+
],
|
|
120
|
+
[ "a is written as b() inch ; ", # Value type declaration with unit and whitespace
|
|
121
|
+
['ValueType: a is written as b in [["inch", 1]];']
|
|
122
|
+
],
|
|
123
|
+
[ "a is written as b() inch;", # Value type declaration with unit
|
|
124
|
+
['ValueType: a is written as b in [["inch", 1]];']
|
|
125
|
+
],
|
|
126
|
+
[ "a is written as b inch^2;", # Value type declaration with unit and exponent
|
|
127
|
+
['ValueType: a is written as b in [["inch", 2]];']
|
|
128
|
+
],
|
|
129
|
+
[ "a is written as b() inch^2 ; ", # Value type declaration with unit and exponent with maximum whitespace
|
|
130
|
+
['ValueType: a is written as b in [["inch", 2]];']
|
|
131
|
+
],
|
|
132
|
+
[ "a is written as b second^-1;", # Value type declaration with unit and negative exponent
|
|
133
|
+
['ValueType: a is written as b in [["second", -1]];']
|
|
134
|
+
],
|
|
135
|
+
[ "a is written as b inch inch;", # Value type declaration with repeated unit
|
|
136
|
+
['ValueType: a is written as b in [["inch", 1], ["inch", 1]];']
|
|
137
|
+
],
|
|
138
|
+
[ "a is written as b inch^2/minute^-1;", # Value type declaration with unit and divided unit with exponents
|
|
139
|
+
['ValueType: a is written as b in [["inch", 2], ["minute", 1]];']
|
|
140
|
+
],
|
|
141
|
+
[ "a is written as b() second^-1/mm^-1 mm^-1;", # Value type declaration with repeated divided unit
|
|
142
|
+
['ValueType: a is written as b in [["second", -1], ["mm", 1], ["mm", 1]];']
|
|
143
|
+
],
|
|
144
|
+
|
|
145
|
+
# Integer value constraints
|
|
146
|
+
[ "a is written as b()restricted to{1};", # Integer, minimal whitespace
|
|
147
|
+
['ValueType: a is written as b ValueConstraint to ([1]);']
|
|
148
|
+
],
|
|
149
|
+
[ "a is written as b() restricted to { 1 } ;", # Integer, maximal whitespace
|
|
150
|
+
['ValueType: a is written as b ValueConstraint to ([1]);']
|
|
151
|
+
],
|
|
152
|
+
[ "a is written as b() restricted to {1..2};", # Integer range, minimal whitespace
|
|
153
|
+
['ValueType: a is written as b ValueConstraint to ([1..2]);']
|
|
154
|
+
],
|
|
155
|
+
[ "a is written as b() restricted to { 1 .. 2 };", # Integer range, maximal whitespace
|
|
156
|
+
['ValueType: a is written as b ValueConstraint to ([1..2]);']
|
|
157
|
+
],
|
|
158
|
+
[ "a is written as b() restricted to {..2};", # Integer range with open start, minimal whitespace
|
|
159
|
+
['ValueType: a is written as b ValueConstraint to ([-Infinity..2]);']
|
|
160
|
+
],
|
|
161
|
+
[ "a is written as b() restricted to { .. 2 };", # Integer range with open start, maximal whitespace
|
|
162
|
+
['ValueType: a is written as b ValueConstraint to ([-Infinity..2]);']
|
|
163
|
+
],
|
|
164
|
+
[ "a is written as b() restricted to { ..2,3};", # Range followed by integer, minimal whitespace
|
|
165
|
+
['ValueType: a is written as b ValueConstraint to ([-Infinity..2, 3]);']
|
|
166
|
+
],
|
|
167
|
+
[ "a is written as b() restricted to { 1,..2,3};", # Integer, open-start range, integer, minimal whitespace
|
|
168
|
+
['ValueType: a is written as b ValueConstraint to ([1, -Infinity..2, 3]);']
|
|
169
|
+
],
|
|
170
|
+
[ "a is written as b() restricted to { .. 2 , 3 };", # Range followed by integer, maximal whitespace
|
|
171
|
+
['ValueType: a is written as b ValueConstraint to ([-Infinity..2, 3]);']
|
|
172
|
+
],
|
|
173
|
+
[ "a is written as b() restricted to { ..2 , 3..4 };",# Range followed by range
|
|
174
|
+
['ValueType: a is written as b ValueConstraint to ([-Infinity..2, 3..4]);']
|
|
175
|
+
],
|
|
176
|
+
[ "a is written as b() restricted to { ..2, 3..};", # Range followed by range with open end, minimal whitespace
|
|
177
|
+
['ValueType: a is written as b ValueConstraint to ([-Infinity..2, 3..Infinity]);']
|
|
178
|
+
],
|
|
179
|
+
[ "a is written as b() restricted to { ..2, 3 .. };", # Range followed by range with open end, maximal whitespace
|
|
180
|
+
['ValueType: a is written as b ValueConstraint to ([-Infinity..2, 3..Infinity]);']
|
|
181
|
+
],
|
|
182
|
+
[ "a is written as b() restricted to { 1e4 } ;", # Integer with exponent
|
|
183
|
+
['ValueType: a is written as b ValueConstraint to ([10000.0]);']
|
|
184
|
+
],
|
|
185
|
+
[ "a is written as b() restricted to { -1e4 } ;", # Negative integer with exponent
|
|
186
|
+
['ValueType: a is written as b ValueConstraint to ([-10000.0]);']
|
|
187
|
+
],
|
|
188
|
+
[ "a is written as b() restricted to { 1e-4 } ;", # Integer with negative exponent
|
|
189
|
+
['ValueType: a is written as b ValueConstraint to ([0.0001]);']
|
|
190
|
+
],
|
|
191
|
+
[ "a is written as b() restricted to { -1e-4 } ;", # Negative integer with negative exponent
|
|
192
|
+
['ValueType: a is written as b ValueConstraint to ([-0.0001]);']
|
|
193
|
+
],
|
|
194
|
+
|
|
195
|
+
# Real value constraints
|
|
196
|
+
[ "a is written as b() restricted to {1.0};", # Real, minimal whitespace
|
|
197
|
+
['ValueType: a is written as b ValueConstraint to ([1.0]);']
|
|
198
|
+
],
|
|
199
|
+
[ "a is written as b() restricted to { 1.0 } ;", # Real, maximal whitespace
|
|
200
|
+
['ValueType: a is written as b ValueConstraint to ([1.0]);']
|
|
201
|
+
],
|
|
202
|
+
[ "a is written as b() restricted to { 1.0e4 } ;", # Real with exponent
|
|
203
|
+
['ValueType: a is written as b ValueConstraint to ([10000.0]);']
|
|
204
|
+
],
|
|
205
|
+
[ "a is written as b() restricted to { 1.0e-4 } ;", # Real with negative exponent
|
|
206
|
+
['ValueType: a is written as b ValueConstraint to ([0.0001]);']
|
|
207
|
+
],
|
|
208
|
+
[ "a is written as b() restricted to { -1.0e-4 } ;", # Negative real with negative exponent
|
|
209
|
+
['ValueType: a is written as b ValueConstraint to ([-0.0001]);']
|
|
210
|
+
],
|
|
211
|
+
[ "a is written as b() restricted to { 1.1 .. 2.2 } ;", # Real range, maximal whitespace
|
|
212
|
+
['ValueType: a is written as b ValueConstraint to ([1.1..2.2]);']
|
|
213
|
+
],
|
|
214
|
+
[ "a is written as b() restricted to { -1.1 .. 2.2 } ;", # Real range, maximal whitespace
|
|
215
|
+
['ValueType: a is written as b ValueConstraint to ([-1.1..2.2]);']
|
|
216
|
+
],
|
|
217
|
+
[ "a is written as b() restricted to { 1.1..2.2};", # Real range, minimal whitespace
|
|
218
|
+
['ValueType: a is written as b ValueConstraint to ([1.1..2.2]);']
|
|
219
|
+
],
|
|
220
|
+
[ "a is written as b() restricted to { 1.1..2 } ;", # Real-integer range
|
|
221
|
+
['ValueType: a is written as b ValueConstraint to ([1.1..2]);']
|
|
222
|
+
],
|
|
223
|
+
[ "a is written as b() restricted to { 1..2.2 } ;", # Integer-real range
|
|
224
|
+
['ValueType: a is written as b ValueConstraint to ([1..2.2]);']
|
|
225
|
+
],
|
|
226
|
+
[ "a is written as b() restricted to { ..2.2};", # Real range with open start
|
|
227
|
+
['ValueType: a is written as b ValueConstraint to ([-Infinity..2.2]);']
|
|
228
|
+
],
|
|
229
|
+
[ "a is written as b() restricted to { 1.1.. };", # Real range with open end
|
|
230
|
+
['ValueType: a is written as b ValueConstraint to ([1.1..Infinity]);']
|
|
231
|
+
],
|
|
232
|
+
[ "a is written as b() restricted to { 1.1.., 2 };", # Real range with open end and following integer
|
|
233
|
+
['ValueType: a is written as b ValueConstraint to ([1.1..Infinity, 2]);']
|
|
234
|
+
],
|
|
235
|
+
|
|
236
|
+
# Strings and string value constraints
|
|
237
|
+
[ "a is written as b() restricted to {''};", # String, empty, minimal whitespace
|
|
238
|
+
['ValueType: a is written as b ValueConstraint to (["\'\'"]);']
|
|
239
|
+
],
|
|
240
|
+
[ "a is written as b() restricted to {'A'};", # String, minimal whitespace
|
|
241
|
+
['ValueType: a is written as b ValueConstraint to (["\'A\'"]);']
|
|
242
|
+
],
|
|
243
|
+
[ "a is written as b() restricted to { 'A' };", # String, maximal whitespace
|
|
244
|
+
['ValueType: a is written as b ValueConstraint to (["\'A\'"]);']
|
|
245
|
+
],
|
|
246
|
+
[ "a is written as b() restricted to { '\\b\\t\\f\\n\\r\\e\\\\' };", # String with special escapes
|
|
247
|
+
["ValueType: a is written as b ValueConstraint to ([\"'\\\\b\\\\t\\\\f\\\\n\\\\r\\\\e\\\\\\\\'\"]);"]
|
|
248
|
+
],
|
|
249
|
+
[ "a is written as b() restricted to { ' ' };", # String with space
|
|
250
|
+
['ValueType: a is written as b ValueConstraint to (["\' \'"]);']
|
|
251
|
+
],
|
|
252
|
+
[ "a is written as b() restricted to { '\t' };", # String with literal tab
|
|
253
|
+
['ValueType: a is written as b ValueConstraint to (["\'\t\'"]);']
|
|
254
|
+
],
|
|
255
|
+
[ "a is written as b() restricted to { '\\0' };", # String with nul character
|
|
256
|
+
["ValueType: a is written as b ValueConstraint to ([\"'\\\\0'\"]);"]
|
|
257
|
+
],
|
|
258
|
+
[ "a is written as b() restricted to { '\\077' };", # String with octal escape
|
|
259
|
+
["ValueType: a is written as b ValueConstraint to ([\"'\\\\077'\"]);"]
|
|
260
|
+
],
|
|
261
|
+
[ "a is written as b() restricted to { '\\0xA9' };", # String with hexadecimal escape
|
|
262
|
+
["ValueType: a is written as b ValueConstraint to ([\"'\\\\0xA9'\"]);"]
|
|
263
|
+
],
|
|
264
|
+
[ "a is written as b() restricted to { '\\0uBabe' };",# String with unicode escape
|
|
265
|
+
["ValueType: a is written as b ValueConstraint to ([\"'\\\\0uBabe'\"]);"]
|
|
266
|
+
],
|
|
267
|
+
[ "a is written as b() restricted to {'A'..'F'};", # String range, minimal whitespace
|
|
268
|
+
['ValueType: a is written as b ValueConstraint to (["\'A\'".."\'F\'"]);']
|
|
269
|
+
],
|
|
270
|
+
[ "a is written as b() restricted to { 'A' .. 'F' };",# String range, maximal whitespace
|
|
271
|
+
['ValueType: a is written as b ValueConstraint to (["\'A\'".."\'F\'"]);']
|
|
272
|
+
],
|
|
273
|
+
[ "a is written as b() restricted to { ..'F' };", # String range, open start
|
|
274
|
+
['ValueType: a is written as b ValueConstraint to (["MIN".."F"]);']
|
|
275
|
+
],
|
|
276
|
+
[ "a is written as b() restricted to { 'A'.. };", # String range, open end
|
|
277
|
+
['ValueType: a is written as b ValueConstraint to (["\'A\'".."MAX"]);']
|
|
278
|
+
],
|
|
279
|
+
|
|
280
|
+
# Value constraints with units
|
|
281
|
+
[ "a is written as b() restricted to {1} inches^2/second;", # constraint with units and exponent
|
|
282
|
+
['ValueType: a is written as b ValueConstraint to ([1]) in [["inches", 2], ["second", -1]];']
|
|
283
|
+
],
|
|
284
|
+
[ "a is written as b() second^-1/mm^-1 mm^-1 restricted to {1} inches^2/second;", # type with unit and constraint with units and exponent
|
|
285
|
+
#['a is written as b ValueConstraint to ([1]) in [["inches", 2], ["second", -1]];']
|
|
286
|
+
["ValueType: a is written as b in [[\"second\", -1], [\"mm\", 1], [\"mm\", 1]] ValueConstraint to ([1]) in [[\"inches\", 2], [\"second\", -1]];"]
|
|
287
|
+
],
|
|
288
|
+
]
|
|
289
|
+
|
|
290
|
+
before :each do
|
|
291
|
+
@parser = TestParser.new
|
|
292
|
+
end
|
|
293
|
+
|
|
294
|
+
ValidNumbersEtc.each do |c|
|
|
295
|
+
source, ast = *c
|
|
296
|
+
it "should parse #{source.inspect}" do
|
|
297
|
+
result = @parser.parse_all(source, :definition)
|
|
298
|
+
|
|
299
|
+
puts @parser.failure_reason unless result
|
|
300
|
+
result.should_not be_nil
|
|
301
|
+
|
|
302
|
+
canonical_form = result.map{|d| d.ast.to_s}
|
|
303
|
+
if ast
|
|
304
|
+
canonical_form.should == ast
|
|
305
|
+
else
|
|
306
|
+
puts "#{source.inspect} should compile to"
|
|
307
|
+
puts "\t#{canonical_form}"
|
|
308
|
+
end
|
|
309
|
+
end
|
|
310
|
+
end
|
|
311
|
+
end
|
|
312
|
+
|