code-ruby 0.4.0 → 0.5.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 (204) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -1
  3. data/Gemfile +2 -1
  4. data/Gemfile.lock +27 -54
  5. data/TODO +17 -0
  6. data/bin/code +56 -31
  7. data/bin/format +3 -0
  8. data/bin/template +62 -20
  9. data/bin/test +17 -0
  10. data/code-ruby.gemspec +1 -3
  11. data/docs/class.code +9 -0
  12. data/docs/euler/1.template +1 -5
  13. data/docs/euler/5.template +0 -1
  14. data/docs/meetup.code +12 -0
  15. data/docs/precedence.template +6 -39
  16. data/docs/rain.code +22 -0
  17. data/docs/slack.code +17 -0
  18. data/docs/stripe.code +7 -0
  19. data/docs/twitter.code +9 -0
  20. data/language-ruby.gemspec +18 -0
  21. data/lib/code/node/base_10.rb +29 -0
  22. data/lib/code/node/base_16.rb +13 -0
  23. data/lib/code/node/base_2.rb +13 -0
  24. data/lib/code/node/base_8.rb +13 -0
  25. data/lib/code/node/boolean.rb +7 -7
  26. data/lib/code/node/call.rb +32 -38
  27. data/lib/code/node/call_argument.rb +11 -27
  28. data/lib/code/node/chained_call.rb +10 -27
  29. data/lib/code/node/code.rb +4 -6
  30. data/lib/code/node/decimal.rb +26 -0
  31. data/lib/code/node/dictionnary.rb +20 -9
  32. data/lib/code/node/equal.rb +18 -20
  33. data/lib/code/node/function.rb +10 -7
  34. data/lib/code/node/function_parameter.rb +31 -0
  35. data/lib/code/node/if.rb +36 -32
  36. data/lib/code/node/if_modifier.rb +35 -36
  37. data/lib/code/node/list.rb +6 -8
  38. data/lib/code/node/negation.rb +5 -23
  39. data/lib/code/node/not.rb +15 -0
  40. data/lib/code/node/nothing.rb +1 -1
  41. data/lib/code/node/number.rb +14 -12
  42. data/lib/code/node/operation.rb +21 -16
  43. data/lib/code/node/power.rb +10 -6
  44. data/lib/code/node/rescue.rb +4 -3
  45. data/lib/code/node/splat.rb +15 -0
  46. data/lib/code/node/statement.rb +48 -70
  47. data/lib/code/node/string.rb +42 -16
  48. data/lib/code/node/ternary.rb +7 -9
  49. data/lib/code/node/unary_minus.rb +5 -12
  50. data/lib/code/node/while.rb +17 -24
  51. data/lib/code/node.rb +7 -8
  52. data/lib/code/object/argument.rb +2 -11
  53. data/lib/code/object/decimal.rb +45 -30
  54. data/lib/code/object/dictionnary.rb +6 -5
  55. data/lib/code/object/function.rb +20 -23
  56. data/lib/code/object/global.rb +11 -6
  57. data/lib/code/object/integer.rb +73 -30
  58. data/lib/code/object/list.rb +40 -34
  59. data/lib/code/object/range.rb +18 -17
  60. data/lib/code/object/ruby_function.rb +12 -6
  61. data/lib/code/object/string.rb +22 -12
  62. data/lib/code/object.rb +82 -24
  63. data/lib/code/parser/addition.rb +12 -20
  64. data/lib/code/parser/and_operator.rb +9 -20
  65. data/lib/code/parser/bitwise_and.rb +9 -20
  66. data/lib/code/parser/bitwise_or.rb +12 -20
  67. data/lib/code/parser/boolean.rb +10 -7
  68. data/lib/code/parser/call.rb +92 -60
  69. data/lib/code/parser/chained_call.rb +47 -0
  70. data/lib/code/parser/class.rb +45 -0
  71. data/lib/code/parser/code.rb +17 -10
  72. data/lib/code/parser/dictionnary.rb +56 -30
  73. data/lib/code/parser/equal.rb +87 -35
  74. data/lib/code/parser/equality.rb +23 -24
  75. data/lib/code/parser/equality_lower.rb +9 -0
  76. data/lib/code/parser/function.rb +67 -42
  77. data/lib/code/parser/greater.rb +25 -0
  78. data/lib/code/parser/group.rb +13 -8
  79. data/lib/code/parser/if.rb +51 -21
  80. data/lib/code/parser/if_modifier.rb +43 -16
  81. data/lib/code/parser/list.rb +32 -19
  82. data/lib/code/parser/multiplication.rb +15 -20
  83. data/lib/code/parser/name.rb +96 -84
  84. data/lib/code/parser/negation.rb +20 -9
  85. data/lib/code/parser/not_keyword.rb +14 -12
  86. data/lib/code/parser/nothing.rb +13 -8
  87. data/lib/code/parser/number.rb +124 -68
  88. data/lib/code/parser/operation.rb +35 -0
  89. data/lib/code/parser/or_keyword.rb +12 -20
  90. data/lib/code/parser/or_operator.rb +9 -20
  91. data/lib/code/parser/power.rb +32 -14
  92. data/lib/code/parser/range.rb +9 -17
  93. data/lib/code/parser/rescue.rb +29 -13
  94. data/lib/code/parser/shift.rb +11 -21
  95. data/lib/code/parser/splat.rb +31 -0
  96. data/lib/code/parser/statement.rb +4 -3
  97. data/lib/code/parser/string.rb +53 -62
  98. data/lib/code/parser/ternary.rb +36 -15
  99. data/lib/code/parser/unary_minus.rb +23 -5
  100. data/lib/code/parser/while.rb +26 -15
  101. data/lib/code/parser/whitespace.rb +49 -0
  102. data/lib/code/parser.rb +15 -0
  103. data/lib/code/ruby.rb +13 -12
  104. data/lib/code-ruby.rb +2 -11
  105. data/lib/code.rb +16 -13
  106. data/lib/language/atom.rb +343 -0
  107. data/lib/language/output.rb +130 -0
  108. data/lib/language/parser/absent/present.rb +8 -0
  109. data/lib/language/parser/absent.rb +6 -0
  110. data/lib/language/parser/end_of_input.rb +6 -0
  111. data/lib/language/parser/interuption.rb +38 -0
  112. data/lib/language/parser/not_end_of_input.rb +6 -0
  113. data/lib/language/parser/str/not_found.rb +16 -0
  114. data/lib/language/parser/str.rb +6 -0
  115. data/lib/language/parser.rb +53 -0
  116. data/lib/language-ruby.rb +10 -0
  117. data/lib/language.rb +80 -0
  118. data/lib/template/node/code_part.rb +1 -1
  119. data/lib/template/node/part.rb +1 -1
  120. data/lib/template/node/template.rb +1 -1
  121. data/lib/template/node/text_part.rb +1 -1
  122. data/lib/template/node.rb +1 -1
  123. data/lib/template/parser/template.rb +26 -17
  124. data/lib/template/parser.rb +15 -0
  125. data/lib/template/version.rb +1 -1
  126. data/lib/template-ruby.rb +2 -11
  127. data/lib/template.rb +6 -11
  128. data/spec/code/addition_spec.rb +13 -0
  129. data/spec/code/and_operator_spec.rb +13 -0
  130. data/spec/code/bitwise_and_spec.rb +13 -0
  131. data/spec/code/bitwise_or_spec.rb +13 -0
  132. data/spec/code/boolean_spec.rb +13 -0
  133. data/spec/code/call_spec.rb +21 -0
  134. data/spec/code/chained_call_spec.rb +16 -0
  135. data/spec/code/dictionnary_spec.rb +17 -0
  136. data/spec/code/equal_spec.rb +26 -0
  137. data/spec/code/equality_spec.rb +13 -0
  138. data/spec/code/function_spec.rb +18 -0
  139. data/spec/code/greater_spec.rb +18 -0
  140. data/spec/code/group_spec.rb +12 -0
  141. data/spec/code/if_modifier_spec.rb +20 -0
  142. data/spec/code/if_spec.rb +25 -0
  143. data/spec/code/list_spec.rb +17 -0
  144. data/spec/code/multiplication_spec.rb +18 -0
  145. data/spec/code/negation_spec.rb +20 -0
  146. data/spec/code/not_keyword_spec.rb +13 -0
  147. data/spec/code/nothing_spec.rb +17 -0
  148. data/spec/code/number_spec.rb +22 -0
  149. data/spec/code/or_keyword_spec.rb +17 -0
  150. data/spec/code/or_operator_spec.rb +16 -0
  151. data/spec/code/parser/boolean_spec.rb +5 -7
  152. data/spec/code/parser/call_spec.rb +16 -56
  153. data/spec/code/parser/chained_call.rb +17 -0
  154. data/spec/code/parser/dictionnary_spec.rb +8 -9
  155. data/spec/code/parser/function_spec.rb +5 -21
  156. data/spec/code/parser/group_spec.rb +18 -0
  157. data/spec/code/parser/list_spec.rb +9 -20
  158. data/spec/code/parser/number_spec.rb +4 -109
  159. data/spec/code/parser/string_spec.rb +9 -17
  160. data/spec/code/parser_spec.rb +23 -0
  161. data/spec/code/power_spec.rb +13 -0
  162. data/spec/code/range_spec.rb +16 -0
  163. data/spec/code/rescue_spec.rb +13 -0
  164. data/spec/code/shift_spec.rb +13 -0
  165. data/spec/code/splat_spec.rb +13 -0
  166. data/spec/code/string_spec.rb +25 -0
  167. data/spec/code/ternary_spec.rb +18 -0
  168. data/spec/code/unary_minus_spec.rb +13 -0
  169. data/spec/code/while_spec.rb +18 -0
  170. data/spec/spec_helper.rb +4 -1
  171. data/template-ruby.gemspec +2 -4
  172. metadata +110 -71
  173. data/lib/code/node/base_10_decimal.rb +0 -32
  174. data/lib/code/node/base_10_integer.rb +0 -32
  175. data/lib/code/node/base_10_number.rb +0 -19
  176. data/lib/code/node/base_16_number.rb +0 -19
  177. data/lib/code/node/base_2_number.rb +0 -19
  178. data/lib/code/node/base_8_number.rb +0 -19
  179. data/lib/code/node/block.rb +0 -17
  180. data/lib/code/node/defined.rb +0 -19
  181. data/lib/code/node/dictionnary_key_value.rb +0 -23
  182. data/lib/code/node/function_argument.rb +0 -45
  183. data/lib/code/node/group.rb +0 -13
  184. data/lib/code/node/keyword_call_argument.rb +0 -30
  185. data/lib/code/node/keyword_function_argument.rb +0 -33
  186. data/lib/code/node/name.rb +0 -28
  187. data/lib/code/node/not_keyword.rb +0 -13
  188. data/lib/code/node/or_keyword.rb +0 -34
  189. data/lib/code/node/range.rb +0 -31
  190. data/lib/code/node/regular_call_argument.rb +0 -34
  191. data/lib/code/node/regular_function_argument.rb +0 -36
  192. data/lib/code/node/string_characters.rb +0 -13
  193. data/lib/code/node/string_component.rb +0 -23
  194. data/lib/code/node/string_interpolation.rb +0 -13
  195. data/lib/code/parser/defined.rb +0 -20
  196. data/lib/code/parser/greater_than.rb +0 -33
  197. data/spec/call_spec.rb +0 -22
  198. data/spec/code/error/type_error_spec.rb +0 -63
  199. data/spec/code/parser/name_spec.rb +0 -15
  200. data/spec/code/parser/nothing_spec.rb +0 -19
  201. data/spec/code_spec.rb +0 -182
  202. data/spec/function_spec.rb +0 -26
  203. data/spec/template/parser/template_spec.rb +0 -19
  204. data/spec/template_spec.rb +0 -52
data/lib/code/object.rb CHANGED
@@ -5,31 +5,44 @@ class Code
5
5
  def call(**args)
6
6
  operator = args.fetch(:operator, nil)
7
7
  arguments = args.fetch(:arguments, [])
8
+ value = arguments.first&.value
8
9
 
9
10
  if operator == "=="
10
- sig(arguments, ::Code::Object)
11
- equal(arguments.first.value)
11
+ sig(arguments) { ::Code::Object }
12
+ equal(value)
12
13
  elsif operator == "==="
13
- sig(arguments, ::Code::Object)
14
- strict_equal(arguments.first.value)
14
+ sig(arguments) { ::Code::Object }
15
+ strict_equal(value)
15
16
  elsif operator == "!="
16
- sig(arguments, ::Code::Object)
17
- different(arguments.first.value)
17
+ sig(arguments) { ::Code::Object }
18
+ different(value)
18
19
  elsif operator == "<=>"
19
- sig(arguments, ::Code::Object)
20
- compare(arguments.first.value)
21
- elsif operator == "&&"
22
- sig(arguments, ::Code::Object)
23
- and_operator(arguments.first.value)
24
- elsif operator == "||"
25
- sig(arguments, ::Code::Object)
26
- or_operator(arguments.first.value)
20
+ sig(arguments) { ::Code::Object }
21
+ compare(value)
22
+ elsif operator == "&&" || operator == "and"
23
+ sig(arguments) { ::Code::Object }
24
+ and_operator(value)
25
+ elsif operator == "||" || operator == "or"
26
+ sig(arguments) { ::Code::Object }
27
+ or_operator(value)
28
+ elsif operator == "!" || operator == "not"
29
+ sig(arguments)
30
+ exclamation_point
31
+ elsif operator == "+"
32
+ sig(arguments)
33
+ self
34
+ elsif operator == ".."
35
+ sig(arguments) { ::Code::Object }
36
+ inclusive_range(value)
37
+ elsif operator == "..."
38
+ sig(arguments) { ::Code::Object }
39
+ exclusive_range(value)
27
40
  elsif operator == "to_string"
28
41
  sig(arguments)
29
42
  to_string
30
43
  else
31
44
  raise(
32
- Code::Error::Undefined.new("#{operator} not defined on #{inspect}"),
45
+ Code::Error::Undefined.new("#{operator} not defined on #{inspect}")
33
46
  )
34
47
  end
35
48
  end
@@ -63,23 +76,52 @@ class Code
63
76
  if respond_to?(:raw)
64
77
  [self.class, raw].hash
65
78
  else
66
- raise NotImplementedError
79
+ raise NotImplementedError.new(self.class.name)
67
80
  end
68
81
  end
69
82
 
70
83
  def to_s
71
- raise NotImplementedError
84
+ raise NotImplementedError.new(self.class.name)
72
85
  end
73
86
 
74
87
  private
75
88
 
76
- def sig(actual_arguments, *expected_arguments)
89
+ def multi_fetch(hash, *keys)
90
+ keys.map { |key| [key, hash.fetch(key)] }.to_h
91
+ end
92
+
93
+ def deep_dup(object)
94
+ if object.is_a?(Array)
95
+ object.map { |element| deep_dup(o) }
96
+ elsif object.is_a?(Hash)
97
+ object.map { |key, value| [deep_dup(key), deep_dup(value)] }.to_h
98
+ elsif object.is_a?(::Code::Object::List)
99
+ ::Code::Object::List.new(object.raw.map { |element| deep_dup(o) })
100
+ elsif object.is_a?(::Code::Object::Dictionnary)
101
+ ::Code::Object::Dictionnary.new(
102
+ object.raw.map { |key, value| [deep_dup(key), deep_dup(value)] }.to_h
103
+ )
104
+ else
105
+ object.dup
106
+ end
107
+ end
108
+
109
+ def sig(actual_arguments, &block)
110
+ if block
111
+ expected_arguments = block.call
112
+ expected_arguments = [
113
+ expected_arguments
114
+ ] unless expected_arguments.is_a?(Array)
115
+ else
116
+ expected_arguments = []
117
+ end
118
+
77
119
  if actual_arguments.size != expected_arguments.size
78
120
  raise(
79
121
  ::Code::Error::ArgumentError.new(
80
122
  "Expected #{expected_arguments.size} arguments, " \
81
- "got #{actual_arguments.size} arguments",
82
- ),
123
+ "got #{actual_arguments.size} arguments"
124
+ )
83
125
  )
84
126
  end
85
127
 
@@ -92,16 +134,16 @@ class Code
92
134
  }
93
135
  raise(
94
136
  ::Code::Error::TypeError.new(
95
- "Expected #{expected_argument}, got #{actual_argument.class}",
96
- ),
137
+ "Expected #{expected_argument}, got #{actual_argument.class}"
138
+ )
97
139
  )
98
140
  end
99
141
  else
100
142
  if !actual_argument.is_a?(expected_argument)
101
143
  raise(
102
144
  ::Code::Error::TypeError.new(
103
- "Expected #{expected_argument}, got #{actual_argument.class}",
104
- ),
145
+ "Expected #{expected_argument}, got #{actual_argument.class}"
146
+ )
105
147
  )
106
148
  end
107
149
  end
@@ -135,5 +177,21 @@ class Code
135
177
  def to_string
136
178
  ::Code::Object::String.new(to_s)
137
179
  end
180
+
181
+ def inclusive_range(value)
182
+ ::Code::Object::Range.new(self, value, exclude_end: false)
183
+ end
184
+
185
+ def exclusive_range(value)
186
+ ::Code::Object::Range.new(self, value, exclude_end: true)
187
+ end
188
+
189
+ def exclamation_point
190
+ if truthy?
191
+ ::Code::Object::Boolean.new(false)
192
+ else
193
+ ::Code::Object::Boolean.new(true)
194
+ end
195
+ end
138
196
  end
139
197
  end
@@ -1,29 +1,21 @@
1
1
  class Code
2
2
  class Parser
3
- class Addition < Parslet::Parser
4
- rule(:multiplication) { ::Code::Parser::Multiplication.new }
5
-
6
- rule(:plus) { str("+") }
7
- rule(:minus) { str("-") }
8
-
9
- rule(:operator) { plus | minus }
3
+ class Addition < Operation
4
+ def statement
5
+ ::Code::Parser::Multiplication
6
+ end
10
7
 
11
- rule(:space) { str(" ") }
12
- rule(:newline) { str("\n") }
13
- rule(:whitespace) { (space | newline).repeat(1) }
14
- rule(:whitespace?) { whitespace.maybe }
8
+ def plus
9
+ str("+")
10
+ end
15
11
 
16
- rule(:addition) do
17
- (
18
- multiplication.as(:first) >>
19
- (
20
- whitespace? >> operator.as(:operator) >> whitespace? >>
21
- multiplication.as(:statement)
22
- ).repeat(1).as(:rest)
23
- ).as(:addition) | multiplication
12
+ def minus
13
+ str("-")
24
14
  end
25
15
 
26
- root(:addition)
16
+ def operator
17
+ plus | minus
18
+ end
27
19
  end
28
20
  end
29
21
  end
@@ -1,28 +1,17 @@
1
1
  class Code
2
2
  class Parser
3
- class AndOperator < Parslet::Parser
4
- rule(:greater_than) { ::Code::Parser::GreaterThan.new }
5
-
6
- rule(:ampersand) { str("&") }
7
-
8
- rule(:operator) { ampersand >> ampersand }
9
-
10
- rule(:space) { str(" ") }
11
- rule(:newline) { str("\n") }
12
- rule(:whitespace) { (space | newline).repeat(1) }
13
- rule(:whitespace?) { whitespace.maybe }
3
+ class AndOperator < Operation
4
+ def statement
5
+ ::Code::Parser::EqualityLower
6
+ end
14
7
 
15
- rule(:and_operator) do
16
- (
17
- greater_than.as(:first) >>
18
- (
19
- whitespace? >> operator.as(:operator) >> whitespace? >>
20
- greater_than.as(:statement)
21
- ).repeat(1).as(:rest)
22
- ).as(:and_operator) | greater_than
8
+ def ampersand
9
+ str("&")
23
10
  end
24
11
 
25
- root(:and_operator)
12
+ def operator
13
+ ampersand << ampersand
14
+ end
26
15
  end
27
16
  end
28
17
  end
@@ -1,28 +1,17 @@
1
1
  class Code
2
2
  class Parser
3
- class BitwiseAnd < Parslet::Parser
4
- rule(:shift) { ::Code::Parser::Shift.new }
5
-
6
- rule(:ampersand) { str("&") }
7
-
8
- rule(:operator) { ampersand }
9
-
10
- rule(:space) { str(" ") }
11
- rule(:newline) { str("\n") }
12
- rule(:whitespace) { (space | newline).repeat(1) }
13
- rule(:whitespace?) { whitespace.maybe }
3
+ class BitwiseAnd < Operation
4
+ def statement
5
+ ::Code::Parser::Shift
6
+ end
14
7
 
15
- rule(:bitwise_and) do
16
- (
17
- shift.as(:first) >>
18
- (
19
- whitespace? >> operator.as(:operator) >> whitespace? >>
20
- shift.as(:statement)
21
- ).repeat(1).as(:rest)
22
- ).as(:bitwise_and) | shift
8
+ def ampersand
9
+ str("&")
23
10
  end
24
11
 
25
- root(:bitwise_and)
12
+ def operator
13
+ ampersand
14
+ end
26
15
  end
27
16
  end
28
17
  end
@@ -1,29 +1,21 @@
1
1
  class Code
2
2
  class Parser
3
- class BitwiseOr < Parslet::Parser
4
- rule(:bitwise_and) { ::Code::Parser::BitwiseAnd.new }
5
-
6
- rule(:pipe) { str("|") }
7
- rule(:caret) { str("^") }
8
-
9
- rule(:operator) { pipe | caret }
3
+ class BitwiseOr < Operation
4
+ def statement
5
+ ::Code::Parser::BitwiseAnd
6
+ end
10
7
 
11
- rule(:space) { str(" ") }
12
- rule(:newline) { str("\n") }
13
- rule(:whitespace) { (space | newline).repeat(1) }
14
- rule(:whitespace?) { whitespace.maybe }
8
+ def pipe
9
+ str("|")
10
+ end
15
11
 
16
- rule(:bitwise_or) do
17
- (
18
- bitwise_and.as(:first) >>
19
- (
20
- whitespace? >> operator.as(:operator) >> whitespace? >>
21
- bitwise_and.as(:statement)
22
- ).repeat(1).as(:rest)
23
- ).as(:bitwise_or) | bitwise_and
12
+ def caret
13
+ str("^")
24
14
  end
25
15
 
26
- root(:bitwise_or)
16
+ def operator
17
+ pipe | caret
18
+ end
27
19
  end
28
20
  end
29
21
  end
@@ -1,14 +1,17 @@
1
1
  class Code
2
2
  class Parser
3
- class Boolean < Parslet::Parser
4
- rule(:nothing) { ::Code::Parser::Nothing.new }
3
+ class Boolean < Language
4
+ def true_keyword
5
+ str("true")
6
+ end
5
7
 
6
- rule(:true_keyword) { str("true") }
7
- rule(:false_keyword) { str("false") }
8
+ def false_keyword
9
+ str("false")
10
+ end
8
11
 
9
- rule(:boolean) { (true_keyword | false_keyword).as(:boolean) | nothing }
10
-
11
- root(:boolean)
12
+ def root
13
+ (true_keyword | false_keyword).aka(:boolean) | ::Code::Parser::Nothing
14
+ end
12
15
  end
13
16
  end
14
17
  end
@@ -1,90 +1,122 @@
1
1
  class Code
2
2
  class Parser
3
- class Call < Parslet::Parser
4
- rule(:dictionnary) { ::Code::Parser::Dictionnary.new }
5
- rule(:code) { ::Code::Parser::Code.new.present }
6
- rule(:name) { ::Code::Parser::Name.new }
7
- rule(:function_arguments) { ::Code::Parser::Function.new.arguments }
3
+ class Call < Language
4
+ def name
5
+ ::Code::Parser::Name
6
+ end
8
7
 
9
- rule(:dot) { str(".") }
10
- rule(:opening_parenthesis) { str("(") }
11
- rule(:closing_parenthesis) { str(")") }
12
- rule(:opening_curly_bracket) { str("{") }
13
- rule(:closing_curly_bracket) { str("}") }
14
- rule(:comma) { str(",") }
15
- rule(:colon) { str(":") }
16
- rule(:ampersand) { str("&") }
17
- rule(:asterisk) { str("*") }
18
- rule(:pipe) { str("|") }
19
- rule(:do_keyword) { str("do") }
20
- rule(:end_keyword) { str("end") }
8
+ def whitespace
9
+ ::Code::Parser::Whitespace
10
+ end
21
11
 
22
- rule(:space) { str(" ") }
23
- rule(:newline) { str("\n") }
24
- rule(:whitespace) { (space | newline).repeat(1) }
25
- rule(:whitespace?) { whitespace.maybe }
12
+ def whitespace?
13
+ whitespace.maybe
14
+ end
26
15
 
27
- rule(:keyword_argument) do
28
- name >> whitespace? >> colon >> whitespace? >> code.as(:value)
16
+ def code
17
+ ::Code::Parser::Code
29
18
  end
30
19
 
31
- rule(:regular_argument) do
32
- ampersand.as(:block).maybe >>
33
- (asterisk >> asterisk).as(:keyword_splat).maybe >>
34
- asterisk.as(:splat).maybe >> code.as(:value)
20
+ def code_present
21
+ ::Code::Parser::Code.new.present
35
22
  end
36
23
 
37
- rule(:argument) do
38
- keyword_argument.as(:keyword) | regular_argument.as(:regular)
24
+ def colon
25
+ str(":")
39
26
  end
40
27
 
41
- rule(:arguments) do
42
- argument.repeat(1, 1) >>
43
- (whitespace? >> comma >> whitespace? >> argument).repeat
28
+ def comma
29
+ str(",")
44
30
  end
45
31
 
46
- rule(:single_call) do
47
- dictionnary.as(:left) >>
48
- (
49
- opening_parenthesis >> whitespace? >>
50
- arguments.as(:arguments).maybe >> whitespace? >>
51
- closing_parenthesis
52
- ) >> block.as(:block).maybe
32
+ def pipe
33
+ str("|")
53
34
  end
54
35
 
55
- rule(:chained_single_call) do
56
- dot >> name >>
57
- (
58
- opening_parenthesis >> whitespace? >>
59
- arguments.as(:arguments).maybe >> whitespace? >>
60
- closing_parenthesis
61
- ).maybe >> block.as(:block).maybe
36
+ def equal
37
+ str("=")
38
+ end
39
+
40
+ def opening_curly_bracket
41
+ str("{")
42
+ end
43
+
44
+ def closing_curly_bracket
45
+ str("}")
46
+ end
47
+
48
+ def opening_parenthesis
49
+ str("(")
50
+ end
51
+
52
+ def closing_parenthesis
53
+ str(")")
54
+ end
55
+
56
+ def do_keyword
57
+ str("do")
58
+ end
59
+
60
+ def end_keyword
61
+ str("end")
62
+ end
63
+
64
+ def keyword_argument
65
+ name.aka(:name) << colon << code_present.aka(:value)
66
+ end
67
+
68
+ def regular_argument
69
+ code_present.aka(:value)
70
+ end
71
+
72
+ def argument
73
+ keyword_argument | regular_argument
74
+ end
75
+
76
+ def arguments
77
+ opening_parenthesis.ignore << whitespace? << argument.repeat(0, 1) <<
78
+ (comma << whitespace? << argument << whitespace?).repeat <<
79
+ whitespace? << closing_parenthesis.ignore.maybe
80
+ end
81
+
82
+ def keyword_parameter
83
+ name.aka(:name) << whitespace? << colon.aka(:keyword) <<
84
+ code_present.aka(:default).maybe
85
+ end
86
+
87
+ def regular_parameter
88
+ name.aka(:name) << whitespace? <<
89
+ (equal << whitespace? << code_present.aka(:default)).maybe
62
90
  end
63
91
 
64
- rule(:chained_call) do
65
- dictionnary.as(:left) >> chained_single_call.repeat(1).as(:right)
92
+ def parameter
93
+ keyword_parameter | regular_parameter
66
94
  end
67
95
 
68
- rule(:block_arguments) do
69
- pipe >> whitespace? >> function_arguments >> whitespace? >> pipe
96
+ def parameters
97
+ pipe.ignore << whitespace? << parameter.repeat(0, 1) <<
98
+ (whitespace? << comma << whitespace? << parameter).repeat <<
99
+ whitespace? << pipe.ignore.maybe
70
100
  end
71
101
 
72
- rule(:block) do
102
+ def block
73
103
  (
74
- whitespace >> do_keyword >> whitespace >>
75
- block_arguments.as(:arguments).maybe >> code.as(:body).maybe >>
76
- end_keyword
104
+ do_keyword << whitespace? << parameters.aka(:parameters).maybe <<
105
+ code.aka(:body) << end_keyword.maybe
77
106
  ) |
78
107
  (
79
- whitespace? >> opening_curly_bracket >> whitespace >>
80
- block_arguments.as(:arguments).maybe >> code.as(:body).maybe >>
81
- closing_curly_bracket
108
+ opening_curly_bracket << whitespace? <<
109
+ parameters.aka(:parameters).maybe << code.aka(:body) <<
110
+ closing_curly_bracket.maybe
82
111
  )
83
112
  end
84
113
 
85
- rule(:call) { (single_call | chained_call).as(:call) | dictionnary }
86
-
87
- root(:call)
114
+ def root
115
+ (
116
+ name.aka(:name) << (whitespace? << arguments.aka(:arguments)).maybe <<
117
+ (whitespace? << block.aka(:block)).maybe
118
+ ).aka(:call)
119
+ end
88
120
  end
89
121
  end
90
122
  end
@@ -0,0 +1,47 @@
1
+ class Code
2
+ class Parser
3
+ class ChainedCall < Operation
4
+ def statement
5
+ ::Code::Parser::Dictionnary
6
+ end
7
+
8
+ def whitespace
9
+ ::Code::Parser::Whitespace
10
+ end
11
+
12
+ def whitespace?
13
+ whitespace.maybe
14
+ end
15
+
16
+ def dot
17
+ str(".")
18
+ end
19
+
20
+ def colon
21
+ str(":")
22
+ end
23
+
24
+ def operator
25
+ dot | (colon << colon)
26
+ end
27
+
28
+ def root
29
+ (
30
+ statement.aka(:first) <<
31
+ (whitespace? << operator << whitespace? << statement)
32
+ .repeat(1)
33
+ .aka(:others)
34
+ .maybe
35
+ )
36
+ .aka(:chained_call)
37
+ .then do |output|
38
+ if output[:chained_call][:others]
39
+ output
40
+ else
41
+ output[:chained_call][:first]
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,45 @@
1
+ class Code
2
+ class Parser
3
+ class Class < Language
4
+ def statement
5
+ ::Code::Parser::While
6
+ end
7
+
8
+ def name
9
+ ::Code::Parser::Name
10
+ end
11
+
12
+ def code
13
+ ::Code::Parser::Code
14
+ end
15
+
16
+ def whitespace
17
+ ::Code::Parser::Whitespace
18
+ end
19
+
20
+ def whitespace?
21
+ whitespace.maybe
22
+ end
23
+
24
+ def class_keyword
25
+ str("class")
26
+ end
27
+
28
+ def end_keyword
29
+ str("end")
30
+ end
31
+
32
+ def lesser
33
+ str("<")
34
+ end
35
+
36
+ def root
37
+ (
38
+ class_keyword << whitespace? << name.aka(:name) <<
39
+ (whitespace? << lesser << name.aka(:superclass)).maybe <<
40
+ code.aka(:body) << end_keyword.maybe
41
+ ).aka(:class) | statement
42
+ end
43
+ end
44
+ end
45
+ end
@@ -1,18 +1,25 @@
1
1
  class Code
2
2
  class Parser
3
- class Code < Parslet::Parser
4
- rule(:statement) { ::Code::Parser::Statement.new }
3
+ class Code < Language
4
+ def whitespace
5
+ ::Code::Parser::Whitespace
6
+ end
7
+
8
+ def whitespace?(&block)
9
+ whitespace.maybe(&block)
10
+ end
5
11
 
6
- rule(:space) { str(" ") }
7
- rule(:newline) { str("\n") }
8
- rule(:whitespace) { (space | newline).repeat(1) }
9
- rule(:whitespace?) { whitespace.maybe }
12
+ def statement
13
+ ::Code::Parser::Statement
14
+ end
15
+
16
+ def present
17
+ (whitespace? << statement << whitespace?).repeat(1)
18
+ end
10
19
 
11
- rule(:present) do
12
- (whitespace?.ignore >> statement >> whitespace?.ignore).repeat(1)
20
+ def root
21
+ present | whitespace?.then { [] }
13
22
  end
14
- rule(:code) { present | whitespace?.ignore }
15
- root(:code)
16
23
  end
17
24
  end
18
25
  end