Class: RBlade::TokenizesStatements

Inherits:
Object
  • Object
show all
Defined in:
lib/rblade/compiler/tokenizes_statements.rb

Instance Method Summary collapse

Instance Method Details

#tokenize!(tokens) ⇒ Object



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
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
# File 'lib/rblade/compiler/tokenizes_statements.rb', line 8

def tokenize!(tokens)
  tokens.map! do |token|
    next(token) if token.type != :unprocessed

    current_match_id = nil
    segments = []
    token.value.split(/
      \s?(?<!\w|@)
      (?:
        (?:
          (?<escaped_at>@@)
          (?<escaped_statement_name>\w++[!\?]?(?!\w))
        )
        |
        (?:
          @
          (?# Statement name )
          (?<statement_name>\w++[!\?]?)
          (?# Optional parameters )
          (?:
            [ \t]*+
            (?# Matched parentheses )
            (?<statement_arguments>
              \(
                (?:
                  [^()#{RegularExpressions::RUBY_STRING_CHARACTERS}]++
                  |
                  #{RegularExpressions::RUBY_STRING}
                  |
                  \g<statement_arguments>
                )*+
              \)
            )
          )?
        )
      )
      \s?
    /xo) do |before_match|
      next if current_match_id == $~.object_id
      current_match_id = $~.object_id

      # Add the current string to the segment list
      unless before_match == ""
        # Skip output between case and when statements
        unless segments.last&.type == :statement && segments.last&.value&.[](:name) == "case"
          RBlade::Utility.append_unprocessed_string_segment!(token, segments, before_match)
        end
      end
      next if $~.nil?

      statement_handle = ($~[:statement_name] || $~[:escaped_statement_name])
        &.downcase
        &.tr("_", "")
      next if statement_handle.nil?

      unless CompilesStatements.has_handler(statement_handle)
        RBlade::Utility.append_unprocessed_string_segment!(token, segments, $&)

        next
      end

      # Skip escaped statements
      if $~&.[](:escaped_at) == "@@"
        segment = $&.dup
        # Remove the first or second @, depending on whether there is whitespace
        segment.slice!(1)

        RBlade::Utility.append_unprocessed_string_segment!(token, segments, segment, 1)

        next
      end

      statement_data = {name: statement_handle}

      unless $~[:statement_arguments].blank?
        arguments = tokenize_arguments! statement_handle, $~[:statement_arguments]

        unless arguments.nil?
          statement_data[:arguments] = arguments
        end

      end

      start_offset = segments.last&.end_offset || token.start_offset
      segments << Token.new(
        type: :statement,
        value: statement_data,
        start_offset: start_offset,
        end_offset: start_offset + $&.length,
      )
    end

    segments
  end.flatten!
end