Class: Rley::Syntax::BaseGrammarBuilder
- Inherits:
-
Object
- Object
- Rley::Syntax::BaseGrammarBuilder
- Defined in:
- lib/rley/syntax/base_grammar_builder.rb
Overview
Builder GoF pattern. Builder builds a complex object (say, a grammar) from simpler objects (terminals and productions) and using a step by step approach.
Instance Attribute Summary collapse
-
#productions ⇒ Array<Production>
readonly
The list of production rules for the grammar to build.
-
#symbols ⇒ Hash{String, GrmSymbol}
readonly
The mapping of grammar symbol names to the matching grammar symbol object.
Instance Method Summary collapse
-
#[](aSymbolName) ⇒ GrmSymbol
Retrieve a grammar symbol from its name.
-
#add_marker(aMarkerSymbol) ⇒ void
Add the given marker symbol to the grammar of the language.
-
#add_production(aProductionRepr) ⇒ Production
(also: #rule)
Add a production rule in the grammar given one key-value pair of the form: String => Array.
-
#add_terminals(*terminalSymbols) ⇒ void
Add the given terminal symbols to the grammar of the language.
-
#grammar ⇒ Grammar
Given the grammar symbols and productions added to the builder, build the resulting grammar (if not yet done).
-
#initialize(&aBlock) ⇒ BaseGrammarBuilder
constructor
Creates a new grammar builder.
-
#suffix_plus ⇒ Object
When a symbol, say symb, in a rhs is followed by a '+' modifier, then a rule will be generated with a lhs named symb + suffix_plus.
- #suffix_plus_last ⇒ Object
- #suffix_plus_more ⇒ Object
Constructor Details
#initialize(&aBlock) ⇒ BaseGrammarBuilder
Creates a new grammar builder.
34 35 36 37 38 39 |
# File 'lib/rley/syntax/base_grammar_builder.rb', line 34 def initialize(&aBlock) @symbols = {} @productions = [] instance_exec(&aBlock) if block_given? end |
Instance Attribute Details
#productions ⇒ Array<Production> (readonly)
Returns The list of production rules for the grammar to build.
21 22 23 |
# File 'lib/rley/syntax/base_grammar_builder.rb', line 21 def productions @productions end |
#symbols ⇒ Hash{String, GrmSymbol} (readonly)
Returns The mapping of grammar symbol names to the matching grammar symbol object.
17 18 19 |
# File 'lib/rley/syntax/base_grammar_builder.rb', line 17 def symbols @symbols end |
Instance Method Details
#[](aSymbolName) ⇒ GrmSymbol
Retrieve a grammar symbol from its name. Raise an exception if not found.
45 46 47 |
# File 'lib/rley/syntax/base_grammar_builder.rb', line 45 def [](aSymbolName) symbols[aSymbolName] end |
#add_marker(aMarkerSymbol) ⇒ void
This method returns an undefined value.
Add the given marker symbol to the grammar of the language
60 61 62 63 |
# File 'lib/rley/syntax/base_grammar_builder.rb', line 60 def add_marker(aMarkerSymbol) new_symb = build_symbol(Marker, aMarkerSymbol) symbols[aMarkerSymbol.name] = new_symb end |
#add_production(aProductionRepr) ⇒ Production Also known as: rule
Add a production rule in the grammar given one key-value pair of the form: String => Array. Where the key is the name of the non-terminal appearing in the left side of the rule. The value, an Array, is a sequence of grammar symbol names. The rule is created and inserted in the grammar.
79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 |
# File 'lib/rley/syntax/base_grammar_builder.rb', line 79 def add_production(aProductionRepr) aProductionRepr.each_pair do |(lhs_name, rhs_repr)| lhs = get_grm_symbol(lhs_name) case rhs_repr when Array rhs_members = rhs_repr.map { |name| get_grm_symbol(name) } when String rhs_lexemes = rhs_repr.scan(/\S+/) rhs_members = rhs_lexemes.map { |name| get_grm_symbol(name) } when Terminal rhs_members = [rhs_repr] end new_prod = Production.new(lhs, rhs_members) productions << new_prod end return productions.last end |
#add_terminals(*terminalSymbols) ⇒ void
This method returns an undefined value.
Add the given terminal symbols to the grammar of the language
52 53 54 55 |
# File 'lib/rley/syntax/base_grammar_builder.rb', line 52 def add_terminals(*terminalSymbols) new_symbs = build_symbols(Terminal, terminalSymbols) symbols.merge!(new_symbs) end |
#grammar ⇒ Grammar
Given the grammar symbols and productions added to the builder, build the resulting grammar (if not yet done).
101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 |
# File 'lib/rley/syntax/base_grammar_builder.rb', line 101 def grammar unless @grammar raise StandardError, 'No symbol found for grammar' if symbols.empty? if productions.empty? raise StandardError, 'No production found for grammar' end # Check that each terminal appears at least in a rhs of a production all_terminals = symbols.values.select do |a_symb| a_symb.kind_of?(Terminal) end in_use = Set.new productions.each do |prod| prod.rhs.members.each do |symb| in_use << symb if symb.kind_of?(Syntax::Terminal) end end unused = all_terminals.reject { |a_term| in_use.include?(a_term) } unless unused.empty? suffix = "#{unused.map(&:name).join(', ')}." raise StandardError, "Useless terminal symbol(s): #{suffix}" end @grammar = Grammar.new(productions.dup) end return @grammar end |
#suffix_plus ⇒ Object
When a symbol, say symb, in a rhs is followed by a '+' modifier, then a rule will be generated with a lhs named symb + suffix_plus
133 134 135 |
# File 'lib/rley/syntax/base_grammar_builder.rb', line 133 def suffix_plus '_plus' end |
#suffix_plus_last ⇒ Object
141 142 143 |
# File 'lib/rley/syntax/base_grammar_builder.rb', line 141 def suffix_plus_last 'base_plus_last' end |
#suffix_plus_more ⇒ Object
137 138 139 |
# File 'lib/rley/syntax/base_grammar_builder.rb', line 137 def suffix_plus_more 'base_plus_more' end |