gisele 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (44) hide show
  1. data/CHANGELOG.md +16 -1
  2. data/Gemfile +1 -0
  3. data/Gemfile.lock +2 -0
  4. data/gisele.gemspec +1 -0
  5. data/gisele.noespec +2 -1
  6. data/lib/gisele/command.rb +21 -6
  7. data/lib/gisele/language/ast/bool_and.rb +14 -0
  8. data/lib/gisele/language/ast/bool_expr.rb +14 -0
  9. data/lib/gisele/language/ast/bool_not.rb +14 -0
  10. data/lib/gisele/language/ast/bool_or.rb +14 -0
  11. data/lib/gisele/language/ast/elsif_clause.rb +14 -0
  12. data/lib/gisele/language/ast/helpers.rb +15 -9
  13. data/lib/gisele/language/ast/if_st.rb +14 -0
  14. data/lib/gisele/language/ast/node.rb +39 -3
  15. data/lib/gisele/language/ast/task_call_st.rb +14 -0
  16. data/lib/gisele/language/ast/var_ref.rb +14 -0
  17. data/lib/gisele/language/ast/when_clause.rb +14 -0
  18. data/lib/gisele/language/ast/while_st.rb +14 -0
  19. data/lib/gisele/language/ast.rb +2 -2
  20. data/lib/gisele/language/dot.yml +19 -0
  21. data/lib/gisele/language/sugar_removal.rb +30 -9
  22. data/lib/gisele/language/syntax/bool_expr.rb +14 -0
  23. data/lib/gisele/language/syntax/bool_lit.rb +1 -1
  24. data/lib/gisele/language/syntax/grammar.citrus +4 -3
  25. data/lib/gisele/language/syntax/node.rb +2 -1
  26. data/lib/gisele/language/to_graph.rb +119 -0
  27. data/lib/gisele/language.rb +4 -1
  28. data/lib/gisele/loader.rb +1 -0
  29. data/lib/gisele/version.rb +1 -1
  30. data/spec/command/main/gisele_ast_ruby.stdout +6 -3
  31. data/spec/command/main/gisele_graph.cmd +1 -0
  32. data/spec/command/main/gisele_graph.stdout +30 -0
  33. data/spec/command/main/gisele_help.stdout +10 -5
  34. data/spec/command/main/gisele_no_sugar.stdout +11 -5
  35. data/spec/command/main/gisele_version.stdout +1 -1
  36. data/spec/fixtures/tasks/complete.gis +18 -0
  37. data/spec/fixtures/tasks/simple.ast +57 -19
  38. data/spec/spec_helper.rb +8 -0
  39. data/spec/unit/language/ast/test_node.rb +22 -0
  40. data/spec/unit/language/sugar_removal/test_if_to_guarded_commands.rb +32 -12
  41. data/spec/unit/language/syntax/test_to_ast.rb +23 -11
  42. data/spec/unit/language/test_syntax.rb +5 -0
  43. data/spec/unit/language/test_to_graph.rb +10 -0
  44. metadata +50 -18
data/CHANGELOG.md CHANGED
@@ -1,4 +1,19 @@
1
- # 0.1.0 / FIX ME
1
+ # 0.2.0 / 2012-02-17
2
+
3
+ ## Enhancements
4
+
5
+ * A --graph option has been added to the main `gisele` shell command. It outputs a graph in
6
+ the graphviz/dot format representing a process as a box-and-arrow workflow.
7
+
8
+ ## Breaking changes
9
+
10
+ * Boolean literals (true, false) are now explicitly represented in boolean expressions,
11
+ under a :bool_lit AST node.
12
+ * All statements and clauses relying on boolean conditions (if_st, while_st, elsif_clause,
13
+ when_clause) have now an explicit :bool_expr node as first child. Previously, a subnode
14
+ of the boolean grammar was used.
15
+
16
+ # 0.1.0 / 2012-02-17
2
17
 
3
18
  ## Enhancements
4
19
 
data/Gemfile CHANGED
@@ -5,6 +5,7 @@ group :runtime do
5
5
  gem "epath", "~> 0.0.1"
6
6
  gem "quickl", "~> 0.4.3"
7
7
  gem "awesome_print", "~> 1.0"
8
+ gem "yargi", "~> 0.2.0"
8
9
  end
9
10
 
10
11
  group :development do
data/Gemfile.lock CHANGED
@@ -16,6 +16,7 @@ GEM
16
16
  diff-lcs (~> 1.1.2)
17
17
  rspec-mocks (2.8.0)
18
18
  wlang (0.10.2)
19
+ yargi (0.2.0)
19
20
 
20
21
  PLATFORMS
21
22
  ruby
@@ -29,3 +30,4 @@ DEPENDENCIES
29
30
  rake (~> 0.9.2)
30
31
  rspec (~> 2.8.0)
31
32
  wlang (~> 0.10.2)
33
+ yargi (~> 0.2.0)
data/gisele.gemspec CHANGED
@@ -131,6 +131,7 @@ Gem::Specification.new do |s|
131
131
  s.add_dependency("epath", "~> 0.0.1")
132
132
  s.add_dependency("quickl", "~> 0.4.3")
133
133
  s.add_dependency("awesome_print", "~> 1.0")
134
+ s.add_dependency("yargi", "~> 0.2.0")
134
135
 
135
136
  # The version of ruby required by this gem
136
137
  #
data/gisele.noespec CHANGED
@@ -12,7 +12,7 @@ variables:
12
12
  upper:
13
13
  Gisele
14
14
  version:
15
- 0.1.0
15
+ 0.2.0
16
16
  summary: |-
17
17
  Gisele is a Process Analyzer Toolset
18
18
  description: |-
@@ -29,6 +29,7 @@ variables:
29
29
  - {name: epath, version: "~> 0.0.1", groups: [runtime]}
30
30
  - {name: quickl, version: "~> 0.4.3", groups: [runtime]}
31
31
  - {name: awesome_print, version: "~> 1.0", groups: [runtime]}
32
+ - {name: yargi, version: "~> 0.2.0", groups: [runtime]}
32
33
  #
33
34
  - {name: rake, version: "~> 0.9.2", groups: [development]}
34
35
  - {name: bundler, version: "~> 1.0", groups: [development]}
@@ -5,7 +5,7 @@ module Gisele
5
5
  #
6
6
  # SYNOPSIS
7
7
  # gisele [--version] [--help]
8
- # gisele [--ast] PROCESS_FILE
8
+ # gisele [--ast | --graph] PROCESS_FILE
9
9
  #
10
10
  # OPTIONS
11
11
  # #{summarized_options}
@@ -14,14 +14,18 @@ module Gisele
14
14
  # The Gisele process analyzer toolset provides tools and technique to model and analyze
15
15
  # complex process models such as care processes.
16
16
  #
17
- # When --ast is used, the command parses a process file and prints its Abstract Syntax
17
+ # When --no-sugar is specified, syntactic sugar is first removed before making any other
18
+ # transformation. For now, this rewrites all `if` statements as explicit `case` guarded
19
+ # commands.
20
+ #
21
+ # When --ast is used, the command parses the process file and prints its Abstract Syntax
18
22
  # Tree (AST) on standard output. By default, this option prints the AST for manual
19
23
  # debugging, that is with colors and extra information. Use --ast=ruby to get a ruby
20
24
  # array for automatic processing.
21
25
  #
22
- # When --no-sugar is specified, syntactic sugar is first removed before making any other
23
- # transformation. For now, this rewrites all `if` statements as explicit `case` guarded
24
- # commands.
26
+ # When --graph is used, the command parses the process file. It then converts the AST into
27
+ # a directed graph representing the process as a box-and-arrow workflow and outputs it on
28
+ # standard output. For now, the only output format available is dot (from graphviz).
25
29
  #
26
30
  class Gisele::Command < Quickl::Command(__FILE__, __LINE__)
27
31
 
@@ -35,6 +39,10 @@ module Gisele
35
39
  opt.on('--no-sugar', 'Apply syntactic sugar removal') do
36
40
  @sugar = false
37
41
  end
42
+ @print_graph = nil
43
+ opt.on('--graph=[MODE]', 'Converts and print a graph (dot)') do |value|
44
+ @print_graph = (value || "dot").to_sym
45
+ end
38
46
  opt.on_tail('--help', "Show this help message") do
39
47
  raise Quickl::Help
40
48
  end
@@ -52,7 +60,9 @@ module Gisele
52
60
 
53
61
  ast = Gisele.ast(file)
54
62
  ast = Gisele::Language::SugarRemoval.new.call(ast) unless @sugar
63
+
55
64
  print_ast(ast, @print_ast) if @print_ast
65
+ print_graph(ast, @print_graph) if @print_graph
56
66
  end
57
67
 
58
68
  private
@@ -68,5 +78,10 @@ module Gisele
68
78
  ap ast, options
69
79
  end
70
80
 
71
- end # class Command
81
+ def print_graph(ast, option)
82
+ graph = Gisele::Language::ToGraph.new.call(ast)
83
+ puts graph.to_dot
84
+ end
85
+
86
+ end # class Command
72
87
  end # module Gisele
@@ -0,0 +1,14 @@
1
+ module Gisele
2
+ module Language
3
+ module AST
4
+ module BoolAnd
5
+ include Node
6
+
7
+ def label
8
+ markers[:match] ? markers[:match].to_s : "(#{self[1].label} and #{self[2].label})"
9
+ end
10
+
11
+ end # module BoolAnd
12
+ end # module AST
13
+ end # module Language
14
+ end # module Gisele
@@ -0,0 +1,14 @@
1
+ module Gisele
2
+ module Language
3
+ module AST
4
+ module BoolExpr
5
+ include Node
6
+
7
+ def label
8
+ markers[:match] ? markers[:match].to_s : last.label
9
+ end
10
+
11
+ end # module BoolExpr
12
+ end # module AST
13
+ end # module Language
14
+ end # module Gisele
@@ -0,0 +1,14 @@
1
+ module Gisele
2
+ module Language
3
+ module AST
4
+ module BoolNot
5
+ include Node
6
+
7
+ def label
8
+ markers[:match] ? markers[:match].to_s : "not(#{last.label})"
9
+ end
10
+
11
+ end # module BoolNot
12
+ end # module AST
13
+ end # module Language
14
+ end # module Gisele
@@ -0,0 +1,14 @@
1
+ module Gisele
2
+ module Language
3
+ module AST
4
+ module BoolOr
5
+ include Node
6
+
7
+ def label
8
+ markers[:match] ? markers[:match].to_s : "(#{self[1].label} or #{self[2].label})"
9
+ end
10
+
11
+ end # module BoolOr
12
+ end # module AST
13
+ end # module Language
14
+ end # module Gisele
@@ -0,0 +1,14 @@
1
+ module Gisele
2
+ module Language
3
+ module AST
4
+ module ElsifClause
5
+ include Node
6
+
7
+ def label
8
+ self[1].label
9
+ end
10
+
11
+ end # module ElsifClause
12
+ end # module AST
13
+ end # module Language
14
+ end # module Gisele
@@ -3,17 +3,17 @@ module Gisele
3
3
  module AST
4
4
  module Helpers
5
5
 
6
- def ast(arg)
7
- return node(arg) if looks_a_node?(arg)
8
- Syntax.ast(arg)
6
+ def ast(arg, markers = {})
7
+ return node(arg, markers) if looks_a_node?(arg)
8
+ ast(Syntax.ast(arg), markers)
9
9
  end
10
10
 
11
- def node(arg)
11
+ def node(arg, markers = {})
12
12
  return arg if arg.is_a?(Node)
13
13
  unless looks_a_node?(arg)
14
14
  raise ArgumentError, "Array expected, #{arg.inspect} found."
15
15
  end
16
- extend_node(arg).tap do |node|
16
+ extend_node(arg, markers).tap do |node|
17
17
  node.children.each{|c| node(c) if looks_a_node?(c)}
18
18
  end
19
19
  end
@@ -24,10 +24,16 @@ module Gisele
24
24
  arg.is_a?(Node) or (arg.is_a?(Array) and arg.first.is_a?(Symbol))
25
25
  end
26
26
 
27
- def extend_node(arg)
28
- modname = Language.rule2mod(arg.first)
29
- mod = AST.const_get(modname) rescue Node
30
- arg.extend(mod)
27
+ def extend_node(arg, markers)
28
+ mod = ast_module(arg)
29
+ arg.extend(mod).tap do |node|
30
+ node.markers = markers
31
+ end
32
+ end
33
+
34
+ def ast_module(node)
35
+ modname = Language.rule2mod(node.first)
36
+ AST.const_get(modname) rescue Node
31
37
  end
32
38
 
33
39
  extend(self)
@@ -0,0 +1,14 @@
1
+ module Gisele
2
+ module Language
3
+ module AST
4
+ module IfSt
5
+ include Node
6
+
7
+ def label
8
+ self[1].label
9
+ end
10
+
11
+ end # module IfSt
12
+ end # module AST
13
+ end # module Language
14
+ end # module Gisele
@@ -3,6 +3,16 @@ module Gisele
3
3
  module AST
4
4
  module Node
5
5
 
6
+ # Returns the node markers
7
+ def markers
8
+ @markers ||= {}
9
+ end
10
+
11
+ # Sets node markers
12
+ def markers=(markers)
13
+ @markers = markers
14
+ end
15
+
6
16
  # Returns the rule name, that is, the first Symbol element
7
17
  # of the node array.
8
18
  #
@@ -24,6 +34,11 @@ module Gisele
24
34
  self[1..-1]
25
35
  end
26
36
 
37
+ # Returns the associated ast_module
38
+ def ast_module
39
+ AST::Helpers.send(:ast_module, self)
40
+ end
41
+
27
42
  # Applies copy-and-transform to this node.
28
43
  #
29
44
  # Example:
@@ -34,7 +49,7 @@ module Gisele
34
49
  # # => [:something, ...]
35
50
  #
36
51
  def copy(&block)
37
- base = AST.node([rule_name])
52
+ base = AST.node([rule_name], markers.dup)
38
53
  children.inject(base, &block)
39
54
  end
40
55
 
@@ -44,11 +59,32 @@ module Gisele
44
59
  # will correctly be applied to the duplicated array.
45
60
  #
46
61
  def dup
47
- AST.node(super)
62
+ AST.node(super, markers.dup)
63
+ end
64
+
65
+ # Returns a label for this AST node
66
+ def label
67
+ ""
68
+ end
69
+
70
+ # Returns attributes to use for dot printing
71
+ def dot_attributes
72
+ attrs = Language::DOT_ATTRIBUTES[rule_name.to_s] || {}
73
+ attrs.merge(:label => label)
48
74
  end
49
75
 
50
76
  end # module Node
51
77
  end # module AST
52
78
  end # module Language
53
79
  end # module Gisele
54
- require_relative 'unit'
80
+ require_relative 'unit'
81
+ require_relative 'task_call_st'
82
+ require_relative 'while_st'
83
+ require_relative 'if_st'
84
+ require_relative 'elsif_clause'
85
+ require_relative 'when_clause'
86
+ require_relative 'bool_expr'
87
+ require_relative 'bool_and'
88
+ require_relative 'bool_or'
89
+ require_relative 'bool_not'
90
+ require_relative 'var_ref'
@@ -0,0 +1,14 @@
1
+ module Gisele
2
+ module Language
3
+ module AST
4
+ module TaskCallSt
5
+ include Node
6
+
7
+ def label
8
+ last.to_s
9
+ end
10
+
11
+ end # module TaskCallSt
12
+ end # module AST
13
+ end # module Language
14
+ end # module Gisele
@@ -0,0 +1,14 @@
1
+ module Gisele
2
+ module Language
3
+ module AST
4
+ module VarRef
5
+ include Node
6
+
7
+ def label
8
+ last.to_s
9
+ end
10
+
11
+ end # module BoolNot
12
+ end # module AST
13
+ end # module Language
14
+ end # module Gisele
@@ -0,0 +1,14 @@
1
+ module Gisele
2
+ module Language
3
+ module AST
4
+ module WhenClause
5
+ include Node
6
+
7
+ def label
8
+ self[1].label
9
+ end
10
+
11
+ end # module WhenClause
12
+ end # module AST
13
+ end # module Language
14
+ end # module Gisele
@@ -0,0 +1,14 @@
1
+ module Gisele
2
+ module Language
3
+ module AST
4
+ module WhileSt
5
+ include Node
6
+
7
+ def label
8
+ self[1].label
9
+ end
10
+
11
+ end # module WhileSt
12
+ end # module AST
13
+ end # module Language
14
+ end # module Gisele
@@ -2,8 +2,8 @@ module Gisele
2
2
  module Language
3
3
  module AST
4
4
 
5
- def node(arg)
6
- AST::Helpers.node(arg)
5
+ def node(arg, markers = {})
6
+ AST::Helpers.node(arg, markers)
7
7
  end
8
8
  module_function :node
9
9
 
@@ -0,0 +1,19 @@
1
+ task_refinement:
2
+ shape: circle
3
+ style: filled
4
+ fillcolor: black
5
+ fixed: true
6
+ width: 0.1
7
+ task_call_st:
8
+ shape: box
9
+ while_st:
10
+ shape: diamond
11
+ if_st:
12
+ shape: diamond
13
+ case_st:
14
+ shape: diamond
15
+ par_st:
16
+ shape: box
17
+ height: 0.1
18
+ style: filled
19
+ fillcolor: black
@@ -15,8 +15,17 @@ module Gisele
15
15
 
16
16
  def on_if_st(node)
17
17
  condition, dost, *clauses = node.children
18
- base = [:case_st, [:when_clause, condition, @main.call(dost)] ]
19
- @condition = negate(condition)
18
+
19
+ # create case_st with same markers as the if_st
20
+ when_clause = [:when_clause, condition, @main.call(dost)]
21
+ when_clause = node(when_clause, node.markers.dup)
22
+ base = [:case_st, when_clause]
23
+ base = node(base, node.markers.dup)
24
+
25
+ # this is the condition for elsif clauses
26
+ @condition = negate(condition.last)
27
+
28
+ # make injection now
20
29
  clauses.inject base do |memo,clause|
21
30
  memo << call(clause)
22
31
  end
@@ -24,17 +33,29 @@ module Gisele
24
33
 
25
34
  def on_elsif_clause(node)
26
35
  condition, dost, = node.children
27
- prev, @condition = @condition, [:bool_and, negate(condition), @condition]
28
- [:when_clause,
29
- [:bool_and, condition, prev],
30
- @main.call(dost)]
36
+
37
+ # install new conditions for me and next elsif clauses
38
+ condition = condition.last
39
+ previous = @condition
40
+ @condition = [:bool_and, negate(condition), @condition]
41
+
42
+ # convert elsif to when and keep the markers
43
+ base = \
44
+ [:when_clause,
45
+ [:bool_expr, [:bool_and, condition, previous]],
46
+ @main.call(dost) ]
47
+ node(base, node.markers.dup)
31
48
  end
32
49
 
33
50
  def on_else_clause(node)
34
51
  dost, = node.children
35
- [:when_clause,
36
- @condition,
37
- @main.call(dost)]
52
+
53
+ # convert else to when and keep the markers
54
+ base = \
55
+ [:when_clause,
56
+ [:bool_expr, @condition],
57
+ @main.call(dost)]
58
+ node(base, node.markers.dup)
38
59
  end
39
60
 
40
61
  private
@@ -0,0 +1,14 @@
1
+ module Gisele
2
+ module Language
3
+ module Syntax
4
+ module BoolExpr
5
+ include Node
6
+
7
+ def _to_ast
8
+ [:bool_expr, captures[:theexpr].first.to_ast]
9
+ end
10
+
11
+ end # module BoolExpr
12
+ end # module Syntax
13
+ end # module Language
14
+ end # module Gisele
@@ -5,7 +5,7 @@ module Gisele
5
5
  include Node
6
6
 
7
7
  def _to_ast
8
- captures[:boolean_literal].first.value
8
+ [:bool_lit, strip == "true"]
9
9
  end
10
10
 
11
11
  end # module BoolLit
@@ -90,7 +90,8 @@ grammar Gisele::Language::Syntax::Grammar
90
90
  ### Boolean expressions
91
91
 
92
92
  rule bool_expr
93
- bool_or
93
+ (spacing theexpr:bool_or)
94
+ <Gisele::Language::Syntax::BoolExpr>
94
95
  end
95
96
 
96
97
  rule bool_or
@@ -112,11 +113,11 @@ grammar Gisele::Language::Syntax::Grammar
112
113
  end
113
114
 
114
115
  rule bool_term
115
- bool_paren | boolean_literal | bool_varref
116
+ bool_paren | bool_lit | bool_varref
116
117
  end
117
118
 
118
119
  rule bool_paren
119
- ('(' spacing expr:bool_expr spacing ')')
120
+ ('(' spacing expr:bool_or spacing ')')
120
121
  <Gisele::Language::Syntax::BoolParen>
121
122
  end
122
123
 
@@ -4,7 +4,7 @@ module Gisele
4
4
  module Node
5
5
 
6
6
  def to_ast
7
- Language::AST.node(_to_ast)
7
+ Language::AST.node(_to_ast, {:match => self})
8
8
  end
9
9
 
10
10
  end # module Node
@@ -20,6 +20,7 @@ require_relative 'bool_paren'
20
20
  require_relative 'bool_not'
21
21
  require_relative 'bool_and'
22
22
  require_relative 'bool_or'
23
+ require_relative 'bool_expr'
23
24
  require_relative 'st_list'
24
25
  require_relative 'implicit_seq_st'
25
26
  require_relative 'task_call_st'
@@ -0,0 +1,119 @@
1
+ module Gisele
2
+ module Language
3
+ class ToGraph < Transformer
4
+ module Connector; end
5
+
6
+ def recurse_on_last(node)
7
+ call(node.last)
8
+ end
9
+ alias :on_unit :recurse_on_last
10
+
11
+ def on_task_def(node)
12
+ @graph = Yargi::Digraph.new
13
+ call(SugarRemoval.new.call(node.last))
14
+ @graph.vertices(Connector).each do |vertex|
15
+ next unless vertex.out_edges.size == 1
16
+ target = vertex.out_edges.first.target
17
+ @graph.reconnect(vertex.in_edges, nil, target)
18
+ @graph.remove_vertex(vertex)
19
+ end
20
+ @graph
21
+ end
22
+
23
+ def on_task_refinement(node)
24
+ entry, exit = add_vertex(node), add_vertex(node)
25
+ c_entry, c_exit = call(node.last)
26
+ connect(entry, c_entry)
27
+ connect(c_exit, exit)
28
+ [entry, exit]
29
+ end
30
+
31
+ def on_seq_st(node)
32
+ mine = entry_and_exit(node)
33
+ current = mine.first
34
+ node.children.each do |child|
35
+ c_entry, c_exit = call(child)
36
+ connect(current, c_entry)
37
+ current = c_exit
38
+ end
39
+ connect(current, mine.last)
40
+ mine
41
+ end
42
+
43
+ def on_par_st(node)
44
+ entry, exit = add_vertex(node), add_vertex(node)
45
+ node.children.each do |child|
46
+ c_entry, c_exit = call(child)
47
+ connect(entry, c_entry)
48
+ connect(c_exit, exit)
49
+ end
50
+ [entry, exit]
51
+ end
52
+
53
+ def on_case_st(node)
54
+ entry, exit = entry_and_exit(node)
55
+
56
+ diamond = add_vertex(node)
57
+ connect(entry, diamond)
58
+
59
+ node.children.each do |when_clause|
60
+ c_entry, c_exit = call(when_clause.last)
61
+ connect(diamond, c_entry, when_clause)
62
+ connect(c_exit, exit)
63
+ end
64
+
65
+ [entry, exit]
66
+ end
67
+
68
+
69
+ def on_while_st(node)
70
+ cond, dost, = node.children
71
+
72
+ entry, exit = entry_and_exit(node)
73
+
74
+ diamond = add_vertex(node)
75
+ connect(entry, diamond)
76
+
77
+ c_entry, c_exit = call(node.last)
78
+
79
+ connect(diamond, exit, false_ast_node)
80
+ connect(diamond, c_entry, true_ast_node)
81
+ connect(c_exit, diamond)
82
+
83
+ [entry, exit]
84
+ end
85
+
86
+ def on_task_call_st(node)
87
+ entry, exit = entry_and_exit(node)
88
+ task = add_vertex(node)
89
+ connect(entry, task)
90
+ connect(task, exit)
91
+ [entry, exit]
92
+ end
93
+
94
+ private
95
+
96
+ def add_vertex(node)
97
+ @graph.add_vertex(node.dot_attributes)
98
+ end
99
+
100
+ def entry_and_exit(node, tag = Connector)
101
+ @graph.add_n_vertices(2, tag)
102
+ end
103
+
104
+ def connect(source, target, node = nil)
105
+ marks = node.nil? ? {} : node.dot_attributes
106
+ @graph.connect(source, target, marks)
107
+ end
108
+
109
+ def false_ast_node
110
+ Syntax.ast("false", :root => :bool_expr)
111
+ end
112
+
113
+ def true_ast_node
114
+ Syntax.ast("true", :root => :bool_expr)
115
+ end
116
+
117
+ end # class SugarRemoval
118
+ end # module Language
119
+ end # module Gisele