template-ruby 0.4.0 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
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 +112 -72
  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