class Carbon::Concrete::Type::Parse
Parses a type. This starts by scanning the string, then parsing it. Each instance should result in a different parsed value; a single instance cannot be re-used for parsing something else. **Not for public consumption.**
@api private @private
Constants
- FUNC_NAME
Public Class Methods
new(scan)
click to toggle source
Initialize the parser.
@param scan [::String] The string to parse.
# File lib/carbon/concrete/type/parse.rb, line 21 def initialize(scan) @string = scan @scanner = StringScanner.new(@string) end
Public Instance Methods
value()
click to toggle source
The resulting value. This should be a name.
@see parse
@return [Type::Name]
# File lib/carbon/concrete/type/parse.rb, line 30 def value @_value ||= parse end
Private Instance Methods
error(expected, given)
click to toggle source
# File lib/carbon/concrete/type/parse.rb, line 164 def error(expected, given) fail ArgumentError, "Unexpected #{given.inspect}, " \ "expected #{expected.map(&:inspect).join(', ')} " \ "(source #{@string})" end
expect(*values)
click to toggle source
# File lib/carbon/concrete/type/parse.rb, line 52 def expect(*values) token = @tokens.next error(values, token[0]) unless values.include?(token[0]) token end
parse()
click to toggle source
# File lib/carbon/concrete/type/parse.rb, line 36 def parse @tokens = scan name = parse_name end
parse_function_name()
click to toggle source
# File lib/carbon/concrete/type/parse.rb, line 73 def parse_function_name name = nil params = [] expect :"." name = case @tokens.peek[0] when :< then expect(:<); "<" when :> then expect(:>); ">" when :+ then expect(:+); "+" else expect(:FNAME)[1] end expect :"(" until @tokens.peek[0] == :")" params << Type.new(parse_name) break unless @tokens.peek[0] == :"," expect :"," end expect :")" Function.new(name, params) end
parse_generic()
click to toggle source
# File lib/carbon/concrete/type/parse.rb, line 113 def parse_generic name = Type.new(parse_name) implements = [] if @tokens.peek[0] == :":" expect :":" implements << Type.new(parse_name) while @tokens.peek[0] == :+ expect :+ implements << Type.new(parse_name) end end Generic.new(name, implements) end
parse_name()
click to toggle source
# File lib/carbon/concrete/type/parse.rb, line 58 def parse_name parts = [parse_name_part] func = nil while @tokens.peek[0] == :"::" expect :"::" parts << parse_name_part end parts = [*parts[0..-2].map(&:strip), parts[-1]] func = parse_function_name if @tokens.peek[0] == :"." Name.new(parts, func) end
parse_name_part()
click to toggle source
# File lib/carbon/concrete/type/parse.rb, line 95 def parse_name_part part = expect(:MNAME) generics = [] if @tokens.peek[0] == :< expect :< until @tokens.peek[0] == :> generics << parse_generic break unless @tokens.peek[0] == :"," expect :"," end expect :> end Part.new(part[1], generics) end
scan() { |single| ... }
click to toggle source
# File lib/carbon/concrete/type/parse.rb, line 41 def scan return to_enum(:scan) unless block_given? until @scanner.eos? single = scan_single yield single if single end yield [:EOS] end
scan_single()
click to toggle source
# File lib/carbon/concrete/type/parse.rb, line 144 def scan_single case when @scanner.scan(/[A-Z][A-Za-z0-9_-]*/) [:MNAME, @scanner[0]] when @scanner.scan(FUNC_NAME) [:FNAME, @scanner[0]] when @scanner.scan(/::/) then [:"::"] when @scanner.scan(/</) then [:<] when @scanner.scan(/>/) then [:>] when @scanner.scan(/,/) then [:","] when @scanner.scan(/:/) then [:":"] when @scanner.scan(/\+/) then [:+] when @scanner.scan(/\./) then [:"."] when @scanner.scan(/\(/) then [:"("] when @scanner.scan(/\)/) then [:")"] when @scanner.scan(/\s+/) else error([], @string[@scanner.pos]) end end