60 lines
1.4 KiB
Ruby
60 lines
1.4 KiB
Ruby
|
module Gitlab
|
||
|
module Ci
|
||
|
module Pipeline
|
||
|
module Expression
|
||
|
class Lexer
|
||
|
include ::Gitlab::Utils::StrongMemoize
|
||
|
|
||
|
LEXEMES = [
|
||
|
Expression::Lexeme::Variable,
|
||
|
Expression::Lexeme::String,
|
||
|
Expression::Lexeme::Null,
|
||
|
Expression::Lexeme::Equals
|
||
|
].freeze
|
||
|
|
||
|
SyntaxError = Class.new(Statement::StatementError)
|
||
|
|
||
|
MAX_TOKENS = 100
|
||
|
|
||
|
def initialize(statement, max_tokens: MAX_TOKENS)
|
||
|
@scanner = StringScanner.new(statement)
|
||
|
@max_tokens = max_tokens
|
||
|
end
|
||
|
|
||
|
def tokens
|
||
|
strong_memoize(:tokens) { tokenize }
|
||
|
end
|
||
|
|
||
|
def lexemes
|
||
|
tokens.map(&:to_lexeme)
|
||
|
end
|
||
|
|
||
|
private
|
||
|
|
||
|
def tokenize
|
||
|
tokens = []
|
||
|
|
||
|
@max_tokens.times do
|
||
|
@scanner.skip(/\s+/) # ignore whitespace
|
||
|
|
||
|
return tokens if @scanner.eos?
|
||
|
|
||
|
lexeme = LEXEMES.find do |type|
|
||
|
type.scan(@scanner).tap do |token|
|
||
|
tokens.push(token) if token.present?
|
||
|
end
|
||
|
end
|
||
|
|
||
|
unless lexeme.present?
|
||
|
raise Lexer::SyntaxError, 'Unknown lexeme found!'
|
||
|
end
|
||
|
end
|
||
|
|
||
|
raise Lexer::SyntaxError, 'Too many tokens!'
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
end
|