Class: Nero::Parser

Inherits:
Object
  • Object
show all
Includes:
Rails::ParserExtension
Defined in:
lib/nero/parser.rb

Constant Summary collapse

TO_INT =
->(v) { Integer(v) }
TO_FLOAT =
->(v) { Float(v) }
TO_BOOL =
->(v) { !%w[0 false no off].include?(v.downcase) }
TO_PATH =
->(v) { Pathname.new(v) }

Instance Method Summary collapse

Constructor Details

#initialize(environ: ENV, root: nil, &block) ⇒ Parser

Returns a new instance of Parser.



10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
# File 'lib/nero/parser.rb', line 10

def initialize(environ: ENV, root: nil, &block)
  @environ = environ
  @root = root&.to_s
  @tags = {}
  add_tag("env", EnvTag.new)
  add_tag("env?", EnvTag.new(optional: true))
  add_tag("env/int", EnvTag.new(coerce: TO_INT))
  add_tag("env/int?", EnvTag.new(coerce: TO_INT, optional: true))
  add_tag("env/integer", EnvTag.new(coerce: TO_INT))
  add_tag("env/integer?", EnvTag.new(coerce: TO_INT, optional: true))
  add_tag("env/bool", EnvTag.new(coerce: TO_BOOL))
  add_tag("env/bool?", EnvTag.new(coerce: TO_BOOL, optional: true))
  add_tag("env/boolean", EnvTag.new(coerce: TO_BOOL))
  add_tag("env/boolean?", EnvTag.new(coerce: TO_BOOL, optional: true))
  add_tag("env/float", EnvTag.new(coerce: TO_FLOAT))
  add_tag("env/float?", EnvTag.new(coerce: TO_FLOAT, optional: true))
  add_tag("env/path", EnvTag.new(coerce: TO_PATH))
  add_tag("env/path?", EnvTag.new(coerce: TO_PATH, optional: true))
  add_tag("str/format", FormatTag.new)
  add_tag("format", FormatTag.new)
  add_tag("ref", RefTag.new)
  block&.call(self)
end

Instance Method Details

#add_tag(name, handler) ⇒ Object



34
35
36
# File 'lib/nero/parser.rb', line 34

def add_tag(name, handler)
  @tags[name] = handler.is_a?(Proc) ? ProcTag.new(handler) : handler
end

#parse(yaml, dir: nil) ⇒ Object



38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
# File 'lib/nero/parser.rb', line 38

def parse(yaml, dir: nil)
  errors = []
  tree = ::Psych.parse_stream(yaml)
  ctx = Context.new(environ: @environ, errors: errors, dir: dir)

  if @root
    mark_inactive_roots(tree)
  end

  visitor = Visitor.build(@tags, ctx)
  result = visitor.accept(tree)
  value = result.first

  if @root
    unless value.is_a?(Hash) && value.key?(@root)
      ctx.add_error("root #{@root.inspect} not found in top-level keys")
      return Result.new(nil, errors.freeze)
    end
    value = value[@root]
  end

  value = resolve_refs(value, value, ctx) if contains_ref?(value)
  Result.new(value, errors.freeze)
end

#parse_file(path) ⇒ Object



63
64
65
66
# File 'lib/nero/parser.rb', line 63

def parse_file(path)
  dir = File.dirname(File.realpath(path))
  parse(File.read(path), dir: dir)
end