rip-parser 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (80) hide show
  1. checksums.yaml +7 -0
  2. data/.editorconfig +15 -0
  3. data/.gitignore +9 -0
  4. data/.rspec +1 -0
  5. data/.ruby-version +1 -0
  6. data/Gemfile +3 -0
  7. data/LICENSE.md +9 -0
  8. data/README.md +13 -0
  9. data/Rakefile +1 -0
  10. data/bin/console +8 -0
  11. data/bin/setup +8 -0
  12. data/legacy/normalizer.rb +279 -0
  13. data/legacy/parser_spec.rb +999 -0
  14. data/legacy/rules.rb +250 -0
  15. data/legacy/rules_spec.rb +1700 -0
  16. data/rip-parser.gemspec +20 -0
  17. data/source/rip/parser/about.rb +9 -0
  18. data/source/rip/parser/error.rb +36 -0
  19. data/source/rip/parser/grammar.rb +23 -0
  20. data/source/rip/parser/keywords.rb +84 -0
  21. data/source/rip/parser/location.rb +47 -0
  22. data/source/rip/parser/node.rb +115 -0
  23. data/source/rip/parser/rules/assignment.rb +23 -0
  24. data/source/rip/parser/rules/binary_condition.rb +24 -0
  25. data/source/rip/parser/rules/character.rb +40 -0
  26. data/source/rip/parser/rules/class.rb +60 -0
  27. data/source/rip/parser/rules/common.rb +47 -0
  28. data/source/rip/parser/rules/date_time.rb +31 -0
  29. data/source/rip/parser/rules/expression.rb +122 -0
  30. data/source/rip/parser/rules/import.rb +23 -0
  31. data/source/rip/parser/rules/invocation.rb +15 -0
  32. data/source/rip/parser/rules/invocation_index.rb +15 -0
  33. data/source/rip/parser/rules/keyword.rb +12 -0
  34. data/source/rip/parser/rules/lambda.rb +45 -0
  35. data/source/rip/parser/rules/list.rb +18 -0
  36. data/source/rip/parser/rules/map.rb +15 -0
  37. data/source/rip/parser/rules/module.rb +29 -0
  38. data/source/rip/parser/rules/number.rb +21 -0
  39. data/source/rip/parser/rules/pair.rb +13 -0
  40. data/source/rip/parser/rules/property.rb +33 -0
  41. data/source/rip/parser/rules/range.rb +15 -0
  42. data/source/rip/parser/rules/reference.rb +16 -0
  43. data/source/rip/parser/rules/string.rb +41 -0
  44. data/source/rip/parser/rules/unit.rb +17 -0
  45. data/source/rip/parser/rules.rb +7 -0
  46. data/source/rip/parser/utilities/normalizer.rb +638 -0
  47. data/source/rip/parser.rb +24 -0
  48. data/source/rip-parser.rb +1 -0
  49. data/spec/fixtures/syntax_sample.rip +96 -0
  50. data/spec/spec_helper.rb +20 -0
  51. data/spec/support/helpers.rb +57 -0
  52. data/spec/support/parslet.rb +1 -0
  53. data/spec/support/shared_examples.rb +9 -0
  54. data/spec/unit/rip/parser/grammar_spec.rb +8 -0
  55. data/spec/unit/rip/parser/location_spec.rb +89 -0
  56. data/spec/unit/rip/parser/node_spec.rb +157 -0
  57. data/spec/unit/rip/parser/rules/assignment_spec.rb +59 -0
  58. data/spec/unit/rip/parser/rules/binary_condition_spec.rb +41 -0
  59. data/spec/unit/rip/parser/rules/character_spec.rb +29 -0
  60. data/spec/unit/rip/parser/rules/class_spec.rb +181 -0
  61. data/spec/unit/rip/parser/rules/common_spec.rb +88 -0
  62. data/spec/unit/rip/parser/rules/date_time_spec.rb +61 -0
  63. data/spec/unit/rip/parser/rules/expression_spec.rb +95 -0
  64. data/spec/unit/rip/parser/rules/import_spec.rb +64 -0
  65. data/spec/unit/rip/parser/rules/invocation_index_spec.rb +46 -0
  66. data/spec/unit/rip/parser/rules/invocation_spec.rb +46 -0
  67. data/spec/unit/rip/parser/rules/keyword_spec.rb +17 -0
  68. data/spec/unit/rip/parser/rules/lambda_spec.rb +174 -0
  69. data/spec/unit/rip/parser/rules/list_spec.rb +45 -0
  70. data/spec/unit/rip/parser/rules/map_spec.rb +36 -0
  71. data/spec/unit/rip/parser/rules/module_spec.rb +63 -0
  72. data/spec/unit/rip/parser/rules/number_spec.rb +40 -0
  73. data/spec/unit/rip/parser/rules/pair_spec.rb +25 -0
  74. data/spec/unit/rip/parser/rules/property_spec.rb +27 -0
  75. data/spec/unit/rip/parser/rules/range_spec.rb +37 -0
  76. data/spec/unit/rip/parser/rules/reference_spec.rb +43 -0
  77. data/spec/unit/rip/parser/rules/string_spec.rb +166 -0
  78. data/spec/unit/rip/parser/rules/unit_spec.rb +17 -0
  79. data/spec/unit/rip/parser_spec.rb +106 -0
  80. metadata +192 -0
@@ -0,0 +1,181 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe Rip::Parser::Rules::Class do
4
+ class ClassParser
5
+ include Rip::Parser::Rules::Class
6
+ include Rip::Parser::Rules::Module
7
+ end
8
+
9
+ let(:parser) { ClassParser.new }
10
+
11
+ describe '#class_block' do
12
+ subject { parser.class_block }
13
+
14
+ it do
15
+ should parse('class {}').as(
16
+ class: 'class',
17
+ body: nil
18
+ )
19
+ end
20
+
21
+ it do
22
+ should parse('class (Collection) { self.foo = 42 }').as(
23
+ class: 'class',
24
+ ancestors: [
25
+ { reference: 'Collection' }
26
+ ],
27
+ body: {
28
+ property: {
29
+ class_self: 'self',
30
+ location: '.',
31
+ property_name: 'foo'
32
+ },
33
+ location: '=',
34
+ property_value: { expression_chain: { integer: '42' } }
35
+ }
36
+ )
37
+ end
38
+
39
+ it do
40
+ should parse('class () { foo = 42; @.initialize = ~> { @.bar = `F } }').as(
41
+ class: 'class',
42
+ ancestors: [],
43
+ body: [
44
+ {
45
+ property: {
46
+ property_name: 'foo'
47
+ },
48
+ location: '=',
49
+ property_value: { expression_chain: { integer: '42' } }
50
+ },
51
+ {
52
+ property: {
53
+ class_prototype: '@',
54
+ location: '.',
55
+ property_name: 'initialize'
56
+ },
57
+ location: '=',
58
+ property_value: {
59
+ swerve_rocket: '~>',
60
+ body: {
61
+ lhs: {
62
+ object: { reference: '@' },
63
+ location: '.',
64
+ property_name: 'bar'
65
+ },
66
+ location: '=',
67
+ rhs: { expression_chain: { location: '`', character: 'F' } }
68
+ }
69
+ }
70
+ }
71
+ ]
72
+ )
73
+ end
74
+ end
75
+
76
+ describe '#class_ancestors' do
77
+ subject { parser.class_ancestors }
78
+
79
+ it { should parse('()').as(ancestors: []) }
80
+
81
+ it do
82
+ should parse('(Queryable)').as(
83
+ ancestors: [
84
+ { reference: 'Queryable' }
85
+ ]
86
+ )
87
+ end
88
+
89
+ it do
90
+ should parse('(Collection, Queryable)').as(
91
+ ancestors: [
92
+ { reference: 'Collection' },
93
+ { reference: 'Queryable' }
94
+ ]
95
+ )
96
+ end
97
+ end
98
+
99
+ describe '#class_property_assignment' do
100
+ subject { parser.class_property_assignment }
101
+
102
+ it do
103
+ should parse('foo = 42').as(
104
+ {
105
+ property: {
106
+ property_name: 'foo'
107
+ },
108
+ location: '=',
109
+ property_value: { expression_chain: { integer: '42' } }
110
+ }
111
+ )
112
+ end
113
+
114
+ it do
115
+ should parse('foo = ~> { 42 }').as(
116
+ {
117
+ property: {
118
+ property_name: 'foo'
119
+ },
120
+ location: '=',
121
+ property_value: {
122
+ swerve_rocket: '~>',
123
+ body: { expression_chain: { integer: '42' } }
124
+ }
125
+ }
126
+ )
127
+ end
128
+
129
+ it do
130
+ should parse('self.[] = -> { 42 }').as(
131
+ {
132
+ property: {
133
+ class_self: 'self',
134
+ location: '.',
135
+ property_name: '[]'
136
+ },
137
+ location: '=',
138
+ property_value: {
139
+ dash_rocket: '->',
140
+ body: { expression_chain: { integer: '42' } }
141
+ }
142
+ }
143
+ )
144
+ end
145
+
146
+ it do
147
+ should parse('@.[] = => { -> { 42 } }').as(
148
+ {
149
+ property: {
150
+ class_prototype: '@',
151
+ location: '.',
152
+ property_name: '[]'
153
+ },
154
+ location: '=',
155
+ property_value: {
156
+ fat_rocket: '=>',
157
+ overloads: [
158
+ {
159
+ dash_rocket: '->',
160
+ body: { expression_chain: { integer: '42' } }
161
+ }
162
+ ]
163
+ }
164
+ }
165
+ )
166
+ end
167
+ end
168
+
169
+ describe '#property_block' do
170
+ subject { parser.property_block }
171
+
172
+ it do
173
+ should parse('~> { 42 }').as(
174
+ swerve_rocket: '~>',
175
+ body: { expression_chain: { integer: '42' } }
176
+ )
177
+ end
178
+
179
+ it { should_not parse('~> {}') }
180
+ end
181
+ end
@@ -0,0 +1,88 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe Rip::Parser::Rules::Common do
4
+ class CommonParser
5
+ include Rip::Parser::Rules::Common
6
+ end
7
+
8
+ let(:parser) { CommonParser.new }
9
+
10
+ describe '#comment' do
11
+ subject { parser.comment }
12
+
13
+ it { should parse('#') }
14
+ it { should parse('# comment') }
15
+ end
16
+
17
+ describe '#space' do
18
+ subject { parser.space }
19
+
20
+ it { should parse(' ') }
21
+ it { should parse("\t") }
22
+ end
23
+
24
+ describe '#spaces' do
25
+ subject { parser.spaces }
26
+
27
+ it { should parse(' ') }
28
+ it { should parse("\t\t") }
29
+ it { should parse(" \t \t ") }
30
+ end
31
+
32
+ describe '#spaces?' do
33
+ subject { parser.spaces? }
34
+
35
+ it { should parse('') }
36
+ it { should parse(' ') }
37
+ it { should parse(" \t \t ") }
38
+ end
39
+
40
+ describe '#line_break' do
41
+ subject { parser.line_break }
42
+
43
+ it { should parse("\n") }
44
+ it { should parse("\r") }
45
+ it { should parse("\r\n") }
46
+ end
47
+
48
+ describe '#line_breaks' do
49
+ subject { parser.line_breaks }
50
+
51
+ it { should parse("\r\n\r\n") }
52
+ it { should parse("\n\n") }
53
+ it { should parse("\r\r") }
54
+ end
55
+
56
+ describe '#line_breaks?' do
57
+ subject { parser.line_breaks? }
58
+
59
+ it { should parse('') }
60
+ it { should parse("\r\n\r\n") }
61
+ it { should parse("\n\n") }
62
+ end
63
+
64
+ describe '#whitespace' do
65
+ subject { parser.whitespace }
66
+
67
+ it { should parse(' ') }
68
+ it { should parse("\t") }
69
+ it { should parse("\n") }
70
+ it { should parse("\r") }
71
+ it { should parse("\r\n") }
72
+ end
73
+
74
+ describe '#whitespaces' do
75
+ subject { parser.whitespaces }
76
+
77
+ it { should parse(' ') }
78
+ it { should parse("\t\t") }
79
+ end
80
+
81
+ describe '#whitespaces?' do
82
+ subject { parser.whitespaces? }
83
+
84
+ it { should parse('') }
85
+ it { should parse("\n") }
86
+ it { should parse("\t\r") }
87
+ end
88
+ end
@@ -0,0 +1,61 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe Rip::Parser::Rules::DateTime do
4
+ class DateTimeParser
5
+ include Rip::Parser::Rules::DateTime
6
+ end
7
+
8
+ let(:parser) { DateTimeParser.new }
9
+
10
+ describe '#date_time' do
11
+ subject { parser.date_time }
12
+
13
+ it do
14
+ should parse('2012-02-12T21:51:50').as(
15
+ date: { year: '2012', month: '02', day: '12' },
16
+ time: { hour: '21', minute: '51', second: '50' }
17
+ )
18
+ end
19
+ end
20
+
21
+ describe '#date' do
22
+ subject { parser.date }
23
+
24
+ it { should parse('2012-02-12').as(year: '2012', month: '02', day: '12') }
25
+ end
26
+
27
+ describe '#time' do
28
+ subject { parser.time }
29
+
30
+ it { should parse('21:51:50').as(hour: '21', minute: '51', second: '50') }
31
+
32
+ it { should parse('12:34:45.678').as(hour: '12', minute: '34', second: '45', sub_second: '678') }
33
+
34
+ it do
35
+ should parse('12:34:45-0500').as(
36
+ hour: '12',
37
+ minute: '34',
38
+ second: '45',
39
+ offset: {
40
+ sign: '-',
41
+ hour: '05',
42
+ minute: '00'
43
+ }
44
+ )
45
+ end
46
+
47
+ it do
48
+ should parse('12:34:45.678+1230').as(
49
+ hour: '12',
50
+ minute: '34',
51
+ second: '45',
52
+ sub_second: '678',
53
+ offset: {
54
+ sign: '+',
55
+ hour: '12',
56
+ minute: '30'
57
+ }
58
+ )
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,95 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe Rip::Parser::Rules::Expression do
4
+ class ExpressionParser
5
+ include Rip::Parser::Rules::Expression
6
+ include Rip::Parser::Rules::Module
7
+ end
8
+
9
+ let(:parser) { ExpressionParser.new }
10
+
11
+ describe '#expression' do
12
+ subject { parser.expression }
13
+
14
+ it { should parse('42') }
15
+ it { should parse('-39.7') }
16
+
17
+ it { should parse('`r') }
18
+
19
+ it { should parse(':rip') }
20
+
21
+ it { should parse('[ "nested", [] ]') }
22
+
23
+ it { should parse('foo') }
24
+
25
+ it { should parse('import :bar') }
26
+
27
+ context 'with nested parenthesis' do
28
+ it { should parse('(( ((`z))) )') }
29
+ it { should parse('(import :bar)') }
30
+ end
31
+
32
+ context 'map literals' do
33
+ it do
34
+ should parse('{ nested: {} }').as(
35
+ expression_chain: {
36
+ location: '{',
37
+ map: [
38
+ {
39
+ expression_chain: [
40
+ { reference: 'nested' },
41
+ {
42
+ location: ':',
43
+ value: {
44
+ expression_chain: { location: '{', map: [] }
45
+ }
46
+ }
47
+ ]
48
+ }
49
+ ]
50
+ }
51
+ )
52
+ end
53
+ end
54
+
55
+ context 'chaining' do
56
+ it do
57
+ should parse('foo.bar').as(expression_chain: [
58
+ { reference: 'foo' },
59
+ { location: '.', property_name: 'bar' }
60
+ ])
61
+ end
62
+
63
+ it do
64
+ should parse('a.b.c').as(expression_chain: [
65
+ { reference: 'a' },
66
+ { location: '.', property_name: 'b' },
67
+ { location: '.', property_name: 'c' }
68
+ ])
69
+ end
70
+
71
+ it do
72
+ should parse('(((((foo).bar()).baz)))').as(
73
+ expression_chain: {
74
+ expression_chain: {
75
+ expression_chain: {
76
+ expression_chain: [
77
+ {
78
+ expression_chain: [
79
+ {
80
+ expression_chain: { reference: 'foo' }
81
+ },
82
+ { location: '.', property_name: 'bar' },
83
+ { location: '(', arguments: [] }
84
+ ]
85
+ },
86
+ { location: '.', property_name: 'baz' }
87
+ ]
88
+ }
89
+ }
90
+ }
91
+ )
92
+ end
93
+ end
94
+ end
95
+ end
@@ -0,0 +1,64 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe Rip::Parser::Rules::Import do
4
+ class ImportParser
5
+ include ::Parslet
6
+
7
+ include Rip::Parser::Rules::Import
8
+ include Rip::Parser::Rules::Reference
9
+
10
+ rule(:expression) { reference }
11
+ end
12
+
13
+ let(:parser) { ImportParser.new }
14
+
15
+ describe '#import' do
16
+ subject { parser.import }
17
+
18
+ it do
19
+ should parse('import :foo').as(import: 'import', module_name: {
20
+ location: ':',
21
+ string: [
22
+ { character: 'f' },
23
+ { character: 'o' },
24
+ { character: 'o' }
25
+ ]
26
+ })
27
+ end
28
+
29
+ it do
30
+ should parse('import(:bar)').as(import: 'import', module_name: {
31
+ location: ':',
32
+ string: [
33
+ { character: 'b' },
34
+ { character: 'a' },
35
+ { character: 'r' }
36
+ ]
37
+ })
38
+ end
39
+
40
+ it do
41
+ should parse('import "bar"').as(import: 'import', module_name: {
42
+ location: '"',
43
+ string: [
44
+ { character: 'b' },
45
+ { character: 'a' },
46
+ { character: 'r' }
47
+ ]
48
+ })
49
+ end
50
+
51
+ it do
52
+ should parse('import "./a/b"').as(import: 'import', module_name: {
53
+ location: '"',
54
+ string: [
55
+ { character: '.' },
56
+ { character: '/' },
57
+ { character: 'a' },
58
+ { character: '/' },
59
+ { character: 'b' }
60
+ ]
61
+ })
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,46 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe Rip::Parser::Rules::InvocationIndex do
4
+ class InvocationIndexParser
5
+ include ::Parslet
6
+
7
+ include Rip::Parser::Rules::InvocationIndex
8
+ include Rip::Parser::Rules::Module
9
+ end
10
+
11
+ let(:parser) { InvocationIndexParser.new }
12
+
13
+ describe '#invocation_index' do
14
+ subject { parser.invocation_index }
15
+
16
+ it { should parse('[]').as(location: '[', index_arguments: []) }
17
+
18
+ it do
19
+ should parse('[`3]').as(
20
+ location: '[',
21
+ index_arguments: [
22
+ {
23
+ expression_chain: { character: '3', location: '`' }
24
+ }
25
+ ]
26
+ )
27
+ end
28
+
29
+ it do
30
+ should parse('[1, 2, 3]').as(
31
+ location: '[',
32
+ index_arguments: [
33
+ {
34
+ expression_chain: { integer: '1' }
35
+ },
36
+ {
37
+ expression_chain: { integer: '2' }
38
+ },
39
+ {
40
+ expression_chain: { integer: '3' }
41
+ }
42
+ ]
43
+ )
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,46 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe Rip::Parser::Rules::Invocation do
4
+ class InvocationParser
5
+ include ::Parslet
6
+
7
+ include Rip::Parser::Rules::Invocation
8
+ include Rip::Parser::Rules::Module
9
+ end
10
+
11
+ let(:parser) { InvocationParser.new }
12
+
13
+ describe '#invocation' do
14
+ subject { parser.invocation }
15
+
16
+ it { should parse('()').as(location: '(', arguments: []) }
17
+
18
+ it do
19
+ should parse('(`3)').as(
20
+ location: '(',
21
+ arguments: [
22
+ {
23
+ expression_chain: { character: '3', location: '`' }
24
+ }
25
+ ]
26
+ )
27
+ end
28
+
29
+ it do
30
+ should parse('(1, 2, 3)').as(
31
+ location: '(',
32
+ arguments: [
33
+ {
34
+ expression_chain: { integer: '1' }
35
+ },
36
+ {
37
+ expression_chain: { integer: '2' }
38
+ },
39
+ {
40
+ expression_chain: { integer: '3' }
41
+ }
42
+ ]
43
+ )
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,17 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe Rip::Parser::Rules::Keyword do
4
+ class KeywordParser
5
+ include Rip::Parser::Rules::Keyword
6
+ end
7
+
8
+ let(:parser) { KeywordParser.new }
9
+
10
+ describe '#keyword' do
11
+ subject { parser.keyword(:import) }
12
+
13
+ it { should parse('import').as(import: 'import') }
14
+
15
+ it { should_not parse('importer') }
16
+ end
17
+ end