# encoding: utf-8 # frozen_string_literal: true require "set" module Carbon module Compiler class Parser # Manages first sets for the parser. This is only for internal # reference to make parsing easier. module Firsts # The class methods that should be placed on the parser. module ClassMethods # The first sets. The key is the name of a node, and the value # is a set of all tokens that can be at the start of that node. # # @return [{Symbol => Set}] def firsts @firsts ||= Hash.new { |h, k| h[k] = Set.new } end # @overload first(name) # Retrieves the first set for the given node name. If none exists, # a `KeyError` is raised. # # @api private # @param name [::Symbol] The name of the node to look up the first # set for. # @return [Set<::Symbol>] The first set # @raise [KeyError] If the node has no defined first set. # @overload first(name, tokens) # Merges the given tokens into the first set of the name of the # node given. # # @api private # @param name [::Symbol] The name of the node that the first set is # for. # @param tokens [<::Symbol>] The tokens that act as the first set # for the node. # @return [void] def first(name, tokens = nil) if tokens firsts[name].merge(tokens) else firsts.fetch(name) end end end # The instance methods that should be placed in the parser. module InstanceMethods # Retrieves the first set for the given node name. # # @param name [Symbol] # @return [Set] def first(name) self.class.firsts.fetch(name) end end # Includes the {ClassMethods} and {InstanceMethods} into the # parser or whatever base includes it. # # @param base [Parser] # @api private def self.included(base) base.extend ClassMethods base.send :include, InstanceMethods end end include Firsts end end end