Class: Expressir::Express::Parser

Inherits:
Object
  • Object
show all
Defined in:
lib/expressir/express/parser.rb

Defined Under Namespace

Classes: Parser

Class Method Summary collapse

Class Method Details

.from_file(file, skip_references: nil, include_source: nil, root_path: nil) ⇒ Model::Repository

Parses Express file into an Express model

Parameters:

  • file (String)

    Express file path

  • skip_references (Boolean) (defaults to: nil)

    skip resolving references

  • include_source (Boolean) (defaults to: nil)

    attach original source code to model elements

Returns:

Raises:

  • (SchemaParseFailure)

    if the schema file fails to parse



605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
# File 'lib/expressir/express/parser.rb', line 605

def self.from_file(file, skip_references: nil, include_source: nil, root_path: nil) # rubocop:disable Metrics/AbcSize
  Expressir::Benchmark.measure_file(file) do
    source = File.read file

    # remove root path from file path
    schema_file = root_path ? Pathname.new(file.to_s).relative_path_from(root_path).to_s : file.to_s

    begin
      ast = Parser.new.parse source
    rescue Parslet::ParseFailed => e
      # Instead of just printing, raise a proper error with file context
      raise Error::SchemaParseFailure.new(schema_file, e)
    end

    visitor = Expressir::Express::Visitor.new(source,
                                              include_source: include_source)
    @repository = visitor.visit_ast ast, :top

    @repository.schemas.each do |schema|
      schema.file = schema_file
      schema.file_basename = File.basename(schema_file, ".exp")
      schema.formatted = schema.to_s(no_remarks: true)
    end

    unless skip_references
      Expressir::Benchmark.measure_references do
        @resolve_references_model_visitor = ResolveReferencesModelVisitor.new
        @resolve_references_model_visitor.visit(@repository)
      end
    end

    @repository
  end
end

.from_files(files, skip_references: nil, include_source: nil, root_path: nil) {|filename, schemas, error| ... } ⇒ Model::Repository

Parses Express files into an Express model

Parameters:

  • files (Array<String>)

    Express file paths

  • skip_references (Boolean) (defaults to: nil)

    skip resolving references

  • include_source (Boolean) (defaults to: nil)

    attach original source code to model elements

Yields:

  • (filename, schemas, error)

    Optional block called for each file processed

Yield Parameters:

  • filename (String)

    Name of the file being processed

  • schemas (Array, nil)

    Array of parsed schemas (nil if parsing failed)

  • error (Exception, nil)

    Error that occurred (nil if parsing succeeded)

Returns:



649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
# File 'lib/expressir/express/parser.rb', line 649

def self.from_files(files, skip_references: nil, include_source: nil,
root_path: nil)
  all_schemas = []

  files.each do |file|
    repository = from_file(file, skip_references: true,
                                 root_path: root_path)
    file_schemas = repository.schemas
    all_schemas.concat(file_schemas)

    # Call the progress block if provided
    yield(file, file_schemas, nil) if block_given?
  rescue StandardError => e
    # Call the progress block with the error if provided
    yield(file, nil, e) if block_given?

    # Re-raise the error if it's not a schema parse failure
    # This allows handling of specific schema parse failures while still propagating other errors
    raise unless e.is_a?(Error::SchemaParseFailure)
  end

  @repository = Model::Repository.new(
    schemas: all_schemas,
  )

  unless skip_references
    Expressir::Benchmark.measure_references do
      @resolve_references_model_visitor = ResolveReferencesModelVisitor.new
      @resolve_references_model_visitor.visit(@repository)
    end
  end

  @repository
end