Class: Ibex::Frontend::Parser
- Inherits:
-
Object
- Object
- Ibex::Frontend::Parser
- Defined in:
- lib/ibex/frontend/parser.rb
Overview
Public grammar parser backed by Ibex's generated LR frontend.
Constant Summary collapse
- DEFAULT_MAX_DIAGNOSTICS =
: Integer
20
Instance Attribute Summary collapse
-
#implementation ⇒ Object
readonly
: GeneratedParser.
Instance Method Summary collapse
-
#initialize(source, file: "(grammar)", mode: :default) ⇒ Parser
constructor
A new instance of Parser.
- #parse ⇒ Object
-
#parse_document ⇒ Object
Parse the grammar and return its lossless source model.
-
#parse_fragment ⇒ Object
Parse an explicit fragment without resolving its includes.
-
#parse_source_document ⇒ Object
Parse either a root grammar or an explicit fragment and return its lossless source model.
-
#parse_with_diagnostics(max_diagnostics: DEFAULT_MAX_DIAGNOSTICS) ⇒ Object
Parse with conservative boundary recovery and collect multiple errors.
Constructor Details
#initialize(source, file: "(grammar)", mode: :default) ⇒ Parser
Returns a new instance of Parser.
23 24 25 26 27 28 29 30 31 32 33 |
# File 'lib/ibex/frontend/parser.rb', line 23 def initialize(source, file: "(grammar)", mode: :default) raise ArgumentError, "mode must be :default or :extended" unless %i[default extended].include?(mode) @mode = mode @lexical_diagnostics = [] #: Array[Diagnostic] @parse_error_message = nil @source_document_error_message = nil tokens = source.is_a?(Array) ? source : tokenize_source(source, file) @tokens = tokens @implementation = GeneratedParser.new(tokens, mode: mode) end |
Instance Attribute Details
#implementation ⇒ Object (readonly)
: GeneratedParser
11 12 13 |
# File 'lib/ibex/frontend/parser.rb', line 11 def implementation @implementation end |
Instance Method Details
#parse ⇒ Object
36 37 38 39 40 41 |
# File 'lib/ibex/frontend/parser.rb', line 36 def parse node = parse_node return node if node.is_a?(AST::Root) raise Ibex::Error, "#{node.loc}: fragment input requires Parser#parse_fragment" end |
#parse_document ⇒ Object
Parse the grammar and return its lossless source model.
54 55 56 57 58 59 |
# File 'lib/ibex/frontend/parser.rb', line 54 def parse_document parsed_document = @parsed_document return parsed_document if parsed_document && parsed_document.ast.is_a?(AST::Root) @parsed_document = source_document!.with_ast(parse) end |
#parse_fragment ⇒ Object
Parse an explicit fragment without resolving its includes.
45 46 47 48 49 50 |
# File 'lib/ibex/frontend/parser.rb', line 45 def parse_fragment node = parse_node return node if node.is_a?(AST::Fragment) raise Ibex::Error, "#{node.loc}: root grammar input cannot be parsed as a fragment" end |
#parse_source_document ⇒ Object
Parse either a root grammar or an explicit fragment and return its lossless source model.
63 64 65 66 67 68 |
# File 'lib/ibex/frontend/parser.rb', line 63 def parse_source_document parsed_document = @parsed_document return parsed_document if parsed_document @parsed_document = source_document!.with_ast(parse_node) end |
#parse_with_diagnostics(max_diagnostics: DEFAULT_MAX_DIAGNOSTICS) ⇒ Object
Parse with conservative boundary recovery and collect multiple errors.
72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 |
# File 'lib/ibex/frontend/parser.rb', line 72 def parse_with_diagnostics(max_diagnostics: DEFAULT_MAX_DIAGNOSTICS) unless max_diagnostics.is_a?(Integer) && max_diagnostics.positive? raise ArgumentError, "max_diagnostics must be a positive integer" end lexical_diagnostics = lexical_diagnostics_for(max_diagnostics) if @source_document.nil? && @lexical_diagnostics.any? return ParseResult.new(diagnostics: lexical_diagnostics, ast: nil, document: nil) end recovery = DiagnosticRecovery.new( @tokens, mode: @mode, max_diagnostics: max_diagnostics ) node, syntax_diagnostics = recovery.parse node = enrich_rule_documentation(node) if node ast, syntax_diagnostics = root_diagnostic_result(node, syntax_diagnostics) diagnostics = merge_diagnostics(lexical_diagnostics, syntax_diagnostics, max_diagnostics) document = if diagnostics.empty? && ast @source_document&.with_ast(ast) else @source_document end ParseResult.new(diagnostics: diagnostics, ast: ast, document: document) end |