skeem 0.0.4 → 0.0.5
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +7 -0
- data/lib/skeem/grammar.rb +2 -0
- data/lib/skeem/parser.rb +6 -2
- data/lib/skeem/{node_builder.rb → s_expr_builder.rb} +10 -18
- data/lib/skeem/s_expr_nodes.rb +13 -1
- data/lib/skeem/tokenizer.rb +5 -4
- data/lib/skeem/version.rb +1 -1
- data/spec/skeem/parser_spec.rb +72 -4
- data/spec/skeem/tokenizer_spec.rb +2 -2
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e25bd8499926a963c98886effec8d51eb78bb441
|
4
|
+
data.tar.gz: fd5e2e65ceffbe1ce202ab1d620645d74a2e03f7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 181ac16e0465292fc39a1ac157e313348afcb36d83243922b7539969a3e506dbbc0e2f97d78cf41f7bcb4a728dd43d1f78477ec8ca3a468841298f61ca51c2ca
|
7
|
+
data.tar.gz: 8c6a36fd38ebcc92a4f208bba5be6ac9f11423a1cfb405970f40bbf141f4c70dc1fa74279365d9d6277ef68b15bf6ff40bd2903eab6c865a246b25ab1e121dbc
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,10 @@
|
|
1
|
+
## [0.0.5] - 2018-08-30
|
2
|
+
Parser now generates correct parse trees for expressions consisting of a single literal.
|
3
|
+
|
4
|
+
### Fixed
|
5
|
+
- Class`Tokenizer` The regexp for real numbers was too restricitive: it didn't recognize real numbers without fractional part.
|
6
|
+
|
7
|
+
|
1
8
|
## [0.0.4] - 2018-08-29
|
2
9
|
### Added
|
3
10
|
- File `s_expr_nodes.rb` with initial implementation of `SExprTerminalNode` classes.
|
data/lib/skeem/grammar.rb
CHANGED
@@ -24,7 +24,9 @@ module Skeem
|
|
24
24
|
rule 'program' => 'cmd_or_def_plus'
|
25
25
|
rule 'cmd_or_def_plus' => 'cmd_or_def_plus cmd_or_def'
|
26
26
|
rule 'cmd_or_def_plus' => 'cmd_or_def'
|
27
|
+
rule 'cmd_or_def' => 'command'
|
27
28
|
rule 'cmd_or_def' => 'definition'
|
29
|
+
rule 'command' => 'expression'
|
28
30
|
rule 'definition' => 'LPAREN DEFINE IDENTIFIER expression RPAREN'
|
29
31
|
rule 'expression' => 'IDENTIFIER'
|
30
32
|
rule 'expression' => 'literal'
|
data/lib/skeem/parser.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
require_relative 'tokenizer'
|
2
2
|
require_relative 'grammar'
|
3
|
+
require_relative 's_expr_builder'
|
3
4
|
|
4
5
|
module Skeem
|
5
6
|
class Parser
|
@@ -7,7 +8,10 @@ module Skeem
|
|
7
8
|
|
8
9
|
def initialize()
|
9
10
|
# Create a Rley facade object
|
10
|
-
@engine = Rley::Engine.new
|
11
|
+
@engine = Rley::Engine.new do |cfg|
|
12
|
+
cfg.diagnose = true
|
13
|
+
cfg.repr_builder = SExprBuilder
|
14
|
+
end
|
11
15
|
|
12
16
|
# Step 1. Load Skeem grammar
|
13
17
|
@engine.use_grammar(Skeem::Grammar)
|
@@ -30,7 +34,7 @@ module Skeem
|
|
30
34
|
raise StandardError, line1 + line2
|
31
35
|
end
|
32
36
|
|
33
|
-
return result
|
37
|
+
return engine.to_ptree(result)
|
34
38
|
end
|
35
39
|
end # class
|
36
40
|
end # module
|
@@ -1,7 +1,7 @@
|
|
1
1
|
require 'stringio'
|
2
|
-
require_relative '
|
2
|
+
require_relative 's_expr_nodes'
|
3
3
|
|
4
|
-
module
|
4
|
+
module Skeem
|
5
5
|
# The purpose of a ASTBuilder is to build piece by piece an AST
|
6
6
|
# (Abstract Syntax Tree) from a sequence of input tokens and
|
7
7
|
# visit events produced by walking over a GFGParsing object.
|
@@ -9,8 +9,14 @@ module SrlRuby
|
|
9
9
|
# The Builder pattern creates a complex object
|
10
10
|
# (say, a parse tree) from simpler objects (terminal and non-terminal
|
11
11
|
# nodes) and using a step by step approach.
|
12
|
-
class
|
13
|
-
Terminal2NodeClass = {
|
12
|
+
class SExprBuilder < Rley::ParseRep::ASTBaseBuilder
|
13
|
+
Terminal2NodeClass = {
|
14
|
+
'BOOLEAN' => SExprBooleanNode,
|
15
|
+
'IDENTIFIER' => SExprIdentifierNode,
|
16
|
+
'INTEGER' => SExprIntegerNode,
|
17
|
+
'REAL' => SExprRealNode,
|
18
|
+
'STRING_LIT' => SExprStringNode
|
19
|
+
}.freeze
|
14
20
|
|
15
21
|
# Create a new AST builder instance.
|
16
22
|
# @param theTokens [Array<Token>] The sequence of input tokens.
|
@@ -28,20 +34,6 @@ module SrlRuby
|
|
28
34
|
def terminal2node
|
29
35
|
Terminal2NodeClass
|
30
36
|
end
|
31
|
-
|
32
|
-
|
33
|
-
# Overriding method.
|
34
|
-
# Factory method for creating a node object for the given
|
35
|
-
# input token.
|
36
|
-
# @param _production [Rley::Syntax::Production]
|
37
|
-
# @param _terminal [Rley::Syntax::Terminal] Terminal symbol associated with the token
|
38
|
-
# @param aTokenPosition [Integer] Position of token in the input stream
|
39
|
-
# @param aToken [Rley::Lexical::Token] The input token
|
40
|
-
def new_leaf_node(_production, _terminal, aTokenPosition, aToken)
|
41
|
-
node = Rley::PTree::TerminalNode.new(aToken, aTokenPosition)
|
42
|
-
|
43
|
-
return node
|
44
|
-
end
|
45
37
|
end # class
|
46
38
|
end # module
|
47
39
|
# End of file
|
data/lib/skeem/s_expr_nodes.rb
CHANGED
@@ -13,7 +13,7 @@ module Skeem
|
|
13
13
|
|
14
14
|
# This method can be overriden
|
15
15
|
def init_value(aValue)
|
16
|
-
self.value = aValue
|
16
|
+
self.value = aValue
|
17
17
|
end
|
18
18
|
|
19
19
|
def symbol()
|
@@ -39,6 +39,7 @@ module Skeem
|
|
39
39
|
end # class
|
40
40
|
|
41
41
|
class SExprNumberNode < SExprTerminalNode
|
42
|
+
end # class
|
42
43
|
|
43
44
|
class SExprRealNode < SExprNumberNode
|
44
45
|
end # class
|
@@ -47,6 +48,17 @@ module Skeem
|
|
47
48
|
end # class
|
48
49
|
|
49
50
|
class SExprStringNode < SExprTerminalNode
|
51
|
+
# Override
|
52
|
+
def init_value(aValue)
|
53
|
+
self.value = aValue.dup
|
54
|
+
end
|
55
|
+
end # class
|
56
|
+
|
57
|
+
class SExprIdentifierNode < SExprTerminalNode
|
58
|
+
# Override
|
59
|
+
def init_value(aValue)
|
60
|
+
self.value = aValue.dup
|
61
|
+
end
|
50
62
|
end # class
|
51
63
|
|
52
64
|
=begin
|
data/lib/skeem/tokenizer.rb
CHANGED
@@ -77,7 +77,8 @@ module Skeem
|
|
77
77
|
token = build_token('BOOLEAN', lexeme)
|
78
78
|
elsif (lexeme = scanner.scan(/[+-]?[0-9]+(?=\s|[|()";]|$)/))
|
79
79
|
token = build_token('INTEGER', lexeme) # Decimal radix
|
80
|
-
elsif (lexeme = scanner.scan(/[+-]?[0-9]
|
80
|
+
elsif (lexeme = scanner.scan(/[+-]?[0-9]+(?:\.[0-9]+)?(?:(?:e|E)[+-]?[0-9]+)?/))
|
81
|
+
# Order dependency: must be tested after INTEGER case
|
81
82
|
token = build_token('REAL', lexeme)
|
82
83
|
elsif (lexeme = scanner.scan(/"(?:\\"|[^"])*"/)) # Double quotes literal?
|
83
84
|
token = build_token('STRING_LIT', lexeme)
|
@@ -130,8 +131,8 @@ module Skeem
|
|
130
131
|
value = to_real(aLexeme, aFormat)
|
131
132
|
when 'STRING_LIT'
|
132
133
|
value = to_string(aLexeme, aFormat)
|
133
|
-
when '
|
134
|
-
value =
|
134
|
+
when 'IDENTIFIER'
|
135
|
+
value = to_identifier(aLexeme, aFormat)
|
135
136
|
else
|
136
137
|
value = aLexeme
|
137
138
|
end
|
@@ -170,7 +171,7 @@ module Skeem
|
|
170
171
|
return value
|
171
172
|
end
|
172
173
|
|
173
|
-
def
|
174
|
+
def to_identifier(aLexeme, aFormat)
|
174
175
|
case aFormat
|
175
176
|
when :default
|
176
177
|
value = aLexeme
|
data/lib/skeem/version.rb
CHANGED
data/spec/skeem/parser_spec.rb
CHANGED
@@ -14,11 +14,79 @@ module Skeem
|
|
14
14
|
end
|
15
15
|
end # context
|
16
16
|
|
17
|
-
context 'Parsing:' do
|
18
|
-
it 'should parse
|
19
|
-
|
20
|
-
|
17
|
+
context 'Parsing literals:' do
|
18
|
+
it 'should parse isolated booleans' do
|
19
|
+
samples = [
|
20
|
+
['#f', false],
|
21
|
+
['#false', false],
|
22
|
+
['#t', true],
|
23
|
+
['#true', true]
|
24
|
+
]
|
25
|
+
samples.each do |source, predicted|
|
26
|
+
ptree = subject.parse(source)
|
27
|
+
expect(ptree.root).to be_kind_of(SExprBooleanNode)
|
28
|
+
expect(ptree.root.value).to eq(predicted)
|
29
|
+
end
|
21
30
|
end
|
31
|
+
|
32
|
+
it 'should parse isolated integers' do
|
33
|
+
samples = [
|
34
|
+
['0', 0],
|
35
|
+
['3', 3],
|
36
|
+
['-3', -3],
|
37
|
+
['+12345', 12345],
|
38
|
+
['-12345', -12345]
|
39
|
+
]
|
40
|
+
samples.each do |source, predicted|
|
41
|
+
ptree = subject.parse(source)
|
42
|
+
expect(ptree.root).to be_kind_of(SExprIntegerNode)
|
43
|
+
expect(ptree.root.value).to eq(predicted)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
it 'should parse isolated real numbers' do
|
48
|
+
samples = [
|
49
|
+
['0.0', 0.0],
|
50
|
+
['3.14', 3.14],
|
51
|
+
['-3.14', -3.14],
|
52
|
+
['+123e+45', 123e+45],
|
53
|
+
['-123e-45', -123e-45]
|
54
|
+
]
|
55
|
+
samples.each do |source, predicted|
|
56
|
+
ptree = subject.parse(source)
|
57
|
+
expect(ptree.root).to be_kind_of(SExprRealNode)
|
58
|
+
expect(ptree.root.value).to eq(predicted)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
it 'should parse isolated strings' do
|
63
|
+
samples = [
|
64
|
+
['"Hello world!"', 'Hello world!']
|
65
|
+
]
|
66
|
+
samples.each do |source, predicted|
|
67
|
+
ptree = subject.parse(source)
|
68
|
+
expect(ptree.root).to be_kind_of(SExprStringNode)
|
69
|
+
expect(ptree.root.value).to eq(predicted)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
it 'should parse isolated identifiers' do
|
74
|
+
samples = [
|
75
|
+
['the-word-recursion-has-many-meanings', 'the-word-recursion-has-many-meanings']
|
76
|
+
]
|
77
|
+
samples.each do |source, predicted|
|
78
|
+
ptree = subject.parse(source)
|
79
|
+
expect(ptree.root).to be_kind_of(SExprIdentifierNode)
|
80
|
+
expect(ptree.root.value).to eq(predicted)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end # context
|
84
|
+
|
85
|
+
context 'Parsing forms:' do
|
86
|
+
# it 'should parse definitions' do
|
87
|
+
# source = '(define r 10)'
|
88
|
+
# expect { subject.parse(source) }.not_to raise_error
|
89
|
+
# end
|
22
90
|
end # context
|
23
91
|
end # describe
|
24
92
|
end # module
|
@@ -84,7 +84,8 @@ module Skeem
|
|
84
84
|
# couple [raw input, expected]
|
85
85
|
["\t\t3.45e+6", 3.45e+6],
|
86
86
|
['+3.45e+6', +3.45e+6],
|
87
|
-
['-3.45e+6', -3.45e+6]
|
87
|
+
['-3.45e+6', -3.45e+6],
|
88
|
+
['123e+45', 1.23e+47]
|
88
89
|
]
|
89
90
|
|
90
91
|
tests.each do |(input, prediction)|
|
@@ -96,7 +97,6 @@ module Skeem
|
|
96
97
|
end
|
97
98
|
end # context
|
98
99
|
|
99
|
-
# TODO
|
100
100
|
context 'String recognition:' do
|
101
101
|
it 'should tokenize strings' do
|
102
102
|
examples = [
|
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.0.
|
4
|
+
version: 0.0.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Dimitri Geshef
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-08-
|
11
|
+
date: 2018-08-30 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rley
|
@@ -86,8 +86,8 @@ files:
|
|
86
86
|
- appveyor.yml
|
87
87
|
- lib/skeem.rb
|
88
88
|
- lib/skeem/grammar.rb
|
89
|
-
- lib/skeem/node_builder.rb
|
90
89
|
- lib/skeem/parser.rb
|
90
|
+
- lib/skeem/s_expr_builder.rb
|
91
91
|
- lib/skeem/s_expr_nodes.rb
|
92
92
|
- lib/skeem/stoken.rb
|
93
93
|
- lib/skeem/tokenizer.rb
|