boolean-expression 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
+