summaryrefslogtreecommitdiff
path: root/lib/gitlab/ci/pipeline/expression/lexer.rb
blob: 038c0e7e3303345a84230999c12e96ab03590061 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
module Gitlab
  module Ci
    module Pipeline
      module Expression
        class Lexer
          LEXEMES = [
            Expression::Lexeme::Variable,
            Expression::Lexeme::String,
            Expression::Lexeme::Equals
          ].freeze

          MAX_CYCLES = 5
          SyntaxError = Class.new(StandardError)

          def initialize(statement)
            @scanner = StringScanner.new(statement)
            @tokens = []
          end

          def tokens
            return @tokens if @tokens.any?

            MAX_CYCLES.times do
              LEXEMES.each do |lexeme|
                @scanner.skip(/\s+/) # ignore whitespace

                lexeme.scan(@scanner).tap do |token|
                  @tokens.push(token) if token.present?
                end

                return @tokens if @scanner.eos?
              end
            end

            raise Lexer::SyntaxError unless @scanner.eos?
          end

          def lexemes
            tokens.map(&:to_lexeme)
          end
        end
      end
    end
  end
end