code-ruby-parser 0.1.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 (96) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +1 -0
  3. data/.overcommit.yml +4 -0
  4. data/Gemfile +5 -0
  5. data/Gemfile.lock +32 -0
  6. data/bin/code-parser +27 -0
  7. data/bin/format +3 -0
  8. data/bin/template-parser +27 -0
  9. data/docs/class.code +9 -0
  10. data/docs/meetup.code +14 -0
  11. data/docs/rain.code +23 -0
  12. data/docs/slack.code +17 -0
  13. data/docs/stripe.code +7 -0
  14. data/docs/twitter.code +7 -0
  15. data/lib/code/parser/addition.rb +13 -0
  16. data/lib/code/parser/and_operator.rb +13 -0
  17. data/lib/code/parser/bitwise_and.rb +13 -0
  18. data/lib/code/parser/bitwise_or.rb +13 -0
  19. data/lib/code/parser/boolean.rb +13 -0
  20. data/lib/code/parser/call.rb +174 -0
  21. data/lib/code/parser/chained_call.rb +41 -0
  22. data/lib/code/parser/class.rb +56 -0
  23. data/lib/code/parser/code.rb +20 -0
  24. data/lib/code/parser/comments.rb +46 -0
  25. data/lib/code/parser/dictionnary.rb +48 -0
  26. data/lib/code/parser/equal.rb +39 -0
  27. data/lib/code/parser/equality.rb +20 -0
  28. data/lib/code/parser/error/syntax_error.rb +36 -0
  29. data/lib/code/parser/error.rb +6 -0
  30. data/lib/code/parser/function.rb +109 -0
  31. data/lib/code/parser/greater_than.rb +13 -0
  32. data/lib/code/parser/group.rb +15 -0
  33. data/lib/code/parser/identifier.rb +54 -0
  34. data/lib/code/parser/if.rb +81 -0
  35. data/lib/code/parser/if_modifier.rb +39 -0
  36. data/lib/code/parser/list.rb +20 -0
  37. data/lib/code/parser/multiplication.rb +13 -0
  38. data/lib/code/parser/negation.rb +18 -0
  39. data/lib/code/parser/not_keyword.rb +24 -0
  40. data/lib/code/parser/nothing.rb +13 -0
  41. data/lib/code/parser/number.rb +39 -0
  42. data/lib/code/parser/operation.rb +44 -0
  43. data/lib/code/parser/or_keyword.rb +13 -0
  44. data/lib/code/parser/or_operator.rb +13 -0
  45. data/lib/code/parser/power.rb +33 -0
  46. data/lib/code/parser/range.rb +13 -0
  47. data/lib/code/parser/rescue.rb +38 -0
  48. data/lib/code/parser/shift.rb +13 -0
  49. data/lib/code/parser/statement.rb +9 -0
  50. data/lib/code/parser/string.rb +61 -0
  51. data/lib/code/parser/ternary.rb +73 -0
  52. data/lib/code/parser/unary_minus.rb +23 -0
  53. data/lib/code/parser/while.rb +36 -0
  54. data/lib/code/parser.rb +237 -0
  55. data/lib/code-ruby-parser.rb +7 -0
  56. data/lib/code.rb +2 -0
  57. data/lib/template/parser.rb +32 -0
  58. data/lib/template-ruby-parser.rb +7 -0
  59. data/lib/template.rb +2 -0
  60. data/spec/code/parser/addition_spec.rb +26 -0
  61. data/spec/code/parser/and_operator_spec.rb +26 -0
  62. data/spec/code/parser/bitwise_and_spec.rb +26 -0
  63. data/spec/code/parser/bitwise_or_spec.rb +26 -0
  64. data/spec/code/parser/boolean_spec.rb +13 -0
  65. data/spec/code/parser/call_spec.rb +52 -0
  66. data/spec/code/parser/chained_call_spec.rb +33 -0
  67. data/spec/code/parser/class_spec.rb +32 -0
  68. data/spec/code/parser/code_spec.rb +13 -0
  69. data/spec/code/parser/dictionnary_spec.rb +40 -0
  70. data/spec/code/parser/equal_spec.rb +42 -0
  71. data/spec/code/parser/equality_spec.rb +26 -0
  72. data/spec/code/parser/function_spec.rb +43 -0
  73. data/spec/code/parser/greater_than_spec.rb +26 -0
  74. data/spec/code/parser/group_spec.rb +13 -0
  75. data/spec/code/parser/if_modifier_spec.rb +26 -0
  76. data/spec/code/parser/if_spec.rb +39 -0
  77. data/spec/code/parser/list_spec.rb +27 -0
  78. data/spec/code/parser/multiplication_spec.rb +26 -0
  79. data/spec/code/parser/negation_spec.rb +13 -0
  80. data/spec/code/parser/not_keyword_spec.rb +21 -0
  81. data/spec/code/parser/nothing_spec.rb +20 -0
  82. data/spec/code/parser/number_spec.rb +24 -0
  83. data/spec/code/parser/or_keyword_spec.rb +26 -0
  84. data/spec/code/parser/or_operator_spec.rb +26 -0
  85. data/spec/code/parser/power_spec.rb +21 -0
  86. data/spec/code/parser/range_spec.rb +21 -0
  87. data/spec/code/parser/rescue_spec.rb +26 -0
  88. data/spec/code/parser/shift_spec.rb +26 -0
  89. data/spec/code/parser/string_spec.rb +27 -0
  90. data/spec/code/parser/ternary_spec.rb +26 -0
  91. data/spec/code/parser/unary_minus_spec.rb +21 -0
  92. data/spec/code/parser/while_spec.rb +32 -0
  93. data/spec/spec_helper.rb +6 -0
  94. data/spec/template/parser_spec.rb +13 -0
  95. data/template-ruby-parser.gemspec +16 -0
  96. metadata +171 -0
@@ -0,0 +1,38 @@
1
+ class Code
2
+ class Parser
3
+ class Rescue < ::Code::Parser
4
+ def parse
5
+ left = parse_subclass(::Code::Parser::Ternary)
6
+
7
+ previous_cursor = cursor
8
+
9
+ comments_before = parse_comments
10
+
11
+ if match(RESCUE_KEYWORD)
12
+ previous_cursor = cursor
13
+ comments_after = parse_comments
14
+ right = parse_subclass(::Code::Parser::Rescue)
15
+
16
+ if right
17
+ {
18
+ rescue: {
19
+ left: left,
20
+ right: right,
21
+ comments_before: comments_before,
22
+ comments_after: comments_after
23
+ }.compact
24
+ }
25
+ else
26
+ @cursor = previous_cursor
27
+ buffer!
28
+ { rescue: { left: left, comments_before: comments_before }.compact }
29
+ end
30
+ else
31
+ @cursor = previous_cursor
32
+ buffer!
33
+ left
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,13 @@
1
+ class Code
2
+ class Parser
3
+ class Shift < ::Code::Parser
4
+ def parse
5
+ parse_subclass(
6
+ ::Code::Parser::Operation,
7
+ operators: [GREATER + GREATER, LESSER + LESSER],
8
+ subclass: ::Code::Parser::Addition
9
+ )
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,9 @@
1
+ class Code
2
+ class Parser
3
+ class Statement < ::Code::Parser
4
+ def parse
5
+ parse_subclass(::Code::Parser::Class)
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,61 @@
1
+ class Code
2
+ class Parser
3
+ class String < ::Code::Parser
4
+ def parse
5
+ if match(SINGLE_QUOTE)
6
+ parse_string(SINGLE_QUOTE)
7
+ elsif match(DOUBLE_QUOTE)
8
+ parse_string(DOUBLE_QUOTE)
9
+ elsif match(COLON) && !next?(SPECIAL)
10
+ buffer!
11
+ consume while !next?(SPECIAL) && !end_of_input?
12
+ { string: buffer }
13
+ else
14
+ parse_subclass(::Code::Parser::Number)
15
+ end
16
+ end
17
+
18
+ private
19
+
20
+ def parse_string(quote)
21
+ buffer!
22
+ output = []
23
+
24
+ while !next?(quote) && !end_of_input?
25
+ c = consume
26
+
27
+ if c == BACKSLASH
28
+ match(OPENING_CURLY_BRACKET) || match(quote)
29
+ elsif c == OPENING_CURLY_BRACKET
30
+ output << { text: escape_string(buffer![..-2]) } if buffer?
31
+
32
+ output << { code: parse_code }
33
+
34
+ match(CLOSING_CURLY_BRACKET)
35
+ buffer!
36
+ end
37
+ end
38
+
39
+ output << { text: escape_string(buffer) } if buffer?
40
+
41
+ match(quote)
42
+
43
+ if output.empty?
44
+ { string: EMPTY_STRING }
45
+ elsif output.one? && output.first.key?(:text)
46
+ { string: output.first[:text] }
47
+ else
48
+ { string: output }
49
+ end
50
+ end
51
+
52
+ def escape_string(string)
53
+ string
54
+ .gsub(SPECIAL_NEWLINE, SPECIAL_NEWLINE_ESCAPED)
55
+ .gsub(BACKSLASH + OPENING_CURLY_BRACKET, OPENING_CURLY_BRACKET)
56
+ .gsub(BACKSLASH + SINGLE_QUOTE, SINGLE_QUOTE)
57
+ .gsub(BACKSLASH + DOUBLE_QUOTE, DOUBLE_QUOTE)
58
+ end
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,73 @@
1
+ class Code
2
+ class Parser
3
+ class Ternary < ::Code::Parser
4
+ def parse
5
+ left = parse_subclass(::Code::Parser::Range)
6
+
7
+ previous_cursor = cursor
8
+ return left if !match(WHITESPACE) && !(first_comments = parse_comments)
9
+ first_comments ||= parse_comments
10
+
11
+ if match(QUESTION_MARK)
12
+ second_comments = parse_comments
13
+
14
+ middle = parse_subclass(::Code::Parser::Ternary)
15
+
16
+ if middle
17
+ previous_cursor = cursor
18
+ third_comments = parse_comments
19
+
20
+ if match(COLON)
21
+ fourth_comments = parse_comments
22
+ right = parse_subclass(::Code::Parser::Ternary)
23
+
24
+ if right
25
+ {
26
+ ternary: {
27
+ left: left,
28
+ middle: middle,
29
+ right: right,
30
+ first_comments: first_comments,
31
+ second_comments: second_comments,
32
+ third_comments: third_comments,
33
+ fourth_comments: fourth_comments
34
+ }.compact
35
+ }
36
+ else
37
+ @cursor = previous_cursor
38
+ buffer!
39
+ {
40
+ ternary: {
41
+ left: left,
42
+ middle: middle,
43
+ first_comments: first_comments,
44
+ second_comments: second_comments
45
+ }.compact
46
+ }
47
+ end
48
+ else
49
+ @cursor = previous_cursor
50
+ buffer!
51
+ {
52
+ ternary: {
53
+ left: left,
54
+ middle: middle,
55
+ first_comments: first_comments,
56
+ second_comments: second_comments
57
+ }.compact
58
+ }
59
+ end
60
+ else
61
+ @cursor = previous_cursor
62
+ buffer!
63
+ left
64
+ end
65
+ else
66
+ @cursor = previous_cursor
67
+ buffer!
68
+ left
69
+ end
70
+ end
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,23 @@
1
+ class Code
2
+ class Parser
3
+ class UnaryMinus < ::Code::Parser
4
+ def parse
5
+ if match(MINUS)
6
+ previous_cursor = cursor
7
+ comments = parse_comments
8
+ right = parse_subclass(::Code::Parser::UnaryMinus)
9
+
10
+ if right
11
+ { unary_minus: { right: right, comments: comments }.compact }
12
+ else
13
+ @cursor = previous_cursor
14
+ buffer!
15
+ parse_subclass(::Code::Parser::Power)
16
+ end
17
+ else
18
+ parse_subclass(::Code::Parser::Power)
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,36 @@
1
+ class Code
2
+ class Parser
3
+ class While < ::Code::Parser
4
+ def parse
5
+ if operator = match([WHILE_KEYWORD, UNTIL_KEYWORD])
6
+ previous_cursor = cursor
7
+
8
+ comments = parse_comments
9
+
10
+ condition = parse_subclass(::Code::Parser::While)
11
+
12
+ if condition
13
+ body = parse_code
14
+
15
+ match(END_KEYWORD)
16
+
17
+ {
18
+ while: {
19
+ operator: operator,
20
+ comments: comments,
21
+ condition: condition,
22
+ body: body
23
+ }.compact
24
+ }
25
+ else
26
+ @cursor = previous_cursor
27
+ buffer!
28
+ parse_subclass(::Code::Parser::If)
29
+ end
30
+ else
31
+ parse_subclass(::Code::Parser::If)
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,237 @@
1
+ class Code
2
+ class Parser
3
+ attr_accessor :input, :cursor, :buffer
4
+
5
+ EMPTY_STRING = ""
6
+
7
+ DIGITS = %w[0 1 2 3 4 5 6 7 8 9]
8
+ NON_ZERO_DIGITS = %w[1 2 3 4 5 6 7 8 9]
9
+
10
+ X = "x"
11
+ O = "o"
12
+ B = "b"
13
+
14
+ SINGLE_QUOTE = "'"
15
+ DOUBLE_QUOTE = '"'
16
+ OPENING_CURLY_BRACKET = "{"
17
+ CLOSING_CURLY_BRACKET = "}"
18
+ OPENING_SQUARE_BRACKET = "["
19
+ CLOSING_SQUARE_BRACKET = "]"
20
+ OPENING_PARENTHESIS = "("
21
+ CLOSING_PARENTHESIS = ")"
22
+ DOT = "."
23
+ BACKSLASH = "\\"
24
+ COMMA = ","
25
+ SPACE = " "
26
+ SLASH = "/"
27
+ ASTERISK = "*"
28
+ NEWLINE = "\n"
29
+ HASH = "#"
30
+ COLON = ":"
31
+ EQUAL = "="
32
+ GREATER = ">"
33
+ LESSER = "<"
34
+ AMPERSAND = "&"
35
+ PIPE = "|"
36
+ UNDERSCORE = "_"
37
+ EXCLAMATION_POINT = "!"
38
+ QUESTION_MARK = "?"
39
+ MINUS = "-"
40
+ PLUS = "+"
41
+ PERCENT = "%"
42
+ CARET = "^"
43
+ TILDE = "~"
44
+
45
+ EQUALS = [
46
+ EQUAL,
47
+ PLUS + EQUAL,
48
+ MINUS + EQUAL,
49
+ ASTERISK + EQUAL,
50
+ SLASH + EQUAL,
51
+ PERCENT + EQUAL,
52
+ GREATER + GREATER + EQUAL,
53
+ LESSER + LESSER + EQUAL,
54
+ AMPERSAND + EQUAL,
55
+ PIPE + EQUAL,
56
+ CARET + EQUAL,
57
+ PIPE + PIPE + EQUAL,
58
+ AMPERSAND + AMPERSAND + EQUAL
59
+ ]
60
+
61
+ WHITESPACE = [SPACE, NEWLINE]
62
+
63
+ SPECIAL_NEWLINE = "\\n"
64
+ SPECIAL_NEWLINE_ESCAPED = "\n"
65
+
66
+ NOTHING_KEYWORD = "nothing"
67
+ NULL_KEYWORD = "null"
68
+ NIL_KEYWORD = "nil"
69
+ TRUE_KEYWORD = "true"
70
+ FALSE_KEYWORD = "false"
71
+ DO_KEYWORD = "do"
72
+ END_KEYWORD = "end"
73
+ RESCUE_KEYWORD = "rescue"
74
+ NOT_KEYWORD = "not"
75
+ OR_KEYWORD = "or"
76
+ AND_KEYWORD = "and"
77
+ IF_KEYWORD = "if"
78
+ UNLESS_KEYWORD = "unless"
79
+ ELSE_KEYWORD = "else"
80
+ ELSIF_KEYWORD = "elsif"
81
+ ELSUNLESS_KEYWORD = "elsunless"
82
+ WHILE_KEYWORD = "while"
83
+ UNTIL_KEYWORD = "until"
84
+ CLASS_KEYWORD = "class"
85
+
86
+ NOTHING_KEYWORDS = [NOTHING_KEYWORD, NULL_KEYWORD, NIL_KEYWORD]
87
+ BOOLEAN_KEYWORDS = [TRUE_KEYWORD, FALSE_KEYWORD]
88
+ KEYWORDS =
89
+ NOTHING_KEYWORDS + BOOLEAN_KEYWORDS +
90
+ [
91
+ DO_KEYWORD, END_KEYWORD, RESCUE_KEYWORD, NOT_KEYWORD, OR_KEYWORD,
92
+ AND_KEYWORD, IF_KEYWORD, UNLESS_KEYWORD, ELSE_KEYWORD, ELSIF_KEYWORD,
93
+ ELSUNLESS_KEYWORD, WHILE_KEYWORD, UNTIL_KEYWORD, CLASS_KEYWORD
94
+ ]
95
+
96
+ SPECIAL = [
97
+ SINGLE_QUOTE, DOUBLE_QUOTE, OPENING_CURLY_BRACKET, CLOSING_CURLY_BRACKET,
98
+ OPENING_SQUARE_BRACKET, CLOSING_SQUARE_BRACKET, BACKSLASH, DOT, COMMA,
99
+ SPACE, SLASH, ASTERISK, NEWLINE, HASH, COLON, EQUAL, GREATER, LESSER,
100
+ OPENING_PARENTHESIS, CLOSING_PARENTHESIS, AMPERSAND, PIPE,
101
+ EXCLAMATION_POINT, QUESTION_MARK, MINUS, PLUS, TILDE
102
+ ]
103
+
104
+ def initialize(
105
+ input,
106
+ cursor: 0,
107
+ buffer: EMPTY_STRING,
108
+ check_end_of_input: true
109
+ )
110
+ @input = input
111
+ @cursor = cursor
112
+ @buffer = buffer
113
+ @check_end_of_input = check_end_of_input
114
+ end
115
+
116
+ def self.parse(input)
117
+ new(input).parse
118
+ end
119
+
120
+ def parse
121
+ output = parse_subclass(::Code::Parser::Code)
122
+
123
+ if check_end_of_input && cursor != input.size
124
+ syntax_error("Unexpected end of input")
125
+ end
126
+
127
+ output
128
+ end
129
+
130
+ private
131
+
132
+ attr_reader :check_end_of_input
133
+
134
+ def syntax_error(message)
135
+ raise(
136
+ ::Code::Parser::Error::SyntaxError.new(
137
+ message,
138
+ input: input,
139
+ line: line,
140
+ column: column,
141
+ offset_lines: offset_lines,
142
+ offset_columns: offset_columns
143
+ )
144
+ )
145
+ end
146
+
147
+ def line
148
+ input[0...cursor].count("\n")
149
+ end
150
+
151
+ def column
152
+ cursor - input.lines[0...line].map(&:size).sum
153
+ end
154
+
155
+ def offset_lines
156
+ buffer.count("\n")
157
+ end
158
+
159
+ def offset_columns
160
+ buffer.size + 1
161
+ end
162
+
163
+ def consume(n = 1)
164
+ if cursor + n <= input.size
165
+ consumed = input[cursor, n]
166
+ @buffer += input[cursor, n]
167
+ @cursor += n
168
+ consumed
169
+ else
170
+ syntax_error("Unexpected end of input")
171
+ end
172
+ end
173
+
174
+ def add(output)
175
+ @output << output if output
176
+ output
177
+ end
178
+
179
+ def next?(expected)
180
+ if expected.is_a?(Array)
181
+ expected.any? { |e| input[cursor, e.size] == e }
182
+ else
183
+ input[cursor, expected.size] == expected
184
+ end
185
+ end
186
+
187
+ def next_next?(expected)
188
+ if expected.is_a?(Array)
189
+ expected.any? { |e| next_next?(e) }
190
+ else
191
+ input[cursor + 1, expected.size] == expected
192
+ end
193
+ end
194
+
195
+ def match(expected)
196
+ if expected.is_a?(Array)
197
+ expected.detect { |e| match(e) }
198
+ else
199
+ if input[cursor, expected.size] == expected
200
+ @buffer += expected
201
+ @cursor += expected.size
202
+ expected
203
+ else
204
+ false
205
+ end
206
+ end
207
+ end
208
+
209
+ def parse_subclass(subclass, **kargs)
210
+ parser =
211
+ subclass.new(input, cursor: cursor, check_end_of_input: false, **kargs)
212
+ output = parser.parse
213
+ @cursor = parser.cursor
214
+ output
215
+ end
216
+
217
+ def parse_code
218
+ parse_subclass(::Code::Parser::Code)
219
+ end
220
+
221
+ def parse_comments(whitespace: WHITESPACE)
222
+ parse_subclass(::Code::Parser::Comments, whitespace: whitespace)
223
+ end
224
+
225
+ def end_of_input?
226
+ cursor >= input.size
227
+ end
228
+
229
+ def buffer?
230
+ buffer != EMPTY_STRING
231
+ end
232
+
233
+ def buffer!
234
+ buffer.tap { @buffer = EMPTY_STRING }
235
+ end
236
+ end
237
+ end
@@ -0,0 +1,7 @@
1
+ require "zeitwerk"
2
+ require "forwardable"
3
+
4
+ loader = Zeitwerk::Loader.for_gem(warn_on_extra_files: false)
5
+ loader.ignore("#{__dir__}/template-ruby-parser.rb")
6
+ loader.ignore("#{__dir__}/code-ruby-parser.rb")
7
+ loader.setup
data/lib/code.rb ADDED
@@ -0,0 +1,2 @@
1
+ class Code
2
+ end
@@ -0,0 +1,32 @@
1
+ class Template
2
+ class Parser < ::Code::Parser
3
+ Version = Gem::Version.new("0.1.0")
4
+
5
+ def parse
6
+ parts = []
7
+
8
+ while !end_of_input?
9
+ c = consume
10
+
11
+ if c == OPENING_CURLY_BRACKET
12
+ parts << { text: escape(buffer!) } if buffer?
13
+ parts << { code: parse_code }
14
+ match(CLOSING_CURLY_BRACKET)
15
+ buffer!
16
+ elsif c == BACKSLASH
17
+ match(OPENING_CURLY_BRACKET)
18
+ end
19
+ end
20
+
21
+ parts << { text: escape(buffer!) } if buffer?
22
+
23
+ parts
24
+ end
25
+
26
+ private
27
+
28
+ def escape(text)
29
+ text.gsub(BACKSLASH + OPENING_CURLY_BRACKET, OPENING_CURLY_BRACKET)
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,7 @@
1
+ require "zeitwerk"
2
+ require "forwardable"
3
+
4
+ loader = Zeitwerk::Loader.for_gem(warn_on_extra_files: false)
5
+ loader.ignore("#{__dir__}/template-ruby-parser.rb")
6
+ loader.ignore("#{__dir__}/code-ruby-parser.rb")
7
+ loader.setup
data/lib/template.rb ADDED
@@ -0,0 +1,2 @@
1
+ class Template
2
+ end
@@ -0,0 +1,26 @@
1
+ require "spec_helper"
2
+
3
+ RSpec.describe ::Code::Parser do
4
+ subject { ::Code::Parser.parse(input) }
5
+
6
+ ["a + b", "a - b", "(a - b) + c", "a - (b + c)"].each do |input|
7
+ context input do
8
+ let!(:input) { input }
9
+
10
+ it { expect { subject }.to_not raise_error }
11
+ end
12
+ end
13
+
14
+ [
15
+ "a /* cool */ * b",
16
+ "a + /* cool */ b",
17
+ "a + b - c /* cool */",
18
+ "a + b - /* cool */ c"
19
+ ].each do |input|
20
+ context input do
21
+ let!(:input) { input }
22
+
23
+ it { expect(subject.to_json).to include("cool") }
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,26 @@
1
+ require "spec_helper"
2
+
3
+ RSpec.describe ::Code::Parser do
4
+ subject { ::Code::Parser.parse(input) }
5
+
6
+ ["a && b", "a && b && c"].each do |input|
7
+ context input do
8
+ let!(:input) { input }
9
+
10
+ it { expect { subject }.to_not raise_error }
11
+ end
12
+ end
13
+
14
+ [
15
+ "a /* cool */ && b",
16
+ "a && /* cool */ b",
17
+ "a && b && c /* cool */",
18
+ "a && b && /* cool */ c"
19
+ ].each do |input|
20
+ context input do
21
+ let!(:input) { input }
22
+
23
+ it { expect(subject.to_json).to include("cool") }
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,26 @@
1
+ require "spec_helper"
2
+
3
+ RSpec.describe ::Code::Parser do
4
+ subject { ::Code::Parser.parse(input) }
5
+
6
+ ["a & b", "a & b & c"].each do |input|
7
+ context input do
8
+ let!(:input) { input }
9
+
10
+ it { expect { subject }.to_not raise_error }
11
+ end
12
+ end
13
+
14
+ [
15
+ "a /* cool */ & b",
16
+ "a & /* cool */ b",
17
+ "a & b & c /* cool */",
18
+ "a & b & /* cool */ c"
19
+ ].each do |input|
20
+ context input do
21
+ let!(:input) { input }
22
+
23
+ it { expect(subject.to_json).to include("cool") }
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,26 @@
1
+ require "spec_helper"
2
+
3
+ RSpec.describe ::Code::Parser do
4
+ subject { ::Code::Parser.parse(input) }
5
+
6
+ ["a | b", "a | b | c"].each do |input|
7
+ context input do
8
+ let!(:input) { input }
9
+
10
+ it { expect { subject }.to_not raise_error }
11
+ end
12
+ end
13
+
14
+ [
15
+ "a /* cool */ | b",
16
+ "a | /* cool */ b",
17
+ "a | b | c /* cool */",
18
+ "a | b | /* cool */ c"
19
+ ].each do |input|
20
+ context input do
21
+ let!(:input) { input }
22
+
23
+ it { expect(subject.to_json).to include("cool") }
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,13 @@
1
+ require "spec_helper"
2
+
3
+ RSpec.describe ::Code::Parser do
4
+ subject { ::Code::Parser.parse(input) }
5
+
6
+ %w[true false].each do |input|
7
+ context input do
8
+ let!(:input) { input }
9
+
10
+ it { expect { subject }.to_not raise_error }
11
+ end
12
+ end
13
+ end