factbase 0.0.2 → 0.0.4
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/lib/factbase/syntax.rb +22 -4
- data/lib/factbase/term.rb +1 -1
- data/lib/factbase.rb +4 -5
- data/test/factbase/test_syntax.rb +36 -3
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: dc21a8440801909645bc06e200ca9b238ab899f6ecd5ef422eec4d082fdbbfaf
|
4
|
+
data.tar.gz: 05fb34e5249ec11dd0cddcfe74888d89a3343c44afada52926f720c102804321
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6c72854f13afe4af7be6a232c12c60025cd9d286559940e96a0ebd9decf748e13e8db4993bffe64f8416d3c03cd20f9a491c06c55434bdba2f53c32edd7d7410
|
7
|
+
data.tar.gz: e44f1b7c3c83f207ead55e5aed42844eb98dd53ee6ef5241be0e0931cbe7670dc0c6103c002ce6a4a7cbc8818784de6c7f600a7102d91a20a2dcc732a62fc5d7
|
data/lib/factbase/syntax.rb
CHANGED
@@ -20,7 +20,6 @@
|
|
20
20
|
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
21
|
# SOFTWARE.
|
22
22
|
|
23
|
-
require 'cgi'
|
24
23
|
require_relative 'fact'
|
25
24
|
require_relative 'term'
|
26
25
|
|
@@ -38,7 +37,9 @@ class Factbase::Syntax
|
|
38
37
|
def to_term
|
39
38
|
@tokens ||= to_tokens
|
40
39
|
@ast ||= to_ast(@tokens, 0)
|
41
|
-
@ast[0]
|
40
|
+
term = @ast[0]
|
41
|
+
raise 'No terms found' if term.nil?
|
42
|
+
term
|
42
43
|
end
|
43
44
|
|
44
45
|
private
|
@@ -51,6 +52,7 @@ class Factbase::Syntax
|
|
51
52
|
# is the term/literal and the second one is the position where the
|
52
53
|
# scanning should continue.
|
53
54
|
def to_ast(tokens, at)
|
55
|
+
raise "Closing too soon at ##{at}" if tokens[at] == :close
|
54
56
|
return [tokens[at], at + 1] unless tokens[at] == :open
|
55
57
|
at += 1
|
56
58
|
op = tokens[at]
|
@@ -58,8 +60,11 @@ class Factbase::Syntax
|
|
58
60
|
operands = []
|
59
61
|
at += 1
|
60
62
|
loop do
|
63
|
+
raise "End of token stream at ##{at}" if tokens[at].nil?
|
61
64
|
break if tokens[at] == :close
|
62
65
|
(operand, at1) = to_ast(tokens, at)
|
66
|
+
raise "Stuck at position ##{at}" if at == at1
|
67
|
+
raise "Jump back at position ##{at}" if at1 < at
|
63
68
|
at = at1
|
64
69
|
operands << operand
|
65
70
|
break if tokens[at] == :close
|
@@ -70,7 +75,19 @@ class Factbase::Syntax
|
|
70
75
|
def to_tokens
|
71
76
|
list = []
|
72
77
|
acc = ''
|
78
|
+
string = false
|
73
79
|
@query.to_s.chars.each do |c|
|
80
|
+
if ['\'', '"'].include?(c)
|
81
|
+
if string && acc[acc.length - 1] == '\\'
|
82
|
+
acc = acc[0..-2]
|
83
|
+
else
|
84
|
+
string = !string
|
85
|
+
end
|
86
|
+
end
|
87
|
+
if string
|
88
|
+
acc += c
|
89
|
+
next
|
90
|
+
end
|
74
91
|
if !acc.empty? && [' ', ')'].include?(c)
|
75
92
|
list << acc
|
76
93
|
acc = ''
|
@@ -86,11 +103,12 @@ class Factbase::Syntax
|
|
86
103
|
acc += c
|
87
104
|
end
|
88
105
|
end
|
106
|
+
raise 'String not closed' if string
|
89
107
|
list.map do |t|
|
90
108
|
if t.is_a?(Symbol)
|
91
109
|
t
|
92
|
-
elsif t.start_with?('\'')
|
93
|
-
|
110
|
+
elsif t.start_with?('\'', '"')
|
111
|
+
t[1..-2]
|
94
112
|
elsif t.match?(/^[0-9]+$/)
|
95
113
|
t.to_i
|
96
114
|
else
|
data/lib/factbase/term.rb
CHANGED
data/lib/factbase.rb
CHANGED
@@ -26,7 +26,7 @@
|
|
26
26
|
# License:: MIT
|
27
27
|
class Factbase
|
28
28
|
# Current version of the library and of this class.
|
29
|
-
VERSION = '0.0.
|
29
|
+
VERSION = '0.0.4'
|
30
30
|
|
31
31
|
# Constructor.
|
32
32
|
def initialize
|
@@ -48,15 +48,14 @@ class Factbase
|
|
48
48
|
|
49
49
|
# Create a query capable of iterating.
|
50
50
|
#
|
51
|
-
# There is a Lisp-like syntax, for example
|
52
|
-
# must be HTML-escaped):
|
51
|
+
# There is a Lisp-like syntax, for example:
|
53
52
|
#
|
54
|
-
# (eq title 'Object
|
53
|
+
# (eq title 'Object Thinking')
|
55
54
|
# (gt time '2024-03-23T03:21:43')
|
56
55
|
# (gt cost 42)
|
57
56
|
# (exists seenBy)
|
58
57
|
# (and
|
59
|
-
# (eq foo
|
58
|
+
# (eq foo 42)
|
60
59
|
# (or
|
61
60
|
# (gt bar 200)
|
62
61
|
# (absent zzz)))
|
@@ -29,12 +29,23 @@ require_relative '../../lib/factbase/syntax'
|
|
29
29
|
# Copyright:: Copyright (c) 2024 Yegor Bugayenko
|
30
30
|
# License:: MIT
|
31
31
|
class TestSyntax < Minitest::Test
|
32
|
+
def test_parses_string_right
|
33
|
+
[
|
34
|
+
"(foo 'abc')",
|
35
|
+
"(foo 'one two')",
|
36
|
+
"(foo 'one two three ')",
|
37
|
+
"(foo 'one two three ' 'tail tail')"
|
38
|
+
].each do |q|
|
39
|
+
assert_equal(q, Factbase::Syntax.new(q).to_term.to_s)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
32
43
|
def test_simple_parsing
|
33
44
|
[
|
34
45
|
'()',
|
35
46
|
'(foo)',
|
36
47
|
'(foo (bar) (zz 77) )',
|
37
|
-
"(eq foo 'Hello
|
48
|
+
"(eq foo 'Hello, world!')",
|
38
49
|
"(or ( a 4) (b 5) () (and () (c 5) (r 7 8s 8is 'Foo')))"
|
39
50
|
].each do |q|
|
40
51
|
Factbase::Syntax.new(q).to_term
|
@@ -46,10 +57,12 @@ class TestSyntax < Minitest::Test
|
|
46
57
|
'(foo)',
|
47
58
|
'(foo 7)',
|
48
59
|
"(foo 7 'Dude')",
|
60
|
+
"(r 'Dude\\'s Friend')",
|
61
|
+
"(r 'I\\'m \\\"good\\\"')",
|
49
62
|
'(foo x y z)',
|
50
63
|
"(foo x y z t f 42 'Hi!' 33)",
|
51
64
|
'(foo (x) y z)',
|
52
|
-
"(foo (x (f (t (y 42 'Hey'))) (f) (r 3)) y z)"
|
65
|
+
"(foo (x (f (t (y 42 'Hey you'))) (f) (r 3)) y z)"
|
53
66
|
].each do |q|
|
54
67
|
assert_equal(q, Factbase::Syntax.new(q).to_term.to_s)
|
55
68
|
end
|
@@ -64,9 +77,29 @@ class TestSyntax < Minitest::Test
|
|
64
77
|
{
|
65
78
|
'(eq z 1)' => true,
|
66
79
|
'(or (eq bar 888) (eq z 1))' => true,
|
67
|
-
"(or (gt bar 100) (eq foo 'Hello
|
80
|
+
"(or (gt bar 100) (eq foo 'Hello, world!'))" => true
|
68
81
|
}.each do |k, v|
|
69
82
|
assert_equal(v, Factbase::Syntax.new(k).to_term.matches?(m), k)
|
70
83
|
end
|
71
84
|
end
|
85
|
+
|
86
|
+
def test_broken_syntax
|
87
|
+
[
|
88
|
+
'',
|
89
|
+
'(foo',
|
90
|
+
'"hello, world!',
|
91
|
+
'(foo 7',
|
92
|
+
"(foo 7 'Dude'",
|
93
|
+
'(foo x y z (',
|
94
|
+
'(foo x y (z t (f 42 ',
|
95
|
+
')foo ) y z)',
|
96
|
+
")y 42 'Hey you)",
|
97
|
+
')',
|
98
|
+
'"'
|
99
|
+
].each do |q|
|
100
|
+
assert_raises do
|
101
|
+
Factbase::Syntax.new(q).to_term
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
72
105
|
end
|