skeem 0.2.16 → 0.2.20

Sign up to get free protection for your applications and to get access to all the features.
@@ -16,8 +16,13 @@ module Skeem
16
16
  # Delimiters: parentheses '(', ')'
17
17
  # Separators: comma
18
18
  class Tokenizer
19
+ # @return [StringScanner]
19
20
  attr_reader(:scanner)
21
+
22
+ # @return [Integer] Current line number
20
23
  attr_reader(:lineno)
24
+
25
+ # @return [Integer] Offset of start of current line
21
26
  attr_reader(:line_start)
22
27
 
23
28
  @@lexeme2name = {
@@ -53,7 +58,7 @@ module Skeem
53
58
  SYNTAX-RULES
54
59
  UNQUOTE
55
60
  UNQUOTE-SPLICING
56
- ].map { |x| [x, x] } .to_h
61
+ ].map { |x| [x, x.sub(/\*$/, '_STAR')] }.to_h
57
62
 
58
63
  class ScanError < StandardError; end
59
64
 
@@ -84,6 +89,8 @@ module Skeem
84
89
 
85
90
  private
86
91
 
92
+ # rubocop: disable Lint/DuplicateBranch
93
+
87
94
  def _next_token
88
95
  skip_intertoken_spaces
89
96
  curr_ch = scanner.peek(1)
@@ -109,7 +116,7 @@ module Skeem
109
116
  elsif (lexeme = scanner.scan(/[+-]?[0-9]+(?:\.[0-9]*)?(?:(?:e|E)[+-]?[0-9]+)?/))
110
117
  # Order dependency: must be tested after INTEGER case
111
118
  token = build_token('REAL', lexeme)
112
- elsif (lexeme = scanner.scan(/#(?:(?:true)|(?:false)|(?:u8)|[\\\(tfeiodx]|(?:\d+[=#]))/))
119
+ elsif (lexeme = scanner.scan(/#(?:(?:true)|(?:false)|(?:u8)|[\\(tfeiodx]|(?:\d+[=#]))/))
113
120
  token = cardinal_token(lexeme)
114
121
  elsif (lexeme = scanner.scan(/"(?:\\"|[^"])*"/)) # Double quotes literal?
115
122
  token = build_token('STRING_LIT', lexeme)
@@ -119,7 +126,7 @@ module Skeem
119
126
  token = build_token(tok_type, lexeme)
120
127
  elsif (lexeme = scanner.scan(/\|(?:[^|])*\|/)) # Vertical bar delimited
121
128
  token = build_token('IDENTIFIER', lexeme)
122
- elsif (lexeme = scanner.scan(/([\+\-])((?=\s|[|()";])|$)/))
129
+ elsif (lexeme = scanner.scan(/([+\-])((?=\s|[|()";])|$)/))
123
130
  # # R7RS peculiar identifiers case 1: isolated plus and minus as identifiers
124
131
  token = build_token('IDENTIFIER', lexeme)
125
132
  elsif (lexeme = scanner.scan(/[+-][a-zA-Z!$%&*\/:<=>?@^_~+-@][a-zA-Z0-9!$%&*+-.\/:<=>?@^_~+-]*/))
@@ -138,6 +145,8 @@ module Skeem
138
145
  return token
139
146
  end
140
147
 
148
+ # rubocop: enable Lint/DuplicateBranch
149
+
141
150
  =begin
142
151
  #u8( This introduces a bytevector constant (section 6.9).
143
152
  Bytevector constants are terminated by ) .
@@ -162,11 +171,10 @@ other literal data (section 2.4).
162
171
  if (lexeme = scanner.scan(/#\\/))
163
172
  if (lexeme = scanner.scan(/(?:alarm|backspace|delete|escape|newline|null|return|space|tab)/))
164
173
  token = build_token('CHAR', lexeme, :name)
165
- elsif (lexeme = scanner.scan(/[^x]/))
166
- token = build_token('CHAR', lexeme, :escaped)
167
174
  elsif (lexeme = scanner.scan(/x[0-9a-fA-F]+/))
168
175
  token = build_token('CHAR', lexeme, :hex_value)
169
- elsif (lexeme = scanner.scan(/x/))
176
+ else
177
+ lexeme = scanner.getch
170
178
  token = build_token('CHAR', lexeme, :escaped)
171
179
  end
172
180
  end
@@ -352,7 +360,6 @@ other literal data (section 2.4).
352
360
  end
353
361
 
354
362
  def skip_block_comment
355
- # require 'debug'
356
363
  scanner.skip(/#\|/)
357
364
  nesting_level = 1
358
365
  loop do
data/lib/skeem/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Skeem
4
- VERSION = '0.2.16'
4
+ VERSION = '0.2.20'
5
5
  end
data/skeem.gemspec CHANGED
@@ -10,6 +10,7 @@ module PkgExtending
10
10
  file_list = Dir[
11
11
  '.rubocop.yml',
12
12
  '.rspec',
13
+ '.travis.yml',
13
14
  '.yardopts',
14
15
  'appveyor.yml',
15
16
  'Gemfile',
@@ -23,7 +24,8 @@ module PkgExtending
23
24
  'lib/**/*.rb',
24
25
  'lib/**/*.skm',
25
26
  'spec/**/*.rb',
26
- 'spec/**/*.skm'
27
+ 'spec/**/*.skm',
28
+ 'spec/**/*.yml'
27
29
  ]
28
30
  aPackage.files = file_list
29
31
  aPackage.test_files = Dir['spec/**/*_spec.rb']
@@ -52,7 +54,7 @@ DESCR
52
54
  SUMMARY
53
55
  spec.homepage = 'https://github.com/famished-tiger/Skeem'
54
56
  spec.license = 'MIT'
55
- spec.required_ruby_version = '>= 2.3.0'
57
+ spec.required_ruby_version = '>= 2.5.0'
56
58
 
57
59
  spec.bindir = 'bin'
58
60
  spec.executables << 'skeem'
@@ -60,12 +62,10 @@ SUMMARY
60
62
  PkgExtending.pkg_files(spec)
61
63
  PkgExtending.pkg_documentation(spec)
62
64
  # Runtime dependencies
63
- spec.add_dependency 'rley', '~> 0.7'
65
+ spec.add_dependency 'rley', '~> 0.8.08'
64
66
 
65
67
  # Development dependencies
66
68
  spec.add_development_dependency 'bundler', '~> 2.0'
67
69
  spec.add_development_dependency 'rake', '~> 12.0'
68
70
  spec.add_development_dependency 'rspec', '~> 3.0'
69
-
70
-
71
71
  end
@@ -12,7 +12,9 @@ module Skeem
12
12
  let(:simple_datum) { integer 42 }
13
13
  let(:listener) do
14
14
  fake = double('fake-subscriber')
15
- fake.define_singleton_method(:accept_all) {}
15
+ fake.define_singleton_method(:accept_all) do
16
+ # Dummy block
17
+ end
16
18
  fake
17
19
  end
18
20
 
@@ -16,7 +16,7 @@ module Skeem
16
16
  end
17
17
 
18
18
  it 'could be initialized with a block argument' do
19
- expect { Interpreter.new { |interp| } }.not_to raise_error
19
+ expect { Interpreter.new(&:runtime) }.not_to raise_error
20
20
  end
21
21
 
22
22
  it 'should have a parser' do
@@ -67,6 +67,7 @@ module Skeem
67
67
  end
68
68
  end
69
69
 
70
+ # rubocop: disable Style/ExponentialNotation
70
71
  it 'should evaluate isolated real numbers' do
71
72
  samples = [
72
73
  ['0.0', 0.0],
@@ -80,6 +81,7 @@ module Skeem
80
81
  expect(result).to eq(predicted)
81
82
  end
82
83
  end
84
+ # rubocop: enable Style/ExponentialNotation
83
85
 
84
86
  it 'should evaluate isolated strings' do
85
87
  samples = [
@@ -31,7 +31,7 @@ SKEEM
31
31
 
32
32
  context 'Defining compound procedures:' do
33
33
  it 'should accept the definition of simple procedure with arity 1' do
34
- source = definition_set + "\n" + 'square'
34
+ source = "#{definition_set}\nsquare"
35
35
  result = subject.run(source)
36
36
 
37
37
  square = result.last
@@ -41,7 +41,7 @@ SKEEM
41
41
  end
42
42
 
43
43
  it 'should accept the definition of simple procedure with arity 2' do
44
- source = definition_set + "\n" + 'sum-of-squares'
44
+ source = "#{definition_set}\nsum-of-squares"
45
45
  result = subject.run(source)
46
46
 
47
47
  square = result.last
@@ -65,14 +65,14 @@ SKEEM
65
65
  end
66
66
 
67
67
  it 'should support the call to a simple procedure with arity 2' do
68
- source = definition_set + "\n" + '(sum-of-squares 3 4)'
68
+ source = "#{definition_set}\n(sum-of-squares 3 4)"
69
69
  result = subject.run(source)
70
70
 
71
71
  expect(result.last).to eq(25)
72
72
  end
73
73
 
74
74
  it 'should support the call to a nested lambda procedure' do
75
- source = definition_set + "\n" + '(f 5)'
75
+ source = "#{definition_set}\n(f 5)"
76
76
  result = subject.run(source)
77
77
 
78
78
  expect(result.last).to eq(136)
@@ -45,6 +45,7 @@ module Skeem
45
45
  end
46
46
  end
47
47
 
48
+ # rubocop: disable Style/ExponentialNotation
48
49
  it 'should parse isolated real numbers' do
49
50
  samples = [
50
51
  ['0.0', 0.0],
@@ -59,6 +60,7 @@ module Skeem
59
60
  expect(ptree.root.value).to eq(predicted)
60
61
  end
61
62
  end
63
+ # rubocop: enable Style/ExponentialNotation
62
64
 
63
65
  it 'should parse isolated strings' do
64
66
  samples = [
@@ -654,8 +654,8 @@ SKEEM
654
654
  ["(append '(a b) '(c d))", array2list_ids(%w[a b c d])],
655
655
  ["(append '(a b) '(c) 'd)", array2list_ids(%w[a b c d])],
656
656
  ["(append '(a (b)) '((c)))", [SkmIdentifier.create('a'),
657
- SkmPair.create_from_a(array2list_ids(['b'])),
658
- SkmPair.create_from_a(array2list_ids(['c']))]],
657
+ SkmPair.create_from_a(array2list_ids(['b'])),
658
+ SkmPair.create_from_a(array2list_ids(['c']))]],
659
659
  ["(append '() 'a)", SkmIdentifier.create('a')]
660
660
  ]
661
661
  compare_to_predicted(checks) do |result, expectation|
@@ -919,8 +919,8 @@ SKEEM
919
919
  result = subject.run(source)
920
920
  expect(result).to be_kind_of(SkmVector)
921
921
  expectation = [SkmInteger.create(0),
922
- SkmPair.new(SkmString.create('Sue'), SkmPair.new(SkmString.create('Sue'), SkmEmptyList.instance)),
923
- SkmString.create('Anna')]
922
+ SkmPair.new(SkmString.create('Sue'), SkmPair.new(SkmString.create('Sue'), SkmEmptyList.instance)),
923
+ SkmString.create('Anna')]
924
924
  expect(result).to eq(expectation)
925
925
 
926
926
  source = <<-SKEEM
@@ -1010,7 +1010,7 @@ SKEEM
1010
1010
  err = StandardError
1011
1011
  msg1 = 'Error: assertion failed on line 3, column 4'
1012
1012
  msg2 = 'with <Skeem::SkmBoolean: false>'
1013
- expect { subject.run(source) }.to raise_error(err, msg1 + ', ' + msg2)
1013
+ expect { subject.run(source) }.to raise_error(err, "#{msg1}, #{msg2}")
1014
1014
  end
1015
1015
  end # context
1016
1016
  end # describe
@@ -149,7 +149,7 @@ module Skeem
149
149
  expect(pproc.call(rtime, no_arg)).to eq(0)
150
150
 
151
151
  many = [SkmString.create('foo'), SkmString.create('bar'),
152
- SkmString.create('quux')]
152
+ SkmString.create('quux')]
153
153
  expect(pproc.call(rtime, many)).to eq(3)
154
154
  end
155
155
  end # context
@@ -96,11 +96,11 @@ module Skeem
96
96
 
97
97
  it 'should push a call to the stack call' do
98
98
  expect { subject.push_call(sample_call) }.not_to raise_error
99
- expect(subject.call_stack.size). to eq(1)
99
+ expect(subject.call_stack.size).to eq(1)
100
100
  expect(subject.caller).to eq(sample_call)
101
101
 
102
102
  subject.push_call(sample_call.clone)
103
- expect(subject.call_stack.size). to eq(2)
103
+ expect(subject.call_stack.size).to eq(2)
104
104
  end
105
105
 
106
106
  it 'should pop a call from the call stack' do
@@ -50,7 +50,7 @@ module Skeem
50
50
  it 'should return its text representation' do
51
51
  txt1 = '<Skeem::SkmCompoundDatum: <Skeem::SkmInteger: 1>,'
52
52
  txt2 = '<Skeem::SkmInteger: 2>, <Skeem::SkmInteger: 3>>'
53
- expect(subject.inspect).to eq(txt1 + ' ' + txt2)
53
+ expect(subject.inspect).to eq("#{txt1} #{txt2}")
54
54
  end
55
55
  end # context
56
56
 
@@ -37,7 +37,7 @@ module Skeem
37
37
 
38
38
  context 'Provided services:' do
39
39
  let(:runtime) { Runtime.new(SkmFrame.new) }
40
- let(:list_length_2) { SkmPair.new(integer(10), subject) }
40
+ let(:list_length2) { SkmPair.new(integer(10), subject) }
41
41
  let(:quirk_element) { double('three') }
42
42
  let(:quirk_members) { [integer(10), quirk_element] }
43
43
 
@@ -71,7 +71,7 @@ module Skeem
71
71
  expect(subject.length).to eq(1)
72
72
 
73
73
  # Use a list of length 2
74
- expect(list_length_2.length).to eq(2)
74
+ expect(list_length2.length).to eq(2)
75
75
  end
76
76
 
77
77
  it 'should respond false to `eqv?` message' do
@@ -113,7 +113,7 @@ module Skeem
113
113
  expect(subject.to_a).to eq([sample_car])
114
114
 
115
115
  # Use a list of length 2
116
- expect(list_length_2.to_a).to eq([integer(10), sample_car])
116
+ expect(list_length2.to_a).to eq([integer(10), sample_car])
117
117
  end
118
118
 
119
119
  it 'should return the last pair of a proper list' do
@@ -133,7 +133,7 @@ module Skeem
133
133
 
134
134
  it 'should return the last element of a list' do
135
135
  expect(subject.last).to eq(sample_car)
136
- expect(list_length_2.last).to eq(sample_car)
136
+ expect(list_length2.last).to eq(sample_car)
137
137
  end
138
138
 
139
139
  it 'should append a new element to a list' do
@@ -227,7 +227,7 @@ module Skeem
227
227
  expect(subject.inspect).to eq(predicted)
228
228
 
229
229
  predicted = '<Skeem::SkmPair: <Skeem::SkmInteger: 10>, <Skeem::SkmInteger: 3>>'
230
- expect(list_length_2.inspect).to eq(predicted)
230
+ expect(list_length2.inspect).to eq(predicted)
231
231
  end
232
232
  end # context
233
233
  end # describe
@@ -47,8 +47,8 @@ module Skeem
47
47
  tokens.each { |token| expect(token).to be_kind_of(Rley::Lexical::Token) }
48
48
  terminals = tokens.map(&:terminal)
49
49
  prediction = %w[LPAREN RPAREN APOSTROPHE
50
- GRAVE_ACCENT PERIOD
51
- COMMA COMMA_AT_SIGN ]
50
+ GRAVE_ACCENT PERIOD
51
+ COMMA COMMA_AT_SIGN ]
52
52
  expect(terminals).to eq(prediction)
53
53
  end
54
54
  end # context
@@ -129,6 +129,7 @@ module Skeem
129
129
  end # context
130
130
 
131
131
  context 'Real number recognition:' do
132
+ # rubocop: disable Style/ExponentialNotation
132
133
  it 'should tokenize real numbers' do
133
134
  tests = [
134
135
  # couple [raw input, expected]
@@ -140,6 +141,7 @@ module Skeem
140
141
 
141
142
  check_tokens(tests, 'REAL')
142
143
  end
144
+ # rubocop: enable Style/ExponentialNotation
143
145
  end # context
144
146
 
145
147
  context 'Character literal recognition:' do
data/spec/spec_helper.rb CHANGED
@@ -17,26 +17,29 @@ RSpec.configure do |config|
17
17
  config.full_backtrace = true
18
18
  end
19
19
 
20
+
20
21
  module InterpreterSpec
21
22
  def expect_expr(aSkeemExpr)
22
23
  result = subject.run(aSkeemExpr)
23
24
  expect(result)
24
25
  end
25
26
 
27
+ # rubocop: disable Lint/RescueException
28
+
26
29
  # This method assumes that 'subject' is a Skeem::Interpreter instance.
27
30
  def compare_to_predicted(arrActualsPredictions)
28
31
  arrActualsPredictions.each_with_index do |(source, predicted), index|
29
- begin
30
- result = subject.run(source)
31
- if block_given?
32
- yield result, predicted
33
- else
34
- expect(result).to eq(predicted)
35
- end
36
- rescue Exception => e
37
- $stderr.puts "Row #{index + 1} failed."
38
- throw e
32
+ result = subject.run(source)
33
+ if block_given?
34
+ yield result, predicted
35
+ else
36
+ expect(result).to eq(predicted)
39
37
  end
38
+
39
+ rescue Exception => e
40
+ $stderr.puts "Row #{index + 1} failed."
41
+ throw e
40
42
  end
41
43
  end
44
+ # rubocop: enable Lint/RescueException
42
45
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: skeem
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.16
4
+ version: 0.2.20
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dimitri Geshef
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-08-18 00:00:00.000000000 Z
11
+ date: 2021-11-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rley
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '0.7'
19
+ version: 0.8.08
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: '0.7'
26
+ version: 0.8.08
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: bundler
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -77,6 +77,7 @@ extra_rdoc_files:
77
77
  files:
78
78
  - ".rspec"
79
79
  - ".rubocop.yml"
80
+ - ".travis.yml"
80
81
  - ".yardopts"
81
82
  - CHANGELOG.md
82
83
  - Gemfile
@@ -139,7 +140,7 @@ homepage: https://github.com/famished-tiger/Skeem
139
140
  licenses:
140
141
  - MIT
141
142
  metadata: {}
142
- post_install_message:
143
+ post_install_message:
143
144
  rdoc_options:
144
145
  - --charset=UTF-8 --exclude="examples|spec"
145
146
  require_paths:
@@ -148,15 +149,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
148
149
  requirements:
149
150
  - - ">="
150
151
  - !ruby/object:Gem::Version
151
- version: 2.3.0
152
+ version: 2.5.0
152
153
  required_rubygems_version: !ruby/object:Gem::Requirement
153
154
  requirements:
154
155
  - - ">="
155
156
  - !ruby/object:Gem::Version
156
157
  version: '0'
157
158
  requirements: []
158
- rubygems_version: 3.0.3
159
- signing_key:
159
+ rubygems_version: 3.1.4
160
+ signing_key:
160
161
  specification_version: 4
161
162
  summary: Skeem is an interpreter of a subset of the Scheme programming language. Scheme
162
163
  is a descendent of the Lisp language.