Class: Ibex::Frontend::DSL::Builder

Inherits:
Object
  • Object
show all
Defined in:
lib/ibex/frontend/dsl.rb

Overview

Mutable definition context whose output is an immutable-shape AST.

Instance Method Summary collapse

Constructor Details

#initialize(class_name:, superclass:, file:) ⇒ Builder

Returns a new instance of Builder.



26
27
28
29
30
31
32
33
34
# File 'lib/ibex/frontend/dsl.rb', line 26

def initialize(class_name:, superclass:, file:)
  @class_name = class_name.to_s
  @superclass = superclass&.to_s
  @file = file
  @line = 1
  @declarations = [] #: Array[AST::declaration]
  @rules = [] #: Array[AST::Rule]
  @user_code = Hash.new { |hash, key| hash[key] = Array.new(0) } #: AST::user_code
end

Instance Method Details

#convert(name, expression) ⇒ Object



77
78
79
80
81
# File 'lib/ibex/frontend/dsl.rb', line 77

def convert(name, expression)
  location = next_location
  pair = AST::Conversion.new(name: name.to_s, expression: expression.to_s, loc: location)
  @declarations << AST::Convert.new(pairs: [pair], loc: location)
end

#display(name, value) ⇒ Object



84
85
86
87
# File 'lib/ibex/frontend/dsl.rb', line 84

def display(name, value)
  @declarations << AST::DisplayName.new(name: name.to_s, value: (value, "display"),
                                        loc: next_location)
end

#expect(conflicts) ⇒ Object



47
48
49
# File 'lib/ibex/frontend/dsl.rb', line 47

def expect(conflicts)
  @declarations << AST::Expect.new(conflicts: conflicts, loc: next_location)
end

#group(*alternatives) ⇒ Object



143
144
145
146
# File 'lib/ibex/frontend/dsl.rb', line 143

def group(*alternatives)
  normalized = alternatives.map { |alternative| Array(alternative).map { |item| normalize_item(item) } }
  AST::Group.new(alternatives: normalized, loc: next_location)
end

#inline(code) ⇒ Object



155
156
157
# File 'lib/ibex/frontend/dsl.rb', line 155

def inline(code)
  AST::InlineAction.new(code: code.to_s, loc: next_location)
end

#next_locationObject



177
178
179
180
181
# File 'lib/ibex/frontend/dsl.rb', line 177

def next_location
  location = Location.new(file: @file, line: @line, column: 1)
  @line += 1
  location
end

#normalize_item(item) ⇒ Object



167
168
169
170
171
172
173
174
# File 'lib/ibex/frontend/dsl.rb', line 167

def normalize_item(item)
  if item.respond_to?(:loc)
    located_item = item #: AST::item
    return located_item
  end

  ref(item)
end

#on_error_reduce(*names) ⇒ Object



62
63
64
# File 'lib/ibex/frontend/dsl.rb', line 62

def on_error_reduce(*names)
  @declarations << AST::OnErrorReduce.new(names: names.map(&:to_s), loc: next_location)
end

#optional(item) ⇒ Object



136
137
# File 'lib/ibex/frontend/dsl.rb', line 136

def optional(item) = AST::Optional.new(item: normalize_item(item), loc: next_location)
# @rbs (Object item) -> AST::Star

#options(*names) ⇒ Object



42
43
44
# File 'lib/ibex/frontend/dsl.rb', line 42

def options(*names)
  @declarations << AST::Options.new(names: names.map(&:to_s), loc: next_location)
end

#param(name, semantic_type = nil) ⇒ Object



96
97
98
99
# File 'lib/ibex/frontend/dsl.rb', line 96

def param(name, semantic_type = nil)
  type = semantic_type && (semantic_type, "%param")
  @declarations << AST::Parameter.new(name: name.to_s, semantic_type: type, loc: next_location)
end

#plus(item) ⇒ Object



140
# File 'lib/ibex/frontend/dsl.rb', line 140

def plus(item) = AST::Plus.new(item: normalize_item(item), loc: next_location)

#precedence(direction: :low_to_high) {|builder| ... } ⇒ Object

Yields:

  • (builder)


107
108
109
110
111
112
# File 'lib/ibex/frontend/dsl.rb', line 107

def precedence(direction: :low_to_high)
  location = next_location
  builder = PrecedenceBuilder.new(self)
  yield builder
  @declarations << AST::Precedence.new(direction: direction, levels: builder.levels, loc: location)
end

#printer(name, code) ⇒ Object



102
103
104
# File 'lib/ibex/frontend/dsl.rb', line 102

def printer(name, code)
  @declarations << AST::Printer.new(name: name.to_s, code: code.to_s, loc: next_location)
end

#recover_sync(*names) ⇒ Object



57
58
59
# File 'lib/ibex/frontend/dsl.rb', line 57

def recover_sync(*names)
  @declarations << AST::Recovery.new(sync_tokens: names.map(&:to_s), loc: next_location)
end

#ref(name, as: nil) ⇒ Object



131
132
133
# File 'lib/ibex/frontend/dsl.rb', line 131

def ref(name, as: nil)
  AST::SymbolReference.new(name: name.to_s, named_reference: as&.to_s, loc: next_location)
end

#rule(lhs) {|builder| ... } ⇒ Object

Yields:

  • (builder)


115
116
117
118
119
120
121
122
# File 'lib/ibex/frontend/dsl.rb', line 115

def rule(lhs)
  location = next_location
  builder = RuleBuilder.new(self, location)
  yield builder
  @rules << AST::Rule.new(
    lhs: lhs.to_s, parameters: [], alternatives: builder.alternatives, loc: location, inline: false
  )
end

#separated_list(item, separator, nonempty: false) ⇒ Object



149
150
151
152
# File 'lib/ibex/frontend/dsl.rb', line 149

def separated_list(item, separator, nonempty: false)
  AST::SeparatedList.new(item: normalize_item(item), separator: normalize_item(separator),
                         nonempty: nonempty, loc: next_location)
end

#star(item) ⇒ Object



138
139
# File 'lib/ibex/frontend/dsl.rb', line 138

def star(item) = AST::Star.new(item: normalize_item(item), loc: next_location)
# @rbs (Object item) -> AST::Plus

#start(*names) ⇒ Object



52
53
54
# File 'lib/ibex/frontend/dsl.rb', line 52

def start(*names)
  @declarations << AST::Start.new(names: names.map(&:to_s), loc: next_location)
end

#test_accept(source) ⇒ Object



67
68
69
# File 'lib/ibex/frontend/dsl.rb', line 67

def test_accept(source)
  @declarations << AST::GrammarTest.new(expectation: :accept, source: source.to_s, loc: next_location)
end

#test_reject(source) ⇒ Object



72
73
74
# File 'lib/ibex/frontend/dsl.rb', line 72

def test_reject(source)
  @declarations << AST::GrammarTest.new(expectation: :reject, source: source.to_s, loc: next_location)
end

#to_astObject



160
161
162
163
164
# File 'lib/ibex/frontend/dsl.rb', line 160

def to_ast
  location = Location.new(file: @file, line: 1, column: 1)
  AST::Root.new(class_name: @class_name, superclass: @superclass, declarations: @declarations,
                rules: @rules, user_code: @user_code, loc: location)
end

#token(*names) ⇒ Object



37
38
39
# File 'lib/ibex/frontend/dsl.rb', line 37

def token(*names)
  @declarations << AST::Tokens.new(names: names.map(&:to_s), loc: next_location)
end

#type(name, value) ⇒ Object



90
91
92
93
# File 'lib/ibex/frontend/dsl.rb', line 90

def type(name, value)
  @declarations << AST::SemanticType.new(name: name.to_s, value: (value, "type"),
                                         loc: next_location)
end

#user_code(name, code) ⇒ Object



125
126
127
128
# File 'lib/ibex/frontend/dsl.rb', line 125

def user_code(name, code)
  key = name.to_s
  @user_code[key] << AST::UserCode.new(name: key, code: code.to_s, loc: next_location)
end