Class: Highway::Compiler::Parse::Parser

Inherits:
Object
  • Object
show all
Defined in:
lib/highway/compiler/parse/parser.rb

Overview

This class is responsible for syntactic analysis of a configuration file. This is the first phase of the compiler.

Instance Method Summary collapse

Constructor Details

#initialize(interface:) ⇒ Parser

Initialize an instance.

Parameters:



23
24
25
# File 'lib/highway/compiler/parse/parser.rb', line 23

def initialize(interface:)
  @interface = interface
end

Instance Method Details

#parse(path:) ⇒ Highway::Compiler::Parse::Tree::Root

Parse the configuration file.

The parser is backwards compatible with previous versions of configuration files.

This method only loads the file, searches for the version declaration and then delegates the wotk to parser of a particular version.

The parser produces a parse tree which is then used by semantic analysis phase to produce semantic tree.

Parameters:

  • path (String)

    Path to configuration file.

Returns:



41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
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
# File 'lib/highway/compiler/parse/parser.rb', line 41

def parse(path:)

  # Load the file.

  unless File.exist?(path)
    @interface.fatal!("The configuration file '#{path}' does not exist.")
  end

  begin
    raw = YAML.load_file(path)
  rescue StandardError => error
    @interface.fatal!("The configuration file '#{path}' is not a valid YAML file.")
  end

  # Make sure it contains a hash.

  unless raw.is_a?(Hash)
    @interface.fatal!("The configuration file does not contain a top-level dictionary.")
  end

  # Specify the known versions and their corresponding subparsers.

  known = {
    1 => Parse::Versions::V1,
  }

  # Find and validate the version.

  unless version = (Integer(raw.fetch("version", nil)) rescue nil)
    @interface.fatal!("Missing or invalid value of: 'version'.")
  end

  unless known.keys.include?(version)
    expected_versions = known.keys.map { |v| "'#{v}'" }.join(", ")
    @interface.fatal!("Invalid value of: 'version'. Expected one of: [#{expected_versions}], got: '#{version}'.")
  end

  # Delegate the work to parser of a specific version.

  subparser = known[version].new(interface: @interface)

  # Parse and return the tree.

  subparser.parse(raw: raw)

end