# frozen_string_literal: true # encoding: UTF-8 #-- # This file is automatically generated. Do not modify it. # Generated by: oedipus_lex version 2.6.0. # Source: lib/synvert/core/node_query/lexer.rex #++ ## # The generated lexer Synvert::Core::NodeQuery::Lexer class Synvert::Core::NodeQuery::Lexer require 'strscan' # :stopdoc: OPEN_ATTRIBUTE = /\[/ CLOSE_ATTRIBUTE = /\]/ OPEN_ARRAY = /\(/ CLOSE_ARRAY = /\)/ OPEN_SELECTOR = /\(/ CLOSE_SELECTOR = /\)/ OPEN_DYNAMIC_ATTRIBUTE = /{{/ CLOSE_DYNAMIC_ATTRIBUTE = /}}/ NODE_TYPE = /\.[a-z]+/ IDENTIFIER = /[\.\w]+/ IDENTIFIER_VALUE = /[\.\w!&:\?<>=]+/ FALSE = /false/ FLOAT = /\d+\.\d+/ INTEGER = /\d+/ NIL = /nil/ REGEXP_BODY = /(?:[^\/]|\\\/)*/ REGEXP = /\/(#{REGEXP_BODY})(?=]+/ TRUE = /true/ SINGLE_QUOTE_STRING = /'.*?'/ DOUBLE_QUOTE_STRING = /".*?"/ # :startdoc: # :stopdoc: class LexerError < StandardError ; end class ScanError < LexerError ; end # :startdoc: ## # The file name / path attr_accessor :filename ## # The StringScanner for this lexer. attr_accessor :ss ## # The current lexical state. attr_accessor :state alias :match :ss ## # The match groups for the current scan. def matches m = (1..9).map { |i| ss[i] } m.pop until m[-1] or m.empty? m end ## # Yields on the current action. def action yield end ## # The current scanner class. Must be overridden in subclasses. def scanner_class StringScanner end unless instance_methods(false).map(&:to_s).include?("scanner_class") ## # Parse the given string. def parse str self.ss = scanner_class.new str self.state ||= nil do_parse end ## # Read in and parse the file at +path+. def parse_file path self.filename = path open path do |f| parse f.read end end ## # The current location in the parse. def location [ (filename || ""), ].compact.join(":") end ## # Lex the next token. def next_token token = nil until ss.eos? or token do token = case state when nil then case when ss.skip(/\s+/) then # do nothing when text = ss.scan(/:has/) then action { [:tPSEUDO_CLASS, text[1..-1]] } when text = ss.scan(/:not_has/) then action { [:tPSEUDO_CLASS, text[1..-1]] } when text = ss.scan(/#{NODE_TYPE}/) then action { [:tNODE_TYPE, text[1..]] } when text = ss.scan(/#{IDENTIFIER}/) then action { [:tGOTO_SCOPE, text] } when text = ss.scan(/>/) then action { [:tRELATIONSHIP, text] } when text = ss.scan(/~/) then action { [:tRELATIONSHIP, text] } when text = ss.scan(/\+/) then action { [:tRELATIONSHIP, text] } when text = ss.scan(/#{OPEN_SELECTOR}/) then action { [:tOPEN_SELECTOR, text] } when text = ss.scan(/#{CLOSE_SELECTOR}/) then action { [:tCLOSE_SELECTOR, text] } when text = ss.scan(/#{OPEN_ATTRIBUTE}/) then action { @nested_count += 1; @state = :KEY; [:tOPEN_ATTRIBUTE, text] } else text = ss.string[ss.pos .. -1] raise ScanError, "can not match (#{state.inspect}) at #{location}: '#{text}'" end when :KEY then case when ss.skip(/\s+/) then # do nothing when ss.skip(/\^=/) then action { @state = :VALUE; [:tOPERATOR, '^='] } when ss.skip(/\$=/) then action { @state = :VALUE; [:tOPERATOR, '$='] } when ss.skip(/\*=/) then action { @state = :VALUE; [:tOPERATOR, '*='] } when ss.skip(/!=/) then action { @state = :VALUE; [:tOPERATOR, '!='] } when ss.skip(/=~/) then action { @state = :VALUE; [:tOPERATOR, '=~'] } when ss.skip(/!~/) then action { @state = :VALUE; [:tOPERATOR, '!~'] } when ss.skip(/>=/) then action { @state = :VALUE; [:tOPERATOR, '>='] } when ss.skip(/<=/) then action { @state = :VALUE; [:tOPERATOR, '<='] } when ss.skip(/>/) then action { @state = :VALUE; [:tOPERATOR, '>'] } when ss.skip(/= 2) # auto-switch state self.state = token.last if token && token.first == :state token end # def next_token def initialize @nested_count = 0 end def do_parse; end end # class