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,50 @@
1
+ # frozen_string_literal: true
2
+
3
+ # An optional pattern
4
+ # for some pattern `p` this is equivalent to (?:p?)
5
+ class MaybePattern < RepeatablePattern
6
+ #
7
+ # Construct a new MaybePattern
8
+ #
9
+ # @param [any] args arguments to pass to {PatternBase#initialize}
10
+ # @api private
11
+ #
12
+ # @see maybe
13
+ # @see PatternBase#maybe
14
+ def initialize(*args)
15
+ # run the normal pattern
16
+ super(*args)
17
+ # add quantifying options
18
+ @at_least = 0
19
+ @at_most = 1
20
+ end
21
+
22
+ # (see Pattern#quantifying_allowed?)
23
+ # @return [false]
24
+ def quantifying_allowed?
25
+ false
26
+ end
27
+
28
+ # (see PatternBase#do_get_to_s_name)
29
+ def do_get_to_s_name(top_level)
30
+ top_level ? "maybe(" : ".maybe("
31
+ end
32
+ end
33
+
34
+ class PatternBase
35
+ #
36
+ # Optionally match pattern
37
+ #
38
+ # @param [PatternBase,Regexp,String,Hash] pattern a pattern to optionally match
39
+ #
40
+ # @return [PatternBase] a pattern to append to
41
+ #
42
+ def maybe(pattern)
43
+ insert(MaybePattern.new(pattern))
44
+ end
45
+ end
46
+
47
+ # (see PatternBase#maybe)
48
+ def maybe(pattern)
49
+ MaybePattern.new(pattern)
50
+ end
@@ -0,0 +1,107 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Provides alternation
4
+ # when one of the passed in patterns is accepted, this pattern is accepted
5
+ class OneOfPattern < PatternBase
6
+ # create a new OneOfPattern
7
+ # this is expects an array of patterns
8
+
9
+ #
10
+ # Create a new OneOfPattern
11
+ #
12
+ # @param [Array<PatternBase,Regexp,String>] patterns a list of patterns to match
13
+ #
14
+ def initialize(patterns, deep_clone = nil, original_arguments = nil)
15
+ if deep_clone == :deep_clone
16
+ super(patterns, deep_clone, original_arguments)
17
+ return
18
+ end
19
+ unless patterns.is_a? Array
20
+ raise <<-HEREDOC.remove_indent
21
+ oneOf() expects an array of patterns, the provided argument is not an array.
22
+ The arguments to oneOf is below
23
+ #{patterns}
24
+ HEREDOC
25
+ end
26
+ super(
27
+ match: "one of",
28
+ patterns: patterns.map do |pattern|
29
+ next pattern if pattern.is_a? PatternBase
30
+
31
+ PatternBase.new(pattern)
32
+ end
33
+ )
34
+ end
35
+
36
+ # (see PatternBase#do_evaluate_self)
37
+ def do_evaluate_self(groups)
38
+ patterns_strings = @arguments[:patterns].map do |pattern|
39
+ regex = pattern.evaluate(groups)
40
+ next regex if pattern.single_entity?
41
+
42
+ "(?:#{regex})"
43
+ end
44
+
45
+ return "(#{patterns_strings.join '|'})" if needs_to_capture?
46
+
47
+ "(?:#{patterns_strings.join '|'})"
48
+ end
49
+
50
+ # (see PatternBase#do_collect_self_groups)
51
+ def do_collect_self_groups(next_group)
52
+ groups = []
53
+ @arguments[:patterns].each do |pattern|
54
+ pat_groups = pattern.collect_group_attributes(next_group)
55
+ groups.concat(pat_groups)
56
+ next_group += pat_groups.length
57
+ end
58
+ groups
59
+ end
60
+
61
+ # (see PatternBase#single_entity?)
62
+ # @return [true]
63
+ def single_entity?
64
+ true
65
+ end
66
+
67
+ # (see PatternBase#map!)
68
+ def map!(map_includes = false, &block)
69
+ @arguments[:patterns].map! { |p| p.map!(map_includes, &block) }
70
+ @next_pattern.map!(map_includes, &block) if @next_pattern.is_a? PatternBase
71
+ map_includes!(&block) if map_includes
72
+ self
73
+ end
74
+
75
+ # (see PatternBase#to_s)
76
+ def to_s(depth = 0, top_level = true)
77
+ indent = " " * depth
78
+ output = top_level ? "oneOf([" : ".oneOf(["
79
+ output += "\n#{indent} "
80
+ output += (@arguments[:patterns].map do |pattern|
81
+ pattern.to_s(depth + 1, true).lstrip
82
+ end).join ",\n#{indent} "
83
+ output += "\n#{indent}])"
84
+ output += @next_pattern.to_s(depth, false).lstrip if @next_pattern
85
+ output
86
+ end
87
+ end
88
+
89
+ class PatternBase
90
+ #
91
+ # Match one of the supplied patterns
92
+ #
93
+ # @param [Array<PatternBase,Regexp,String>] patterns a list of patterns to match
94
+ #
95
+ # @return [PatternBase] a pattern to append to
96
+ #
97
+ def oneOf(patterns)
98
+ insert(OneOfPattern.new(patterns))
99
+ end
100
+ end
101
+
102
+ #
103
+ # (see PatternBase#oneOf)
104
+ #
105
+ def oneOf(patterns)
106
+ OneOfPattern.new(patterns)
107
+ end
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+
3
+ # An optional repeated pattern
4
+ # for some pattern `p` this is equivalent to (?:p+)
5
+ class OneOrMoreOfPattern < RepeatablePattern
6
+ def initialize(*args)
7
+ # run the normal pattern
8
+ super(*args)
9
+ # add quantifying options
10
+ @at_least = 1
11
+ @at_most = nil
12
+ end
13
+
14
+ # (see Pattern#quantifying_allowed?)
15
+ # @return [false]
16
+ def quantifying_allowed?
17
+ false
18
+ end
19
+
20
+ # (see PatternBase#do_get_to_s_name)
21
+ def do_get_to_s_name(top_level)
22
+ top_level ? "oneOrMoreOf(" : ".oneOrMoreOf("
23
+ end
24
+ end
25
+
26
+ class PatternBase
27
+ #
28
+ # Match pattern one or more times
29
+ #
30
+ # @param [PatternBase,Regexp,String,Hash] pattern a pattern to match
31
+ #
32
+ # @return [PatternBase] a pattern to append to
33
+ #
34
+ def oneOrMoreOf(pattern)
35
+ insert(OneOrMoreOfPattern.new(pattern))
36
+ end
37
+ end
38
+
39
+ # (see PatternBase#oneOrMoreOf)
40
+ def oneOrMoreOf(pattern)
41
+ OneOrMoreOfPattern.new(pattern)
42
+ end
@@ -0,0 +1,55 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../regex_operators/alternation'
4
+
5
+ # Provides alternation
6
+ # Either the previous pattern or provided pattern is accepted
7
+ # @note OneOfPattern is likely just as powerful and less confusing
8
+ class OrPattern < PatternBase
9
+ #
10
+ # (see PatternBase#evaluate_operator)
11
+ #
12
+ # @return [AlternationOperator] the alternation operator
13
+ #
14
+ def evaluate_operator
15
+ AlternationOperator.new
16
+ end
17
+
18
+ #
19
+ # Raises an error to prevent use as initial type
20
+ #
21
+ # @param _ignored ignored
22
+ #
23
+ # @return [void]
24
+ #
25
+ def evaluate(*_ignored)
26
+ raise "evaluate is not implemented for OrPattern"
27
+ end
28
+
29
+ # (see PatternBase#do_get_to_s_name)
30
+ def do_get_to_s_name(top_level)
31
+ top_level ? "or(" : ".or("
32
+ end
33
+
34
+ # (see PatternBase#single_entity?)
35
+ # @return [true]
36
+ def single_entity?
37
+ true
38
+ end
39
+ end
40
+
41
+ class PatternBase
42
+ #
43
+ # Match either the preceding pattern chain or pattern
44
+ #
45
+ # @param [PatternBase,Regexp,String,Hash] pattern a pattern to match
46
+ # instead of the previous chain
47
+ #
48
+ # @return [PatternBase] a pattern to append to
49
+ #
50
+ def or(pattern)
51
+ insert(OrPattern.new(pattern))
52
+ end
53
+ end
54
+
55
+ # or does not have a top level option
@@ -0,0 +1,102 @@
1
+ # frozen_string_literal: true
2
+
3
+ #
4
+ # Implements using a pattern that has not been defined
5
+ #
6
+ class PlaceholderPattern < PatternBase
7
+ #
8
+ # Constructs a new placeholder pattern
9
+ # @overload initialize(placeholder)
10
+ # @param [Symbol] placeholder the name to replace with
11
+ #
12
+ # @overload initialize(opts, deep_clone, original)
13
+ # @param (see PatternBase#initialize)
14
+ #
15
+ def initialize(placeholder, deep_clone = nil, original_arguments = nil)
16
+ if deep_clone == :deep_clone
17
+ super(placeholder, deep_clone, original_arguments)
18
+ else
19
+ super(
20
+ match: Regexp.new("placeholder(?##{placeholder})"),
21
+ placeholder: placeholder
22
+ )
23
+ end
24
+ end
25
+
26
+ # (see PatternBase#to_s)
27
+ def to_s(depth = 0, top_level = true)
28
+ return super unless @match == "placeholder"
29
+
30
+ output = top_level ? "placeholder(" : ".placeholder("
31
+ output += ":#{@arguments[:placeholder]})"
32
+ output += @next_pattern.to_s(depth, false).lstrip if @next_pattern
33
+ output
34
+ end
35
+
36
+ # (see PatternBase#to_tag)
37
+ # @note this raises a runtime error if the pattern has not been resolved
38
+ def to_tag
39
+ if @match.is_a?(String) && @match.start_with?("placeholder")
40
+ placeholder = @arguments[:placeholder]
41
+ raise "Attempting to create a tag from an unresolved placeholder `:#{placeholder}'"
42
+ end
43
+
44
+ super()
45
+ end
46
+
47
+ # (see PatternBase#evaluate)
48
+ # @note this raises a runtime error if the pattern has not been resolved
49
+ def evaluate(groups = nil)
50
+ if @match.is_a?(String) && @match.start_with?("placeholder")
51
+ raise "Attempting to evaluate an unresolved placeholder `:#{@arguments[:placeholder]}'"
52
+ end
53
+
54
+ super(groups)
55
+ end
56
+
57
+ #
58
+ # Resolves the placeholder
59
+ #
60
+ # @param [Hash] repository the repository to use to resolve the placeholder
61
+ #
62
+ # @return [self]
63
+ #
64
+ def resolve!(repository)
65
+ unless repository[@arguments[:placeholder]].is_a? PatternBase
66
+ raise ":#{@arguments[:placeholder]} is not a pattern and cannot be substituted"
67
+ end
68
+
69
+ @match = repository[@arguments[:placeholder]].__deep_clone__
70
+ self
71
+ # repository[@arguments[:placeholder]].resolve(repository)
72
+ end
73
+ end
74
+
75
+ class PatternBase
76
+ #
77
+ # Match a pattern that does not exist yet
78
+ #
79
+ # @param [Symbol] placeholder the name of the pattern to match
80
+ #
81
+ # @return [PatternBase] a pattern to append to
82
+ #
83
+ def placeholder(placeholder)
84
+ insert(PlaceholderPattern.new(placeholder))
85
+ end
86
+
87
+ #
88
+ # Resolves any placeholder patterns
89
+ #
90
+ # @param [Hash] repository the repository to resolve patterns with
91
+ #
92
+ # @return [PatternBase] a copy of self with placeholders resolved
93
+ #
94
+ def resolve(repository)
95
+ __deep_clone__.map!(true) { |s| s.resolve!(repository) if s.respond_to? :resolve! }.freeze
96
+ end
97
+ end
98
+
99
+ # (see PatternBase#placeholder)
100
+ def placeholder(placeholder)
101
+ PlaceholderPattern.new(placeholder)
102
+ end
@@ -0,0 +1,76 @@
1
+ # frozen_string_literal: true
2
+
3
+ #
4
+ # Implements subexp calls
5
+ # for some group N whose reference is "foo"
6
+ # recursivelyMatch("foo") results in the pattern /\gN/
7
+ #
8
+ class RecursivelyMatchPattern < PatternBase
9
+ def initialize(reference, deep_clone = nil, original_arguments = nil)
10
+ if reference.is_a? String
11
+ super(
12
+ match: Regexp.new("(?#[:subroutine:#{reference}:])"),
13
+ subroutine_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 ? "recursivelyMatch(" : ".recursivelyMatch("
24
+ output += "\"#{@arguments[:subroutine_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
+
50
+ #
51
+ # RecursivelyMatchPattern can cause its capture groups to be rematched
52
+ #
53
+ # @return [true] rematching is possible
54
+ #
55
+ def self_capture_group_rematch
56
+ true
57
+ end
58
+ end
59
+
60
+ class PatternBase
61
+ #
62
+ # Recursively match some outer pattern
63
+ #
64
+ # @param [String] reference a reference to an outer pattern
65
+ #
66
+ # @return [PatternBase] a PatternBase to append to
67
+ #
68
+ def recursivelyMatch(reference)
69
+ insert(RecursivelyMatchPattern.new(reference))
70
+ end
71
+ end
72
+
73
+ # (see PatternBase#recursivelyMatch)
74
+ def recursivelyMatch(reference)
75
+ RecursivelyMatchPattern.new(reference)
76
+ end
@@ -0,0 +1,50 @@
1
+ # frozen_string_literal: true
2
+
3
+ # An repeated pattern
4
+ # for some pattern `p` this is equivalent to (?:p*)
5
+ class ZeroOrMoreOfPattern < RepeatablePattern
6
+ #
7
+ # Construct a new ZeroOrMoreOfPattern
8
+ #
9
+ # @param [any] args arguments to pass to {PatternBase#initialize}
10
+ # @api private
11
+ #
12
+ # @see zeroOrMoreOf
13
+ # @see PatternBase#zeroOrMoreOf
14
+ def initialize(*args)
15
+ # run the normal pattern
16
+ super(*args)
17
+ # add quantifying options
18
+ @at_least = 0
19
+ @at_most = nil
20
+ end
21
+
22
+ # (see Pattern#quantifying_allowed?)
23
+ # @return [false]
24
+ def quantifying_allowed?
25
+ false
26
+ end
27
+
28
+ # (see PatternBase#do_get_to_s_name)
29
+ def do_get_to_s_name(top_level)
30
+ top_level ? "zeroOrMoreOf(" : ".zeroOrMoreOf("
31
+ end
32
+ end
33
+
34
+ class PatternBase
35
+ #
36
+ # Match pattern zero or more times
37
+ #
38
+ # @param [PatternBase,Regexp,String,Hash] pattern a pattern to match
39
+ #
40
+ # @return [PatternBase] a pattern to append to
41
+ #
42
+ def zeroOrMoreOf(pattern)
43
+ insert(ZeroOrMoreOfPattern.new(pattern))
44
+ end
45
+ end
46
+
47
+ # (see PatternBase#zeroOrMoreOf)
48
+ def zeroOrMoreOf(pattern)
49
+ ZeroOrMoreOfPattern.new(pattern)
50
+ end