# encoding: utf-8 # frozen_string_literal: true module Carbon module Compiler class Scanner # Performs the scanning. module Main protected def scan false || scan_keywords || scan_identifiers || scan_operators || scan_comment || scan_whitespace || error! end # rubocop:disable Metrics/CyclomaticComplexity def scan_identifiers false || match(/[a-z][A-Za-z0-9_-]*[!?=]?/, :IDENTIFIER) || match(/(0[xX][0-9a-fA-F]+)(_?[ui][0-9]+)?/, :NUMBER) || match(/(0|[1-9][0-9]*)(_?[ui][0-9]+)?/, :NUMBER) || match(/[A-Z][A-Za-z0-9_-]*/, :MNAME) || match(/"(([^"\\]|\\.)*)"/, :STRING) || false end KEYWORDS = %i( finally return struct module catch elsif match trait while self else enum for def end let try do if _ ).sort_by(&:size).reverse.freeze def scan_keywords KEYWORDS.find do |keyword| m = match(/#{Regexp.escape(keyword)}(?![a-zA-Z0-9!?=_-])/, keyword) return m if m end || false end OPERATORS = %w( === :: => == && || != << >> <= >= + - ~ ! * / % : ; & | [ ] ( ) { } < > . , = ^ [] []= ).sort_by(&:size).reverse.freeze def scan_operators OPERATORS.find do |operator| m = match(operator) return m if m end || false end def scan_comment if @scanner.scan(/\#.+?(\r\n|\r|\n)/) @line += 1 @last = @scanner.charpos - 1 true end end def scan_whitespace if @scanner.scan(/\r\n|\r|\n/) @line += 1 @last = @scanner.charpos - 1 true elsif @scanner.scan(/[ \v\t\f]/) true end end end end end end