skeem 0.2.15 → 0.2.16

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 (56) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +17 -11
  3. data/CHANGELOG.md +5 -0
  4. data/Gemfile +2 -0
  5. data/README.md +3 -2
  6. data/Rakefile +2 -0
  7. data/appveyor.yml +3 -4
  8. data/bin/skeem +15 -15
  9. data/lib/skeem.rb +2 -0
  10. data/lib/skeem/datum_dsl.rb +12 -3
  11. data/lib/skeem/element_visitor.rb +5 -2
  12. data/lib/skeem/grammar.rb +86 -24
  13. data/lib/skeem/interpreter.rb +5 -3
  14. data/lib/skeem/parser.rb +6 -4
  15. data/lib/skeem/primitive/primitive_builder.rb +128 -115
  16. data/lib/skeem/primitive/primitive_procedure.rb +17 -20
  17. data/lib/skeem/runtime.rb +9 -5
  18. data/lib/skeem/s_expr_builder.rb +46 -104
  19. data/lib/skeem/s_expr_nodes.rb +116 -90
  20. data/lib/skeem/skeem_exception.rb +0 -0
  21. data/lib/skeem/skm_binding.rb +6 -7
  22. data/lib/skeem/skm_compound_datum.rb +8 -4
  23. data/lib/skeem/skm_element.rb +14 -12
  24. data/lib/skeem/skm_empty_list.rb +6 -4
  25. data/lib/skeem/skm_exception.rb +9 -0
  26. data/lib/skeem/skm_expression.rb +3 -1
  27. data/lib/skeem/skm_frame.rb +3 -2
  28. data/lib/skeem/skm_pair.rb +23 -18
  29. data/lib/skeem/skm_procedure_exec.rb +8 -6
  30. data/lib/skeem/skm_simple_datum.rb +13 -12
  31. data/lib/skeem/skm_unary_expression.rb +15 -17
  32. data/lib/skeem/tokenizer.rb +32 -25
  33. data/lib/skeem/version.rb +3 -1
  34. data/skeem.gemspec +6 -4
  35. data/spec/skeem/add4.skm +4 -0
  36. data/spec/skeem/datum_dsl_spec.rb +13 -12
  37. data/spec/skeem/element_visitor_spec.rb +12 -10
  38. data/spec/skeem/interpreter_spec.rb +74 -46
  39. data/spec/skeem/lambda_spec.rb +9 -7
  40. data/spec/skeem/parser_spec.rb +21 -19
  41. data/spec/skeem/primitive/primitive_builder_spec.rb +57 -48
  42. data/spec/skeem/primitive/primitive_procedure_spec.rb +15 -13
  43. data/spec/skeem/runtime_spec.rb +18 -16
  44. data/spec/skeem/s_expr_nodes_spec.rb +8 -6
  45. data/spec/skeem/skm_compound_datum_spec.rb +11 -9
  46. data/spec/skeem/skm_element_spec.rb +7 -5
  47. data/spec/skeem/skm_empty_list_spec.rb +7 -5
  48. data/spec/skeem/skm_frame_spec.rb +5 -4
  49. data/spec/skeem/skm_pair_spec.rb +4 -3
  50. data/spec/skeem/skm_procedure_exec_spec.rb +2 -0
  51. data/spec/skeem/skm_simple_datum_spec.rb +24 -22
  52. data/spec/skeem/skm_unary_expression_spec.rb +11 -9
  53. data/spec/skeem/tokenizer_spec.rb +53 -44
  54. data/spec/skeem_spec.rb +2 -0
  55. data/spec/spec_helper.rb +4 -2
  56. metadata +7 -4
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 182cf920c536bb07dd813c34eae74af24181813a9d96fdd39c786cc28043f135
4
- data.tar.gz: ba4cf5ce2df8d1708f3504e57a14b62734146f3c8a47043cf2d5ffdf591e35d6
3
+ metadata.gz: c6b187bafcc1084e3c45a68f552bb5756b8dc51338f5241fa64ad5f60f1f94c7
4
+ data.tar.gz: f6925b7497ab8a2ab678c7b5483907b374caed4f7a9b00e1d22d3d53c141191c
5
5
  SHA512:
6
- metadata.gz: bd03dfab05470ee167464113844c3a8b0b3174f58cd4607034f417218b91ec024e26aff941ac78e750be30ff216d18be97171b030c3f3055803443f421ad6c19
7
- data.tar.gz: 2cd279dca2e9202e6a924373a01c1a49e493ea2379131284639b07977714c72df751574a8252231d15182dc6b23d55206aaa11be062502b4840a5d9a27143199
6
+ metadata.gz: b8e2cd533cd3e1661f1c205ab87179e8d1a48a1e23d5c5867c6106f54b56fe076fda0ae2eaa1a28045633dc4e3eb80ec891abf8dd3f03f6698e53c5e308173be
7
+ data.tar.gz: 68e3b66e4821062f9792e37b9b2d89134e10a21fcb6f0e3fc1a591243a1be8930cb5a18fcc9add86850a47cbfa9be4f7c2a2239bb94e3f187082efb2a2392412
data/.rubocop.yml CHANGED
@@ -5,6 +5,9 @@ AllCops:
5
5
  Layout/CaseIndentation:
6
6
  Enabled: false
7
7
 
8
+ Layout/ClosingHeredocIndentation:
9
+ Enabled: false
10
+
8
11
  Layout/CommentIndentation:
9
12
  Enabled: false
10
13
 
@@ -13,7 +16,7 @@ Layout/ElseAlignment:
13
16
 
14
17
  Layout/EmptyLines:
15
18
  Enabled: false
16
-
19
+
17
20
  Layout/EndAlignment:
18
21
  Enabled: false
19
22
 
@@ -26,10 +29,10 @@ Layout/IndentationWidth:
26
29
 
27
30
  Layout/IndentationConsistency:
28
31
  Enabled: true
29
-
32
+
30
33
  Layout/IndentHeredoc:
31
34
  Enabled: false
32
-
35
+
33
36
  Layout/MultilineHashBraceLayout:
34
37
  Enabled: true
35
38
 
@@ -38,10 +41,10 @@ Layout/SpaceAroundOperators:
38
41
 
39
42
  Layout/SpaceInsideParens:
40
43
  Enabled: true
41
-
44
+
42
45
  Layout/Tab:
43
46
  Enabled: true
44
-
47
+
45
48
  Layout/TrailingBlankLines:
46
49
  Enabled: true
47
50
 
@@ -100,10 +103,10 @@ Naming/ConstantName:
100
103
 
101
104
  Naming/ClassAndModuleCamelCase:
102
105
  Enabled: false
103
-
106
+
104
107
  Naming/UncommunicativeBlockParamName:
105
108
  Enabled: true
106
-
109
+
107
110
  Naming/UncommunicativeMethodParamName:
108
111
  Enabled: false
109
112
 
@@ -167,12 +170,15 @@ Style/InverseMethods:
167
170
  Style/Next:
168
171
  Enabled: false
169
172
 
173
+ Style/NumericLiterals:
174
+ Enabled: false
175
+
170
176
  Style/RaiseArgs:
171
177
  Enabled: true
172
178
 
173
179
  Style/RedundantReturn:
174
180
  Enabled: false
175
-
181
+
176
182
  Style/RedundantSelf:
177
183
  Enabled: true
178
184
 
@@ -181,15 +187,15 @@ Style/RegexpLiteral:
181
187
 
182
188
  Style/PercentLiteralDelimiters:
183
189
  Enabled: false
184
-
190
+
185
191
  Style/StderrPuts:
186
- Enabled: false
192
+ Enabled: false
187
193
 
188
194
  Style/StringLiterals:
189
195
  Enabled: true
190
196
 
191
197
  Style/TernaryParentheses:
192
198
  Enabled: false
193
-
199
+
194
200
  Style/UnlessElse:
195
201
  Enabled: false
data/CHANGELOG.md CHANGED
@@ -1,3 +1,8 @@
1
+ ## [0.2.16] - 2019-08-18
2
+ - Code refactoring to use string frozen magic comments (as a consequence, srl_ruby runs only on Rubies 2.3 or newer).
3
+ - Code restyling to please rubocop 0.7.40.
4
+
5
+
1
6
  ## [0.2.15] - 2019-07-02
2
7
  - Added a basic command-line and console interface for Skeem interpreter.
3
8
  - Added procedures: `display!`, `newline`, `make-list`
data/Gemfile CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  source 'https://rubygems.org'
2
4
 
3
5
  git_source(:github) { |repo_name| "https://github.com/#{repo_name}" }
data/README.md CHANGED
@@ -32,7 +32,8 @@ If you're not familiar to Scheme, the section [About Scheme](#about-scheme) cont
32
32
 
33
33
  ## Usage
34
34
  Once the gem is installed, the `skeem` executable can be used.
35
- It allows to run the interpreter from the command line.
35
+ It allows to run the interpreter from a REPL console or from the command line.
36
+ Another way to interact with the Skeem interpreter is to embed it in your Ruby code.
36
37
 
37
38
  ### Launching a REPL session
38
39
  To start a REPL (Read-Eval-Print-Loop) session, just type:
@@ -42,7 +43,7 @@ To start a REPL (Read-Eval-Print-Loop) session, just type:
42
43
 
43
44
  Skeem displays a greeting, a prompt and then waits for your input:
44
45
  ```
45
- Welcome to Skeem 0.2.15.
46
+ Welcome to Skeem 0.2.16.
46
47
  >
47
48
  ```
48
49
 
data/Rakefile CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'bundler/gem_tasks'
2
4
  require 'rspec/core/rake_task'
3
5
 
data/appveyor.yml CHANGED
@@ -1,17 +1,16 @@
1
1
  version: '{build}'
2
- max_jobs: 3
2
+ max_jobs: 5
3
3
  environment:
4
4
  matrix:
5
+ - Ruby_version: 26-x64
5
6
  - Ruby_version: 25-x64
6
7
  - Ruby_version: 24-x64
7
8
  - Ruby_version: 23-x64
9
+ - Ruby_version: 26
8
10
  - Ruby_version: 25
9
11
  - Ruby_version: 24
10
12
  - Ruby_version: 23
11
13
 
12
- # These are failing
13
- # - Ruby_version: 26
14
- # - Ruby_version: 26-x64
15
14
 
16
15
  install:
17
16
  - set PATH=C:\Ruby%Ruby_version%\bin;%PATH%
data/bin/skeem CHANGED
@@ -1,20 +1,22 @@
1
1
  #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
2
3
 
3
4
  require 'skeem'
4
5
 
5
6
  class SkeemREPL
6
7
  attr_reader :interpreter
7
8
 
8
- def initialize()
9
+ def initialize
9
10
  @interpreter = Skeem::Interpreter.new
10
11
  end
11
12
 
12
13
  def run_session
13
- puts "Welcome to Skeem #{Skeem::VERSION}."
14
+ puts "Welcome to Skeem #{Skeem::VERSION}."
14
15
  loop do
15
16
  print '> '
16
17
  input = gets.chomp.strip
17
- break if input == '(quit)' || input == '(exit)'
18
+ break if %w[(quit) (exit)].include?(input)
19
+
18
20
  process_input(input)
19
21
  end
20
22
  end
@@ -22,15 +24,13 @@ class SkeemREPL
22
24
  def run_file(aFilename)
23
25
  if File.exist?(aFilename)
24
26
  valid_fname = aFilename
25
- else # Retry by adding extension...
26
- if File.extname(aFilename).empty?
27
- if File.exist?(aFilename + '.skm')
28
- valid_fname = aFilename + '.skm'
29
- elsif File.exist?(aFilename + '.scm')
30
- valid_fname = aFilename + '.scm'
31
- else
32
- valid_fname = nil
33
- end
27
+ elsif File.extname(aFilename).empty? # Retry by adding extension...
28
+ if File.exist?(aFilename + '.skm')
29
+ valid_fname = aFilename + '.skm'
30
+ elsif File.exist?(aFilename + '.scm')
31
+ valid_fname = aFilename + '.scm'
32
+ else
33
+ valid_fname = nil
34
34
  end
35
35
  end
36
36
 
@@ -43,8 +43,8 @@ class SkeemREPL
43
43
  def process_input(input)
44
44
  begin
45
45
  ptree = interpreter.parse(input)
46
- rescue StandardError => exc
47
- $stderr.puts exc.message
46
+ rescue StandardError => e
47
+ $stderr.puts e.message
48
48
  return
49
49
  end
50
50
 
@@ -69,4 +69,4 @@ if ARGV.empty?
69
69
  djinn.run_session
70
70
  else
71
71
  djinn.run_file(ARGV[0])
72
- end
72
+ end
data/lib/skeem.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # File: skeem.rb
2
4
  # This file acts as a jumping-off point for loading dependencies expected
3
5
  # for a Skeem client.
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require_relative 'skm_simple_datum'
2
4
  require_relative 'skm_compound_datum'
3
5
  require_relative 'skm_pair'
@@ -19,6 +21,7 @@ module Skeem
19
21
  else
20
22
  raise StandardError, aBoolean.inspect
21
23
  end
24
+ result
22
25
  end
23
26
 
24
27
  def integer(aLiteral)
@@ -32,6 +35,7 @@ module Skeem
32
35
  else
33
36
  raise StandardError, aLiteral.inspect
34
37
  end
38
+ result
35
39
  end
36
40
 
37
41
  def rational(aLiteral)
@@ -45,6 +49,7 @@ module Skeem
45
49
  else
46
50
  raise StandardError, aLiteral.inspect
47
51
  end
52
+ result
48
53
  end
49
54
 
50
55
  def real(aLiteral)
@@ -58,6 +63,7 @@ module Skeem
58
63
  else
59
64
  raise StandardError, aLiteral.inspect
60
65
  end
66
+ result
61
67
  end
62
68
 
63
69
  def char(aLiteral)
@@ -75,6 +81,7 @@ module Skeem
75
81
  else
76
82
  raise StandardError, aLiteral.inspect
77
83
  end
84
+ result
78
85
  end
79
86
 
80
87
  def string(aLiteral)
@@ -88,6 +95,7 @@ module Skeem
88
95
  else
89
96
  SkmString.create(aLiteral.to_s)
90
97
  end
98
+ result
91
99
  end
92
100
 
93
101
  def identifier(aLiteral)
@@ -101,6 +109,7 @@ module Skeem
101
109
  else
102
110
  raise StandardError, aLiteral.inspect
103
111
  end
112
+ result
104
113
  end
105
114
 
106
115
  alias symbol identifier
@@ -150,7 +159,7 @@ module Skeem
150
159
  SkmBoolean.create(aLiteral)
151
160
  when String
152
161
  parse_literal(aLiteral)
153
- when SkmPair # Special case: not a PORO literal
162
+ when SkmPair # Special case: not a PORO literal
154
163
  # One assumes that a Skeem list contains only Skeem datum objects
155
164
  SkmPair.create_from_a(aLiteral.to_a)
156
165
  when SkmUndefined
@@ -158,6 +167,7 @@ module Skeem
158
167
  else
159
168
  raise StandardError, aLiteral.inspect
160
169
  end
170
+ result
161
171
  end
162
172
 
163
173
  private
@@ -177,6 +187,5 @@ module Skeem
177
187
  string(aLiteral)
178
188
  end
179
189
  end
180
-
181
190
  end # module
182
- end # module
191
+ end # module
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Skeem
2
4
  class SkmElementVisitor
3
5
  # Link to the root element to visit
@@ -12,6 +14,7 @@ module Skeem
12
14
  # @param aRoot [SkmElement] the parse tree to visit.
13
15
  def initialize(aRoot)
14
16
  raise StandardError if aRoot.nil?
17
+
15
18
  @root = aRoot
16
19
  @subscribers = []
17
20
  end
@@ -57,7 +60,6 @@ module Skeem
57
60
  broadcast(:after_empty_list, anEmptyList)
58
61
  end
59
62
 
60
-
61
63
  def visit_pair(aPair)
62
64
  broadcast(:before_pair, aPair)
63
65
  traverse_car_cdr(aPair)
@@ -110,8 +112,9 @@ module Skeem
110
112
  def broadcast(msg, *args)
111
113
  subscribers.each do |subscr|
112
114
  next unless subscr.respond_to?(msg) || subscr.respond_to?(:accept_all)
115
+
113
116
  subscr.send(msg, runtime, *args)
114
117
  end
115
118
  end
116
119
  end # class
117
- end # module
120
+ end # module
data/lib/skeem/grammar.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # Grammar for Skeem (a subset of Scheme language)
2
4
  require 'rley' # Load the gem
3
5
 
@@ -11,7 +13,7 @@ module Skeem
11
13
  # Delimiters, separators...
12
14
  add_terminals('APOSTROPHE', 'COMMA', 'COMMA_AT_SIGN')
13
15
  add_terminals('GRAVE_ACCENT', 'LPAREN', 'RPAREN')
14
- add_terminals('PERIOD', 'ARROW')
16
+ add_terminals('PERIOD', 'UNDERSCORE', 'ARROW', 'ELLIPSIS')
15
17
  add_terminals('VECTOR_BEGIN')
16
18
 
17
19
  # Literal values...
@@ -19,9 +21,9 @@ module Skeem
19
21
  add_terminals('CHAR', 'STRING_LIT', 'IDENTIFIER')
20
22
 
21
23
  # Keywords...
22
- add_terminals('BEGIN', 'COND', 'DEFINE', 'DO', 'ELSE')
23
- add_terminals('IF', 'LAMBDA', 'LET', 'LET*')
24
- add_terminals('QUOTE', 'QUASIQUOTE', 'SET!')
24
+ add_terminals('BEGIN', 'COND', 'DEFINE', 'DEFINE-SYNTAX', 'DO')
25
+ add_terminals('ELSE', 'IF', 'INCLUDE', 'LAMBDA', 'LET', 'LET*')
26
+ add_terminals('QUOTE', 'QUASIQUOTE', 'SET!', 'SYNTAX-RULES')
25
27
  add_terminals('UNQUOTE', 'UNQUOTE-SPLICING')
26
28
 
27
29
  rule('program' => 'cmd_or_def_plus').as 'main'
@@ -33,6 +35,7 @@ module Skeem
33
35
  rule 'command' => 'expression'
34
36
  rule('definition' => 'LPAREN DEFINE IDENTIFIER expression RPAREN').as 'definition'
35
37
  rule('definition' => 'LPAREN DEFINE LPAREN IDENTIFIER def_formals RPAREN body RPAREN').as 'alt_definition'
38
+ rule('definition' => 'syntax_definition')
36
39
  rule('definition' => 'LPAREN BEGIN definition_star RPAREN').as 'definitions_within_begin'
37
40
  rule('expression' => 'IDENTIFIER').as 'variable_reference'
38
41
  rule 'expression' => 'literal'
@@ -41,8 +44,9 @@ module Skeem
41
44
  rule 'expression' => 'conditional'
42
45
  rule 'expression' => 'assignment'
43
46
  rule 'expression' => 'derived_expression'
47
+ rule 'expression' => 'includer'
44
48
  rule 'literal' => 'quotation'
45
- rule 'literal' => 'self-evaluating'
49
+ rule 'literal' => 'self-evaluating'
46
50
  rule('quotation' => 'APOSTROPHE datum').as 'quotation_short'
47
51
  rule('quotation' => 'LPAREN QUOTE datum RPAREN').as 'quotation'
48
52
  rule 'self-evaluating' => 'BOOLEAN'
@@ -64,8 +68,8 @@ module Skeem
64
68
  rule('vector' => 'VECTOR_BEGIN datum_star RPAREN').as 'vector'
65
69
  rule('datum_plus' => 'datum_plus datum').as 'multiple_datums'
66
70
  rule('datum_plus' => 'datum').as 'last_datum'
67
- rule('datum_star' => 'datum_star datum').as 'datum_star'
68
- rule('datum_star' => []).as 'no_datum_yet'
71
+ rule('datum_star' => 'datum_star datum').as 'star_default'
72
+ rule('datum_star' => []).as 'star_base' ## 'no_datum_yet'
69
73
  rule 'symbol' => 'IDENTIFIER'
70
74
  rule('procedure_call' => 'LPAREN operator RPAREN').as 'proc_call_nullary'
71
75
  rule('procedure_call' => 'LPAREN operator operand_plus RPAREN').as 'proc_call_args'
@@ -79,16 +83,17 @@ module Skeem
79
83
  rule('formals' => 'LPAREN identifier_star RPAREN').as 'fixed_arity_formals'
80
84
  rule('formals' => 'IDENTIFIER').as 'variadic_formals'
81
85
  rule('formals' => 'LPAREN identifier_plus PERIOD IDENTIFIER RPAREN').as 'dotted_formals'
82
- rule('identifier_star' => 'identifier_star IDENTIFIER').as 'identifier_star'
83
- rule('identifier_star' => []).as 'no_identifier_yet'
86
+ rule('syntax_definition' => 'LPAREN DEFINE-SYNTAX keyword transformer_spec RPAREN').as 'syntax_definition'
87
+ rule('identifier_star' => 'identifier_star IDENTIFIER').as 'star_default'
88
+ rule('identifier_star' => []).as 'star_base' ## 'no_identifier_yet'
84
89
  rule('identifier_plus' => 'identifier_plus IDENTIFIER').as 'multiple_identifiers'
85
90
  rule('identifier_plus' => 'IDENTIFIER').as 'last_identifier'
86
91
  rule('body' => 'definition_star sequence').as 'body'
87
- rule('definition_star' => 'definition_star definition').as 'definition_star'
88
- rule('definition_star' => []).as 'no_definition_yet'
92
+ rule('definition_star' => 'definition_star definition').as 'star_default'
93
+ rule('definition_star' => []).as 'star_base' ## 'no_definition_yet'
89
94
  rule('sequence' => 'command_star expression').as 'sequence'
90
- rule('command_star' => 'command_star command').as 'multiple_commands'
91
- rule('command_star' => []).as 'no_command_yet'
95
+ rule('command_star' => 'command_star command').as 'star_default'
96
+ rule('command_star' => []).as 'star_base' ## 'no_command_yet'
92
97
  rule('conditional' => 'LPAREN IF test consequent alternate RPAREN').as 'conditional'
93
98
  rule 'test' => 'expression'
94
99
  rule 'consequent' => 'expression'
@@ -101,13 +106,15 @@ module Skeem
101
106
  rule('derived_expression' => 'LPAREN COND cond_clause_plus RPAREN').as 'cond_form'
102
107
  rule('derived_expression' => 'LPAREN COND cond_clause_star LPAREN ELSE sequence RPAREN RPAREN').as 'cond_else_form'
103
108
  rule('derived_expression' => 'LPAREN LET LPAREN binding_spec_star RPAREN body RPAREN').as 'short_let_form'
109
+ # TODO: implement "named let"
110
+ rule('derived_expression' => 'LPAREN LET IDENTIFIER LPAREN binding_spec_star RPAREN body RPAREN') # .as 'named_form'
104
111
  rule('derived_expression' => 'LPAREN LET* LPAREN binding_spec_star RPAREN body RPAREN').as 'let_star_form'
105
112
 
106
- # As the R7RS grammar is too restrictive,
113
+ # As the R7RS grammar is too restrictive,
107
114
  # the next rule was made more general than its standard counterpart
108
115
  rule('derived_expression' => 'LPAREN BEGIN body RPAREN').as 'begin_expression'
109
116
  do_syntax = <<-END_SYNTAX
110
- LPAREN DO LPAREN iteration_spec_star RPAREN
117
+ LPAREN DO LPAREN iteration_spec_star RPAREN
111
118
  LPAREN test do_result RPAREN
112
119
  command_star RPAREN
113
120
  END_SYNTAX
@@ -115,25 +122,29 @@ END_SYNTAX
115
122
  rule 'derived_expression' => 'quasiquotation'
116
123
  rule('cond_clause_plus' => 'cond_clause_plus cond_clause').as 'multiple_cond_clauses'
117
124
  rule('cond_clause_plus' => 'cond_clause').as 'last_cond_clauses'
118
- rule('cond_clause_star' => 'cond_clause_star cond_clause').as 'cond_clauses_star'
119
- rule('cond_clause_star' => []).as 'last_cond_clauses_star'
125
+ rule('cond_clause_star' => 'cond_clause_star cond_clause').as 'star_default'
126
+ rule('cond_clause_star' => []).as 'star_base' ## 'last_cond_clauses_star'
120
127
  rule('cond_clause' => 'LPAREN test sequence RPAREN').as 'cond_clause'
121
128
  rule('cond_clause' => 'LPAREN test RPAREN')
122
129
  rule('cond_clause' => 'LPAREN test ARROW recipient RPAREN').as 'cond_arrow_clause'
123
130
  rule('recipient' => 'expression')
124
131
  rule('quasiquotation' => 'LPAREN QUASIQUOTE qq_template RPAREN').as 'quasiquotation'
125
132
  rule('quasiquotation' => 'GRAVE_ACCENT qq_template').as 'quasiquotation_short'
126
- rule('binding_spec_star' => 'binding_spec_star binding_spec').as 'multiple_binding_specs'
127
- rule('binding_spec_star' => []).as 'no_binding_spec_yet'
133
+ rule('binding_spec_star' => 'binding_spec_star binding_spec').as 'star_default'
134
+ rule('binding_spec_star' => []).as 'star_base' ## 'no_binding_spec_yet'
128
135
  rule('binding_spec' => 'LPAREN IDENTIFIER expression RPAREN').as 'binding_spec'
129
- rule('iteration_spec_star' => 'iteration_spec_star iteration_spec').as 'multiple_iter_specs'
130
- rule('iteration_spec_star' => []).as 'no_iter_spec_yet'
136
+ rule('iteration_spec_star' => 'iteration_spec_star iteration_spec').as 'star_default'
137
+ rule('iteration_spec_star' => []).as 'star_base' ## 'no_iter_spec_yet'
131
138
  rule('iteration_spec' => 'LPAREN IDENTIFIER init step RPAREN').as 'iteration_spec_long'
132
139
  rule('iteration_spec' => 'LPAREN IDENTIFIER init RPAREN').as 'iteration_spec_short'
133
140
  rule('init' => 'expression')
134
141
  rule('step' => 'expression')
135
142
  rule 'do_result' => 'sequence'
136
- rule('do_result' => []).as 'empty_do_result'
143
+ rule('do_result' => []).as 'star_base' ## 'empty_do_result'
144
+ rule('keyword' => 'IDENTIFIER')
145
+ rule('includer' => 'LPAREN INCLUDE string_plus RPAREN').as 'include'
146
+ rule('string_plus' => 'string_plus STRING_LIT').as 'multiple_string'
147
+ rule('string_plus' => 'STRING_LIT').as 'last_single_string'
137
148
  rule 'qq_template' => 'simple_datum'
138
149
  rule 'qq_template' => 'list_qq_template'
139
150
  rule 'qq_template' => 'vector_qq_template'
@@ -144,14 +155,65 @@ END_SYNTAX
144
155
  rule('vector_qq_template' => 'VECTOR_BEGIN qq_template_or_splice_star RPAREN').as 'vector_qq'
145
156
  rule('unquotation' => 'COMMA qq_template').as 'unquotation_short'
146
157
  rule 'unquotation' => 'LPAREN UNQUOTE qq_template RPAREN'
147
- rule('qq_template_or_splice_star' => 'qq_template_or_splice_star qq_template_or_splice').as 'multiple_template_splice'
148
- rule('qq_template_or_splice_star' => []).as 'no_template_splice_yet'
158
+ rule('qq_template_or_splice_star' => 'qq_template_or_splice_star qq_template_or_splice').as 'star_default'
159
+ rule('qq_template_or_splice_star' => []).as 'star_base' ## 'no_template_splice_yet'
149
160
  rule 'qq_template_or_splice_plus' => 'qq_template_or_splice_plus qq_template_or_splice'
150
161
  rule 'qq_template_or_splice_plus' => 'qq_template_or_splice'
151
162
  rule 'qq_template_or_splice' => 'qq_template'
152
163
  rule 'qq_template_or_splice' => 'splicing_unquotation'
153
164
  rule 'splicing_unquotation' => 'COMMA_AT_SIGN qq_template'
154
165
  rule 'splicing_unquotation' => 'LPAREN UNQUOTE-SPLICING qq_template RPAREN'
166
+ rule('transformer_spec' => 'LPAREN SYNTAX-RULES LPAREN identifier_star RPAREN syntax_rule_star RPAREN').as 'transformer_syntax'
167
+ rule('transformer_spec' => 'LPAREN SYNTAX-RULES IDENTIFIER LPAREN identifier_star RPAREN syntax_rule_star RPAREN')
168
+ rule('syntax_rule_star' => 'syntax_rule_star syntax_rule').as 'star_default'
169
+ rule('syntax_rule_star' => []).as 'star_base'
170
+ rule('syntax_rule' => 'LPAREN pattern template RPAREN').as 'syntax_rule'
171
+ rule('pattern' => 'pattern_identifier')
172
+ rule('pattern' => 'UNDERSCORE')
173
+ rule('pattern' => 'LPAREN pattern_star RPAREN')
174
+ rule('pattern' => 'LPAREN pattern_plus PERIOD pattern RPAREN')
175
+ rule('pattern' => 'LPAREN pattern_plus ELLIPSIS pattern_star RPAREN')
176
+ rule('pattern' => 'LPAREN pattern_plus ELLIPSIS pattern_star PERIOD pattern RPAREN')
177
+ rule('pattern' => 'VECTOR_BEGIN pattern_star RPAREN')
178
+ rule('pattern' => 'VECTOR_BEGIN pattern_plus ELLIPSIS pattern_star RPAREN')
179
+ rule('pattern' => 'pattern_datum')
180
+ rule('pattern_star' => 'pattern_star pattern').as 'star_default'
181
+ rule('pattern_star' => []).as 'star_base'
182
+ rule('pattern_plus' => 'pattern_plus pattern')
183
+ rule('pattern_plus' => 'pattern')
184
+ rule('pattern_datum' => 'STRING_LIT')
185
+ rule('pattern_datum' => 'CHAR')
186
+ rule('pattern_datum' => 'BOOLEAN')
187
+ rule('pattern_datum' => 'number')
188
+ # rule('pattern_datum' => 'bytevector')
189
+ rule('template' => 'pattern_identifier')
190
+ rule('template' => 'LPAREN template_element_star RPAREN')
191
+ rule('template' => 'LPAREN template_element_plus PERIOD template RPAREN')
192
+ rule('template' => 'VECTOR_BEGIN template_element_star RPAREN')
193
+ rule('template' => 'template_datum')
194
+ rule('template_element_star' => 'template_element_star template_element').as 'star_default'
195
+ rule('template_element_star' => []).as 'star_base'
196
+ rule('template_element_plus' => 'template_element_plus template_element')
197
+ rule('template_element_plus' => 'template_element')
198
+ rule('template_element' => 'template')
199
+ rule('template_element' => 'template ELLIPSIS')
200
+ rule('template_datum' => 'pattern_datum')
201
+ rule('pattern_identifier' => 'IDENTIFIER')
202
+ # Ugly: specailized production rule per keyword...
203
+ rule('pattern_identifier' => 'BEGIN')
204
+ rule('pattern_identifier' => 'COND')
205
+ rule('pattern_identifier' => 'DEFINE')
206
+ rule('pattern_identifier' => 'ELSE')
207
+ rule('pattern_identifier' => 'IF')
208
+ rule('pattern_identifier' => 'INCLUDE')
209
+ rule('pattern_identifier' => 'LAMBDA')
210
+ rule('pattern_identifier' => 'LET')
211
+ rule('pattern_identifier' => 'LET*')
212
+ rule('pattern_identifier' => 'QUOTE')
213
+ rule('pattern_identifier' => 'QUASIQUOTE')
214
+ rule('pattern_identifier' => 'SET!')
215
+ rule('pattern_identifier' => 'UNQUOTE')
216
+ rule('pattern_identifier' => 'UNQUOTE-SPLICING')
155
217
  end
156
218
 
157
219
  # And now build the grammar and make it accessible via a global constant