Class: Depager::Grammar

Inherits:
Object
  • Object
show all
Defined in:
lib/depager/grammar.rb

Direct Known Subclasses

LALR::Grammar

Defined Under Namespace

Classes: SymbolSet

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(rulelist, terms, nonterms, precs = nil) ⇒ Grammar

Returns a new instance of Grammar.



7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# File 'lib/depager/grammar.rb', line 7

def initialize(rulelist, terms, nonterms, precs = nil)
  @precs    = precs
  @nonterms = nonterms.invert
  @terms    = terms.invert
  @syms     = nonterms.invert.merge(terms.invert)

  @rulelist = rulelist
  @lhs_to_rule = []
  @nonterms.size.times { |i| @lhs_to_rule[i] = [] }
  @empty_rules = {}
  @rulelist.each_with_index do |rule, rx|
    rule.grammar = self
    rule.n = rx
    @lhs_to_rule[rule.lhs] << rule
    @empty_rules[rule.lhs] = rule.n if rule.rhs.empty?
  end
  make_sym_mask
  make_sym_first
  initialize_depend
end

Instance Attribute Details

#f0eObject

Returns the value of attribute f0e.



5
6
7
# File 'lib/depager/grammar.rb', line 5

def f0e
  @f0e
end

#first1Object

Returns the value of attribute first1.



5
6
7
# File 'lib/depager/grammar.rb', line 5

def first1
  @first1
end

#lhs_to_ruleObject

Returns the value of attribute lhs_to_rule.



5
6
7
# File 'lib/depager/grammar.rb', line 5

def lhs_to_rule
  @lhs_to_rule
end

#mask_symObject (readonly)

Returns the value of attribute mask_sym.



55
56
57
# File 'lib/depager/grammar.rb', line 55

def mask_sym
  @mask_sym
end

#nontermsObject

Returns the value of attribute nonterms.



5
6
7
# File 'lib/depager/grammar.rb', line 5

def nonterms
  @nonterms
end

#precsObject

Returns the value of attribute precs.



5
6
7
# File 'lib/depager/grammar.rb', line 5

def precs
  @precs
end

#rulelistObject

Returns the value of attribute rulelist.



5
6
7
# File 'lib/depager/grammar.rb', line 5

def rulelist
  @rulelist
end

#symsObject

Returns the value of attribute syms.



5
6
7
# File 'lib/depager/grammar.rb', line 5

def syms
  @syms
end

#termsObject

Returns the value of attribute terms.



5
6
7
# File 'lib/depager/grammar.rb', line 5

def terms
  @terms
end

Instance Method Details

#[](n) ⇒ Object



118
119
120
# File 'lib/depager/grammar.rb', line 118

def [](n)
  @rulelist[n]
end

#first(p) ⇒ Object



92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
# File 'lib/depager/grammar.rb', line 92

def first(p)
  return symset([EPS]) if p.empty?

  r = symset
  x = 0
  p.each do |i|
    unless i == EPS
      r.merge! @first1[i]
      break unless @first1[i].include? EPS
    end
    x += 1
  end
  r.delete EPS
  r << EPS if x == p.size

  r
end

#initialize_dependObject



28
# File 'lib/depager/grammar.rb', line 28

def initialize_depend; end

#make_sym_firstObject



57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
# File 'lib/depager/grammar.rb', line 57

def make_sym_first
  @first1 = {}
  @syms.each_key do |s|
    @first1[s] = symset

    @first1[s] << s   if term? s
    @first1[s] << EPS if @empty_rules[s]
  end

  begin
    changed = false
    @nonterms.size.times do |lhs|
      @lhs_to_rule[lhs].each do |rule|
        rule.rhs.each do |s|
          unless @first1[s].subset_of?(@first1[lhs])
            # warn "%b\n%b" % [@first1[s].set, @first1[lhs].set]
            # warn "update{"
            # warn "  R:#{symname(s)}:#{@first1[s].inspect}"
            # warn "  L:#{symname(lhs)}:#{@first1[lhs].inspect}"
            @first1[lhs].merge! @first1[s]
            # warn "  L:#{symname(lhs)}:#{@first1[lhs].inspect}"
            # warn "}"
            changed = true
          end
          break unless @first1[s].include? EPS
        end
        if !@first1[lhs].include?(EPS) && rule.rhs.all? { |i| @first1[i].include? EPS }
          @first1[lhs] << EPS
          changed = true
        end
      end
    end
  end while changed
end

#make_sym_maskObject



30
31
32
33
34
35
36
37
38
39
40
# File 'lib/depager/grammar.rb', line 30

def make_sym_mask
  @sym_mask = {}
  @mask_sym = []
  @terms.sort_by { |a, _b| a }.each_with_index do |i, x|
    @sym_mask[i[0]] = 1 << x
    @mask_sym[x] = i[0]
  end

  @sym_mask[EPS] = (1 << @sym_mask.size)
  @mask_sym << EPS
end

#mask_sizeObject



51
52
53
# File 'lib/depager/grammar.rb', line 51

def mask_size
  @mask_sym.size
end

#nonterm?(i) ⇒ Boolean

Returns:

  • (Boolean)


114
115
116
# File 'lib/depager/grammar.rb', line 114

def nonterm?(i)
  i && i < @nonterms.size
end

#sym_mask(sym) ⇒ Object



47
48
49
# File 'lib/depager/grammar.rb', line 47

def sym_mask(sym)
  @sym_mask[sym]
end

#symname(sym) ⇒ Object



122
123
124
125
126
127
128
129
130
131
132
# File 'lib/depager/grammar.rb', line 122

def symname(sym)
  name = @syms[sym]
  return nil        unless sym.is_a? Integer
  return "$start"   if sym == 0
  return "$empty"   if sym == EPS
  return "$end"     if name.nil?
  return "$error"   if name == false
  return name.to_s  if name.is_a? Symbol

  "'#{name}'"
end

#symset(syms = nil) ⇒ Object



42
43
44
45
# File 'lib/depager/grammar.rb', line 42

def symset(syms = nil)
  ss = SymbolSet.new(self)
  syms ? ss.concat_array(syms) : ss
end

#term?(i) ⇒ Boolean

Returns:

  • (Boolean)


110
111
112
# File 'lib/depager/grammar.rb', line 110

def term?(i)
  i && i >= @nonterms.size
end