Class: EBNFLL1Parser

Inherits:
Object
  • Object
show all
Includes:
EBNF::LL1::Parser, EBNF::Terminals, EBNFParserMeta
Defined in:
examples/ebnf-ll1-parser/parser.rb

Defined Under Namespace

Classes: ProdResult

Constant Summary

Constants included from EBNF::Terminals

EBNF::Terminals::CHAR, EBNF::Terminals::HEX, EBNF::Terminals::LHS, EBNF::Terminals::O_RANGE, EBNF::Terminals::PASS, EBNF::Terminals::POSTFIX, EBNF::Terminals::RANGE, EBNF::Terminals::RANGE_NOT_LHS, EBNF::Terminals::R_CHAR, EBNF::Terminals::STRING1, EBNF::Terminals::STRING2, EBNF::Terminals::SYMBOL, EBNF::Terminals::SYMBOL_BASE

Constants included from EBNFParserMeta

EBNFParserMeta::BRANCH, EBNFParserMeta::CLEANUP, EBNFParserMeta::FIRST, EBNFParserMeta::FOLLOW, EBNFParserMeta::PASS, EBNFParserMeta::START, EBNFParserMeta::TERMINALS

Instance Attribute Summary collapse

Attributes included from EBNF::LL1::Parser

#lineno

Instance Method Summary collapse

Methods included from EBNF::LL1::Parser

#add_prod_data, #add_prod_datum, #debug, #depth, #error, #parse, #prod_data, #progress, #warn

Constructor Details

#initialize(input, **options, &block) ⇒ self

Parser invocation.

On start, yield ourselves if a block is given, otherwise, return this parser instance

Parameters:

  • input (#read, #to_s)
  • options (Hash{Symbol => Object})

Options Hash (**options):

  • :level (Boolean)

    Trace level. 0(debug), 1(info), 2(warn), 3(error).



274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
# File 'examples/ebnf-ll1-parser/parser.rb', line 274

def initialize(input, **options, &block)
  # Read input, if necessary, which will be used in a Scanner which feads the Lexer.
  @input = input.respond_to?(:read) ? input.read : input.to_s

  # If the `level` option is set, instantiate a logger for collecting trace information.
  if options.key?(:level)
    options[:logger] ||= Logger.new(STDERR).
      tap {|x| x.level = options[:level]}.
      tap {|x| x.formatter = lambda {|severity, datetime, progname, msg| "#{severity} #{msg}\n"}}
  end

  parsing_terminals = false
  @ast = []
  parse(@input, START.to_sym, branch: BRANCH,
                              first: FIRST,
                              follow: FOLLOW,
                              cleanup: CLEANUP,
                              whitespace: EBNF::Terminals::PASS,
                              reset_on_start: true,
                              **options
  ) do |context, *data|
    rule = case context
    when :terminals
      # After parsing `@terminals`
      # This changes the state of the parser to treat subsequent rules as terminals.
      parsing_terminals = true
      rule = EBNF::Rule.new(nil, nil, data.first, kind: :terminals)
    when :pass
      # After parsing `@pass`
      # This defines a specific rule for whitespace.
      rule = EBNF::Rule.new(nil, nil, data.first, kind: :pass)
    when :rule
      # A rule which has already been turned into a `Rule` object.
      rule = data.first
      rule.kind = :terminal if parsing_terminals
      rule
    end
    @ast << rule if rule
  end
  @ast
end

Instance Attribute Details

#astArray<EBNF::Rule> (readonly)

Abstract syntax tree from parse

Returns:



37
38
39
# File 'examples/ebnf-ll1-parser/parser.rb', line 37

def ast
  @ast
end

Instance Method Details

#to_sxp(**options) ⇒ String

Output formatted S-Expression of grammar

Returns:

  • (String)


319
320
321
322
323
# File 'examples/ebnf-ll1-parser/parser.rb', line 319

def to_sxp(**options)
  require 'sxp' unless defined?(SXP)
  # Output rules as a formatted S-Expression
  SXP::Generator.string(@ast.map(&:for_sxp))
end