Class: Ibex::IR::Automaton

Inherits:
Object
  • Object
show all
Defined in:
lib/ibex/ir/automaton_ir.rb,
sig/ibex/ir/automaton_ir.rbs

Overview

Immutable LALR automaton and its source grammar.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(grammar:, states:, conflict_summary:, algorithm: "lalr1", grammar_digest: nil, schema_version: SCHEMA_VERSION, entry_states: nil) ⇒ Automaton

Returns a new instance of Automaton.

RBS:

  • (grammar: Grammar, states: Array[AutomatonState], conflict_summary: conflict_summary, ?algorithm: String, ?grammar_digest: String?, ?schema_version: Integer, ?entry_states: Hash[String, Integer]?) -> void

Parameters:

  • grammar: (Grammar)
  • states: (Array[AutomatonState])
  • conflict_summary: (conflict_summary)
  • algorithm: (String) (defaults to: "lalr1")
  • grammar_digest: (String, nil) (defaults to: nil)
  • schema_version: (Integer) (defaults to: SCHEMA_VERSION)
  • entry_states: (Hash[String, Integer], nil) (defaults to: nil)


84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
# File 'lib/ibex/ir/automaton_ir.rb', line 84

def initialize(grammar:, states:, conflict_summary:, algorithm: "lalr1", grammar_digest: nil,
               schema_version: SCHEMA_VERSION, entry_states: nil)
  unless SUPPORTED_SCHEMA_VERSIONS.include?(schema_version)
    raise Ibex::Error, "unsupported automaton schema_version #{schema_version.inspect}"
  end

  grammar = Migration.to_v2(grammar) if schema_version >= 2 && grammar.schema_version != schema_version
  raise Ibex::Error, "automaton migration did not produce a grammar" unless grammar.is_a?(Grammar)
  unless grammar.schema_version == schema_version
    raise Ibex::Error,
          "automaton schema_version #{schema_version} requires Grammar IR v#{schema_version}, " \
          "got v#{grammar.schema_version}"
  end

  @algorithm = algorithm.freeze
  @grammar = grammar
  @grammar_digest = (grammar_digest || digest_for(grammar)).freeze
  @states = states.freeze
  @entry_states = IR.deep_freeze(entry_states || { grammar.start => 0 })
  validate_entry_states
  @conflict_summary = IR.deep_freeze(conflict_summary)
  @schema_version = schema_version
  freeze
end

Instance Attribute Details

#algorithmString (readonly)

Signature:

  • String

Returns:

  • (String)


73
74
75
# File 'lib/ibex/ir/automaton_ir.rb', line 73

def algorithm
  @algorithm
end

#conflict_summaryconflict_summary (readonly)

Signature:

  • conflict_summary

Returns:



78
79
80
# File 'lib/ibex/ir/automaton_ir.rb', line 78

def conflict_summary
  @conflict_summary
end

#entry_statesHash[String, Integer] (readonly)

Signature:

  • Hash[String, Integer]

Returns:

  • (Hash[String, Integer])


77
78
79
# File 'lib/ibex/ir/automaton_ir.rb', line 77

def entry_states
  @entry_states
end

#grammarGrammar (readonly)

Signature:

  • Grammar

Returns:



75
76
77
# File 'lib/ibex/ir/automaton_ir.rb', line 75

def grammar
  @grammar
end

#grammar_digestString (readonly)

Signature:

  • String

Returns:

  • (String)


74
75
76
# File 'lib/ibex/ir/automaton_ir.rb', line 74

def grammar_digest
  @grammar_digest
end

#schema_versionInteger (readonly)

Signature:

  • Integer

Returns:

  • (Integer)


79
80
81
# File 'lib/ibex/ir/automaton_ir.rb', line 79

def schema_version
  @schema_version
end

#statesArray[AutomatonState] (readonly)

Signature:

  • Array[AutomatonState]

Returns:



76
77
78
# File 'lib/ibex/ir/automaton_ir.rb', line 76

def states
  @states
end

Instance Method Details

#digest_for(grammar) ⇒ String

RBS:

  • (Grammar grammar) -> String

Parameters:

Returns:

  • (String)


136
137
138
139
# File 'lib/ibex/ir/automaton_ir.rb', line 136

def digest_for(grammar)
  require "digest"
  "sha256:#{Digest::SHA256.hexdigest(IR::Serialize.dump(grammar))}"
end

#to_hHash[Symbol, untyped]

RBS:

  • () -> Hash[Symbol, untyped]

Returns:

  • (Hash[Symbol, untyped])


110
111
112
113
114
115
116
117
# File 'lib/ibex/ir/automaton_ir.rb', line 110

def to_h
  value = { ibex_ir: "automaton", schema_version: @schema_version, algorithm: @algorithm,
            grammar_digest: @grammar_digest, grammar: @grammar.to_h,
            states: @states.map { |state| state.to_h(@grammar) },
            conflict_summary: @conflict_summary } #: Hash[Symbol, untyped]
  value[:entry_states] = @entry_states unless @entry_states == { @grammar.start => 0 }
  value
end

#validate_entry_statesvoid

This method returns an undefined value.

RBS:

  • () -> void



122
123
124
125
126
127
128
129
130
131
132
133
# File 'lib/ibex/ir/automaton_ir.rb', line 122

def validate_entry_states
  ordered = @grammar.starts.select { |name| @entry_states.key?(name) }
  unless @entry_states.any? && @entry_states.keys == ordered
    raise Ibex::Error, "(ir):1:1: automaton entry states must be an ordered subset of grammar starts"
  end

  @entry_states.each do |name, state|
    next if state.between?(0, @states.length - 1)

    raise Ibex::Error, "(ir):1:1: entry #{name} references missing state #{state}"
  end
end