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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 870d9d422444751180a6e69d1be17c9f89ac46e168d7fc1023e7df22829f9134
4
- data.tar.gz: 21e5886fc43c7f297a5f0dd4070d738efb4d6b2ff1f1b9d261d0007bf9ce483d
3
+ metadata.gz: dc21a8440801909645bc06e200ca9b238ab899f6ecd5ef422eec4d082fdbbfaf
4
+ data.tar.gz: 05fb34e5249ec11dd0cddcfe74888d89a3343c44afada52926f720c102804321
5
5
  SHA512:
6
- metadata.gz: 91992d0fe70646084d7da8091ca5659a3f1aa64c474cfbf328278d40b0e5bc56233abb3b316435660ca3522afd3af275c29291b4f178136ef0544cf173a6d243
7
- data.tar.gz: 97c605569af192e7f6960c0bac50777134acb917aa2085b6195d89be95687cde606084569db351025c7c0d4472247feb5f394af1e346a9f14c6af7d5422c2242
6
+ metadata.gz: 6c72854f13afe4af7be6a232c12c60025cd9d286559940e96a0ebd9decf748e13e8db4993bffe64f8416d3c03cd20f9a491c06c55434bdba2f53c32edd7d7410
7
+ data.tar.gz: e44f1b7c3c83f207ead55e5aed42844eb98dd53ee6ef5241be0e0931cbe7670dc0c6103c002ce6a4a7cbc8818784de6c7f600a7102d91a20a2dcc732a62fc5d7
@@ -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
- CGI.unescapeHTML(t[1..-2])
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
@@ -44,7 +44,7 @@ class Factbase::Term
44
44
  items << @op
45
45
  items += @operands.map do |o|
46
46
  if o.is_a?(String)
47
- "'#{o}'"
47
+ "'#{o.gsub("'", "\\\\'").gsub('"', '\\\\"')}'"
48
48
  else
49
49
  o.to_s
50
50
  end
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.2'
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 (all string literals
52
- # must be HTML-escaped):
51
+ # There is a Lisp-like syntax, for example:
53
52
  #
54
- # (eq title 'Object&#20;Thinking')
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 '42')
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,&#x20;world!')",
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,&#x20;world!'))" => true
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
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: factbase
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.0.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Yegor Bugayenko