gisele-language 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.md +5 -0
- data/Gemfile +12 -0
- data/Gemfile.lock +26 -0
- data/LICENCE.md +22 -0
- data/Manifest.txt +13 -0
- data/README.md +7 -0
- data/Rakefile +11 -0
- data/gisele-language.gemspec +188 -0
- data/gisele-language.noespec +24 -0
- data/lib/gisele/language/ast/bool_and.rb +14 -0
- data/lib/gisele/language/ast/bool_expr.rb +22 -0
- data/lib/gisele/language/ast/bool_not.rb +14 -0
- data/lib/gisele/language/ast/bool_or.rb +14 -0
- data/lib/gisele/language/ast/case_st.rb +14 -0
- data/lib/gisele/language/ast/else_clause.rb +14 -0
- data/lib/gisele/language/ast/elsif_clause.rb +14 -0
- data/lib/gisele/language/ast/if_st.rb +14 -0
- data/lib/gisele/language/ast/node.rb +35 -0
- data/lib/gisele/language/ast/task_call_st.rb +14 -0
- data/lib/gisele/language/ast/var_ref.rb +14 -0
- data/lib/gisele/language/ast/when_clause.rb +14 -0
- data/lib/gisele/language/ast/while_st.rb +14 -0
- data/lib/gisele/language/grammar.citrus +236 -0
- data/lib/gisele/language/grammar.sexp.yml +83 -0
- data/lib/gisele/language/processors/elsif_flattener.rb +36 -0
- data/lib/gisele/language/processors/if_to_case.rb +65 -0
- data/lib/gisele/language/processors/scoping_helper.rb +32 -0
- data/lib/gisele/language/processors/sugar_removal.rb +17 -0
- data/lib/gisele/language/processors.rb +4 -0
- data/lib/gisele/language/syntax/bool_and.rb +14 -0
- data/lib/gisele/language/syntax/bool_expr.rb +14 -0
- data/lib/gisele/language/syntax/bool_lit.rb +14 -0
- data/lib/gisele/language/syntax/bool_not.rb +14 -0
- data/lib/gisele/language/syntax/bool_or.rb +14 -0
- data/lib/gisele/language/syntax/bool_paren.rb +14 -0
- data/lib/gisele/language/syntax/case_st.rb +19 -0
- data/lib/gisele/language/syntax/else_clause.rb +14 -0
- data/lib/gisele/language/syntax/elsif_clause.rb +16 -0
- data/lib/gisele/language/syntax/event_set.rb +15 -0
- data/lib/gisele/language/syntax/fluent_def.rb +18 -0
- data/lib/gisele/language/syntax/if_st.rb +18 -0
- data/lib/gisele/language/syntax/implicit_seq_st.rb +16 -0
- data/lib/gisele/language/syntax/node.rb +40 -0
- data/lib/gisele/language/syntax/par_st.rb +14 -0
- data/lib/gisele/language/syntax/seq_st.rb +14 -0
- data/lib/gisele/language/syntax/st_list.rb +14 -0
- data/lib/gisele/language/syntax/task_call_st.rb +14 -0
- data/lib/gisele/language/syntax/task_def.rb +18 -0
- data/lib/gisele/language/syntax/trackvar_def.rb +19 -0
- data/lib/gisele/language/syntax/unit_def.rb +14 -0
- data/lib/gisele/language/syntax/var_ref.rb +14 -0
- data/lib/gisele/language/syntax/when_clause.rb +16 -0
- data/lib/gisele/language/syntax/while_st.rb +16 -0
- data/lib/gisele/language.rb +31 -0
- data/lib/gisele-language/loader.rb +3 -0
- data/lib/gisele-language/version.rb +16 -0
- data/lib/gisele-language.rb +19 -0
- data/spec/fixtures/tasks/complete.gis +40 -0
- data/spec/fixtures/tasks/simple.ast +51 -0
- data/spec/fixtures/tasks/simple.gis +16 -0
- data/spec/language/ast/test_bool_expr.rb +50 -0
- data/spec/language/grammar_sexp/test_case_st.rb +20 -0
- data/spec/language/grammar_sexp/test_event_set.rb +14 -0
- data/spec/language/grammar_sexp/test_fluent_def.rb +18 -0
- data/spec/language/grammar_sexp/test_initially.rb +18 -0
- data/spec/language/grammar_sexp/test_nop_st.rb +10 -0
- data/spec/language/grammar_sexp/test_when_clause.rb +12 -0
- data/spec/language/processors/test_elsif_flattener.rb +94 -0
- data/spec/language/processors/test_if_to_case.rb +105 -0
- data/spec/language/processors/test_scoping_helper.rb +45 -0
- data/spec/language/syntax/grammar/test_bool_expr.rb +34 -0
- data/spec/language/syntax/grammar/test_boolean_literal.rb +17 -0
- data/spec/language/syntax/grammar/test_case_st.rb +60 -0
- data/spec/language/syntax/grammar/test_event.rb +18 -0
- data/spec/language/syntax/grammar/test_event_name.rb +21 -0
- data/spec/language/syntax/grammar/test_event_set.rb +26 -0
- data/spec/language/syntax/grammar/test_fluent_def.rb +21 -0
- data/spec/language/syntax/grammar/test_if_st.rb +21 -0
- data/spec/language/syntax/grammar/test_par_st.rb +11 -0
- data/spec/language/syntax/grammar/test_process_statement.rb +19 -0
- data/spec/language/syntax/grammar/test_seq_st.rb +11 -0
- data/spec/language/syntax/grammar/test_spaces.rb +19 -0
- data/spec/language/syntax/grammar/test_spacing.rb +17 -0
- data/spec/language/syntax/grammar/test_task_def.rb +35 -0
- data/spec/language/syntax/grammar/test_task_name.rb +19 -0
- data/spec/language/syntax/grammar/test_task_start_or_end.rb +17 -0
- data/spec/language/syntax/grammar/test_trackvar_def.rb +21 -0
- data/spec/language/syntax/grammar/test_unit_def.rb +29 -0
- data/spec/language/syntax/grammar/test_variable_name.rb +51 -0
- data/spec/language/syntax/grammar/test_when_clause.rb +21 -0
- data/spec/language/syntax/grammar/test_while_st.rb +11 -0
- data/spec/language/syntax/to_ast/test_bool_expr.rb +32 -0
- data/spec/language/syntax/to_ast/test_case_st.rb +47 -0
- data/spec/language/syntax/to_ast/test_else_clause.rb +13 -0
- data/spec/language/syntax/to_ast/test_elsif_clause.rb +15 -0
- data/spec/language/syntax/to_ast/test_event_set.rb +24 -0
- data/spec/language/syntax/to_ast/test_fluent_def.rb +26 -0
- data/spec/language/syntax/to_ast/test_if_st.rb +39 -0
- data/spec/language/syntax/to_ast/test_par_st.rb +12 -0
- data/spec/language/syntax/to_ast/test_seq_st.rb +12 -0
- data/spec/language/syntax/to_ast/test_task_call_st.rb +10 -0
- data/spec/language/syntax/to_ast/test_task_def.rb +44 -0
- data/spec/language/syntax/to_ast/test_trackvar_def.rb +26 -0
- data/spec/language/syntax/to_ast/test_unit_def.rb +28 -0
- data/spec/language/syntax/to_ast/test_var_ref.rb +12 -0
- data/spec/language/syntax/to_ast/test_when_clause.rb +15 -0
- data/spec/language/syntax/to_ast/test_while_st.rb +24 -0
- data/spec/language/test_syntax.rb +51 -0
- data/spec/spec_helper.rb +44 -0
- data/spec/test_gisele-language.rb +8 -0
- data/tasks/gem.rake +73 -0
- data/tasks/spec_test.rake +71 -0
- metadata +269 -0
@@ -0,0 +1,105 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
module Gisele::Language
|
3
|
+
describe IfToCase do
|
4
|
+
|
5
|
+
def ast(source)
|
6
|
+
Gisele.ast(Gisele.parse(source.strip, :root => :if_st))
|
7
|
+
end
|
8
|
+
|
9
|
+
def rewrite(ast)
|
10
|
+
@rewrited = IfToCase.call(ast)
|
11
|
+
end
|
12
|
+
|
13
|
+
after{
|
14
|
+
(sexp_grammar[:case_st] === @rewrited).should be_true
|
15
|
+
}
|
16
|
+
|
17
|
+
it 'rewrites single if correctly' do
|
18
|
+
source = ast("if goodCond Task1 end")
|
19
|
+
expected = \
|
20
|
+
[:case_st, nil,
|
21
|
+
[:when_clause,
|
22
|
+
[:bool_expr, [:var_ref, "goodCond"]],
|
23
|
+
[:task_call_st, "Task1"] ]]
|
24
|
+
rewrite(source).should eq(expected)
|
25
|
+
end
|
26
|
+
|
27
|
+
it 'negates the else clause' do
|
28
|
+
source = ast("if goodCond Task1 else Task2 end")
|
29
|
+
expected = \
|
30
|
+
[:case_st, nil,
|
31
|
+
[:when_clause,
|
32
|
+
[:bool_expr, [:var_ref, "goodCond"]],
|
33
|
+
[:task_call_st, "Task1"] ],
|
34
|
+
[:when_clause,
|
35
|
+
[:bool_expr, [:bool_not, [:var_ref, "goodCond"]]],
|
36
|
+
[:task_call_st, "Task2"] ]
|
37
|
+
]
|
38
|
+
rewrite(source).should eq(expected)
|
39
|
+
end
|
40
|
+
|
41
|
+
it 'handles elsif clauses correctly' do
|
42
|
+
source = ast(<<-IF)
|
43
|
+
if c1 Task1
|
44
|
+
elsif c2 Task2
|
45
|
+
elsif c3 Task3
|
46
|
+
else Task4
|
47
|
+
end
|
48
|
+
IF
|
49
|
+
expected = \
|
50
|
+
[:case_st, nil,
|
51
|
+
[:when_clause,
|
52
|
+
[:bool_expr, [:var_ref, "c1"]],
|
53
|
+
[:task_call_st, "Task1"] ],
|
54
|
+
[:when_clause,
|
55
|
+
[:bool_expr, [:bool_and,
|
56
|
+
[:var_ref, "c2"],
|
57
|
+
[:bool_not, [:var_ref, "c1"]] ]],
|
58
|
+
[:task_call_st, "Task2"] ],
|
59
|
+
[:when_clause,
|
60
|
+
[:bool_expr, [:bool_and,
|
61
|
+
[:var_ref, "c3"],
|
62
|
+
[:bool_and,
|
63
|
+
[:bool_not, [:var_ref, "c2"]],
|
64
|
+
[:bool_not, [:var_ref, "c1"]] ]]],
|
65
|
+
[:task_call_st, "Task3"] ],
|
66
|
+
[:when_clause,
|
67
|
+
[:bool_expr, [:bool_and,
|
68
|
+
[:bool_not, [:var_ref, "c3"]],
|
69
|
+
[:bool_and,
|
70
|
+
[:bool_not, [:var_ref, "c2"]],
|
71
|
+
[:bool_not, [:var_ref, "c1"]]]]],
|
72
|
+
[:task_call_st, "Task4"] ],
|
73
|
+
]
|
74
|
+
rewrite(source).should eq(expected)
|
75
|
+
end
|
76
|
+
|
77
|
+
it 'avoids double negations' do
|
78
|
+
source = ast("if not(goodCond) Task1 else Task2 end")
|
79
|
+
expected = \
|
80
|
+
[:case_st, nil,
|
81
|
+
[:when_clause,
|
82
|
+
[:bool_expr, [:bool_not, [:var_ref, "goodCond"]]],
|
83
|
+
[:task_call_st, "Task1"] ],
|
84
|
+
[:when_clause,
|
85
|
+
[:bool_expr, [:var_ref, "goodCond"]],
|
86
|
+
[:task_call_st, "Task2"] ] ]
|
87
|
+
rewrite(source).should eq(expected)
|
88
|
+
end
|
89
|
+
|
90
|
+
it 'keeps traceability markers on a single if' do
|
91
|
+
if_st = ast("if goodCond Task1 end")
|
92
|
+
rw_st = rewrite(if_st)
|
93
|
+
rw_st.tracking_markers.should eq(if_st.tracking_markers)
|
94
|
+
rw_st.last.tracking_markers.should eq(if_st.tracking_markers)
|
95
|
+
end
|
96
|
+
|
97
|
+
it 'keeps traceability markers when a else if present' do
|
98
|
+
if_st = ast("if goodCond Task1 else Task2 end")
|
99
|
+
rw_st = rewrite(if_st)
|
100
|
+
rw_st.tracking_markers.should eq(if_st.tracking_markers)
|
101
|
+
rw_st.last.tracking_markers.should eq(if_st.last.tracking_markers)
|
102
|
+
end
|
103
|
+
|
104
|
+
end
|
105
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
module Gisele::Language
|
3
|
+
describe ScopingHelper do
|
4
|
+
|
5
|
+
let(:rw_class) do
|
6
|
+
Class.new(Sexpr::Rewriter) do
|
7
|
+
grammar Gisele::Language
|
8
|
+
helper ScopingHelper
|
9
|
+
|
10
|
+
def on_hello(node)
|
11
|
+
scope_stack.dup
|
12
|
+
end
|
13
|
+
|
14
|
+
def on_missing(node)
|
15
|
+
call(node.sexpr_body.last)
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
end
|
20
|
+
let(:rw){ rw_class.new }
|
21
|
+
|
22
|
+
it 'installs the methods on the rewriter' do
|
23
|
+
rw.respond_to?(:scope_stack).should be_true
|
24
|
+
end
|
25
|
+
|
26
|
+
it 'does nothing special on non _def nodes' do
|
27
|
+
node = [:hello, "world"]
|
28
|
+
rw.call(node).should eq([])
|
29
|
+
end
|
30
|
+
|
31
|
+
it 'keeps _def nodes as successive scopes' do
|
32
|
+
second = [:task_def, [:hello]]
|
33
|
+
first = [:task_def, second]
|
34
|
+
rw.call(first).should eq([first, second])
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'pops scopes when returning along the stack' do
|
38
|
+
second = [:task_def, [:hello]]
|
39
|
+
first = [:task_def, second]
|
40
|
+
rw.call(first)
|
41
|
+
rw.scope_stack.should eq([])
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
module Gisele::Language
|
3
|
+
describe Grammar, 'bool_expr' do
|
4
|
+
|
5
|
+
it 'parses single variable references' do
|
6
|
+
parse('diagKnown', :bool_expr).should eq('diagKnown')
|
7
|
+
end
|
8
|
+
|
9
|
+
it 'parses boolean literals' do
|
10
|
+
parse('true', :bool_expr).should eq('true')
|
11
|
+
parse('false', :bool_expr).should eq('false')
|
12
|
+
end
|
13
|
+
|
14
|
+
it 'parses negated expression' do
|
15
|
+
parse('not diagKnown', :bool_expr).should eq('not diagKnown')
|
16
|
+
parse('not true', :bool_expr).should eq('not true')
|
17
|
+
parse('not false', :bool_expr).should eq('not false')
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'parses or expressions' do
|
21
|
+
parse('diagKnown or platLow', :bool_expr).should eq('diagKnown or platLow')
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'parses and expressions' do
|
25
|
+
parse('diagKnown and platLow', :bool_expr).should eq('diagKnown and platLow')
|
26
|
+
end
|
27
|
+
|
28
|
+
it 'parses complex expressions' do
|
29
|
+
expr = 'diagKnown and (platLow or not(metastased and mplus))'
|
30
|
+
parse(expr, :bool_expr).should eq(expr)
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
module Gisele::Language
|
3
|
+
describe Grammar, 'boolean_literal' do
|
4
|
+
|
5
|
+
it 'parses booleans' do
|
6
|
+
parse('true', :boolean_literal).should eq('true')
|
7
|
+
parse('false', :boolean_literal).should eq('false')
|
8
|
+
end
|
9
|
+
|
10
|
+
it 'does not parses integers' do
|
11
|
+
lambda{
|
12
|
+
parse('0', :boolean_literal)
|
13
|
+
}.should raise_error(Citrus::ParseError)
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
module Gisele::Language
|
3
|
+
describe Grammar, 'case_st' do
|
4
|
+
|
5
|
+
it 'supports a single when clause' do
|
6
|
+
expr = <<-CASE_ST.strip
|
7
|
+
case
|
8
|
+
when goodCond
|
9
|
+
Task1
|
10
|
+
end
|
11
|
+
CASE_ST
|
12
|
+
parse(expr, :case_st).should eq(expr)
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'supports boolean expressions in when clauses' do
|
16
|
+
expr = <<-CASE_ST.strip
|
17
|
+
case
|
18
|
+
when not(goodCond) or badCond
|
19
|
+
Task1
|
20
|
+
end
|
21
|
+
CASE_ST
|
22
|
+
parse(expr, :case_st).should eq(expr)
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'supports a multiple when clauses' do
|
26
|
+
expr = <<-CASE_ST.strip
|
27
|
+
case
|
28
|
+
when goodCond
|
29
|
+
Task1
|
30
|
+
when badCond
|
31
|
+
Task2
|
32
|
+
end
|
33
|
+
CASE_ST
|
34
|
+
parse(expr, :case_st).should eq(expr)
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'supports an else clause' do
|
38
|
+
expr = <<-CASE_ST.strip
|
39
|
+
case
|
40
|
+
when goodCond
|
41
|
+
Task1
|
42
|
+
else
|
43
|
+
Task2
|
44
|
+
end
|
45
|
+
CASE_ST
|
46
|
+
parse(expr, :case_st).should eq(expr)
|
47
|
+
end
|
48
|
+
|
49
|
+
it 'supports an optional variable name' do
|
50
|
+
expr = <<-CASE_ST.strip
|
51
|
+
case someVariable
|
52
|
+
when goodCond
|
53
|
+
Task1
|
54
|
+
end
|
55
|
+
CASE_ST
|
56
|
+
parse(expr, :case_st).should eq(expr)
|
57
|
+
end
|
58
|
+
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
module Gisele::Language
|
3
|
+
describe Grammar, 'event' do
|
4
|
+
|
5
|
+
it 'parses correct events' do
|
6
|
+
parse('Task:start', :event).should eq('Task:start')
|
7
|
+
parse('Task:end', :event).should eq('Task:end')
|
8
|
+
parse('an_event', :event).should eq('an_event')
|
9
|
+
end
|
10
|
+
|
11
|
+
it 'raises on invalid event names' do
|
12
|
+
lambda{
|
13
|
+
parse('Task', :event)
|
14
|
+
}.should raise_error(Citrus::ParseError)
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
module Gisele::Language
|
3
|
+
describe Grammar, 'event_name' do
|
4
|
+
|
5
|
+
it 'parses correct event names' do
|
6
|
+
parse('a', :event_name).should eq('a')
|
7
|
+
parse('event', :event_name).should eq('event')
|
8
|
+
parse('event_name', :event_name).should eq('event_name')
|
9
|
+
end
|
10
|
+
|
11
|
+
it 'raises on invalid variable names' do
|
12
|
+
lambda{
|
13
|
+
parse('NotAnEventName', :event_name)
|
14
|
+
}.should raise_error(Citrus::ParseError)
|
15
|
+
lambda{
|
16
|
+
parse('notAnEventName', :event_name)
|
17
|
+
}.should raise_error(Citrus::ParseError)
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
module Gisele::Language
|
3
|
+
describe Grammar, 'event_set' do
|
4
|
+
|
5
|
+
it 'parses empty sets' do
|
6
|
+
parse('{}', :event_set).should eq('{}')
|
7
|
+
parse('{ }', :event_set).should eq('{ }')
|
8
|
+
end
|
9
|
+
|
10
|
+
it 'parses event singletons' do
|
11
|
+
parse('{Task:start}', :event_set).should eq('{Task:start}')
|
12
|
+
parse('{ Task:start }', :event_set).should eq('{ Task:start }')
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'parses event sets' do
|
16
|
+
parse('{Task:start, Task:end}', :event_set).should eq('{Task:start, Task:end}')
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'recognizes invalid events in the set' do
|
20
|
+
lambda{
|
21
|
+
parse('{Task:start, NotAnEvent}', :event_set)
|
22
|
+
}.should raise_error(Citrus::ParseError)
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
module Gisele::Language
|
3
|
+
describe Grammar, 'fluent_def' do
|
4
|
+
|
5
|
+
it 'parses valid fluent definitions' do
|
6
|
+
defn = 'fluent diagKnown {Diagnosis:start}, {Treatment:end} initially false'
|
7
|
+
parse(defn, :fluent_def).should eq(defn)
|
8
|
+
end
|
9
|
+
|
10
|
+
it 'supports a missing initial value' do
|
11
|
+
defn = 'fluent diagKnown {Diagnosis:start}, {Treatment:end}'
|
12
|
+
parse(defn, :fluent_def).should eq(defn)
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'supports empty sets for events' do
|
16
|
+
defn = 'fluent diagKnown {}, {} initially true'
|
17
|
+
parse(defn, :fluent_def).should eq(defn)
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
module Gisele::Language
|
3
|
+
describe Grammar, 'if_st' do
|
4
|
+
|
5
|
+
it 'parses a single if statement' do
|
6
|
+
expr = 'if goodCond Task end'
|
7
|
+
parse(expr, :if_st).should eq(expr)
|
8
|
+
end
|
9
|
+
|
10
|
+
it 'supports an optional else' do
|
11
|
+
expr = 'if goodCond GoodTask else BadTask end'
|
12
|
+
parse(expr, :if_st).should eq(expr)
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'supports an optional elsif clauses' do
|
16
|
+
expr = 'if goodCond GoodTask elsif otherCond OtherTask elsif yetAnother BadTask end'
|
17
|
+
parse(expr, :if_st).should eq(expr)
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
module Gisele::Language
|
3
|
+
describe Grammar, 'process_statement' do
|
4
|
+
|
5
|
+
it 'parses a simple process statement' do
|
6
|
+
expr = <<-PROCESS.strip
|
7
|
+
DoSomething
|
8
|
+
if goodCond
|
9
|
+
DoForGood
|
10
|
+
else
|
11
|
+
DoForBad
|
12
|
+
end
|
13
|
+
CleanDesk
|
14
|
+
PROCESS
|
15
|
+
parse(expr, :process_statement).should eq(expr)
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
module Gisele::Language
|
3
|
+
describe Grammar, 'spaces' do
|
4
|
+
|
5
|
+
it 'parses all kind of spaces' do
|
6
|
+
parse(' ', :spaces).should eq(' ')
|
7
|
+
parse("\t", :spaces).should eq("\t")
|
8
|
+
parse("\n", :spaces).should eq("\n")
|
9
|
+
parse(" \t\n", :spaces).should eq(" \t\n")
|
10
|
+
end
|
11
|
+
|
12
|
+
it 'enforces mandatory spacing' do
|
13
|
+
lambda{
|
14
|
+
parse('', :spaces)
|
15
|
+
}.should raise_error(Citrus::ParseError)
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
module Gisele::Language
|
3
|
+
describe Grammar, 'spacing' do
|
4
|
+
|
5
|
+
it 'parses all kind of spaces' do
|
6
|
+
parse(' ', :spacing).should eq(' ')
|
7
|
+
parse("\t", :spacing).should eq("\t")
|
8
|
+
parse("\n", :spacing).should eq("\n")
|
9
|
+
parse(" \t\n", :spacing).should eq(" \t\n")
|
10
|
+
end
|
11
|
+
|
12
|
+
it 'does not enforces mandatory spacing' do
|
13
|
+
parse('', :spacing).should eq('')
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
module Gisele::Language
|
3
|
+
describe Grammar, 'task_def' do
|
4
|
+
|
5
|
+
it 'parses a simple implicit task definition' do
|
6
|
+
taskdef = <<-TASKDEF.strip
|
7
|
+
task Process
|
8
|
+
Diagnosis
|
9
|
+
end
|
10
|
+
TASKDEF
|
11
|
+
parse(taskdef, :task_def).should eq(taskdef)
|
12
|
+
end
|
13
|
+
|
14
|
+
it 'allows any statement' do
|
15
|
+
taskdef = <<-TASKDEF.strip
|
16
|
+
task Process
|
17
|
+
while true Diagnosis end
|
18
|
+
end
|
19
|
+
TASKDEF
|
20
|
+
parse(taskdef, :task_def).should eq(taskdef)
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'supports optional variable definitions in the signature' do
|
24
|
+
taskdef = <<-TASKDEF.strip
|
25
|
+
task Process
|
26
|
+
fluent diagKnown {Diagnosis:start}, {} initially false
|
27
|
+
trackvar mplus {Diagnosis:end}
|
28
|
+
Diagnosis
|
29
|
+
end
|
30
|
+
TASKDEF
|
31
|
+
parse(taskdef, :task_def).should eq(taskdef)
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
module Gisele::Language
|
3
|
+
describe Grammar,'task_name' do
|
4
|
+
|
5
|
+
it 'parses correct task names' do
|
6
|
+
parse('A', :task_name).should eq('A')
|
7
|
+
parse('Diagnosis', :task_name).should eq('Diagnosis')
|
8
|
+
parse('TaskName', :task_name).should eq('TaskName')
|
9
|
+
parse('Task_Name', :task_name).should eq('Task_Name')
|
10
|
+
end
|
11
|
+
|
12
|
+
it 'raises on invalid task names' do
|
13
|
+
lambda{
|
14
|
+
parse('not_a_task_name', :task_name)
|
15
|
+
}.should raise_error(Citrus::ParseError)
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
module Gisele::Language
|
3
|
+
describe Grammar, 'task_start_or_end' do
|
4
|
+
|
5
|
+
it 'parses correct event names' do
|
6
|
+
parse('Task:start', :task_start_or_end).should eq('Task:start')
|
7
|
+
parse('Task:end', :task_start_or_end).should eq('Task:end')
|
8
|
+
end
|
9
|
+
|
10
|
+
it 'raises on simple task names' do
|
11
|
+
lambda{
|
12
|
+
parse('Task', :task_start_or_end)
|
13
|
+
}.should raise_error(Citrus::ParseError)
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
module Gisele::Language
|
3
|
+
describe Grammar, 'trackvar_def' do
|
4
|
+
|
5
|
+
it 'parses valid tracking variable definitions' do
|
6
|
+
defn = 'trackvar plateletLow {BloodTest:end}'
|
7
|
+
parse(defn, :trackvar_def).should eq(defn)
|
8
|
+
end
|
9
|
+
|
10
|
+
it 'supports an optional initial value' do
|
11
|
+
defn = 'trackvar plateletLow {BloodTest:end} initially false'
|
12
|
+
parse(defn, :trackvar_def).should eq(defn)
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'supports optional obsolete events' do
|
16
|
+
defn = 'trackvar plateletLow {BloodTest:end}, {Chemotherapy:end}'
|
17
|
+
parse(defn, :trackvar_def).should eq(defn)
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
module Gisele::Language
|
3
|
+
describe Grammar, 'unit' do
|
4
|
+
|
5
|
+
it 'parses a single task definition' do
|
6
|
+
expr = <<-UNIT.strip
|
7
|
+
task Task1 end
|
8
|
+
UNIT
|
9
|
+
parse(expr, :unit_def).should eq(expr)
|
10
|
+
end
|
11
|
+
|
12
|
+
it 'accepts multiple task definitions' do
|
13
|
+
expr = <<-UNIT.strip
|
14
|
+
task Task1 end
|
15
|
+
task Task2 end
|
16
|
+
UNIT
|
17
|
+
parse(expr, :unit_def).should eq(expr)
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'allows trailing spaces' do
|
21
|
+
expr = <<-UNIT
|
22
|
+
task Task1 end
|
23
|
+
task Task2 end
|
24
|
+
UNIT
|
25
|
+
parse(expr, :unit_def).should eq(expr)
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
module Gisele::Language
|
3
|
+
describe Grammar, 'variable_name' do
|
4
|
+
|
5
|
+
RESERVED_WORDS = [
|
6
|
+
"if",
|
7
|
+
"else",
|
8
|
+
"elsif",
|
9
|
+
"when",
|
10
|
+
"while",
|
11
|
+
"seq",
|
12
|
+
"par",
|
13
|
+
"task",
|
14
|
+
"refinement",
|
15
|
+
"fluent",
|
16
|
+
"trackvar",
|
17
|
+
"initially",
|
18
|
+
"end",
|
19
|
+
"not",
|
20
|
+
"or",
|
21
|
+
"and",
|
22
|
+
"true",
|
23
|
+
"false"
|
24
|
+
]
|
25
|
+
|
26
|
+
it 'parses correct variable names' do
|
27
|
+
parse('a', :variable_name).should eq('a')
|
28
|
+
parse('diagnosis', :variable_name).should eq('diagnosis')
|
29
|
+
parse('varName', :variable_name).should eq('varName')
|
30
|
+
end
|
31
|
+
|
32
|
+
it 'does not allow reserved words' do
|
33
|
+
RESERVED_WORDS.each do |word|
|
34
|
+
lambda{
|
35
|
+
parse(word.to_s + " ", :variable_name)
|
36
|
+
}.should raise_error(Citrus::ParseError)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
it 'allows a reserved word as prefix' do
|
41
|
+
parse('ifSomething', :variable_name).should eq('ifSomething')
|
42
|
+
end
|
43
|
+
|
44
|
+
it 'raises on invalid variable names' do
|
45
|
+
lambda{
|
46
|
+
parse('NotAVarName', :variable_name)
|
47
|
+
}.should raise_error(Citrus::ParseError)
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
module Gisele::Language
|
3
|
+
describe Grammar, 'when_clause' do
|
4
|
+
|
5
|
+
it 'parses a single when clause statement' do
|
6
|
+
expr = 'when goodCond Task'
|
7
|
+
parse(expr, :when_clause).should eq(expr)
|
8
|
+
end
|
9
|
+
|
10
|
+
it 'supports a boolean expression' do
|
11
|
+
expr = 'when not(goodCond and badCond) Task'
|
12
|
+
parse(expr, :when_clause).should eq(expr)
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'supports an complex process statement' do
|
16
|
+
expr = 'when goodCond Task1 par Task2 Task3 end'
|
17
|
+
parse(expr, :when_clause).should eq(expr)
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
21
|
+
end
|