boolean-expression 0.0.1

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.
@@ -0,0 +1,143 @@
1
+ #--
2
+ # Copyleft meh. [http://meh.paranoid.pk | meh@paranoici.org]
3
+ #
4
+ # This file is part of boolean-expression.
5
+ #
6
+ # boolean-expression is free software: you can redistribute it and/or modify
7
+ # it under the terms of the GNU Affero General Public License as published
8
+ # by the Free Software Foundation, either version 3 of the License, or
9
+ # (at your option) any later version.
10
+ #
11
+ # boolean-expression is distributed in the hope that it will be useful,
12
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ # GNU Affero General Public License for more details.
15
+ #
16
+ # You should have received a copy of the GNU Affero General Public License
17
+ # along with boolean-expression. If not, see <http://www.gnu.org/licenses/>.
18
+ #++
19
+
20
+ unless defined?(Boolean)
21
+ class Boolean; end
22
+ end
23
+
24
+ class Boolean::Expression
25
+ EvaluationError = Class.new(Exception)
26
+
27
+ class << self
28
+ def parse (text)
29
+ base = Group.new
30
+ name = nil
31
+ stack = [base]
32
+ logic = nil
33
+
34
+ text.to_s.each_char.to_a.each_with_index {|char, index|
35
+ begin
36
+ if char == ')' && stack.length == 1
37
+ raise SyntaxError.new('Closing an unopened parenthesis')
38
+ end
39
+
40
+ if char.match(/\s|\(|\)/) || (!logic && ['|', '&', '!'].member?(char))
41
+ if logic || (name && name.match(/(and|or|not)/i))
42
+ stack.last << Logic.new(logic || name)
43
+ logic = nil
44
+ name = nil
45
+ elsif name
46
+ stack.last << Name.new(name)
47
+ name = nil
48
+ end
49
+ end
50
+
51
+ if name || logic
52
+ name << char if name
53
+ logic << char if logic
54
+ else
55
+ case char
56
+ when '('; stack.push Group.new
57
+ when ')'; stack[-2] << stack.pop
58
+ when '|'; logic = '|'
59
+ when '&'; logic = '&'
60
+ when '!'; stack.last << Logic.new('!')
61
+ else; name = char if !char.match(/\s/)
62
+ end
63
+ end
64
+ rescue SyntaxError => e
65
+ raise "#{e.message} near `#{text[index - 4, 8]}` at character #{index}"
66
+ end
67
+ }
68
+
69
+ if stack.length != 1
70
+ raise SyntaxError.new('Not all parenthesis are closed')
71
+ end
72
+
73
+ if logic
74
+ raise SyntaxError.new('The expression cannot end with a logic operator')
75
+ end
76
+
77
+ base << Name.new(name) if name
78
+
79
+ if base.length == 1 && base.first.is_a?(Group)
80
+ base = base.first
81
+ end
82
+
83
+ self.new(base)
84
+ end
85
+
86
+ alias [] parse
87
+ end
88
+
89
+ attr_reader :base
90
+
91
+ def initialize (base=Group.new)
92
+ @base = base
93
+ end
94
+
95
+ def evaluate (*args)
96
+ _evaluate(@base, args.flatten.compact.map {|piece|
97
+ piece.to_s
98
+ })
99
+ end
100
+
101
+ alias [] evaluate
102
+
103
+ def to_s
104
+ @base.inspect
105
+ end
106
+
107
+ private
108
+ def _evaluate (group, pieces)
109
+ return false if pieces.empty?
110
+
111
+ values = []
112
+
113
+ group.each {|thing|
114
+ case thing
115
+ when Logic; values << thing
116
+ when Group; values << _evaluate(thing, pieces)
117
+ when Name; values << pieces.member?(thing.to_s)
118
+ end
119
+ }
120
+
121
+ at = 0
122
+ while at < values.length
123
+ if values[at].is_a?(Logic) && values[at].type == :not
124
+ values[at] = values.delete_at(at).evaluate(values[at])
125
+ values[at] = !values[at]
126
+ end
127
+
128
+ at += 1
129
+ end
130
+
131
+ while values.length > 1
132
+ a, logic, b = values.shift(3)
133
+
134
+ values.unshift(logic.evaluate(a, b))
135
+ end
136
+
137
+ values.first
138
+ end
139
+ end
140
+
141
+ require 'boolean/expression/name'
142
+ require 'boolean/expression/logic'
143
+ require 'boolean/expression/group'
@@ -0,0 +1,24 @@
1
+ #--
2
+ # Copyleft meh. [http://meh.paranoid.pk | meh@paranoici.org]
3
+ #
4
+ # This file is part of boolean-expression.
5
+ #
6
+ # boolean-expression is free software: you can redistribute it and/or modify
7
+ # it under the terms of the GNU Affero General Public License as published
8
+ # by the Free Software Foundation, either version 3 of the License, or
9
+ # (at your option) any later version.
10
+ #
11
+ # boolean-expression is distributed in the hope that it will be useful,
12
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ # GNU Affero General Public License for more details.
15
+ #
16
+ # You should have received a copy of the GNU Affero General Public License
17
+ # along with boolean-expression. If not, see <http://www.gnu.org/licenses/>.
18
+ #++
19
+
20
+ class Boolean::Expression::Group < Array
21
+ def inspect
22
+ '(' + self.map {|e| e.inspect}.join(' ') + ')'
23
+ end
24
+ end
@@ -0,0 +1,44 @@
1
+ #--
2
+ # Copyleft meh. [http://meh.paranoid.pk | meh@paranoici.org]
3
+ #
4
+ # This file is part of boolean-expression.
5
+ #
6
+ # boolean-expression is free software: you can redistribute it and/or modify
7
+ # it under the terms of the GNU Affero General Public License as published
8
+ # by the Free Software Foundation, either version 3 of the License, or
9
+ # (at your option) any later version.
10
+ #
11
+ # boolean-expression is distributed in the hope that it will be useful,
12
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ # GNU Affero General Public License for more details.
15
+ #
16
+ # You should have received a copy of the GNU Affero General Public License
17
+ # along with boolean-expression. If not, see <http://www.gnu.org/licenses/>.
18
+ #++
19
+
20
+ class Boolean::Expression::Logic
21
+ attr_reader :type
22
+
23
+ def initialize (what)
24
+ @type = case what
25
+ when '!', /not/i then :not
26
+ when '&&', /and/i then :and
27
+ when '||', /or/i then :or
28
+ end
29
+
30
+ raise SyntaxError.new('Invalid logical operator, logical fallacies everywhere') unless @type
31
+ end
32
+
33
+ def evaluate (a, b=nil)
34
+ case @type
35
+ when :not then !a
36
+ when :and then !!(a && b)
37
+ when :or then !!(a || b)
38
+ end
39
+ end
40
+
41
+ def inspect
42
+ self.type.to_s.upcase
43
+ end
44
+ end
@@ -0,0 +1,24 @@
1
+ #--
2
+ # Copyleft meh. [http://meh.paranoid.pk | meh@paranoici.org]
3
+ #
4
+ # This file is part of boolean-expression.
5
+ #
6
+ # boolean-expression is free software: you can redistribute it and/or modify
7
+ # it under the terms of the GNU Affero General Public License as published
8
+ # by the Free Software Foundation, either version 3 of the License, or
9
+ # (at your option) any later version.
10
+ #
11
+ # boolean-expression is distributed in the hope that it will be useful,
12
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ # GNU Affero General Public License for more details.
15
+ #
16
+ # You should have received a copy of the GNU Affero General Public License
17
+ # along with boolean-expression. If not, see <http://www.gnu.org/licenses/>.
18
+ #++
19
+
20
+ class Boolean::Expression::Name < String
21
+ def inspect
22
+ self.to_s.downcase
23
+ end
24
+ end
metadata ADDED
@@ -0,0 +1,57 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: boolean-expression
3
+ version: !ruby/object:Gem::Version
4
+ prerelease:
5
+ version: 0.0.1
6
+ platform: ruby
7
+ authors:
8
+ - meh.
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+
13
+ date: 2011-06-22 00:00:00 Z
14
+ dependencies: []
15
+
16
+ description:
17
+ email: meh@paranoici.org
18
+ executables: []
19
+
20
+ extensions: []
21
+
22
+ extra_rdoc_files: []
23
+
24
+ files:
25
+ - lib/boolean/expression.rb
26
+ - lib/boolean/expression/logic.rb
27
+ - lib/boolean/expression/name.rb
28
+ - lib/boolean/expression/group.rb
29
+ homepage: http://github.com/meh/boolean-expression
30
+ licenses: []
31
+
32
+ post_install_message:
33
+ rdoc_options: []
34
+
35
+ require_paths:
36
+ - lib
37
+ required_ruby_version: !ruby/object:Gem::Requirement
38
+ none: false
39
+ requirements:
40
+ - - ">="
41
+ - !ruby/object:Gem::Version
42
+ version: "0"
43
+ required_rubygems_version: !ruby/object:Gem::Requirement
44
+ none: false
45
+ requirements:
46
+ - - ">="
47
+ - !ruby/object:Gem::Version
48
+ version: "0"
49
+ requirements: []
50
+
51
+ rubyforge_project:
52
+ rubygems_version: 1.8.5
53
+ signing_key:
54
+ specification_version: 3
55
+ summary: A simple library to evaluate boolean expressions.
56
+ test_files: []
57
+