sequitur 0.1.10 → 0.1.11

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,106 +1,106 @@
1
- require_relative 'production'
2
- require_relative 'grammar_visitor'
3
-
4
- module Sequitur # Module for classes implementing the Sequitur algorithm
5
-
6
- # A dynamic grammar is a context-free grammar that can be built incrementally.
7
- # Formally, a grammar has:
8
- # One start production
9
- # Zero or more other productions
10
- # Each production has a rhs that is a sequence of grammar symbols.
11
- # Grammar symbols are categorized into
12
- # -terminal symbols (i.e. String, Ruby Symbol,...)
13
- # -non-terminal symbols (i.e. ProductionRef)
14
- class DynamicGrammar
15
- # Link to the start production.
16
- attr_reader(:start)
17
-
18
- # The set of production rules of the grammar
19
- attr_reader(:productions)
20
-
21
- # nodoc Trace the execution of the algorithm.
22
- attr(:trace)
23
-
24
-
25
- # Constructor.
26
- # Build a grammar with one empty rule as start/start rule.
27
- def initialize()
28
- @start = Production.new
29
- @productions = [ start ]
30
- @trace = false
31
- end
32
-
33
- public
34
-
35
- # Emit a text representation of the grammar.
36
- # Each production rule is emitted per line.
37
- # @return [String]
38
- def to_string()
39
- rule_text = productions.map(&:to_string).join("\n")
40
- return rule_text
41
- end
42
-
43
-
44
- # Add a given production to the grammar.
45
- # @param aProduction [Production]
46
- def add_production(aProduction)
47
- # TODO: remove output
48
- puts "Adding #{aProduction.object_id}" if trace
49
- puts aProduction.to_string if trace
50
- productions << aProduction
51
- end
52
-
53
-
54
- # Remove a production with given index from the grammar
55
- # @param anIndex [Fixnum]
56
- # @return [Production] the production removed from the grammar.
57
- def remove_production(anIndex)
58
- puts "Before production removal #{productions[anIndex].object_id}" if trace
59
- puts to_string if trace
60
- prod = productions.delete_at(anIndex)
61
- # TODO: remove output
62
- puts('Removed: ' + prod.to_string) if trace
63
- prod.clear_rhs
64
-
65
- return prod
66
- end
67
-
68
-
69
- # Add the given token to the grammar.
70
- # Append the token to the rhs of the start/start rule.
71
- # @param aToken [Object] input token to add
72
- def add_token(aToken)
73
- append_symbol_to(start, aToken)
74
- end
75
-
76
- # Part of the 'visitee' role in the Visitor design pattern.
77
- # A visitee is expected to accept the visit from a visitor object
78
- # @param aVisitor [GrammarVisitor] the visitor object
79
- def accept(aVisitor)
80
- aVisitor.start_visit_grammar(self)
81
-
82
- # Let's proceed with the visit of productions
83
- productions.each { |prod| prod.accept(aVisitor) }
84
-
85
- aVisitor.end_visit_grammar(self)
86
- end
87
-
88
- # Factory method. Returns a visitor for this grammar.
89
- # @return [GrammarVisitor]
90
- def visitor()
91
- return GrammarVisitor.new(self)
92
- end
93
-
94
- protected
95
-
96
- # Append a given symbol to the rhs of passed production.
97
- # @param aProduction [Production]
98
- # @param aSymbol [Object]
99
- def append_symbol_to(aProduction, aSymbol)
100
- aProduction.append_symbol(aSymbol)
101
- end
102
- end # class
103
-
104
- end # module
105
-
106
- # End of file
1
+ require_relative 'production'
2
+ require_relative 'grammar_visitor'
3
+
4
+ module Sequitur # Module for classes implementing the Sequitur algorithm
5
+
6
+ # A dynamic grammar is a context-free grammar that can be built incrementally.
7
+ # Formally, a grammar has:
8
+ # One start production
9
+ # Zero or more other productions
10
+ # Each production has a rhs that is a sequence of grammar symbols.
11
+ # Grammar symbols are categorized into
12
+ # -terminal symbols (i.e. String, Ruby Symbol,...)
13
+ # -non-terminal symbols (i.e. ProductionRef)
14
+ class DynamicGrammar
15
+ # Link to the start production.
16
+ attr_reader(:start)
17
+
18
+ # The set of production rules of the grammar
19
+ attr_reader(:productions)
20
+
21
+ # nodoc Trace the execution of the algorithm.
22
+ attr(:trace)
23
+
24
+
25
+ # Constructor.
26
+ # Build a grammar with one empty rule as start/start rule.
27
+ def initialize()
28
+ @start = Production.new
29
+ @productions = [ start ]
30
+ @trace = false
31
+ end
32
+
33
+ public
34
+
35
+ # Emit a text representation of the grammar.
36
+ # Each production rule is emitted per line.
37
+ # @return [String]
38
+ def to_string()
39
+ rule_text = productions.map(&:to_string).join("\n")
40
+ return rule_text
41
+ end
42
+
43
+
44
+ # Add a given production to the grammar.
45
+ # @param aProduction [Production]
46
+ def add_production(aProduction)
47
+ # TODO: remove output
48
+ puts "Adding #{aProduction.object_id}" if trace
49
+ puts aProduction.to_string if trace
50
+ productions << aProduction
51
+ end
52
+
53
+
54
+ # Remove a production with given index from the grammar
55
+ # @param anIndex [Fixnum]
56
+ # @return [Production] the production removed from the grammar.
57
+ def remove_production(anIndex)
58
+ puts "Before production removal #{productions[anIndex].object_id}" if trace
59
+ puts to_string if trace
60
+ prod = productions.delete_at(anIndex)
61
+ # TODO: remove output
62
+ puts('Removed: ' + prod.to_string) if trace
63
+ prod.clear_rhs
64
+
65
+ return prod
66
+ end
67
+
68
+
69
+ # Add the given token to the grammar.
70
+ # Append the token to the rhs of the start/start rule.
71
+ # @param aToken [Object] input token to add
72
+ def add_token(aToken)
73
+ append_symbol_to(start, aToken)
74
+ end
75
+
76
+ # Part of the 'visitee' role in the Visitor design pattern.
77
+ # A visitee is expected to accept the visit from a visitor object
78
+ # @param aVisitor [GrammarVisitor] the visitor object
79
+ def accept(aVisitor)
80
+ aVisitor.start_visit_grammar(self)
81
+
82
+ # Let's proceed with the visit of productions
83
+ productions.each { |prod| prod.accept(aVisitor) }
84
+
85
+ aVisitor.end_visit_grammar(self)
86
+ end
87
+
88
+ # Factory method. Returns a visitor for this grammar.
89
+ # @return [GrammarVisitor]
90
+ def visitor()
91
+ return GrammarVisitor.new(self)
92
+ end
93
+
94
+ protected
95
+
96
+ # Append a given symbol to the rhs of passed production.
97
+ # @param aProduction [Production]
98
+ # @param aSymbol [Object]
99
+ def append_symbol_to(aProduction, aSymbol)
100
+ aProduction.append_symbol(aSymbol)
101
+ end
102
+ end # class
103
+
104
+ end # module
105
+
106
+ # End of file
@@ -1,39 +1,39 @@
1
- module Sequitur
2
-
3
- # Namespace dedicated to grammar formatters.
4
- module Formatter
5
-
6
- # Superclass for grammar formatters.
7
- class BaseFormatter
8
- # The IO output stream in which the formatter's result will be sent.
9
- attr(:output)
10
-
11
- # Constructor.
12
- # @param anIO [IO] an output IO where the formatter's result will
13
- # be placed.
14
- def initialize(anIO)
15
- @output = anIO
16
- end
17
-
18
- public
19
-
20
- # Given a grammar or a grammar visitor, perform the visit
21
- # and render the visit events in the output stream.
22
- # @param aGrmOrVisitor [DynamicGrammar or GrammarVisitor]
23
- def render(aGrmOrVisitor)
24
- if aGrmOrVisitor.kind_of?(GrammarVisitor)
25
- a_visitor = aGrmOrVisitor
26
- else
27
- a_visitor = aGrmOrVisitor.visitor
28
- end
29
-
30
- a_visitor.subscribe(self)
31
- a_visitor.start
32
- a_visitor.unsubscribe(self)
33
- end
34
-
35
- end # class
36
- end # module
37
- end # module
38
-
39
- # End of file
1
+ module Sequitur
2
+
3
+ # Namespace dedicated to grammar formatters.
4
+ module Formatter
5
+
6
+ # Superclass for grammar formatters.
7
+ class BaseFormatter
8
+ # The IO output stream in which the formatter's result will be sent.
9
+ attr(:output)
10
+
11
+ # Constructor.
12
+ # @param anIO [IO] an output IO where the formatter's result will
13
+ # be placed.
14
+ def initialize(anIO)
15
+ @output = anIO
16
+ end
17
+
18
+ public
19
+
20
+ # Given a grammar or a grammar visitor, perform the visit
21
+ # and render the visit events in the output stream.
22
+ # @param aGrmOrVisitor [DynamicGrammar or GrammarVisitor]
23
+ def render(aGrmOrVisitor)
24
+ if aGrmOrVisitor.kind_of?(GrammarVisitor)
25
+ a_visitor = aGrmOrVisitor
26
+ else
27
+ a_visitor = aGrmOrVisitor.visitor
28
+ end
29
+
30
+ a_visitor.subscribe(self)
31
+ a_visitor.start
32
+ a_visitor.unsubscribe(self)
33
+ end
34
+
35
+ end # class
36
+ end # module
37
+ end # module
38
+
39
+ # End of file
@@ -1,95 +1,95 @@
1
- require_relative 'base_formatter'
2
-
3
- module Sequitur
4
- module Formatter
5
-
6
- # A formatter class that can render a dynamic grammar in plain text.
7
- # @example
8
- # some_grammar = ... # Points to a DynamicGrammar-like object
9
- # # Output the result to the standard console output
10
- # formatter = Sequitur::Formatter::BaseText.new(STDOUT)
11
- # # Render the grammar (through a visitor)
12
- # formatter.run(some_grammar.visitor)
13
- class BaseText < BaseFormatter
14
-
15
- # Constructor.
16
- # @param anIO [IO] The output stream to which the rendered grammar
17
- # is written.
18
- def initialize(anIO)
19
- super(anIO)
20
- @prod_lookup = {}
21
- end
22
-
23
- public
24
-
25
- # Method called by a GrammarVisitor to which the formatter subscribed.
26
- # Notification of a visit event: the visitor is about to visit a grammar
27
- # @param aGrammar [DynamicGrammar-like object]
28
- def before_grammar(aGrammar)
29
- aGrammar.productions.each_with_index do |a_prod, index|
30
- prod_lookup[a_prod] = index
31
- end
32
- end
33
-
34
- # Method called by a GrammarVisitor to which the formatter subscribed.
35
- # Notification of a visit event: the visitor is about to visit
36
- # a production
37
- # @param aProduction [aProduction]
38
- def before_production(aProduction)
39
- p_name = prod_name(aProduction)
40
- output.print p_name
41
- end
42
-
43
- # Method called by a GrammarVisitor to which the formatter subscribed.
44
- # Notification of a visit event: the visitor is about to visit
45
- # the rhs of a production
46
- # @param _ [Array]
47
- def before_rhs(_)
48
- output.print ' :'
49
- end
50
-
51
- # Method called by a GrammarVisitor to which the formatter subscribed.
52
- # Notification of a visit event: the visitor is about to visit
53
- # a terminal symbol from the rhs of a production
54
- # @param aSymbol [Object]
55
- def before_terminal(aSymbol)
56
- output.print " #{aSymbol}"
57
- end
58
-
59
- # Method called by a GrammarVisitor to which the formatter subscribed.
60
- # Notification of a visit event: the visitor is about to visit
61
- # a non-terminal (= an allusion to a production) in the rhs of a
62
- # production
63
- # @param aProduction [Production] a production occurring in the rhs
64
- def before_non_terminal(aProduction)
65
- p_name = prod_name(aProduction)
66
- output.print " #{p_name}"
67
- end
68
-
69
- # Method called by a GrammarVisitor to which the formatter subscribed.
70
- # Notification of a visit event: the visitor complete the visit
71
- # of a production
72
- def after_production(_)
73
- output.print ".\n"
74
- end
75
-
76
- private
77
-
78
- # Read accessor of the production lookup
79
- def prod_lookup()
80
- return @prod_lookup
81
- end
82
-
83
- # Generate a name of a given production.
84
- # @param aProduction [Production]
85
- def prod_name(aProduction)
86
- prod_index = prod_lookup[aProduction]
87
- name = (prod_index == 0) ? 'start' : "P#{prod_index}"
88
- return name
89
- end
90
-
91
- end # class
92
- end # module
93
- end # module
94
-
95
- # End of file
1
+ require_relative 'base_formatter'
2
+
3
+ module Sequitur
4
+ module Formatter
5
+
6
+ # A formatter class that can render a dynamic grammar in plain text.
7
+ # @example
8
+ # some_grammar = ... # Points to a DynamicGrammar-like object
9
+ # # Output the result to the standard console output
10
+ # formatter = Sequitur::Formatter::BaseText.new(STDOUT)
11
+ # # Render the grammar (through a visitor)
12
+ # formatter.run(some_grammar.visitor)
13
+ class BaseText < BaseFormatter
14
+
15
+ # Constructor.
16
+ # @param anIO [IO] The output stream to which the rendered grammar
17
+ # is written.
18
+ def initialize(anIO)
19
+ super(anIO)
20
+ @prod_lookup = {}
21
+ end
22
+
23
+ public
24
+
25
+ # Method called by a GrammarVisitor to which the formatter subscribed.
26
+ # Notification of a visit event: the visitor is about to visit a grammar
27
+ # @param aGrammar [DynamicGrammar-like object]
28
+ def before_grammar(aGrammar)
29
+ aGrammar.productions.each_with_index do |a_prod, index|
30
+ prod_lookup[a_prod] = index
31
+ end
32
+ end
33
+
34
+ # Method called by a GrammarVisitor to which the formatter subscribed.
35
+ # Notification of a visit event: the visitor is about to visit
36
+ # a production
37
+ # @param aProduction [aProduction]
38
+ def before_production(aProduction)
39
+ p_name = prod_name(aProduction)
40
+ output.print p_name
41
+ end
42
+
43
+ # Method called by a GrammarVisitor to which the formatter subscribed.
44
+ # Notification of a visit event: the visitor is about to visit
45
+ # the rhs of a production
46
+ # @param _ [Array]
47
+ def before_rhs(_)
48
+ output.print ' :'
49
+ end
50
+
51
+ # Method called by a GrammarVisitor to which the formatter subscribed.
52
+ # Notification of a visit event: the visitor is about to visit
53
+ # a terminal symbol from the rhs of a production
54
+ # @param aSymbol [Object]
55
+ def before_terminal(aSymbol)
56
+ output.print " #{aSymbol}"
57
+ end
58
+
59
+ # Method called by a GrammarVisitor to which the formatter subscribed.
60
+ # Notification of a visit event: the visitor is about to visit
61
+ # a non-terminal (= an allusion to a production) in the rhs of a
62
+ # production
63
+ # @param aProduction [Production] a production occurring in the rhs
64
+ def before_non_terminal(aProduction)
65
+ p_name = prod_name(aProduction)
66
+ output.print " #{p_name}"
67
+ end
68
+
69
+ # Method called by a GrammarVisitor to which the formatter subscribed.
70
+ # Notification of a visit event: the visitor complete the visit
71
+ # of a production
72
+ def after_production(_)
73
+ output.print ".\n"
74
+ end
75
+
76
+ private
77
+
78
+ # Read accessor of the production lookup
79
+ def prod_lookup()
80
+ return @prod_lookup
81
+ end
82
+
83
+ # Generate a name of a given production.
84
+ # @param aProduction [Production]
85
+ def prod_name(aProduction)
86
+ prod_index = prod_lookup[aProduction]
87
+ name = (prod_index == 0) ? 'start' : "P#{prod_index}"
88
+ return name
89
+ end
90
+
91
+ end # class
92
+ end # module
93
+ end # module
94
+
95
+ # End of file