Class: Lrama::Grammar

Inherits:
Object
  • Object
show all
Defined in:
lib/lrama/grammar.rb,
lib/lrama/grammar/code.rb,
lib/lrama/grammar/rule.rb,
lib/lrama/grammar/union.rb,
lib/lrama/grammar/symbol.rb,
lib/lrama/grammar/printer.rb,
lib/lrama/grammar/auxiliary.rb,
lib/lrama/grammar/reference.rb,
lib/lrama/grammar/precedence.rb,
lib/lrama/grammar/error_token.rb

Overview

Grammar is the result of parsing an input grammar file

Defined Under Namespace

Classes: Auxiliary, Code, ErrorToken, Precedence, Printer, Reference, Rule, Symbol, Union

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeGrammar

Returns a new instance of Grammar.



28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
# File 'lib/lrama/grammar.rb', line 28

def initialize
  @printers = []
  @error_tokens = []
  @symbols = []
  @types = []
  @_rules = []
  @rules = []
  @sym_to_rules = {}
  @empty_symbol = nil
  @eof_symbol = nil
  @error_symbol = nil
  @undef_symbol = nil
  @accept_symbol = nil
  @aux = Auxiliary.new

  append_special_symbols
end

Instance Attribute Details

#_rulesObject

Returns the value of attribute _rules.



21
22
23
# File 'lib/lrama/grammar.rb', line 21

def _rules
  @_rules
end

#accept_symbolObject (readonly)

Returns the value of attribute accept_symbol.



20
21
22
# File 'lib/lrama/grammar.rb', line 20

def accept_symbol
  @accept_symbol
end

#auxObject (readonly)

Returns the value of attribute aux.



20
21
22
# File 'lib/lrama/grammar.rb', line 20

def aux
  @aux
end

#eof_symbolObject (readonly)

Returns the value of attribute eof_symbol.



20
21
22
# File 'lib/lrama/grammar.rb', line 20

def eof_symbol
  @eof_symbol
end

#error_symbolObject (readonly)

Returns the value of attribute error_symbol.



20
21
22
# File 'lib/lrama/grammar.rb', line 20

def error_symbol
  @error_symbol
end

#error_tokensObject

Returns the value of attribute error_tokens.



21
22
23
# File 'lib/lrama/grammar.rb', line 21

def error_tokens
  @error_tokens
end

#expectObject

Returns the value of attribute expect.



21
22
23
# File 'lib/lrama/grammar.rb', line 21

def expect
  @expect
end

#initial_actionObject

Returns the value of attribute initial_action.



21
22
23
# File 'lib/lrama/grammar.rb', line 21

def initial_action
  @initial_action
end

#lex_paramObject

Returns the value of attribute lex_param.



21
22
23
# File 'lib/lrama/grammar.rb', line 21

def lex_param
  @lex_param
end

#parse_paramObject

Returns the value of attribute parse_param.



21
22
23
# File 'lib/lrama/grammar.rb', line 21

def parse_param
  @parse_param
end

#printersObject

Returns the value of attribute printers.



21
22
23
# File 'lib/lrama/grammar.rb', line 21

def printers
  @printers
end

#rulesObject

Returns the value of attribute rules.



21
22
23
# File 'lib/lrama/grammar.rb', line 21

def rules
  @rules
end

#sym_to_rulesObject

Returns the value of attribute sym_to_rules.



21
22
23
# File 'lib/lrama/grammar.rb', line 21

def sym_to_rules
  @sym_to_rules
end

#symbolsObject

Returns the value of attribute symbols.



21
22
23
# File 'lib/lrama/grammar.rb', line 21

def symbols
  @symbols
end

#typesObject

Returns the value of attribute types.



21
22
23
# File 'lib/lrama/grammar.rb', line 21

def types
  @types
end

#undef_symbolObject (readonly)

Returns the value of attribute undef_symbol.



20
21
22
# File 'lib/lrama/grammar.rb', line 20

def undef_symbol
  @undef_symbol
end

#unionObject

Returns the value of attribute union.



21
22
23
# File 'lib/lrama/grammar.rb', line 21

def union
  @union
end

Instance Method Details

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



50
51
52
# File 'lib/lrama/grammar.rb', line 50

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

#add_left(sym, precedence) ⇒ Object



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

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

#add_nonassoc(sym, precedence) ⇒ Object



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

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

#add_nterm(id:, alias_name: nil, tag: nil) ⇒ Object



79
80
81
82
83
84
85
86
87
88
89
90
# File 'lib/lrama/grammar.rb', line 79

def add_nterm(id:, alias_name: nil, tag: nil)
  return if @symbols.find {|s| s.id == id }

  sym = Symbol.new(
    id: id, alias_name: alias_name, number: nil, tag: tag,
    term: false, token_id: nil, nullable: nil,
  )
  @symbols << sym
  @nterms = nil

  return sym
end

#add_precedence(sym, precedence) ⇒ Object



108
109
110
# File 'lib/lrama/grammar.rb', line 108

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

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



46
47
48
# File 'lib/lrama/grammar.rb', line 46

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

#add_right(sym, precedence) ⇒ Object



104
105
106
# File 'lib/lrama/grammar.rb', line 104

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

#add_rule(lhs:, rhs:, lineno:) ⇒ Object



121
122
123
# File 'lib/lrama/grammar.rb', line 121

def add_rule(lhs:, rhs:, lineno:)
  @_rules << [lhs, rhs, lineno]
end

#add_term(id:, alias_name: nil, tag: nil, token_id: nil, replace: false) ⇒ Object



54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
# File 'lib/lrama/grammar.rb', line 54

def add_term(id:, alias_name: nil, tag: nil, token_id: nil, replace: false)
  if token_id && (sym = @symbols.find {|s| s.token_id == token_id })
    if replace
      sym.id = id
      sym.alias_name = alias_name
      sym.tag = tag
    end

    return sym
  end

  if sym = @symbols.find {|s| s.id == id }
    return sym
  end

  sym = Symbol.new(
    id: id, alias_name: alias_name, number: nil, tag: tag,
    term: true, token_id: token_id, nullable: false
  )
  @symbols << sym
  @terms = nil

  return sym
end

#add_type(id:, tag:) ⇒ Object



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

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

#build_code(type, token_code) ⇒ Object



133
134
135
136
# File 'lib/lrama/grammar.rb', line 133

def build_code(type, token_code)
  build_references(token_code)
  Code.new(type: type, token_code: token_code)
end

#build_references(token_code) ⇒ Object



125
126
127
128
129
130
131
# File 'lib/lrama/grammar.rb', line 125

def build_references(token_code)
  token_code.references.map! do |type, value, tag, first_column, last_column|
    Reference.new(type: type, value: value, ex_tag: tag, first_column: first_column, last_column: last_column)
  end

  token_code
end

#compute_first_setObject



222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
# File 'lib/lrama/grammar.rb', line 222

def compute_first_set
  terms.each do |term|
    term.first_set = Set.new([term]).freeze
    term.first_set_bitmap = Lrama::Bitmap.from_array([term.number])
  end

  nterms.each do |nterm|
    nterm.first_set = Set.new([]).freeze
    nterm.first_set_bitmap = Lrama::Bitmap.from_array([])
  end

  while true do
    changed = false

    @rules.each do |rule|
      rule.rhs.each do |r|
        if rule.lhs.first_set_bitmap | r.first_set_bitmap != rule.lhs.first_set_bitmap
          changed = true
          rule.lhs.first_set_bitmap = rule.lhs.first_set_bitmap | r.first_set_bitmap
        end

        break unless r.nullable
      end
    end

    break unless changed
  end

  nterms.each do |nterm|
    nterm.first_set = Lrama::Bitmap.to_array(nterm.first_set_bitmap).map do |number|
      find_symbol_by_number!(number)
    end.to_set
  end
end

#compute_nullableObject



173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
# File 'lib/lrama/grammar.rb', line 173

def compute_nullable
  @rules.each do |rule|
    case
    when rule.rhs.empty?
      rule.nullable = true
    when rule.rhs.any?(&:term)
      rule.nullable = false
    else
      # noop
    end
  end

  while true do
    rs  = @rules.select {|e| e.nullable.nil? }
    nts = nterms.select {|e| e.nullable.nil? }
    rule_count_1  = rs.count
    nterm_count_1 = nts.count

    rs.each do |rule|
      if rule.rhs.all?(&:nullable)
        rule.nullable = true
      end
    end

    nts.each do |nterm|
      find_rules_by_symbol!(nterm).each do |rule|
        if rule.nullable
          nterm.nullable = true
        end
      end
    end

    rule_count_2  = @rules.count {|e| e.nullable.nil? }
    nterm_count_2 = nterms.count {|e| e.nullable.nil? }

    if (rule_count_1 == rule_count_2) && (nterm_count_1 == nterm_count_2)
      break
    end
  end

  rules.select {|r| r.nullable.nil? }.each do |rule|
    rule.nullable = false
  end

  nterms.select {|r| r.nullable.nil? }.each do |nterm|
    nterm.nullable = false
  end
end

#create_token(type, s_value, line, column) ⇒ Object



485
486
487
488
489
490
491
# File 'lib/lrama/grammar.rb', line 485

def create_token(type, s_value, line, column)
  t = Token.new(type: type, s_value: s_value)
  t.line = line
  t.column = column

  return t
end

#epilogue=(epilogue) ⇒ Object



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

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

#epilogue_first_lineno=(epilogue_first_lineno) ⇒ Object



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

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

#extract_referencesObject



311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
# File 'lib/lrama/grammar.rb', line 311

def extract_references
  unless initial_action.nil?
    scanner = StringScanner.new(initial_action.s_value)
    references = []

    while !scanner.eos? do
      start = scanner.pos
      case
      # $ references
      # It need to wrap an identifier with brackets to use ".-" for identifiers
      when scanner.scan(/\$(<[a-zA-Z0-9_]+>)?\$/) # $$, $<long>$
        tag = scanner[1] ? Lrama::Lexer::Token.new(type: Lrama::Lexer::Token::Tag, s_value: scanner[1]) : nil
        references << [:dollar, "$", tag, start, scanner.pos - 1]
      when scanner.scan(/\$(<[a-zA-Z0-9_]+>)?(\d+)/) # $1, $2, $<long>1
        tag = scanner[1] ? Lrama::Lexer::Token.new(type: Lrama::Lexer::Token::Tag, s_value: scanner[1]) : nil
        references << [:dollar, Integer(scanner[2]), tag, start, scanner.pos - 1]
      when scanner.scan(/\$(<[a-zA-Z0-9_]+>)?([a-zA-Z_][a-zA-Z0-9_]*)/) # $foo, $expr, $<long>program (named reference without brackets)
        tag = scanner[1] ? Lrama::Lexer::Token.new(type: Lrama::Lexer::Token::Tag, s_value: scanner[1]) : nil
        references << [:dollar, scanner[2], tag, start, scanner.pos - 1]
      when scanner.scan(/\$(<[a-zA-Z0-9_]+>)?\[([a-zA-Z_.][-a-zA-Z0-9_.]*)\]/) # $expr.right, $expr-right, $<long>program (named reference with brackets)
        tag = scanner[1] ? Lrama::Lexer::Token.new(type: Lrama::Lexer::Token::Tag, s_value: scanner[1]) : nil
        references << [:dollar, scanner[2], tag, start, scanner.pos - 1]

      # @ references
      # It need to wrap an identifier with brackets to use ".-" for identifiers
      when scanner.scan(/@\$/) # @$
        references << [:at, "$", nil, start, scanner.pos - 1]
      when scanner.scan(/@(\d+)/) # @1
        references << [:at, Integer(scanner[1]), nil, start, scanner.pos - 1]
      when scanner.scan(/@([a-zA-Z][a-zA-Z0-9_]*)/) # @foo, @expr (named reference without brackets)
        references << [:at, scanner[1], nil, start, scanner.pos - 1]
      when scanner.scan(/@\[([a-zA-Z_.][-a-zA-Z0-9_.]*)\]/) # @expr.right, @expr-right  (named reference with brackets)
        references << [:at, scanner[1], nil, start, scanner.pos - 1]
      else
        scanner.getch
      end
    end

    initial_action.token_code.references = references
    build_references(initial_action.token_code)
  end

  @printers.each do |printer|
    scanner = StringScanner.new(printer.code.s_value)
    references = []

    while !scanner.eos? do
      start = scanner.pos
      case
      # $ references
      # It need to wrap an identifier with brackets to use ".-" for identifiers
      when scanner.scan(/\$(<[a-zA-Z0-9_]+>)?\$/) # $$, $<long>$
        tag = scanner[1] ? Lrama::Lexer::Token.new(type: Lrama::Lexer::Token::Tag, s_value: scanner[1]) : nil
        references << [:dollar, "$", tag, start, scanner.pos - 1]
      when scanner.scan(/\$(<[a-zA-Z0-9_]+>)?(\d+)/) # $1, $2, $<long>1
        tag = scanner[1] ? Lrama::Lexer::Token.new(type: Lrama::Lexer::Token::Tag, s_value: scanner[1]) : nil
        references << [:dollar, Integer(scanner[2]), tag, start, scanner.pos - 1]
      when scanner.scan(/\$(<[a-zA-Z0-9_]+>)?([a-zA-Z_][a-zA-Z0-9_]*)/) # $foo, $expr, $<long>program (named reference without brackets)
        tag = scanner[1] ? Lrama::Lexer::Token.new(type: Lrama::Lexer::Token::Tag, s_value: scanner[1]) : nil
        references << [:dollar, scanner[2], tag, start, scanner.pos - 1]
      when scanner.scan(/\$(<[a-zA-Z0-9_]+>)?\[([a-zA-Z_.][-a-zA-Z0-9_.]*)\]/) # $expr.right, $expr-right, $<long>program (named reference with brackets)
        tag = scanner[1] ? Lrama::Lexer::Token.new(type: Lrama::Lexer::Token::Tag, s_value: scanner[1]) : nil
        references << [:dollar, scanner[2], tag, start, scanner.pos - 1]

      # @ references
      # It need to wrap an identifier with brackets to use ".-" for identifiers
      when scanner.scan(/@\$/) # @$
        references << [:at, "$", nil, start, scanner.pos - 1]
      when scanner.scan(/@(\d+)/) # @1
        references << [:at, Integer(scanner[1]), nil, start, scanner.pos - 1]
      when scanner.scan(/@([a-zA-Z][a-zA-Z0-9_]*)/) # @foo, @expr (named reference without brackets)
        references << [:at, scanner[1], nil, start, scanner.pos - 1]
      when scanner.scan(/@\[([a-zA-Z_.][-a-zA-Z0-9_.]*)\]/) # @expr.right, @expr-right  (named reference with brackets)
        references << [:at, scanner[1], nil, start, scanner.pos - 1]
      else
        scanner.getch
      end
    end

    printer.code.token_code.references = references
    build_references(printer.code.token_code)
  end

  @error_tokens.each do |error_token|
    scanner = StringScanner.new(error_token.code.s_value)
    references = []

    while !scanner.eos? do
      start = scanner.pos
      case
      # $ references
      # It need to wrap an identifier with brackets to use ".-" for identifiers
      when scanner.scan(/\$(<[a-zA-Z0-9_]+>)?\$/) # $$, $<long>$
        tag = scanner[1] ? Lrama::Lexer::Token.new(type: Lrama::Lexer::Token::Tag, s_value: scanner[1]) : nil
        references << [:dollar, "$", tag, start, scanner.pos - 1]
      when scanner.scan(/\$(<[a-zA-Z0-9_]+>)?(\d+)/) # $1, $2, $<long>1
        tag = scanner[1] ? Lrama::Lexer::Token.new(type: Lrama::Lexer::Token::Tag, s_value: scanner[1]) : nil
        references << [:dollar, Integer(scanner[2]), tag, start, scanner.pos - 1]
      when scanner.scan(/\$(<[a-zA-Z0-9_]+>)?([a-zA-Z_][a-zA-Z0-9_]*)/) # $foo, $expr, $<long>program (named reference without brackets)
        tag = scanner[1] ? Lrama::Lexer::Token.new(type: Lrama::Lexer::Token::Tag, s_value: scanner[1]) : nil
        references << [:dollar, scanner[2], tag, start, scanner.pos - 1]
      when scanner.scan(/\$(<[a-zA-Z0-9_]+>)?\[([a-zA-Z_.][-a-zA-Z0-9_.]*)\]/) # $expr.right, $expr-right, $<long>program (named reference with brackets)
        tag = scanner[1] ? Lrama::Lexer::Token.new(type: Lrama::Lexer::Token::Tag, s_value: scanner[1]) : nil
        references << [:dollar, scanner[2], tag, start, scanner.pos - 1]

      # @ references
      # It need to wrap an identifier with brackets to use ".-" for identifiers
      when scanner.scan(/@\$/) # @$
        references << [:at, "$", nil, start, scanner.pos - 1]
      when scanner.scan(/@(\d+)/) # @1
        references << [:at, Integer(scanner[1]), nil, start, scanner.pos - 1]
      when scanner.scan(/@([a-zA-Z][a-zA-Z0-9_]*)/) # @foo, @expr (named reference without brackets)
        references << [:at, scanner[1], nil, start, scanner.pos - 1]
      when scanner.scan(/@\[([a-zA-Z_.][-a-zA-Z0-9_.]*)\]/) # @expr.right, @expr-right  (named reference with brackets)
        references << [:at, scanner[1], nil, start, scanner.pos - 1]
      else
        scanner.getch
      end
    end

    error_token.code.token_code.references = references
    build_references(error_token.code.token_code)
  end

  @_rules.each do |lhs, rhs, _|
    rhs.each_with_index do |token, index|
      next if token.class == Lrama::Grammar::Symbol || token.type != Lrama::Lexer::Token::User_code

      scanner = StringScanner.new(token.s_value)
      references = []

      while !scanner.eos? do
        start = scanner.pos
        case
        # $ references
        # It need to wrap an identifier with brackets to use ".-" for identifiers
        when scanner.scan(/\$(<[a-zA-Z0-9_]+>)?\$/) # $$, $<long>$
          tag = scanner[1] ? Lrama::Lexer::Token.new(type: Lrama::Lexer::Token::Tag, s_value: scanner[1]) : nil
          references << [:dollar, "$", tag, start, scanner.pos - 1]
        when scanner.scan(/\$(<[a-zA-Z0-9_]+>)?(\d+)/) # $1, $2, $<long>1
          tag = scanner[1] ? Lrama::Lexer::Token.new(type: Lrama::Lexer::Token::Tag, s_value: scanner[1]) : nil
          references << [:dollar, Integer(scanner[2]), tag, start, scanner.pos - 1]
        when scanner.scan(/\$(<[a-zA-Z0-9_]+>)?([a-zA-Z_][a-zA-Z0-9_]*)/) # $foo, $expr, $<long>program (named reference without brackets)
          tag = scanner[1] ? Lrama::Lexer::Token.new(type: Lrama::Lexer::Token::Tag, s_value: scanner[1]) : nil
          references << [:dollar, scanner[2], tag, start, scanner.pos - 1]
        when scanner.scan(/\$(<[a-zA-Z0-9_]+>)?\[([a-zA-Z_.][-a-zA-Z0-9_.]*)\]/) # $expr.right, $expr-right, $<long>program (named reference with brackets)
          tag = scanner[1] ? Lrama::Lexer::Token.new(type: Lrama::Lexer::Token::Tag, s_value: scanner[1]) : nil
          references << [:dollar, scanner[2], tag, start, scanner.pos - 1]

        # @ references
        # It need to wrap an identifier with brackets to use ".-" for identifiers
        when scanner.scan(/@\$/) # @$
          references << [:at, "$", nil, start, scanner.pos - 1]
        when scanner.scan(/@(\d+)/) # @1
          references << [:at, Integer(scanner[1]), nil, start, scanner.pos - 1]
        when scanner.scan(/@([a-zA-Z][a-zA-Z0-9_]*)/) # @foo, @expr (named reference without brackets)
          references << [:at, scanner[1], nil, start, scanner.pos - 1]
        when scanner.scan(/@\[([a-zA-Z_.][-a-zA-Z0-9_.]*)\]/) # @expr.right, @expr-right  (named reference with brackets)
          references << [:at, scanner[1], nil, start, scanner.pos - 1]

        when scanner.scan(/\/\*/)
          scanner.scan_until(/\*\//)
        else
          scanner.getch
        end
      end

      token.references = references
      token.numberize_references(lhs, rhs)
      build_references(token)
    end
  end
end

#find_rules_by_symbol(sym) ⇒ Object



291
292
293
# File 'lib/lrama/grammar.rb', line 291

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

#find_rules_by_symbol!(sym) ⇒ Object



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

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

#find_symbol_by_id(id) ⇒ Object



267
268
269
270
271
272
# File 'lib/lrama/grammar.rb', line 267

def find_symbol_by_id(id)
  @symbols.find do |sym|
    # TODO: validate uniqueness of Token#s_value and Symbol#alias_name
    sym.id == id || sym.alias_name == id.s_value
  end
end

#find_symbol_by_id!(id) ⇒ Object



274
275
276
# File 'lib/lrama/grammar.rb', line 274

def find_symbol_by_id!(id)
  find_symbol_by_id(id) || (raise "Symbol not found: #{id}")
end

#find_symbol_by_number!(number) ⇒ Object



278
279
280
281
282
283
284
285
# File 'lib/lrama/grammar.rb', line 278

def find_symbol_by_number!(number)
  sym = @symbols[number]

  raise "Symbol not found: #{number}" unless sym
  raise "[BUG] Symbol number mismatch. #{number}, #{sym}" if sym.number != number

  sym
end

#find_symbol_by_s_value(s_value) ⇒ Object



257
258
259
260
261
# File 'lib/lrama/grammar.rb', line 257

def find_symbol_by_s_value(s_value)
  @symbols.find do |sym|
    sym.id.s_value == s_value
  end
end

#find_symbol_by_s_value!(s_value) ⇒ Object



263
264
265
# File 'lib/lrama/grammar.rb', line 263

def find_symbol_by_s_value!(s_value)
  find_symbol_by_s_value(s_value) || (raise "Symbol not found: #{s_value}")
end

#ntermsObject



307
308
309
# File 'lib/lrama/grammar.rb', line 307

def nterms
  @nterms ||= @symbols.select(&:nterm?)
end

#nterms_countObject



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

def nterms_count
  nterms.count
end

#prepareObject



154
155
156
157
158
159
160
161
162
163
164
165
# File 'lib/lrama/grammar.rb', line 154

def prepare
  normalize_rules
  collect_symbols
  replace_token_with_symbol
  fill_symbol_number
  fill_default_precedence
  fill_sym_to_rules
  fill_nterm_type
  fill_symbol_printer
  fill_symbol_error_token
  @symbols.sort_by!(&:number)
end

#prologue=(prologue) ⇒ Object



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

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

#prologue_first_lineno=(prologue_first_lineno) ⇒ Object



138
139
140
# File 'lib/lrama/grammar.rb', line 138

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

#set_precedence(sym, precedence) ⇒ Object



112
113
114
115
# File 'lib/lrama/grammar.rb', line 112

def set_precedence(sym, precedence)
  raise "" if sym.nterm?
  sym.precedence = precedence
end

#set_union(code, lineno) ⇒ Object



117
118
119
# File 'lib/lrama/grammar.rb', line 117

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

#termsObject



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

def terms
  @terms ||= @symbols.select(&:term?)
end

#terms_countObject



295
296
297
# File 'lib/lrama/grammar.rb', line 295

def terms_count
  terms.count
end

#validate!Object

TODO: More validation methods



168
169
170
171
# File 'lib/lrama/grammar.rb', line 168

def validate!
  validate_symbol_number_uniqueness!
  validate_no_declared_type_reference!
end