rggen 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (152) hide show
  1. checksums.yaml +7 -0
  2. data/.rubocop.yml +7 -0
  3. data/.rubocop_todo.yml +91 -0
  4. data/CODE_OF_CONDUCT.md +49 -0
  5. data/LICENSE.txt +21 -0
  6. data/README.md +31 -0
  7. data/bin/rggen +6 -0
  8. data/lib/rggen/base/component.rb +27 -0
  9. data/lib/rggen/base/component_factory.rb +46 -0
  10. data/lib/rggen/base/hierarchical_accessors.rb +87 -0
  11. data/lib/rggen/base/hierarchical_item_accessors.rb +79 -0
  12. data/lib/rggen/base/item.rb +24 -0
  13. data/lib/rggen/base/item_factory.rb +20 -0
  14. data/lib/rggen/builder/builder.rb +69 -0
  15. data/lib/rggen/builder/category.rb +52 -0
  16. data/lib/rggen/builder/component_entry.rb +50 -0
  17. data/lib/rggen/builder/component_store.rb +42 -0
  18. data/lib/rggen/builder/input_component_store.rb +25 -0
  19. data/lib/rggen/builder/item_store.rb +89 -0
  20. data/lib/rggen/builder/list_item_entry.rb +81 -0
  21. data/lib/rggen/builder/output_component_store.rb +13 -0
  22. data/lib/rggen/builder/simple_item_entry.rb +33 -0
  23. data/lib/rggen/builtins/bit_field/bit_assignment.rb +39 -0
  24. data/lib/rggen/builtins/bit_field/field_model_creation.rb +25 -0
  25. data/lib/rggen/builtins/bit_field/field_model_declaration.rb +9 -0
  26. data/lib/rggen/builtins/bit_field/initial_value.rb +36 -0
  27. data/lib/rggen/builtins/bit_field/name.rb +26 -0
  28. data/lib/rggen/builtins/bit_field/reference.rb +42 -0
  29. data/lib/rggen/builtins/bit_field/reserved.rb +9 -0
  30. data/lib/rggen/builtins/bit_field/ro.rb +19 -0
  31. data/lib/rggen/builtins/bit_field/rw.erb +13 -0
  32. data/lib/rggen/builtins/bit_field/rw.rb +25 -0
  33. data/lib/rggen/builtins/bit_field/type.rb +205 -0
  34. data/lib/rggen/builtins/bit_field/wo.rb +5 -0
  35. data/lib/rggen/builtins/global/address_width.rb +17 -0
  36. data/lib/rggen/builtins/global/data_width.rb +20 -0
  37. data/lib/rggen/builtins/loaders/configuration/json_loader.rb +7 -0
  38. data/lib/rggen/builtins/loaders/configuration/yaml_loader.rb +7 -0
  39. data/lib/rggen/builtins/loaders/register_map/csv_loader.rb +14 -0
  40. data/lib/rggen/builtins/loaders/register_map/xls_loader.rb +19 -0
  41. data/lib/rggen/builtins/loaders/register_map/xlsx_ods_loader.rb +24 -0
  42. data/lib/rggen/builtins/register/accessibility.rb +23 -0
  43. data/lib/rggen/builtins/register/address_decoder.erb +16 -0
  44. data/lib/rggen/builtins/register/address_decoder.rb +92 -0
  45. data/lib/rggen/builtins/register/array.rb +133 -0
  46. data/lib/rggen/builtins/register/field_model_creator.rb +10 -0
  47. data/lib/rggen/builtins/register/field_model_declarations.rb +7 -0
  48. data/lib/rggen/builtins/register/name.rb +26 -0
  49. data/lib/rggen/builtins/register/offset_address.rb +55 -0
  50. data/lib/rggen/builtins/register/read_data.rb +36 -0
  51. data/lib/rggen/builtins/register/reg_model_constructor.rb +17 -0
  52. data/lib/rggen/builtins/register/reg_model_creation.rb +64 -0
  53. data/lib/rggen/builtins/register/reg_model_declaration.rb +13 -0
  54. data/lib/rggen/builtins/register/reg_model_definition.rb +22 -0
  55. data/lib/rggen/builtins/register/shadow.rb +130 -0
  56. data/lib/rggen/builtins/register/shadow_index_configurator.rb +53 -0
  57. data/lib/rggen/builtins/register/uniqueness_validator.rb +48 -0
  58. data/lib/rggen/builtins/register_block/apb.erb +27 -0
  59. data/lib/rggen/builtins/register_block/apb.rb +20 -0
  60. data/lib/rggen/builtins/register_block/base_address.rb +64 -0
  61. data/lib/rggen/builtins/register_block/block_model_constructor.rb +14 -0
  62. data/lib/rggen/builtins/register_block/block_model_default_map_creator.rb +39 -0
  63. data/lib/rggen/builtins/register_block/block_model_definition.rb +18 -0
  64. data/lib/rggen/builtins/register_block/byte_size.rb +37 -0
  65. data/lib/rggen/builtins/register_block/clock_reset.rb +8 -0
  66. data/lib/rggen/builtins/register_block/host_if.rb +46 -0
  67. data/lib/rggen/builtins/register_block/module_definition.rb +13 -0
  68. data/lib/rggen/builtins/register_block/name.rb +26 -0
  69. data/lib/rggen/builtins/register_block/ral_package_definition.rb +19 -0
  70. data/lib/rggen/builtins/register_block/reg_model_creator.rb +14 -0
  71. data/lib/rggen/builtins/register_block/reg_model_declarations.rb +7 -0
  72. data/lib/rggen/builtins/register_block/response_mux.erb +14 -0
  73. data/lib/rggen/builtins/register_block/response_mux.rb +16 -0
  74. data/lib/rggen/builtins/register_block/signal_declarations.rb +9 -0
  75. data/lib/rggen/builtins.rb +52 -0
  76. data/lib/rggen/commands.rb +23 -0
  77. data/lib/rggen/core_components/configuration/configuration_factory.rb +23 -0
  78. data/lib/rggen/core_components/configuration/item_factory.rb +13 -0
  79. data/lib/rggen/core_components/configuration/raise_error.rb +11 -0
  80. data/lib/rggen/core_components/configuration/setup.rb +14 -0
  81. data/lib/rggen/core_components/ral/item.rb +16 -0
  82. data/lib/rggen/core_components/ral/setup.rb +19 -0
  83. data/lib/rggen/core_components/register_map/bit_field_factory.rb +11 -0
  84. data/lib/rggen/core_components/register_map/component.rb +12 -0
  85. data/lib/rggen/core_components/register_map/generic_map.rb +69 -0
  86. data/lib/rggen/core_components/register_map/item.rb +22 -0
  87. data/lib/rggen/core_components/register_map/item_factory.rb +13 -0
  88. data/lib/rggen/core_components/register_map/loader.rb +13 -0
  89. data/lib/rggen/core_components/register_map/raise_error.rb +17 -0
  90. data/lib/rggen/core_components/register_map/register_block_factory.rb +29 -0
  91. data/lib/rggen/core_components/register_map/register_factory.rb +18 -0
  92. data/lib/rggen/core_components/register_map/register_map_factory.rb +21 -0
  93. data/lib/rggen/core_components/register_map/setup.rb +33 -0
  94. data/lib/rggen/core_components/rtl/component.rb +28 -0
  95. data/lib/rggen/core_components/rtl/item.rb +83 -0
  96. data/lib/rggen/core_components/rtl/setup.rb +19 -0
  97. data/lib/rggen/core_components.rb +23 -0
  98. data/lib/rggen/core_extensions/facets.rb +17 -0
  99. data/lib/rggen/core_extensions/forwardable.rb +26 -0
  100. data/lib/rggen/core_extensions/integer.rb +5 -0
  101. data/lib/rggen/core_extensions/math.rb +7 -0
  102. data/lib/rggen/exceptions.rb +22 -0
  103. data/lib/rggen/generator.rb +185 -0
  104. data/lib/rggen/input_base/component.rb +19 -0
  105. data/lib/rggen/input_base/component_factory.rb +58 -0
  106. data/lib/rggen/input_base/item.rb +170 -0
  107. data/lib/rggen/input_base/item_factory.rb +13 -0
  108. data/lib/rggen/input_base/loader.rb +14 -0
  109. data/lib/rggen/input_base/regexp_patterns.rb +29 -0
  110. data/lib/rggen/output_base/code_block.rb +72 -0
  111. data/lib/rggen/output_base/code_utility.rb +44 -0
  112. data/lib/rggen/output_base/component.rb +88 -0
  113. data/lib/rggen/output_base/component_factory.rb +32 -0
  114. data/lib/rggen/output_base/item.rb +175 -0
  115. data/lib/rggen/output_base/item_factory.rb +6 -0
  116. data/lib/rggen/output_base/line.rb +28 -0
  117. data/lib/rggen/output_base/template_utility.rb +29 -0
  118. data/lib/rggen/output_base/verilog_utility/class_definition.rb +23 -0
  119. data/lib/rggen/output_base/verilog_utility/declaration.rb +70 -0
  120. data/lib/rggen/output_base/verilog_utility/identifier.rb +29 -0
  121. data/lib/rggen/output_base/verilog_utility/module_definition.rb +47 -0
  122. data/lib/rggen/output_base/verilog_utility/package_definition.rb +67 -0
  123. data/lib/rggen/output_base/verilog_utility/structure_definition.rb +52 -0
  124. data/lib/rggen/output_base/verilog_utility/subroutine_definition.rb +43 -0
  125. data/lib/rggen/output_base/verilog_utility.rb +66 -0
  126. data/lib/rggen/version.rb +6 -0
  127. data/lib/rggen.rb +65 -0
  128. data/ral/compile.f +4 -0
  129. data/ral/rggen_ral_block.svh +84 -0
  130. data/ral/rggen_ral_field.svh +47 -0
  131. data/ral/rggen_ral_macros.svh +22 -0
  132. data/ral/rggen_ral_map.svh +124 -0
  133. data/ral/rggen_ral_pkg.sv +14 -0
  134. data/ral/rggen_ral_reg.svh +52 -0
  135. data/ral/rggen_ral_shadow_reg.svh +188 -0
  136. data/rggen.gemspec +45 -0
  137. data/rtl/bit_field/rggen_bit_field_rw.sv +28 -0
  138. data/rtl/register/rggen_address_decoder.sv +49 -0
  139. data/rtl/register_block/rggen_host_if_apb.sv +40 -0
  140. data/rtl/register_block/rggen_response_mux.sv +82 -0
  141. data/sample/sample.csv +14 -0
  142. data/sample/sample.json +4 -0
  143. data/sample/sample.xls +0 -0
  144. data/sample/sample.xlsx +0 -0
  145. data/sample/sample.yaml +2 -0
  146. data/sample/sample_0.sv +285 -0
  147. data/sample/sample_0_ral_pkg.sv +99 -0
  148. data/sample/sample_1.sv +172 -0
  149. data/sample/sample_1_ral_pkg.sv +53 -0
  150. data/sample/sample_setup.rb +21 -0
  151. data/setup/default.rb +11 -0
  152. metadata +296 -0
@@ -0,0 +1,83 @@
1
+ module RgGen
2
+ module RTL
3
+ class Item < OutputBase::Item
4
+ use_verilog_utility
5
+
6
+ def initialize(owner)
7
+ super(owner)
8
+ @identifiers = []
9
+ @signal_declarations = []
10
+ @port_declarations = []
11
+ @parameter_declarations = []
12
+ @localparam_declarations = []
13
+ end
14
+
15
+ attr_reader :identifiers
16
+ attr_reader :signal_declarations
17
+ attr_reader :port_declarations
18
+ attr_reader :parameter_declarations
19
+ attr_reader :localparam_declarations
20
+
21
+ private
22
+
23
+ class << self
24
+ private
25
+
26
+ def define_declaration_method(method_name)
27
+ define_method(method_name) do |handle_name, attributes = {}|
28
+ attributes[:name] ||= handle_name.to_s
29
+ add_identifier(handle_name, attributes[:name])
30
+ add_declaration(method_name, attributes)
31
+ end
32
+ private method_name
33
+ end
34
+ end
35
+
36
+ define_declaration_method :wire
37
+ define_declaration_method :reg
38
+ define_declaration_method :logic
39
+ define_declaration_method :input
40
+ define_declaration_method :output
41
+ define_declaration_method :parameter
42
+ define_declaration_method :localparam
43
+
44
+ def group(group_name, &body)
45
+ create_group(group_name)
46
+ instance_exec(&body)
47
+ @group = nil
48
+ end
49
+
50
+ def add_declaration(type, attributes)
51
+ attribute_key, declaration_type, declarations =
52
+ case type
53
+ when :wire, :reg, :logic
54
+ [:data_type, :variable, signal_declarations]
55
+ when :input, :output
56
+ [:direction, :port, port_declarations]
57
+ when :parameter
58
+ [:parameter_type, :parameter, parameter_declarations]
59
+ when :localparam
60
+ [:parameter_type, :parameter, localparam_declarations]
61
+ end
62
+ attributes[attribute_key] = type
63
+ declarations << create_declaration(declaration_type, attributes)
64
+ end
65
+
66
+ def add_identifier(handle_name, name)
67
+ identifier = create_identifier(name)
68
+ (@group || self).instance_exec do
69
+ instance_variable_set(handle_name.variablize, identifier)
70
+ attr_singleton_reader(handle_name)
71
+ end
72
+ identifiers << handle_name if @group.nil?
73
+ end
74
+
75
+ def create_group(group_name)
76
+ instance_variable_set(group_name.variablize, Object.new)
77
+ attr_singleton_reader(group_name)
78
+ identifiers << group_name
79
+ @group = __send__(group_name)
80
+ end
81
+ end
82
+ end
83
+ end
@@ -0,0 +1,19 @@
1
+ module RgGen
2
+ module RTL
3
+ output_component_store :rtl do
4
+ entry do
5
+ component_class OutputBase::Component
6
+ component_factory OutputBase::ComponentFactory
7
+ end
8
+
9
+ entry [:register_block, :register, :bit_field] do
10
+ component_class Component
11
+ component_factory OutputBase::ComponentFactory
12
+ item_base Item
13
+ item_factory OutputBase::ItemFactory
14
+ end
15
+
16
+ output_directory 'rtl'
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,23 @@
1
+ require_relative 'core_components/configuration/raise_error'
2
+ require_relative 'core_components/configuration/configuration_factory'
3
+ require_relative 'core_components/configuration/item_factory'
4
+ require_relative 'core_components/configuration/setup'
5
+
6
+ require_relative 'core_components/register_map/generic_map'
7
+ require_relative 'core_components/register_map/loader'
8
+ require_relative 'core_components/register_map/raise_error'
9
+ require_relative 'core_components/register_map/component'
10
+ require_relative 'core_components/register_map/item'
11
+ require_relative 'core_components/register_map/register_map_factory'
12
+ require_relative 'core_components/register_map/register_block_factory'
13
+ require_relative 'core_components/register_map/register_factory'
14
+ require_relative 'core_components/register_map/bit_field_factory'
15
+ require_relative 'core_components/register_map/item_factory'
16
+ require_relative 'core_components/register_map/setup'
17
+
18
+ require_relative 'core_components/rtl/component'
19
+ require_relative 'core_components/rtl/item'
20
+ require_relative 'core_components/rtl/setup'
21
+
22
+ require_relative 'core_components/ral/item'
23
+ require_relative 'core_components/ral/setup'
@@ -0,0 +1,17 @@
1
+ require 'facets/enumerable/exclude'
2
+ require 'facets/enumerable/sum'
3
+ require 'facets/file/ext'
4
+ require 'facets/hash/symbolize_keys'
5
+ require 'facets/integer/multiple'
6
+ require 'facets/kernel/attr_singleton'
7
+ require 'facets/kernel/not'
8
+ require 'facets/kernel/not_nil'
9
+ require 'facets/module/attr_setter'
10
+ require 'facets/numeric/positive'
11
+ require 'facets/range/overlap'
12
+ require 'facets/regexp/op_add'
13
+ require 'facets/regexp/op_or'
14
+ require 'facets/string/indent'
15
+ require 'facets/string/quote'
16
+ require 'facets/string/variablize'
17
+ require 'facets/symbol/variablize'
@@ -0,0 +1,26 @@
1
+ module Forwardable
2
+ def def_class_delegator(method, ali = method)
3
+ def_delegator('self.class', method, ali)
4
+ end
5
+
6
+ def def_class_delegators(*methods)
7
+ def_instance_delegators('self.class', *methods)
8
+ end
9
+
10
+ alias_method :class_delegator , :def_class_delegator
11
+ alias_method :class_delegators, :def_class_delegators
12
+ end
13
+
14
+ module SingleForwardable
15
+ def def_object_delegator(target, method, ali = method)
16
+ define_singleton_method(ali) do |*args, &block|
17
+ target.__send__(method, *args, &block)
18
+ end
19
+ end
20
+
21
+ def def_object_delegators(target, *methods)
22
+ methods.each do |method|
23
+ def_object_delegator(target, method)
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,5 @@
1
+ class Integer
2
+ def pow2?
3
+ positive? && (ord & pred).zero?
4
+ end
5
+ end
@@ -0,0 +1,7 @@
1
+ module Math
2
+ module_function
3
+
4
+ def clog2(value)
5
+ Math.log2(value).ceil
6
+ end
7
+ end
@@ -0,0 +1,22 @@
1
+ module RgGen
2
+ class RgGenError < StandardError
3
+ end
4
+
5
+ class BuilderError < RgGenError
6
+ end
7
+
8
+ class LoadError < RgGenError
9
+ end
10
+
11
+ class ConfigurationError < RgGenError
12
+ end
13
+
14
+ class RegisterMapError < RgGenError
15
+ def initialize(message, position)
16
+ super(message)
17
+ @position = position
18
+ end
19
+
20
+ attr_reader :position
21
+ end
22
+ end
@@ -0,0 +1,185 @@
1
+ module RgGen
2
+ class Generator
3
+ Context = Struct.new(:options, :configuration, :register_map) do
4
+ def initialize
5
+ super
6
+ self.options = {}
7
+ end
8
+ end
9
+
10
+ class Option
11
+ def initialize(kind)
12
+ @kind = kind
13
+ end
14
+
15
+ attr_accessor :short
16
+ attr_accessor :long
17
+ attr_accessor :class
18
+ attr_writer :default
19
+ attr_writer :description
20
+ attr_writer :body
21
+
22
+ def on(parser, options)
23
+ options[@kind] = @default if @default
24
+ parser.on(*args) do |value|
25
+ parser.instance_exec(value, options, @kind, &body)
26
+ end
27
+ end
28
+
29
+ def args
30
+ [@short, @long, @class, description].compact
31
+ end
32
+
33
+ def description
34
+ return nil unless @description || @default
35
+ d = ''
36
+ d << @description.to_s
37
+ d << "(default: #{@default})" if @default
38
+ d
39
+ end
40
+
41
+ def body
42
+ @body || default_body
43
+ end
44
+
45
+ def default_body
46
+ proc do |value, options, kind|
47
+ options[kind] = value
48
+ end
49
+ end
50
+ end
51
+
52
+ class << self
53
+ def options
54
+ @options ||= []
55
+ end
56
+
57
+ private
58
+
59
+ def add_option(kind, &body)
60
+ options << Option.new(kind)
61
+ body.call(options.last)
62
+ end
63
+ end
64
+
65
+ add_option :setup do |option|
66
+ option.long = '--setup FILE'
67
+ option.default = File.join(RGGEN_HOME, 'setup', 'default.rb')
68
+ option.description = 'Specify a setup file to set up RgGen tool'
69
+ end
70
+
71
+ add_option :configuration do |option|
72
+ option.short = '-c'
73
+ option.long = '--configuration FILE'
74
+ option.description = 'Specify a configuration file ' \
75
+ 'for generated source code'
76
+ end
77
+
78
+ add_option :output do |option|
79
+ option.short = '-o'
80
+ option.long = '--output DIR'
81
+ option.default = './'
82
+ option.description = 'Specify output directory'
83
+ end
84
+
85
+ add_option :except do |option|
86
+ option.long = '--except [TYPE1,TYPE2,...]'
87
+ option.class = Array
88
+ option.description = 'Disable the given output file type(s)'
89
+ option.body = proc do |value, options, kind|
90
+ options[kind] ||= []
91
+ options[kind].concat(value.map(&:to_sym))
92
+ end
93
+ end
94
+
95
+ add_option :version do |option|
96
+ option.short = '-v'
97
+ option.long = '--version'
98
+ option.description = 'Display the version'
99
+ option.body = proc do
100
+ puts ver
101
+ exit
102
+ end
103
+ end
104
+
105
+ add_option :help do |option|
106
+ option.short = '-h'
107
+ option.long = '--help'
108
+ option.description = 'Display this message'
109
+ option.body = proc do
110
+ puts help
111
+ exit
112
+ end
113
+ end
114
+
115
+ def run(argv)
116
+ Context.new.tap do |context|
117
+ parse_options(argv, context)
118
+ load_setup(context)
119
+ load_configuration(context)
120
+ load_register_map(context, argv.first)
121
+ write_files(context)
122
+ end
123
+ end
124
+
125
+ private
126
+
127
+ def parse_options(argv, context)
128
+ option_parser(context.options).parse!(argv)
129
+ end
130
+
131
+ def option_parser(options)
132
+ OptionParser.new do |parser|
133
+ parser.version = RgGen::VERSION
134
+ parser.program_name = 'rggen'
135
+ parser.banner = 'Usage: rggen [options] REGISTER_MAP'
136
+ add_option_switches(parser, options)
137
+ end
138
+ end
139
+
140
+ def add_option_switches(parser, options)
141
+ self.class.options.each do |option|
142
+ option.on(parser, options)
143
+ end
144
+ end
145
+
146
+ def load_setup(context)
147
+ load(context.options[:setup])
148
+ end
149
+
150
+ def build_factory(component_name)
151
+ RgGen.builder.build_factory(component_name)
152
+ end
153
+
154
+ def load_configuration(context)
155
+ context.configuration =
156
+ build_factory(:configuration).create(context.options[:configuration])
157
+ end
158
+
159
+ def load_register_map(context, file)
160
+ context.register_map =
161
+ build_factory(:register_map).create(context.configuration, file)
162
+ end
163
+
164
+ def write_files(context)
165
+ file_generators(context).each do |generator|
166
+ generator.write_file(context.options[:output])
167
+ end
168
+ end
169
+
170
+ def file_generators(context)
171
+ available_output_components(context).map do |component|
172
+ build_factory(component).create(
173
+ context.configuration, context.register_map
174
+ )
175
+ end
176
+ end
177
+
178
+ def available_output_components(context)
179
+ except = context.options[:except]
180
+ RgGen.builder.stored_output_components.select do |component|
181
+ except.nil? || except.exclude?(component)
182
+ end
183
+ end
184
+ end
185
+ end
@@ -0,0 +1,19 @@
1
+ module RgGen
2
+ module InputBase
3
+ class Component < Base::Component
4
+ def add_item(item)
5
+ super(item)
6
+ def_object_delegators(@items.last, *item.fields)
7
+ end
8
+
9
+ def fields
10
+ items.flat_map(&:fields)
11
+ end
12
+
13
+ def validate
14
+ items.each(&:validate)
15
+ children.each(&:validate)
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,58 @@
1
+ module RgGen
2
+ module InputBase
3
+ class ComponentFactory < Base::ComponentFactory
4
+ attr_writer :loaders
5
+
6
+ def create(*args)
7
+ if @root_factory
8
+ file = args.pop
9
+ source = load(file)
10
+ args << source
11
+
12
+ component = super(*args)
13
+ component.validate
14
+ else
15
+ component = super(*args)
16
+ end
17
+ component
18
+ end
19
+
20
+ private
21
+
22
+ def create_items(component, *sources)
23
+ create_active_items(component, *sources)
24
+ create_passive_items(component, *sources[0..-2])
25
+ end
26
+
27
+ def create_passive_items(component, *sources)
28
+ passive_item_factories.each do |factory|
29
+ create_item(factory, component, *sources)
30
+ end
31
+ end
32
+
33
+ def active_item_factories
34
+ @item_factories.each_with_object({}) do |(name, factory), factories|
35
+ factories[name] = factory if factory.active_item_factory?
36
+ end
37
+ end
38
+
39
+ def passive_item_factories
40
+ @item_factories.each_value.select(&:passive_item_factory?)
41
+ end
42
+
43
+ def load(file)
44
+ load_file(file)
45
+ end
46
+
47
+ def load_file(file)
48
+ find_loader(file).load_file(file)
49
+ end
50
+
51
+ def find_loader(file)
52
+ loader = @loaders && @loaders.find { |l| l.acceptable?(file) }
53
+ return loader.new unless loader.nil?
54
+ fail RgGen::LoadError, "unsupported file type: #{File.ext(file)}"
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,170 @@
1
+ module RgGen
2
+ module InputBase
3
+ class Item < Base::Item
4
+ include RegxpPatterns
5
+
6
+ class InputMatcher
7
+ def initialize(pattern, options)
8
+ @options = options
9
+ @pattern =
10
+ if @options.fetch(:match_wholly, true)
11
+ /\A#{pattern}\z/
12
+ else
13
+ pattern
14
+ end
15
+ end
16
+
17
+ attr_reader :match_data
18
+
19
+ def match_automatically?
20
+ @options.fetch(:match_automatically, true)
21
+ end
22
+
23
+ def match(rhs)
24
+ rhs = rhs.to_s if @options[:convert_to_string]
25
+ rhs = delete_blanks(rhs) if @options.fetch(:ignore_blank, true)
26
+ @match_data =
27
+ case rhs
28
+ when @pattern
29
+ Regexp.last_match
30
+ end
31
+ end
32
+
33
+ private
34
+
35
+ BLANK_REGEXP = [
36
+ /\A[ \t]+/,
37
+ /(?<=\w)[ \t]+(?=[[:punct:]])/,
38
+ /(?<=[[:punct:]])[ \t]+(?=\w)/,
39
+ /[ \t]+\z/
40
+ ].inject(&:|).freeze
41
+
42
+ def delete_blanks(rhs)
43
+ return rhs unless rhs.respond_to?(:gsub)
44
+ rhs.gsub(BLANK_REGEXP, '')
45
+ end
46
+ end
47
+
48
+ define_helpers do
49
+ attr_reader :builders
50
+ attr_reader :validators
51
+ attr_reader :input_matcher
52
+
53
+ def field(field_name, options = {}, &body)
54
+ return if fields.include?(field_name)
55
+
56
+ define_method(field_name) do
57
+ field_method(field_name, options, body)
58
+ end
59
+
60
+ fields << field_name
61
+ end
62
+
63
+ def fields
64
+ @fields ||= []
65
+ end
66
+
67
+ def build(&body)
68
+ @builders ||= []
69
+ @builders << body
70
+ end
71
+
72
+ def validate(&body)
73
+ @validators ||= []
74
+ @validators << body
75
+ end
76
+
77
+ def input_pattern(pattern, options = {})
78
+ @input_matcher = InputMatcher.new(pattern, options)
79
+ end
80
+
81
+ def active_item?
82
+ !passive_item?
83
+ end
84
+
85
+ def passive_item?
86
+ @builders.nil? || @builders.empty?
87
+ end
88
+ end
89
+
90
+ def self.inherited(subclass)
91
+ [:@fields, :@builders, :@validators].each do |v|
92
+ subclass.inherit_class_instance_variable(v, self, &:dup)
93
+ end
94
+ subclass.inherit_class_instance_variable(:@input_matcher, self)
95
+ end
96
+
97
+ class_delegator :fields
98
+ class_delegator :builders
99
+ class_delegator :validators
100
+ class_delegator :input_matcher
101
+
102
+ def build(*sources)
103
+ return unless builders
104
+ pattern_match(sources.last) if match_automatically?
105
+ builders.each do |builder|
106
+ instance_exec(*sources, &builder)
107
+ end
108
+ end
109
+
110
+ def validate
111
+ return if @validated
112
+ return unless validators
113
+ validators.each do |validator|
114
+ instance_exec(&validator)
115
+ end
116
+ @validated = true
117
+ end
118
+
119
+ private
120
+
121
+ def pattern_match(rhs)
122
+ input_matcher && input_matcher.match(rhs)
123
+ end
124
+
125
+ def match_data
126
+ input_matcher && input_matcher.match_data
127
+ end
128
+
129
+ def pattern_matched?
130
+ match_data.not_nil?
131
+ end
132
+
133
+ def captures
134
+ match_data && match_data.captures
135
+ end
136
+
137
+ def match_automatically?
138
+ input_matcher && input_matcher.match_automatically?
139
+ end
140
+
141
+ def field_method(field_name, options, body)
142
+ validate if options[:need_validation]
143
+ if body
144
+ instance_exec(&body)
145
+ elsif options[:forward_to_helper]
146
+ self.class.__send__(field_name)
147
+ elsif options.key?(:forward_to)
148
+ __send__(options[:forward_to])
149
+ else
150
+ default_field_method(field_name, options[:default])
151
+ end
152
+ end
153
+
154
+ def default_field_method(field_name, default_value)
155
+ variable_name =
156
+ if field_name =~ /\A([a-zA-Z0-9]\w*)\?\z/
157
+ Regexp.last_match[1].variablize
158
+ else
159
+ field_name.variablize
160
+ end
161
+
162
+ if instance_variable_defined?(variable_name)
163
+ instance_variable_get(variable_name)
164
+ else
165
+ default_value
166
+ end
167
+ end
168
+ end
169
+ end
170
+ end
@@ -0,0 +1,13 @@
1
+ module RgGen
2
+ module InputBase
3
+ class ItemFactory < Base::ItemFactory
4
+ def active_item_factory?
5
+ !passive_item_factory?
6
+ end
7
+
8
+ def passive_item_factory?
9
+ @target_items.nil? && @target_item.passive_item?
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,14 @@
1
+ module RgGen
2
+ module InputBase
3
+ class Loader
4
+ class << self
5
+ attr_writer :supported_types
6
+
7
+ def acceptable?(file_name)
8
+ ext = File.ext(file_name).to_sym
9
+ @supported_types.any? { |type| type.casecmp(ext) == 0 }
10
+ end
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,29 @@
1
+ module RgGen
2
+ module InputBase
3
+ module RegxpPatterns
4
+ BIN_REGEXP = /0b(?:[01][01_]*)?[01]/i
5
+ OCT_REGEXP = /0o(?:[0-7][0-7_]*)?[0-7]/i
6
+ DEC_REGEXP = /(?:[1-9][\d_]*)?\d/
7
+ HEX_REGEXP = /0x(?:\h[\h_]*)?\h/i
8
+
9
+ UNSIGNED_NUMBER_REGEXP = (
10
+ /\b/ + (BIN_REGEXP | OCT_REGEXP | DEC_REGEXP | HEX_REGEXP) + /\b/
11
+ ).freeze
12
+ VARIABLE_NAME_REGEXP = /\b[a-z_][a-z0-9_]*\b/i
13
+
14
+ def self.included(klass)
15
+ klass.extend(self)
16
+ end
17
+
18
+ private
19
+
20
+ def number
21
+ UNSIGNED_NUMBER_REGEXP
22
+ end
23
+
24
+ def variable_name
25
+ VARIABLE_NAME_REGEXP
26
+ end
27
+ end
28
+ end
29
+ end