Class: Rley::Syntax::GrammarBuilder
- Inherits:
-
Object
- Object
- Rley::Syntax::GrammarBuilder
- Defined in:
- lib/rley/syntax/grammar_builder.rb
Overview
Builder GoF pattern. Builder pattern 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 ⇒ Object
readonly
The list of production rules for the grammar to build.
-
#symbols ⇒ Object
readonly
The list of symbols of the language.
Instance Method Summary collapse
-
#[](aSymbolName) ⇒ GrmSymbol
Retrieve a grammar symbol from its name.
-
#add_production(aProductionRepr) ⇒ Object
(also: #rule)
Add a production rule in the grammar given one key-value pair of the form: String => Array.
-
#add_terminals(*terminalSymbols) ⇒ Object
Add the given terminal symbols to the grammar of the language.
-
#grammar ⇒ Object
Given the grammar symbols and productions added to the builder, build the resulting grammar (if not yet done).
-
#initialize(&aBlock) ⇒ GrammarBuilder
constructor
A new instance of GrammarBuilder.
Constructor Details
#initialize(&aBlock) ⇒ GrammarBuilder
Returns a new instance of GrammarBuilder.
22 23 24 25 26 27 |
# File 'lib/rley/syntax/grammar_builder.rb', line 22 def initialize(&aBlock) @symbols = {} @productions = [] instance_exec(&aBlock) if block_given? end |
Instance Attribute Details
#productions ⇒ Object (readonly)
The list of production rules for the grammar to build
19 20 21 |
# File 'lib/rley/syntax/grammar_builder.rb', line 19 def productions @productions end |
#symbols ⇒ Object (readonly)
The list of symbols of the language. Grammar symbols are categorized into terminal (symbol) and non-terminal (symbol).
16 17 18 |
# File 'lib/rley/syntax/grammar_builder.rb', line 16 def symbols @symbols end |
Instance Method Details
#[](aSymbolName) ⇒ GrmSymbol
Retrieve a grammar symbol from its name. Raise an exception if not found.
33 34 35 |
# File 'lib/rley/syntax/grammar_builder.rb', line 33 def [](aSymbolName) return symbols[aSymbolName] end |
#add_production(aProductionRepr) ⇒ Object 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. Example: builder.add_production('A' => ['a', 'A', 'c'])
54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 |
# File 'lib/rley/syntax/grammar_builder.rb', line 54 def add_production(aProductionRepr) aProductionRepr.each_pair do |(lhs_name, rhs_repr)| lhs = get_nonterminal(lhs_name) case rhs_repr when Array rhs_constituents = rhs_repr.map { |name| get_nonterminal(name) } when String rhs_constituents = [ get_nonterminal(rhs_repr) ] when Terminal rhs_constituents = [ rhs_repr ] end new_prod = Production.new(lhs, rhs_constituents) productions << new_prod end end |
#add_terminals(*terminalSymbols) ⇒ Object
Add the given terminal symbols to the grammar of the language
39 40 41 42 |
# File 'lib/rley/syntax/grammar_builder.rb', line 39 def add_terminals(*terminalSymbols) new_symbs = build_symbols(Terminal, terminalSymbols) symbols.merge!(new_symbs) end |
#grammar ⇒ Object
Given the grammar symbols and productions added to the builder, build the resulting grammar (if not yet done).
72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 |
# File 'lib/rley/syntax/grammar_builder.rb', line 72 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 non-terminal appears at least once in lhs. all_non_terminals = symbols.values.select { |s| s.is_a?(NonTerminal) } all_non_terminals.each do |n_term| next if productions.any? { |prod| n_term == prod.lhs } raise StandardError, "Nonterminal #{n_term.name} not rewritten" end @grammar = Grammar.new(productions.dup) end return @grammar end |