gisele 0.0.1 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.md +39 -1
- data/gisele.noespec +1 -1
- data/lib/gisele/command.rb +13 -4
- data/lib/gisele/errors.rb +21 -0
- data/lib/gisele/language/ast/helpers.rb +37 -0
- data/lib/gisele/language/ast/node.rb +54 -0
- data/lib/gisele/language/ast/unit.rb +10 -0
- data/lib/gisele/language/ast.rb +14 -0
- data/lib/gisele/language/sugar_removal.rb +53 -0
- data/lib/gisele/language/syntax/bool_and.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/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/grammar.citrus +202 -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 +35 -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 +17 -0
- data/lib/gisele/language/syntax/task_refinement.rb +15 -0
- data/lib/gisele/language/syntax/task_signature.rb +15 -0
- data/lib/gisele/language/syntax/trackvar_def.rb +19 -0
- data/lib/gisele/language/syntax/unit.rb +14 -0
- data/lib/gisele/language/syntax/var_ref.rb +14 -0
- data/lib/gisele/language/syntax/while_st.rb +16 -0
- data/lib/gisele/language/syntax.rb +29 -0
- data/lib/gisele/language/transformer.rb +38 -0
- data/lib/gisele/language.rb +15 -1
- data/lib/gisele/version.rb +2 -2
- data/lib/gisele.rb +7 -1
- data/spec/command/main/gisele_ast_ruby.stdout +38 -28
- data/spec/command/main/gisele_help.stdout +5 -0
- data/spec/command/main/gisele_no_sugar.cmd +1 -0
- data/spec/command/main/gisele_no_sugar.stdout +61 -0
- data/spec/fixtures/tasks/simple.ast +18 -14
- data/spec/fixtures/tasks/simple.gis +2 -0
- data/spec/spec_helper.rb +3 -3
- data/spec/test_examples.rb +3 -3
- data/spec/unit/language/ast/test_node.rb +61 -0
- data/spec/unit/language/sugar_removal/test_if_to_guarded_commands.rb +90 -0
- data/spec/unit/language/{test_grammar.rb → syntax/test_grammar.rb} +18 -30
- data/spec/unit/language/syntax/test_to_ast.rb +245 -0
- data/spec/unit/language/test_ast.rb +21 -247
- data/spec/unit/language/test_syntax.rb +48 -0
- data/spec/unit/language/test_transformer.rb +68 -0
- data/spec/unit/test_language.rb +35 -0
- metadata +69 -25
- data/lib/gisele/language/grammar.citrus +0 -246
- data/lib/gisele/language/parser.rb +0 -30
- data/spec/unit/language/test_parser.rb +0 -27
@@ -0,0 +1,35 @@
|
|
1
|
+
module Gisele
|
2
|
+
module Language
|
3
|
+
module Syntax
|
4
|
+
module Node
|
5
|
+
|
6
|
+
def to_ast
|
7
|
+
Language::AST.node(_to_ast)
|
8
|
+
end
|
9
|
+
|
10
|
+
end # module Node
|
11
|
+
end # module Syntax
|
12
|
+
end # module Language
|
13
|
+
end # module Gisele
|
14
|
+
require_relative 'event_set'
|
15
|
+
require_relative 'fluent_def'
|
16
|
+
require_relative 'trackvar_def'
|
17
|
+
require_relative 'var_ref'
|
18
|
+
require_relative 'bool_lit'
|
19
|
+
require_relative 'bool_paren'
|
20
|
+
require_relative 'bool_not'
|
21
|
+
require_relative 'bool_and'
|
22
|
+
require_relative 'bool_or'
|
23
|
+
require_relative 'st_list'
|
24
|
+
require_relative 'implicit_seq_st'
|
25
|
+
require_relative 'task_call_st'
|
26
|
+
require_relative 'seq_st'
|
27
|
+
require_relative 'par_st'
|
28
|
+
require_relative 'while_st'
|
29
|
+
require_relative 'if_st'
|
30
|
+
require_relative 'else_clause'
|
31
|
+
require_relative 'elsif_clause'
|
32
|
+
require_relative 'task_refinement'
|
33
|
+
require_relative 'task_signature'
|
34
|
+
require_relative 'task_def'
|
35
|
+
require_relative 'unit'
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Gisele
|
2
|
+
module Language
|
3
|
+
module Syntax
|
4
|
+
module TaskDef
|
5
|
+
include Node
|
6
|
+
|
7
|
+
def _to_ast
|
8
|
+
name = captures[:task_name].first.strip
|
9
|
+
sig = captures[:task_signature].map{|x| x.to_ast}.first || [:task_signature]
|
10
|
+
ref = captures[:task_refinement].map{|x| x.to_ast}.first || [:task_refinement]
|
11
|
+
[:task_def, name, sig, ref]
|
12
|
+
end
|
13
|
+
|
14
|
+
end # module TaskDef
|
15
|
+
end # module Syntax
|
16
|
+
end # module Language
|
17
|
+
end # module Gisele
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module Gisele
|
2
|
+
module Language
|
3
|
+
module Syntax
|
4
|
+
module TaskRefinement
|
5
|
+
include Node
|
6
|
+
|
7
|
+
def _to_ast
|
8
|
+
main = captures[:process_statement].first.to_ast
|
9
|
+
[:task_refinement, main]
|
10
|
+
end
|
11
|
+
|
12
|
+
end # module TaskRefinement
|
13
|
+
end # module Syntax
|
14
|
+
end # module Language
|
15
|
+
end # module Gisele
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module Gisele
|
2
|
+
module Language
|
3
|
+
module Syntax
|
4
|
+
module TaskSignature
|
5
|
+
include Node
|
6
|
+
|
7
|
+
def _to_ast
|
8
|
+
list = captures[:task_signature_element].map{|x| x.to_ast}
|
9
|
+
[:task_signature] + list
|
10
|
+
end
|
11
|
+
|
12
|
+
end # module TaskSignature
|
13
|
+
end # module Syntax
|
14
|
+
end # module Language
|
15
|
+
end # module Gisele
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Gisele
|
2
|
+
module Language
|
3
|
+
module Syntax
|
4
|
+
module TrackvarDef
|
5
|
+
include Node
|
6
|
+
|
7
|
+
def _to_ast
|
8
|
+
name = captures[:variable_name].first.strip
|
9
|
+
init, term = captures[:event_set].map{|x| x.to_ast}
|
10
|
+
term = [:event_set] unless term
|
11
|
+
initval = captures[:initially_def].first
|
12
|
+
initval = (initval && !initval.empty?) ? initval.value : nil
|
13
|
+
[:trackvar, name, init, term, initval]
|
14
|
+
end
|
15
|
+
|
16
|
+
end # module TrackvarDef
|
17
|
+
end # module Syntax
|
18
|
+
end # module Language
|
19
|
+
end # module Gisele
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module Gisele
|
2
|
+
module Language
|
3
|
+
module Syntax
|
4
|
+
module WhileSt
|
5
|
+
include Node
|
6
|
+
|
7
|
+
def _to_ast
|
8
|
+
cond = captures[:bool_expr].first.to_ast
|
9
|
+
dost = captures[:process_statement].first.to_ast
|
10
|
+
[:while_st, cond, dost]
|
11
|
+
end
|
12
|
+
|
13
|
+
end # module WhileSt
|
14
|
+
end # module Syntax
|
15
|
+
end # module Language
|
16
|
+
end # module Gisele
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require_relative 'syntax/node'
|
2
|
+
module Gisele
|
3
|
+
module Language
|
4
|
+
module Syntax
|
5
|
+
Citrus.load(File.expand_path('../syntax/grammar', __FILE__))
|
6
|
+
|
7
|
+
def parse(input, options = {})
|
8
|
+
source = parsing_source(input)
|
9
|
+
Grammar.parse(source, options)
|
10
|
+
end
|
11
|
+
module_function :parse
|
12
|
+
|
13
|
+
def ast(input, parse_options = {})
|
14
|
+
parse(input, parse_options).to_ast
|
15
|
+
end
|
16
|
+
module_function :ast
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
def parsing_source(input)
|
21
|
+
input = File.read(input.to_path) if input.respond_to?(:to_path)
|
22
|
+
input = input.to_str if input.respond_to?(:to_str)
|
23
|
+
input
|
24
|
+
end
|
25
|
+
module_function :parsing_source
|
26
|
+
|
27
|
+
end # module Syntax
|
28
|
+
end # module Language
|
29
|
+
end # module Gisele
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module Gisele
|
2
|
+
module Language
|
3
|
+
class Transformer
|
4
|
+
include AST::Helpers
|
5
|
+
|
6
|
+
def call(node)
|
7
|
+
node = pre_call(node)
|
8
|
+
meth = :"on_#{node.rule_name}"
|
9
|
+
meth = :"on_missing" unless respond_to?(meth)
|
10
|
+
post_call send(meth, node)
|
11
|
+
end
|
12
|
+
|
13
|
+
def on_missing(node)
|
14
|
+
raise UnexpectedNodeError, "Unexpected node: #{node.rule_name}"
|
15
|
+
end
|
16
|
+
|
17
|
+
protected
|
18
|
+
|
19
|
+
def pre_call(node)
|
20
|
+
unless looks_a_node?(node)
|
21
|
+
raise ArgumentError, "AST node expected, got #{node.inspect}", caller
|
22
|
+
end
|
23
|
+
node(node)
|
24
|
+
end
|
25
|
+
|
26
|
+
def post_call(transformed)
|
27
|
+
looks_a_node?(transformed) ? node(transformed) : transformed
|
28
|
+
end
|
29
|
+
|
30
|
+
def copy_and_applyall(node)
|
31
|
+
node.copy do |memo,child|
|
32
|
+
memo << (child.is_a?(AST::Node) ? call(child) : child)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
end # class Transformer
|
37
|
+
end # module Language
|
38
|
+
end # module Gisele
|
data/lib/gisele/language.rb
CHANGED
@@ -1,6 +1,20 @@
|
|
1
1
|
module Gisele
|
2
2
|
module Language
|
3
3
|
|
4
|
+
def rule2mod(rule)
|
5
|
+
rule.to_s.gsub(/(^|_)([a-z])/){|x| $2.capitalize}.to_sym
|
6
|
+
end
|
7
|
+
module_function :rule2mod
|
8
|
+
|
9
|
+
def mod2rule(mod)
|
10
|
+
mod = mod.name.to_s.split('::').last.to_sym if mod.is_a?(Module)
|
11
|
+
mod.to_s.gsub(/[A-Z]/){|x| "_#{x.downcase}"}[1..-1].to_sym
|
12
|
+
end
|
13
|
+
module_function :mod2rule
|
14
|
+
|
4
15
|
end # module Language
|
5
16
|
end # module Gisele
|
6
|
-
require_relative 'language/
|
17
|
+
require_relative 'language/syntax'
|
18
|
+
require_relative 'language/ast'
|
19
|
+
require_relative 'language/transformer'
|
20
|
+
require_relative 'language/sugar_removal'
|
data/lib/gisele/version.rb
CHANGED
data/lib/gisele.rb
CHANGED
@@ -1,14 +1,20 @@
|
|
1
1
|
require_relative "gisele/version"
|
2
2
|
require_relative "gisele/loader"
|
3
|
+
require_relative 'gisele/errors'
|
3
4
|
#
|
4
5
|
# Gisele is a Process Analyzer Toolset
|
5
6
|
#
|
6
7
|
module Gisele
|
7
8
|
|
8
9
|
def parse(input)
|
9
|
-
Language::
|
10
|
+
Language::Syntax::parse(input)
|
10
11
|
end
|
11
12
|
module_function :parse
|
12
13
|
|
14
|
+
def ast(input)
|
15
|
+
Language::Syntax::ast(input)
|
16
|
+
end
|
17
|
+
module_function :ast
|
18
|
+
|
13
19
|
end # module Gisele
|
14
20
|
require_relative 'gisele/language'
|
@@ -1,43 +1,53 @@
|
|
1
1
|
[
|
2
|
-
:
|
3
|
-
"Simple",
|
2
|
+
:unit,
|
4
3
|
[
|
5
|
-
:
|
4
|
+
:task_def,
|
5
|
+
"Simple",
|
6
6
|
[
|
7
|
-
:
|
8
|
-
"diagKnown",
|
7
|
+
:task_signature,
|
9
8
|
[
|
10
|
-
:
|
11
|
-
"
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
9
|
+
:fluent,
|
10
|
+
"diagKnown",
|
11
|
+
[
|
12
|
+
:event_set,
|
13
|
+
"Diagnosis:start"
|
14
|
+
],
|
15
|
+
[
|
16
|
+
:event_set,
|
17
|
+
"Treatment:end"
|
18
|
+
],
|
19
|
+
nil
|
20
|
+
]
|
21
|
+
],
|
22
22
|
[
|
23
|
-
:
|
23
|
+
:task_refinement,
|
24
24
|
[
|
25
|
-
:
|
25
|
+
:seq_st,
|
26
26
|
[
|
27
|
-
:
|
27
|
+
:if_st,
|
28
|
+
[
|
29
|
+
:bool_not,
|
30
|
+
[
|
31
|
+
:var_ref,
|
32
|
+
"diagKnown"
|
33
|
+
]
|
34
|
+
],
|
28
35
|
[
|
29
|
-
:
|
30
|
-
"
|
36
|
+
:task_call_st,
|
37
|
+
"Diagnosis"
|
38
|
+
],
|
39
|
+
[
|
40
|
+
:else_clause,
|
41
|
+
[
|
42
|
+
:task_call_st,
|
43
|
+
"NoDiag"
|
44
|
+
]
|
31
45
|
]
|
32
46
|
],
|
33
47
|
[
|
34
|
-
:
|
35
|
-
"
|
48
|
+
:task_call_st,
|
49
|
+
"Treatment"
|
36
50
|
]
|
37
|
-
],
|
38
|
-
[
|
39
|
-
:task_call,
|
40
|
-
"Treatment"
|
41
51
|
]
|
42
52
|
]
|
43
53
|
]
|
@@ -7,6 +7,7 @@ SYNOPSIS
|
|
7
7
|
|
8
8
|
OPTIONS
|
9
9
|
--ast=[MODE] Prints the process abstract syntax tree (debug,ruby)
|
10
|
+
--no-sugar Apply syntactic sugar removal
|
10
11
|
--help Show this help message
|
11
12
|
--version Show version and exit
|
12
13
|
|
@@ -19,4 +20,8 @@ DESCRIPTION
|
|
19
20
|
debugging, that is with colors and extra information. Use --ast=ruby to get a ruby
|
20
21
|
array for automatic processing.
|
21
22
|
|
23
|
+
When --no-sugar is specified, syntactic sugar is first removed before making any other
|
24
|
+
transformation. For now, this rewrites all `if` statements as explicit `case` guarded
|
25
|
+
commands.
|
26
|
+
|
22
27
|
SystemExit
|
@@ -0,0 +1 @@
|
|
1
|
+
gisele --no-sugar --ast=ruby tasks/simple.gis
|
@@ -0,0 +1,61 @@
|
|
1
|
+
[
|
2
|
+
:unit,
|
3
|
+
[
|
4
|
+
:task_def,
|
5
|
+
"Simple",
|
6
|
+
[
|
7
|
+
:task_signature,
|
8
|
+
[
|
9
|
+
:fluent,
|
10
|
+
"diagKnown",
|
11
|
+
[
|
12
|
+
:event_set,
|
13
|
+
"Diagnosis:start"
|
14
|
+
],
|
15
|
+
[
|
16
|
+
:event_set,
|
17
|
+
"Treatment:end"
|
18
|
+
],
|
19
|
+
nil
|
20
|
+
]
|
21
|
+
],
|
22
|
+
[
|
23
|
+
:task_refinement,
|
24
|
+
[
|
25
|
+
:seq_st,
|
26
|
+
[
|
27
|
+
:case_st,
|
28
|
+
[
|
29
|
+
:when_clause,
|
30
|
+
[
|
31
|
+
:bool_not,
|
32
|
+
[
|
33
|
+
:var_ref,
|
34
|
+
"diagKnown"
|
35
|
+
]
|
36
|
+
],
|
37
|
+
[
|
38
|
+
:task_call_st,
|
39
|
+
"Diagnosis"
|
40
|
+
]
|
41
|
+
],
|
42
|
+
[
|
43
|
+
:when_clause,
|
44
|
+
[
|
45
|
+
:var_ref,
|
46
|
+
"diagKnown"
|
47
|
+
],
|
48
|
+
[
|
49
|
+
:task_call_st,
|
50
|
+
"NoDiag"
|
51
|
+
]
|
52
|
+
]
|
53
|
+
],
|
54
|
+
[
|
55
|
+
:task_call_st,
|
56
|
+
"Treatment"
|
57
|
+
]
|
58
|
+
]
|
59
|
+
]
|
60
|
+
]
|
61
|
+
]
|
@@ -1,15 +1,19 @@
|
|
1
|
-
[:
|
2
|
-
[:
|
3
|
-
[:
|
4
|
-
[:
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
[:
|
10
|
-
[:
|
11
|
-
[:
|
12
|
-
|
13
|
-
|
14
|
-
|
1
|
+
[:unit,
|
2
|
+
[:task_def, "Simple",
|
3
|
+
[:task_signature,
|
4
|
+
[:fluent, "diagKnown",
|
5
|
+
[:event_set, "Diagnosis:start"],
|
6
|
+
[:event_set, "Treatment:end"],
|
7
|
+
nil ]
|
8
|
+
],
|
9
|
+
[:task_refinement,
|
10
|
+
[:seq_st,
|
11
|
+
[:if_st,
|
12
|
+
[:bool_not, [:var_ref, "diagKnown"]],
|
13
|
+
[:task_call_st, "Diagnosis"],
|
14
|
+
[:else_clause,
|
15
|
+
[:task_call_st, "NoDiag"] ]],
|
16
|
+
[:task_call_st, "Treatment"]]
|
17
|
+
]
|
18
|
+
]
|
15
19
|
]
|
data/spec/spec_helper.rb
CHANGED
@@ -11,7 +11,7 @@ ensure
|
|
11
11
|
$stdout, $stderr = stdout, stderr
|
12
12
|
end
|
13
13
|
|
14
|
-
module
|
14
|
+
module SpecHelpers
|
15
15
|
|
16
16
|
def fixtures_dir
|
17
17
|
(Path.dir/:fixtures)
|
@@ -24,6 +24,6 @@ module Helpers
|
|
24
24
|
end
|
25
25
|
|
26
26
|
RSpec.configure do |c|
|
27
|
-
c.extend
|
28
|
-
c.include
|
27
|
+
c.extend SpecHelpers
|
28
|
+
c.include SpecHelpers
|
29
29
|
end
|
data/spec/test_examples.rb
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
describe "The examples" do
|
3
|
-
|
3
|
+
|
4
4
|
(Path.backfind(".[examples]")/:examples).glob("**/*.gis").each do |file|
|
5
5
|
|
6
6
|
describe file do
|
7
7
|
it 'parses without any error' do
|
8
|
-
Gisele::
|
8
|
+
Gisele::ast(file).should be_a(Array)
|
9
9
|
end
|
10
10
|
end
|
11
11
|
|
12
12
|
end
|
13
|
-
|
13
|
+
|
14
14
|
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
module Gisele::Language::AST
|
3
|
+
describe Node do
|
4
|
+
include Helpers
|
5
|
+
|
6
|
+
describe 'rule_name' do
|
7
|
+
it 'returns the first array element' do
|
8
|
+
node([:hello]).rule_name.should eq(:hello)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
describe 'children' do
|
13
|
+
|
14
|
+
it 'returns all but the rule name' do
|
15
|
+
node([:hello, "world", "!"]).children.should eq(["world", "!"])
|
16
|
+
end
|
17
|
+
|
18
|
+
it 'returns an empty array when no children' do
|
19
|
+
node([:hello]).children.should eq([])
|
20
|
+
end
|
21
|
+
|
22
|
+
end # children
|
23
|
+
|
24
|
+
describe 'copy' do
|
25
|
+
|
26
|
+
it 'collects block results ala `inject`' do
|
27
|
+
source = node([:unit, "world", "gisele"])
|
28
|
+
target = source.copy do |memo,child|
|
29
|
+
memo << child.upcase
|
30
|
+
end
|
31
|
+
target.should be_a(Unit)
|
32
|
+
target.should eq([:unit, "WORLD", "GISELE"])
|
33
|
+
end
|
34
|
+
|
35
|
+
it 'returns a real equal copy when no children' do
|
36
|
+
source = node([:unit])
|
37
|
+
target = source.copy do |memo,child| end
|
38
|
+
target.should eq(source)
|
39
|
+
target.object_id.should_not eq(source.object_id)
|
40
|
+
target.should be_a(Unit)
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
44
|
+
|
45
|
+
describe 'dup' do
|
46
|
+
|
47
|
+
it 'duplicates the underlying array' do
|
48
|
+
arr = [:unit, "etc."]
|
49
|
+
node(arr).dup.should eq(arr)
|
50
|
+
end
|
51
|
+
|
52
|
+
it 'ensures duplicated array is still a node' do
|
53
|
+
arr = [:unit, "etc."]
|
54
|
+
node(arr).dup.should be_a(Unit)
|
55
|
+
node(arr).dup.should be_a(Node)
|
56
|
+
end
|
57
|
+
|
58
|
+
end # dup
|
59
|
+
|
60
|
+
end
|
61
|
+
end
|