textmate_grammar 0.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +21 -0
  3. data/lib/textmate_grammar/generated/grammar.rb +32 -0
  4. data/lib/textmate_grammar/generated/rule.rb +144 -0
  5. data/lib/textmate_grammar/grammar.rb +670 -0
  6. data/lib/textmate_grammar/grammar_plugin.rb +189 -0
  7. data/lib/textmate_grammar/import_patterns.rb +14 -0
  8. data/lib/textmate_grammar/linters/flat_includes.rb +32 -0
  9. data/lib/textmate_grammar/linters/includes_then_tag_as.rb +48 -0
  10. data/lib/textmate_grammar/linters/standard_naming.rb +226 -0
  11. data/lib/textmate_grammar/linters/start_match_empty.rb +49 -0
  12. data/lib/textmate_grammar/linters/tests.rb +19 -0
  13. data/lib/textmate_grammar/linters/unused_unresolved.rb +9 -0
  14. data/lib/textmate_grammar/pattern_extensions/look_ahead_for.rb +32 -0
  15. data/lib/textmate_grammar/pattern_extensions/look_ahead_to_avoid.rb +31 -0
  16. data/lib/textmate_grammar/pattern_extensions/look_behind_for.rb +31 -0
  17. data/lib/textmate_grammar/pattern_extensions/look_behind_to_avoid.rb +31 -0
  18. data/lib/textmate_grammar/pattern_extensions/lookaround_pattern.rb +169 -0
  19. data/lib/textmate_grammar/pattern_extensions/match_result_of.rb +67 -0
  20. data/lib/textmate_grammar/pattern_extensions/maybe.rb +50 -0
  21. data/lib/textmate_grammar/pattern_extensions/one_of.rb +107 -0
  22. data/lib/textmate_grammar/pattern_extensions/one_or_more_of.rb +42 -0
  23. data/lib/textmate_grammar/pattern_extensions/or_pattern.rb +55 -0
  24. data/lib/textmate_grammar/pattern_extensions/placeholder.rb +102 -0
  25. data/lib/textmate_grammar/pattern_extensions/recursively_match.rb +76 -0
  26. data/lib/textmate_grammar/pattern_extensions/zero_or_more_of.rb +50 -0
  27. data/lib/textmate_grammar/pattern_variations/base_pattern.rb +870 -0
  28. data/lib/textmate_grammar/pattern_variations/legacy_pattern.rb +61 -0
  29. data/lib/textmate_grammar/pattern_variations/pattern.rb +9 -0
  30. data/lib/textmate_grammar/pattern_variations/pattern_range.rb +233 -0
  31. data/lib/textmate_grammar/pattern_variations/repeatable_pattern.rb +204 -0
  32. data/lib/textmate_grammar/regex_operator.rb +182 -0
  33. data/lib/textmate_grammar/regex_operators/alternation.rb +24 -0
  34. data/lib/textmate_grammar/regex_operators/concat.rb +23 -0
  35. data/lib/textmate_grammar/stdlib/common.rb +20 -0
  36. data/lib/textmate_grammar/tokens.rb +110 -0
  37. data/lib/textmate_grammar/transforms/add_ending.rb +25 -0
  38. data/lib/textmate_grammar/transforms/bailout.rb +92 -0
  39. data/lib/textmate_grammar/transforms/fix_repeated_tag_as.rb +75 -0
  40. data/lib/textmate_grammar/transforms/resolve_placeholders.rb +121 -0
  41. data/lib/textmate_grammar/util.rb +198 -0
  42. data/lib/textmate_grammar.rb +4 -0
  43. metadata +85 -0
@@ -0,0 +1,49 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'textmate_grammar/util'
4
+
5
+ #
6
+ # Warns when a PatternRange has a start_pattern that matches the empty string
7
+ #
8
+ class StartMatchEmpty < GrammarLinter
9
+ #
10
+ # (see GrammarLinter#pre_lint)
11
+ #
12
+ def pre_lint(pattern, options)
13
+ return true unless pattern.is_a? PatternRange
14
+
15
+ regexp = with_no_warnings do
16
+ Regexp.new(pattern.start_pattern.evaluate.gsub("\\G", '\uFFFF'))
17
+ end
18
+ if "" =~ regexp and !options[:zeroLengthStart?]
19
+ puts "Warning: #{pattern.start_pattern.evaluate}"
20
+ puts "matches the zero length string (\"\").\n\n"
21
+ puts "This means that the patternRange always matches"
22
+ puts "You can disable this warning by setting :zeroLengthStart? to true."
23
+ puts "The pattern is:\n#{pattern}"
24
+ end
25
+ true # return true for warnings
26
+ end
27
+
28
+ #
29
+ # Contributes the option :zeroLengthStart?
30
+ #
31
+ # :zeroLengthStart? disables this linter
32
+ #
33
+ # @return (see GrammarPlugin.options)
34
+ #
35
+ def self.options
36
+ [:zeroLengthStart?]
37
+ end
38
+
39
+ #
40
+ # Displays the state of the options
41
+ #
42
+ # @return (see GrammarPlugin.display_options)
43
+ #
44
+ def self.display_options(indent, options)
45
+ ",\n#{indent}zeroLengthStart?: #{options[:zeroLengthStart?]}"
46
+ end
47
+ end
48
+
49
+ Grammar.register_linter(StartMatchEmpty.new)
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ #
4
+ # Runs the unit tests on each pattern
5
+ #
6
+ class RunPatternTests < GrammarLinter
7
+ #
8
+ # Runs the unit tests on each pattern
9
+ #
10
+ # @return [Boolean] the result of the unit tests
11
+ #
12
+ def pre_lint(pattern, _options)
13
+ return true unless pattern.is_a? PatternBase
14
+
15
+ pattern.run_tests
16
+ end
17
+ end
18
+
19
+ Grammar.register_linter(RunPatternTests.new)
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ class UnusedUnresolvedLinter < GrammarLinter
4
+ def post_lint(grammar_hash)
5
+ true
6
+ end
7
+ end
8
+
9
+ Grammar.register_linter(UnusedUnresolvedLinter.new)
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "./lookaround_pattern.rb"
4
+
5
+
6
+ class PatternBase
7
+ #
8
+ # Equivalent to lookAround with type set to :lookAheadFor
9
+ #
10
+ # @param (see lookAround)
11
+ #
12
+ # @return (see lookAround)
13
+ #
14
+ def lookAheadFor(pattern)
15
+ if pattern.is_a? Hash
16
+ pattern[:type] = :lookAheadFor
17
+ else
18
+ pattern = {match: pattern, type: :lookAheadFor}
19
+ end
20
+ lookAround(pattern)
21
+ end
22
+ end
23
+
24
+ # (see PatternBase#lookAheadFor)
25
+ def lookAheadFor(pattern)
26
+ if pattern.is_a? Hash
27
+ pattern[:type] = :lookAheadFor
28
+ else
29
+ pattern = {match: pattern, type: :lookAheadFor}
30
+ end
31
+ lookAround(pattern)
32
+ end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "./lookaround_pattern.rb"
4
+
5
+ class PatternBase
6
+ #
7
+ # Equivalent to lookAround with type set to :lookAheadToAvoid
8
+ #
9
+ # @param (see lookAround)
10
+ #
11
+ # @return (see lookAround)
12
+ #
13
+ def lookAheadToAvoid(pattern)
14
+ if pattern.is_a? Hash
15
+ pattern[:type] = :lookAheadToAvoid
16
+ else
17
+ pattern = {match: pattern, type: :lookAheadToAvoid}
18
+ end
19
+ lookAround(pattern)
20
+ end
21
+ end
22
+
23
+ # (see PatternBase#lookAheadToAvoid)
24
+ def lookAheadToAvoid(pattern)
25
+ if pattern.is_a? Hash
26
+ pattern[:type] = :lookAheadToAvoid
27
+ else
28
+ pattern = {match: pattern, type: :lookAheadToAvoid}
29
+ end
30
+ lookAround(pattern)
31
+ end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "./lookaround_pattern.rb"
4
+
5
+ class PatternBase
6
+ #
7
+ # Equivalent to lookAround with type set to :lookBehindFor
8
+ #
9
+ # @param (see lookAround)
10
+ #
11
+ # @return (see lookAround)
12
+ #
13
+ def lookBehindFor(pattern)
14
+ if pattern.is_a? Hash
15
+ pattern[:type] = :lookBehindFor
16
+ else
17
+ pattern = {match: pattern, type: :lookBehindFor}
18
+ end
19
+ lookAround(pattern)
20
+ end
21
+ end
22
+
23
+ # (see PatternBase#lookBehindFor)
24
+ def lookBehindFor(pattern)
25
+ if pattern.is_a? Hash
26
+ pattern[:type] = :lookBehindFor
27
+ else
28
+ pattern = {match: pattern, type: :lookBehindFor}
29
+ end
30
+ lookAround(pattern)
31
+ end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "./lookaround_pattern.rb"
4
+
5
+ class PatternBase
6
+ #
7
+ # Equivalent to lookAround with type set to :lookBehindToAvoid
8
+ #
9
+ # @param (see lookAround)
10
+ #
11
+ # @return (see lookAround)
12
+ #
13
+ def lookBehindToAvoid(pattern)
14
+ if pattern.is_a? Hash
15
+ pattern[:type] = :lookBehindToAvoid
16
+ else
17
+ pattern = {match: pattern, type: :lookBehindToAvoid}
18
+ end
19
+ lookAround(pattern)
20
+ end
21
+ end
22
+
23
+ # (see PatternBase#lookBehindToAvoid)
24
+ def lookBehindToAvoid(pattern)
25
+ if pattern.is_a? Hash
26
+ pattern[:type] = :lookBehindToAvoid
27
+ else
28
+ pattern = {match: pattern, type: :lookBehindToAvoid}
29
+ end
30
+ lookAround(pattern)
31
+ end
@@ -0,0 +1,169 @@
1
+ # frozen_string_literal: true
2
+
3
+ #
4
+ # Implements lookarounds
5
+ # for some pattern p this is equivalent to one of /(?=p)/, /(?!p)/, /(?<p)/, /(?<!p)/
6
+ # depending on the type
7
+ #
8
+ class LookAroundPattern < PatternBase
9
+ # (see PatternBase#do_evaluate_self)
10
+ def do_evaluate_self(groups)
11
+ self_regex = @match
12
+ self_regex = @match.evaluate(groups) if @match.is_a? PatternBase
13
+
14
+ case @arguments[:type]
15
+ when :lookAheadFor then self_regex = "(?=#{self_regex})"
16
+ when :lookAheadToAvoid then self_regex = "(?!#{self_regex})"
17
+ when :lookBehindFor then self_regex = "(?<=#{self_regex})"
18
+ when :lookBehindToAvoid then self_regex = "(?<!#{self_regex})"
19
+ end
20
+
21
+ if needs_to_capture?
22
+ raise "You cannot capture a lookAround\nconsider capturing the pattern inside"
23
+ end
24
+
25
+ self_regex
26
+ end
27
+
28
+ # (see PatternBase#do_get_to_s_name)
29
+ def do_get_to_s_name(top_level)
30
+ top_level ? "lookAround(" : ".lookAround("
31
+ end
32
+
33
+ # (see PatternBase#do_add_attributes)
34
+ def do_add_attributes(indent)
35
+ ",\n#{indent} type: :#{@arguments[:type]}"
36
+ end
37
+
38
+ # (see PatternBase#single_entity?)
39
+ # @return [true]
40
+ def single_entity?
41
+ true
42
+ end
43
+ end
44
+
45
+ class PatternBase
46
+ #
47
+ # Looks around for the pattern
48
+ #
49
+ # @param [Hash] pattern pattern constructor
50
+ # option [Symbol] :type the look-around type
51
+ # can be one of :lookAheadFor, :lookAheadToAvoid, :lookBehindFor, :lookBehindToAvoid
52
+ #
53
+ # @return [PatternBase] a pattern to append to
54
+ #
55
+ def lookAround(pattern)
56
+ insert(LookAroundPattern.new(pattern))
57
+ end
58
+
59
+ #
60
+ # Equivalent to lookAround with type set to :lookBehindToAvoid
61
+ #
62
+ # @param (see lookAround)
63
+ #
64
+ # @return (see lookAround)
65
+ #
66
+ def lookBehindToAvoid(pattern)
67
+ if pattern.is_a? Hash
68
+ pattern[:type] = :lookBehindToAvoid
69
+ else
70
+ pattern = {match: pattern, type: :lookBehindToAvoid}
71
+ end
72
+ lookAround(pattern)
73
+ end
74
+
75
+ #
76
+ # Equivalent to lookAround with type set to :lookBehindFor
77
+ #
78
+ # @param (see lookAround)
79
+ #
80
+ # @return (see lookAround)
81
+ #
82
+ def lookBehindFor(pattern)
83
+ if pattern.is_a? Hash
84
+ pattern[:type] = :lookBehindFor
85
+ else
86
+ pattern = {match: pattern, type: :lookBehindFor}
87
+ end
88
+ lookAround(pattern)
89
+ end
90
+
91
+ #
92
+ # Equivalent to lookAround with type set to :lookAheadToAvoid
93
+ #
94
+ # @param (see lookAround)
95
+ #
96
+ # @return (see lookAround)
97
+ #
98
+ def lookAheadToAvoid(pattern)
99
+ if pattern.is_a? Hash
100
+ pattern[:type] = :lookAheadToAvoid
101
+ else
102
+ pattern = {match: pattern, type: :lookAheadToAvoid}
103
+ end
104
+ lookAround(pattern)
105
+ end
106
+
107
+ #
108
+ # Equivalent to lookAround with type set to :lookAheadFor
109
+ #
110
+ # @param (see lookAround)
111
+ #
112
+ # @return (see lookAround)
113
+ #
114
+ def lookAheadFor(pattern)
115
+ if pattern.is_a? Hash
116
+ pattern[:type] = :lookAheadFor
117
+ else
118
+ pattern = {match: pattern, type: :lookAheadFor}
119
+ end
120
+ lookAround(pattern)
121
+ end
122
+ end
123
+
124
+ # (see PatternBase#lookAround)
125
+ def lookAround(pattern)
126
+ LookAroundPattern.new(pattern)
127
+ end
128
+
129
+ # TODO: eliminate this code duplication
130
+
131
+ # (see PatternBase#lookBehindToAvoid)
132
+ def lookBehindToAvoid(pattern)
133
+ if pattern.is_a? Hash
134
+ pattern[:type] = :lookBehindToAvoid
135
+ else
136
+ pattern = {match: pattern, type: :lookBehindToAvoid}
137
+ end
138
+ lookAround(pattern)
139
+ end
140
+
141
+ # (see PatternBase#lookBehindFor)
142
+ def lookBehindFor(pattern)
143
+ if pattern.is_a? Hash
144
+ pattern[:type] = :lookBehindFor
145
+ else
146
+ pattern = {match: pattern, type: :lookBehindFor}
147
+ end
148
+ lookAround(pattern)
149
+ end
150
+
151
+ # (see PatternBase#lookAheadToAvoid)
152
+ def lookAheadToAvoid(pattern)
153
+ if pattern.is_a? Hash
154
+ pattern[:type] = :lookAheadToAvoid
155
+ else
156
+ pattern = {match: pattern, type: :lookAheadToAvoid}
157
+ end
158
+ lookAround(pattern)
159
+ end
160
+
161
+ # (see PatternBase#lookAheadFor)
162
+ def lookAheadFor(pattern)
163
+ if pattern.is_a? Hash
164
+ pattern[:type] = :lookAheadFor
165
+ else
166
+ pattern = {match: pattern, type: :lookAheadFor}
167
+ end
168
+ lookAround(pattern)
169
+ end
@@ -0,0 +1,67 @@
1
+ # frozen_string_literal: true
2
+
3
+ #
4
+ # Implements back references
5
+ # for some group N whose reference is "foo"
6
+ # matchResultOf("foo") results in the pattern /\N/
7
+ #
8
+ class MatchResultOfPattern < PatternBase
9
+ def initialize(reference, deep_clone = nil, original_arguments = nil)
10
+ if reference.is_a? String
11
+ super(
12
+ match: Regexp.new("(?#[:backreference:#{reference}:])"),
13
+ backreference_key: reference
14
+ )
15
+ else
16
+ # most likely __deep_clone__ was called, just call the super initializer
17
+ super(reference, deep_clone, original_arguments)
18
+ end
19
+ end
20
+
21
+ # (see PatternBase#to_s)
22
+ def to_s(depth = 0, top_level = true)
23
+ output = top_level ? "matchResultOf(" : ".matchResultOf("
24
+ output += "\"#{@arguments[:backreference_key]}\")"
25
+ output += @next_pattern.to_s(depth, false).lstrip if @next_pattern
26
+ output
27
+ end
28
+
29
+ # (see PatternBase#single_entity?)
30
+ # @return [true]
31
+ def single_entity?
32
+ true
33
+ end
34
+
35
+ # (see PatternBase#self_scramble_references)
36
+ def self_scramble_references
37
+ scramble = lambda do |name|
38
+ return name if name.start_with?("__scrambled__")
39
+
40
+ "__scrambled__" + name
41
+ end
42
+
43
+ key = @arguments[:subroutine_key]
44
+ scrambled = scramble.call(key)
45
+
46
+ @match = @match.sub(key, scrambled)
47
+ @arguments[:subroutine_key] = scrambled
48
+ end
49
+ end
50
+
51
+ class PatternBase
52
+ #
53
+ # Match the result of some other pattern
54
+ #
55
+ # @param [String] reference a reference to match the result of
56
+ #
57
+ # @return [PatternBase] a pattern to append to
58
+ #
59
+ def matchResultOf(reference)
60
+ insert(MatchResultOfPattern.new(reference))
61
+ end
62
+ end
63
+
64
+ # (see PatternBase#matchResultOf)
65
+ def matchResultOf(reference)
66
+ MatchResultOfPattern.new(reference)
67
+ end