Class: Lrama::Grammar

Inherits:
Object
  • Object
show all
Extended by:
Forwardable
Defined in:
lib/lrama/grammar.rb,
lib/lrama/grammar/code.rb,
lib/lrama/grammar/rule.rb,
lib/lrama/grammar/type.rb,
lib/lrama/grammar/union.rb,
lib/lrama/grammar/symbol.rb,
lib/lrama/grammar/binding.rb,
lib/lrama/grammar/counter.rb,
lib/lrama/grammar/printer.rb,
lib/lrama/grammar/auxiliary.rb,
lib/lrama/grammar/reference.rb,
lib/lrama/grammar/destructor.rb,
lib/lrama/grammar/precedence.rb,
lib/lrama/grammar/error_token.rb,
lib/lrama/grammar/percent_code.rb,
lib/lrama/grammar/rule_builder.rb,
lib/lrama/grammar/inline/resolver.rb,
lib/lrama/grammar/code/rule_action.rb,
lib/lrama/grammar/symbols/resolver.rb,
lib/lrama/grammar/code/printer_code.rb,
lib/lrama/grammar/parameterized/rhs.rb,
lib/lrama/grammar/parameterized/rule.rb,
lib/lrama/grammar/code/destructor_code.rb,
lib/lrama/grammar/code/no_reference_code.rb,
lib/lrama/grammar/parameterized/resolver.rb,
lib/lrama/grammar/code/initial_action_code.rb

Overview

Grammar is the result of parsing an input grammar file

Defined Under Namespace

Classes: Auxiliary, Binding, Code, Counter, Destructor, ErrorToken, Inline, Parameterized, PercentCode, Precedence, Printer, Reference, Rule, RuleBuilder, Symbol, Symbols, Type, Union

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(rule_counter, locations, define = {}) ⇒ Grammar

Returns a new instance of Grammar.



110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
# File 'lib/lrama/grammar.rb', line 110

def initialize(rule_counter, locations, define = {})
  @rule_counter = rule_counter

  # Code defined by "%code"
  @percent_codes = []
  @printers = []
  @destructors = []
  @error_tokens = []
  @symbols_resolver = Grammar::Symbols::Resolver.new
  @types = []
  @rule_builders = []
  @rules = []
  @sym_to_rules = {}
  @parameterized_resolver = Parameterized::Resolver.new
  @empty_symbol = nil
  @eof_symbol = nil
  @error_symbol = nil
  @undef_symbol = nil
  @accept_symbol = nil
  @aux = Auxiliary.new
  @no_stdlib = false
  @locations = locations
  @define = define
  @required = false
  @precedences = []
  @start_nterm = nil

  append_special_symbols
end

Instance Attribute Details

#accept_symbolObject (readonly)

: Grammar::Symbol



78
79
80
# File 'lib/lrama/grammar.rb', line 78

def accept_symbol
  @accept_symbol
end

#after_pop_stackObject

: Lexer::Token::Base



93
94
95
# File 'lib/lrama/grammar.rb', line 93

def after_pop_stack
  @after_pop_stack
end

#after_reduceObject

: Lexer::Token::Base



91
92
93
# File 'lib/lrama/grammar.rb', line 91

def after_reduce
  @after_reduce
end

#after_shiftObject

: Lexer::Token::Base



89
90
91
# File 'lib/lrama/grammar.rb', line 89

def after_shift
  @after_shift
end

#after_shift_error_tokenObject

: Lexer::Token::Base



92
93
94
# File 'lib/lrama/grammar.rb', line 92

def after_shift_error_token
  @after_shift_error_token
end

#auxObject (readonly)

: Auxiliary



79
80
81
# File 'lib/lrama/grammar.rb', line 79

def aux
  @aux
end

#before_reduceObject

: Lexer::Token::Base



90
91
92
# File 'lib/lrama/grammar.rb', line 90

def before_reduce
  @before_reduce
end

#defineObject

: Hash[String, String]



101
102
103
# File 'lib/lrama/grammar.rb', line 101

def define
  @define
end

#eof_symbolObject (readonly)

: Grammar::Symbol



75
76
77
# File 'lib/lrama/grammar.rb', line 75

def eof_symbol
  @eof_symbol
end

#error_symbolObject (readonly)

: Grammar::Symbol



76
77
78
# File 'lib/lrama/grammar.rb', line 76

def error_symbol
  @error_symbol
end

#error_tokensObject

: Array



85
86
87
# File 'lib/lrama/grammar.rb', line 85

def error_tokens
  @error_tokens
end

#expectObject

: Integer



83
84
85
# File 'lib/lrama/grammar.rb', line 83

def expect
  @expect
end

#initial_actionObject

: Grammar::Code::InitialActionCode



88
89
90
# File 'lib/lrama/grammar.rb', line 88

def initial_action
  @initial_action
end

#lex_paramObject

: String



86
87
88
# File 'lib/lrama/grammar.rb', line 86

def lex_param
  @lex_param
end

#locationsObject

: bool



100
101
102
# File 'lib/lrama/grammar.rb', line 100

def locations
  @locations
end

#no_stdlibObject

: bool



99
100
101
# File 'lib/lrama/grammar.rb', line 99

def no_stdlib
  @no_stdlib
end

#parameterized_resolverObject (readonly)

: Parameterized::Resolver



80
81
82
# File 'lib/lrama/grammar.rb', line 80

def parameterized_resolver
  @parameterized_resolver
end

#parse_paramObject

: String



87
88
89
# File 'lib/lrama/grammar.rb', line 87

def parse_param
  @parse_param
end

#percent_codesObject (readonly)

: Array



74
75
76
# File 'lib/lrama/grammar.rb', line 74

def percent_codes
  @percent_codes
end

#precedencesObject (readonly)

: Array



81
82
83
# File 'lib/lrama/grammar.rb', line 81

def precedences
  @precedences
end

#printersObject

: Array



84
85
86
# File 'lib/lrama/grammar.rb', line 84

def printers
  @printers
end

#requiredObject

: bool



102
103
104
# File 'lib/lrama/grammar.rb', line 102

def required
  @required
end

#rule_buildersObject

: Array



97
98
99
# File 'lib/lrama/grammar.rb', line 97

def rule_builders
  @rule_builders
end

#rulesObject

: Array



96
97
98
# File 'lib/lrama/grammar.rb', line 96

def rules
  @rules
end

#sym_to_rulesObject

: Hash[Integer, Array[Rule]]



98
99
100
# File 'lib/lrama/grammar.rb', line 98

def sym_to_rules
  @sym_to_rules
end

#symbols_resolverObject

: Symbols::Resolver



94
95
96
# File 'lib/lrama/grammar.rb', line 94

def symbols_resolver
  @symbols_resolver
end

#typesObject

: Array



95
96
97
# File 'lib/lrama/grammar.rb', line 95

def types
  @types
end

#undef_symbolObject (readonly)

: Grammar::Symbol



77
78
79
# File 'lib/lrama/grammar.rb', line 77

def undef_symbol
  @undef_symbol
end

#unionObject

: Union



82
83
84
# File 'lib/lrama/grammar.rb', line 82

def union
  @union
end

Instance Method Details

#add_destructor(ident_or_tags:, token_code:, lineno:) ⇒ Object



151
152
153
# File 'lib/lrama/grammar.rb', line 151

def add_destructor(ident_or_tags:, token_code:, lineno:)
  @destructors << Destructor.new(ident_or_tags: ident_or_tags, token_code: token_code, lineno: lineno)
end

#add_error_token(ident_or_tags:, token_code:, lineno:) ⇒ Object



161
162
163
# File 'lib/lrama/grammar.rb', line 161

def add_error_token(ident_or_tags:, token_code:, lineno:)
  @error_tokens << ErrorToken.new(ident_or_tags: ident_or_tags, token_code: token_code, lineno: lineno)
end

#add_left(sym, precedence, s_value, lineno) ⇒ Object



176
177
178
# File 'lib/lrama/grammar.rb', line 176

def add_left(sym, precedence, s_value, lineno)
  set_precedence(sym, Precedence.new(symbol: sym, s_value: s_value, type: :left, precedence: precedence, lineno: lineno))
end

#add_nonassoc(sym, precedence, s_value, lineno) ⇒ Object



171
172
173
# File 'lib/lrama/grammar.rb', line 171

def add_nonassoc(sym, precedence, s_value, lineno)
  set_precedence(sym, Precedence.new(symbol: sym, s_value: s_value, type: :nonassoc, precedence: precedence, lineno: lineno))
end

#add_parameterized_rule(rule) ⇒ Object



221
222
223
# File 'lib/lrama/grammar.rb', line 221

def add_parameterized_rule(rule)
  @parameterized_resolver.add_rule(rule)
end

#add_percent_code(id:, code:) ⇒ Object



146
147
148
# File 'lib/lrama/grammar.rb', line 146

def add_percent_code(id:, code:)
  @percent_codes << PercentCode.new(id.s_value, code.s_value)
end

#add_precedence(sym, precedence, s_value, lineno) ⇒ Object



186
187
188
# File 'lib/lrama/grammar.rb', line 186

def add_precedence(sym, precedence, s_value, lineno)
  set_precedence(sym, Precedence.new(symbol: sym, s_value: s_value, type: :precedence, precedence: precedence, lineno: lineno))
end

#add_printer(ident_or_tags:, token_code:, lineno:) ⇒ Object



156
157
158
# File 'lib/lrama/grammar.rb', line 156

def add_printer(ident_or_tags:, token_code:, lineno:)
  @printers << Printer.new(ident_or_tags: ident_or_tags, token_code: token_code, lineno: lineno)
end

#add_right(sym, precedence, s_value, lineno) ⇒ Object



181
182
183
# File 'lib/lrama/grammar.rb', line 181

def add_right(sym, precedence, s_value, lineno)
  set_precedence(sym, Precedence.new(symbol: sym, s_value: s_value, type: :right, precedence: precedence, lineno: lineno))
end

#add_rule_builder(builder) ⇒ Object



216
217
218
# File 'lib/lrama/grammar.rb', line 216

def add_rule_builder(builder)
  @rule_builders << builder
end

#add_type(id:, tag:) ⇒ Object



166
167
168
# File 'lib/lrama/grammar.rb', line 166

def add_type(id:, tag:)
  @types << Type.new(id: id, tag: tag)
end

#create_rule_builder(rule_counter, midrule_action_counter) ⇒ Object



141
142
143
# File 'lib/lrama/grammar.rb', line 141

def create_rule_builder(rule_counter, midrule_action_counter)
  RuleBuilder.new(rule_counter, midrule_action_counter, @parameterized_resolver)
end

#epilogue=(epilogue) ⇒ Object



251
252
253
# File 'lib/lrama/grammar.rb', line 251

def epilogue=(epilogue)
  @aux.epilogue = epilogue
end

#epilogue_first_lineno=(epilogue_first_lineno) ⇒ Object



246
247
248
# File 'lib/lrama/grammar.rb', line 246

def epilogue_first_lineno=(epilogue_first_lineno)
  @aux.epilogue_first_lineno = epilogue_first_lineno
end

#find_rules_by_symbol(sym) ⇒ Object



288
289
290
# File 'lib/lrama/grammar.rb', line 288

def find_rules_by_symbol(sym)
  @sym_to_rules[sym.number]
end

#find_rules_by_symbol!(sym) ⇒ Object



283
284
285
# File 'lib/lrama/grammar.rb', line 283

def find_rules_by_symbol!(sym)
  find_rules_by_symbol(sym) || (raise "Rules for #{sym} not found")
end

#ielr_defined?Boolean

Returns:

  • (Boolean)


303
304
305
# File 'lib/lrama/grammar.rb', line 303

def ielr_defined?
  @define.key?('lr.type') && @define['lr.type'] == 'ielr'
end

#parameterized_rulesObject



226
227
228
# File 'lib/lrama/grammar.rb', line 226

def parameterized_rules
  @parameterized_resolver.rules
end

#prepareObject



256
257
258
259
260
261
262
263
264
265
266
267
268
# File 'lib/lrama/grammar.rb', line 256

def prepare
  resolve_inline_rules
  normalize_rules
  collect_symbols
  set_lhs_and_rhs
  fill_default_precedence
  fill_symbols
  fill_sym_to_rules
  sort_precedence
  compute_nullable
  compute_first_set
  set_locations
end

#prepend_parameterized_rules(rules) ⇒ Object



231
232
233
# File 'lib/lrama/grammar.rb', line 231

def prepend_parameterized_rules(rules)
  @parameterized_resolver.rules = rules + @parameterized_resolver.rules
end

#prologue=(prologue) ⇒ Object



241
242
243
# File 'lib/lrama/grammar.rb', line 241

def prologue=(prologue)
  @aux.prologue = prologue
end

#prologue_first_lineno=(prologue_first_lineno) ⇒ Object



236
237
238
# File 'lib/lrama/grammar.rb', line 236

def prologue_first_lineno=(prologue_first_lineno)
  @aux.prologue_first_lineno = prologue_first_lineno
end

#select_rules_by_s_value(s_value) ⇒ Object



293
294
295
# File 'lib/lrama/grammar.rb', line 293

def select_rules_by_s_value(s_value)
  @rules.select {|rule| rule.lhs.id.s_value == s_value }
end

#set_precedence(sym, precedence) ⇒ Object



205
206
207
208
# File 'lib/lrama/grammar.rb', line 205

def set_precedence(sym, precedence)
  @precedences << precedence
  sym.precedence = precedence
end

#set_start_nterm(id) ⇒ Object



191
192
193
194
195
196
197
198
199
200
201
202
# File 'lib/lrama/grammar.rb', line 191

def set_start_nterm(id)
  # When multiple `%start` directives are defined, Bison does not generate an error,
  # whereas Lrama does generate an error.
  # Related Bison's specification are
  #   refs: https://www.gnu.org/software/bison/manual/html_node/Multiple-start_002dsymbols.html
  if @start_nterm.nil?
    @start_nterm = id
  else
    start = @start_nterm #: Lrama::Lexer::Token::Base
    raise "Start non-terminal is already set to #{start.s_value} (line: #{start.first_line}). Cannot set to #{id.s_value} (line: #{id.first_line})."
  end
end

#set_union(code, lineno) ⇒ Object



211
212
213
# File 'lib/lrama/grammar.rb', line 211

def set_union(code, lineno)
  @union = Union.new(code: code, lineno: lineno)
end

#unique_rule_s_valuesObject



298
299
300
# File 'lib/lrama/grammar.rb', line 298

def unique_rule_s_values
  @rules.map {|rule| rule.lhs.id.s_value }.uniq
end

#validate!Object

TODO: More validation methods

  • Validation for no_declared_type_reference


275
276
277
278
279
280
# File 'lib/lrama/grammar.rb', line 275

def validate!
  @symbols_resolver.validate!
  validate_no_precedence_for_nterm!
  validate_rule_lhs_is_nterm!
  validate_duplicated_precedence!
end