skeem 0.0.4 → 0.0.5
Sign up to get free protection for your applications and to get access to all the features.
- 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
|