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.
- checksums.yaml +7 -0
- data/LICENSE +21 -0
- data/lib/textmate_grammar/generated/grammar.rb +32 -0
- data/lib/textmate_grammar/generated/rule.rb +144 -0
- data/lib/textmate_grammar/grammar.rb +670 -0
- data/lib/textmate_grammar/grammar_plugin.rb +189 -0
- data/lib/textmate_grammar/import_patterns.rb +14 -0
- data/lib/textmate_grammar/linters/flat_includes.rb +32 -0
- data/lib/textmate_grammar/linters/includes_then_tag_as.rb +48 -0
- data/lib/textmate_grammar/linters/standard_naming.rb +226 -0
- data/lib/textmate_grammar/linters/start_match_empty.rb +49 -0
- data/lib/textmate_grammar/linters/tests.rb +19 -0
- data/lib/textmate_grammar/linters/unused_unresolved.rb +9 -0
- data/lib/textmate_grammar/pattern_extensions/look_ahead_for.rb +32 -0
- data/lib/textmate_grammar/pattern_extensions/look_ahead_to_avoid.rb +31 -0
- data/lib/textmate_grammar/pattern_extensions/look_behind_for.rb +31 -0
- data/lib/textmate_grammar/pattern_extensions/look_behind_to_avoid.rb +31 -0
- data/lib/textmate_grammar/pattern_extensions/lookaround_pattern.rb +169 -0
- data/lib/textmate_grammar/pattern_extensions/match_result_of.rb +67 -0
- data/lib/textmate_grammar/pattern_extensions/maybe.rb +50 -0
- data/lib/textmate_grammar/pattern_extensions/one_of.rb +107 -0
- data/lib/textmate_grammar/pattern_extensions/one_or_more_of.rb +42 -0
- data/lib/textmate_grammar/pattern_extensions/or_pattern.rb +55 -0
- data/lib/textmate_grammar/pattern_extensions/placeholder.rb +102 -0
- data/lib/textmate_grammar/pattern_extensions/recursively_match.rb +76 -0
- data/lib/textmate_grammar/pattern_extensions/zero_or_more_of.rb +50 -0
- data/lib/textmate_grammar/pattern_variations/base_pattern.rb +870 -0
- data/lib/textmate_grammar/pattern_variations/legacy_pattern.rb +61 -0
- data/lib/textmate_grammar/pattern_variations/pattern.rb +9 -0
- data/lib/textmate_grammar/pattern_variations/pattern_range.rb +233 -0
- data/lib/textmate_grammar/pattern_variations/repeatable_pattern.rb +204 -0
- data/lib/textmate_grammar/regex_operator.rb +182 -0
- data/lib/textmate_grammar/regex_operators/alternation.rb +24 -0
- data/lib/textmate_grammar/regex_operators/concat.rb +23 -0
- data/lib/textmate_grammar/stdlib/common.rb +20 -0
- data/lib/textmate_grammar/tokens.rb +110 -0
- data/lib/textmate_grammar/transforms/add_ending.rb +25 -0
- data/lib/textmate_grammar/transforms/bailout.rb +92 -0
- data/lib/textmate_grammar/transforms/fix_repeated_tag_as.rb +75 -0
- data/lib/textmate_grammar/transforms/resolve_placeholders.rb +121 -0
- data/lib/textmate_grammar/util.rb +198 -0
- data/lib/textmate_grammar.rb +4 -0
- 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,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
|