gisele 0.0.1 → 0.1.0
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/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
|