rast 0.1.0.pre
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +2 -0
- data/.rspec +1 -0
- data/.rubocop.yml +3 -0
- data/Gemfile +14 -0
- data/Gemfile.lock +72 -0
- data/Guardfile +36 -0
- data/README.md +25 -0
- data/examples/logic_checker.rb +23 -0
- data/examples/prime_number.rb +19 -0
- data/examples/recruiter.rb +50 -0
- data/examples/worker.rb +12 -0
- data/lib/rast/assert.rb +7 -0
- data/lib/rast/converters/bool_converter.rb +10 -0
- data/lib/rast/converters/float_converter.rb +8 -0
- data/lib/rast/converters/int_converter.rb +8 -0
- data/lib/rast/converters/str_converter.rb +8 -0
- data/lib/rast/parameter_generator.rb +109 -0
- data/lib/rast/rast_spec.rb +44 -0
- data/lib/rast/rules/logic_helper.rb +132 -0
- data/lib/rast/rules/operator.rb +18 -0
- data/lib/rast/rules/rule.rb +93 -0
- data/lib/rast/rules/rule_evaluator.rb +273 -0
- data/lib/rast/rules/rule_processor.rb +41 -0
- data/lib/rast/rules/rule_validator.rb +63 -0
- data/lib/rast/spec_dsl.rb +96 -0
- data/lib/rast/version.rb +3 -0
- data/lib/rast.rb +46 -0
- data/lib/template_spec.yml +18 -0
- data/rast.gemspec +30 -0
- metadata +73 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: eb63e35c4439e5fc90b4e25ce9981739f624a114d6f8848eb07576eac93e9222
|
4
|
+
data.tar.gz: 12f0b43bd2385dada9e6272e8895054911c3bee8fbe2ff267914ceae996f5a82
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 5c39d99e9dde201939565dc47372a0cff3be2e83a77ca2162275982ac15b7e73fc8fa83270761ed7b615093e078ed0d6a4324f30883de1258bb38a14082f8fad
|
7
|
+
data.tar.gz: 103f18839c943b5c30af075fe567386d553be83a7f9f4598e5a77c3917df19362a60fbcaca65bf30873dcbc52b64470cad6318584a037d560732af0eb24921c0
|
data/.gitignore
ADDED
data/.rspec
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--require spec_helper
|
data/.rubocop.yml
ADDED
data/Gemfile
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
source 'https://rubygems.org'
|
4
|
+
|
5
|
+
git_source(:github) { |repo_name| "https://github.com/#{repo_name}" }
|
6
|
+
|
7
|
+
group :test do
|
8
|
+
gem 'guard-rspec', require: false
|
9
|
+
gem 'pry'
|
10
|
+
gem 'pry-nav'
|
11
|
+
gem 'rspec'
|
12
|
+
gem 'simplecov'
|
13
|
+
gem 'simplecov-html'
|
14
|
+
end
|
data/Gemfile.lock
ADDED
@@ -0,0 +1,72 @@
|
|
1
|
+
GEM
|
2
|
+
remote: https://rubygems.org/
|
3
|
+
specs:
|
4
|
+
coderay (1.1.2)
|
5
|
+
diff-lcs (1.3)
|
6
|
+
docile (1.3.2)
|
7
|
+
ffi (1.12.2)
|
8
|
+
formatador (0.2.5)
|
9
|
+
guard (2.16.2)
|
10
|
+
formatador (>= 0.2.4)
|
11
|
+
listen (>= 2.7, < 4.0)
|
12
|
+
lumberjack (>= 1.0.12, < 2.0)
|
13
|
+
nenv (~> 0.1)
|
14
|
+
notiffany (~> 0.0)
|
15
|
+
pry (>= 0.9.12)
|
16
|
+
shellany (~> 0.0)
|
17
|
+
thor (>= 0.18.1)
|
18
|
+
guard-compat (1.2.1)
|
19
|
+
guard-rspec (4.7.3)
|
20
|
+
guard (~> 2.1)
|
21
|
+
guard-compat (~> 1.1)
|
22
|
+
rspec (>= 2.99.0, < 4.0)
|
23
|
+
listen (3.2.1)
|
24
|
+
rb-fsevent (~> 0.10, >= 0.10.3)
|
25
|
+
rb-inotify (~> 0.9, >= 0.9.10)
|
26
|
+
lumberjack (1.2.4)
|
27
|
+
method_source (0.9.2)
|
28
|
+
nenv (0.3.0)
|
29
|
+
notiffany (0.1.3)
|
30
|
+
nenv (~> 0.1)
|
31
|
+
shellany (~> 0.0)
|
32
|
+
pry (0.12.2)
|
33
|
+
coderay (~> 1.1.0)
|
34
|
+
method_source (~> 0.9.0)
|
35
|
+
pry-nav (0.3.0)
|
36
|
+
pry (>= 0.9.10, < 0.13.0)
|
37
|
+
rb-fsevent (0.10.3)
|
38
|
+
rb-inotify (0.10.1)
|
39
|
+
ffi (~> 1.0)
|
40
|
+
rspec (3.9.0)
|
41
|
+
rspec-core (~> 3.9.0)
|
42
|
+
rspec-expectations (~> 3.9.0)
|
43
|
+
rspec-mocks (~> 3.9.0)
|
44
|
+
rspec-core (3.9.1)
|
45
|
+
rspec-support (~> 3.9.1)
|
46
|
+
rspec-expectations (3.9.0)
|
47
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
48
|
+
rspec-support (~> 3.9.0)
|
49
|
+
rspec-mocks (3.9.1)
|
50
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
51
|
+
rspec-support (~> 3.9.0)
|
52
|
+
rspec-support (3.9.2)
|
53
|
+
shellany (0.0.1)
|
54
|
+
simplecov (0.18.5)
|
55
|
+
docile (~> 1.1)
|
56
|
+
simplecov-html (~> 0.11)
|
57
|
+
simplecov-html (0.12.2)
|
58
|
+
thor (1.0.1)
|
59
|
+
|
60
|
+
PLATFORMS
|
61
|
+
ruby
|
62
|
+
|
63
|
+
DEPENDENCIES
|
64
|
+
guard-rspec
|
65
|
+
pry
|
66
|
+
pry-nav
|
67
|
+
rspec
|
68
|
+
simplecov
|
69
|
+
simplecov-html
|
70
|
+
|
71
|
+
BUNDLED WITH
|
72
|
+
2.1.4
|
data/Guardfile
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# A sample Guardfile
|
4
|
+
# More info at https://github.com/guard/guard#readme
|
5
|
+
|
6
|
+
## Uncomment and set this to only include directories you want to watch
|
7
|
+
# directories %w(app lib config test spec features) \
|
8
|
+
# .select{|d| Dir.exist?(d) ? d : UI.warning("Directory #{d} does not exist")}
|
9
|
+
|
10
|
+
## Note: if you are using the `directories` clause above and you are not
|
11
|
+
## watching the project directory ('.'), then you will want to move
|
12
|
+
## the Guardfile to a watched dir and symlink it back, e.g.
|
13
|
+
#
|
14
|
+
# $ mkdir config
|
15
|
+
# $ mv Guardfile config/
|
16
|
+
# $ ln -s config/Guardfile .
|
17
|
+
#
|
18
|
+
# and, you'll have to watch "config/Guardfile" instead of "Guardfile"
|
19
|
+
|
20
|
+
# guard :rubocop do
|
21
|
+
# watch(%r{.+\.rb$})
|
22
|
+
# watch(%r{(?:.+/)?\.rubocop(?:_todo)?\.yml$}) { |m| File.dirname(m[0]) }
|
23
|
+
# end
|
24
|
+
|
25
|
+
guard :rspec, cmd: 'bundle exec rspec -fd' do
|
26
|
+
require 'guard/rspec/dsl'
|
27
|
+
|
28
|
+
Guard::RSpec::Dsl.new(self)
|
29
|
+
|
30
|
+
watch(%r{^spec/.+_spec\.rb$})
|
31
|
+
# watch(%r{^spec\/.*?\/(.+_spec\.)yml$}) { |m| "#{m}.rb" }
|
32
|
+
watch(%r{^lib/(.+)\.rb$}) { |_m| 'spec/examples/prime_number_spec.rb' }
|
33
|
+
# watch(%r{^lib/(.+)\.rb$}) { |_m| 'spec/examples/logic_checker_spec.rb' }
|
34
|
+
# watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
|
35
|
+
watch('spec/spec_helper.rb') { 'spec' }
|
36
|
+
end
|
data/README.md
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
# Overview
|
2
|
+
RSpec All Scenario Testing
|
3
|
+
|
4
|
+
## Definition of terms
|
5
|
+
|
6
|
+
spec - as defined in the yaml file, the individual elements under `specs`
|
7
|
+
|
8
|
+
scenario - a specific combination of tokens from vars, it can uniquely identify a fixture.
|
9
|
+
|
10
|
+
fixture - instance of a spec, containing a scenario, reference back to the spec, and the expected result for the given scenario.
|
11
|
+
|
12
|
+
vars - raw list of variables to be combined into multiple fixtures.
|
13
|
+
|
14
|
+
rule - set of outcome paired with rule clause.
|
15
|
+
exemption/exclusions - rule defining variable combinations to be excluded from the test.
|
16
|
+
|
17
|
+
outcome - the left portion of a rule e.g. `true: true&true`
|
18
|
+
|
19
|
+
clause - the right portion of a rule
|
20
|
+
|
21
|
+
|
22
|
+
##
|
23
|
+
|
24
|
+
When running the tests, the execution starts at the spec file, then invoking the
|
25
|
+
DSL. The DSL will then invoke the parameter generator to generate the scenarios.
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# LogicChecker ported from Java
|
4
|
+
#
|
5
|
+
# @author Royce Remulla
|
6
|
+
#
|
7
|
+
class LogicChecker
|
8
|
+
# Perform logical AND operation on two arguments.
|
9
|
+
#
|
10
|
+
# @param argument1 first argument of Boolean type.
|
11
|
+
# @param argument2 second argument of Boolean type.
|
12
|
+
def and(argument1, argument2)
|
13
|
+
argument1 && argument2
|
14
|
+
end
|
15
|
+
|
16
|
+
# Perform logical OR operation on two arguments.
|
17
|
+
#
|
18
|
+
# @param argument1 first argument of Boolean type.
|
19
|
+
# @param argument2 second argument of Boolean type.
|
20
|
+
def or(argument1, argument2)
|
21
|
+
argument1 || argument2
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Example that returns true if the number passed is a prime number
|
4
|
+
class PrimeNumber
|
5
|
+
def prime?(number)
|
6
|
+
is_prime = true
|
7
|
+
raise "Invalid number: #{number}" if number <= 0
|
8
|
+
|
9
|
+
if number == 1
|
10
|
+
is_prime = false
|
11
|
+
elsif number > 2
|
12
|
+
(2...number).each do |i|
|
13
|
+
is_prime = number % i != 0
|
14
|
+
break unless is_prime
|
15
|
+
end
|
16
|
+
end
|
17
|
+
is_prime
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Rules
|
4
|
+
class Recruiter
|
5
|
+
def score; end
|
6
|
+
|
7
|
+
def position; end
|
8
|
+
|
9
|
+
def assess
|
10
|
+
case position
|
11
|
+
when 'Manager'
|
12
|
+
assess_manager(score)
|
13
|
+
when 'Senior Engineer'
|
14
|
+
assess_sr_engineer(score)
|
15
|
+
when 'Engineer'
|
16
|
+
assess_engineer(score)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
# Shortlist score of 9, accept 10, and reject the rest
|
23
|
+
def assess_manager(score)
|
24
|
+
return 'Shortlist' if score == 9
|
25
|
+
|
26
|
+
return 'Accept' if score == 10
|
27
|
+
|
28
|
+
'Reject'
|
29
|
+
end
|
30
|
+
|
31
|
+
# Shortlist score of 8, accept 9 or 10, and reject the rest
|
32
|
+
def assess_sr_engineer(score)
|
33
|
+
return 'Shortlist' if score == 8
|
34
|
+
|
35
|
+
return 'Accept' if score > 8
|
36
|
+
|
37
|
+
'Reject'
|
38
|
+
end
|
39
|
+
|
40
|
+
# Score of 9 and above are overqualified, shortlist 7, accept 8, and reject the rest.
|
41
|
+
def assess_engineer(score)
|
42
|
+
return 'Over Qualified' if score > 8
|
43
|
+
|
44
|
+
return 'Accept' if score == 8
|
45
|
+
|
46
|
+
return 'Shortlist' if score == 7
|
47
|
+
|
48
|
+
'Reject'
|
49
|
+
end
|
50
|
+
end
|
data/examples/worker.rb
ADDED
data/lib/rast/assert.rb
ADDED
@@ -0,0 +1,109 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'pry'
|
4
|
+
require 'yaml'
|
5
|
+
require_relative 'rast_spec'
|
6
|
+
require_relative 'rules/rule'
|
7
|
+
require_relative 'rules/rule_evaluator'
|
8
|
+
require_relative 'rules/rule_validator'
|
9
|
+
|
10
|
+
require_relative 'converters/float_converter'
|
11
|
+
|
12
|
+
# Generates the test parameters.
|
13
|
+
class ParameterGenerator
|
14
|
+
def initialize(yaml_path: '')
|
15
|
+
@specs_config = YAML.load_file(yaml_path)['specs']
|
16
|
+
|
17
|
+
# p @specs_config
|
18
|
+
end
|
19
|
+
|
20
|
+
# addCase. Generate the combinations, then add the fixture to the final list
|
21
|
+
def generate_fixtures(spec_id: '')
|
22
|
+
spec_config = @specs_config[spec_id]
|
23
|
+
|
24
|
+
spec_config[:description] = spec_id
|
25
|
+
spec = instantiate_spec(spec_config)
|
26
|
+
|
27
|
+
list = []
|
28
|
+
|
29
|
+
variables = spec.variables
|
30
|
+
var_first = spec.variables.first
|
31
|
+
multipliers = []
|
32
|
+
|
33
|
+
(1...variables.size).each { |i| multipliers << variables.values[i].dup }
|
34
|
+
scenarios = var_first.last.product(*multipliers)
|
35
|
+
add_fixtures(scenarios: scenarios, spec: spec, list: list)
|
36
|
+
list
|
37
|
+
end
|
38
|
+
|
39
|
+
private
|
40
|
+
|
41
|
+
def valid_case?(scenario, spec)
|
42
|
+
return true if spec.exempt_rule.nil?
|
43
|
+
|
44
|
+
exempt_rule = fixture.exempt_rule
|
45
|
+
rule_evaluator = RuleEvaluator.new(converters: spec.converters)
|
46
|
+
rule_evaluator.parse(exempt_rule)
|
47
|
+
!ruleEvaluator.evaluate(scenario, spec.converters)
|
48
|
+
end
|
49
|
+
|
50
|
+
# add all fixtures to the list.
|
51
|
+
def add_fixtures(scenarios: [], spec: nil, list: [])
|
52
|
+
validator = RuleValidator.new
|
53
|
+
|
54
|
+
scenarios.each do |scenario|
|
55
|
+
next unless valid_case?(scenario, spec)
|
56
|
+
|
57
|
+
list << build_param(validator, scenario, spec)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def build_param(validator, scenario, spec)
|
62
|
+
param = { spec: spec, scenario: {} }
|
63
|
+
token_converter = {}
|
64
|
+
|
65
|
+
spec.variables.keys.each_with_index do |key, index|
|
66
|
+
spec.variables[key].each do |element|
|
67
|
+
unless spec.converters.nil?
|
68
|
+
token_converter[element.to_s] = spec.converters[index]
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
spec.variables.keys.zip(scenario) do |array|
|
74
|
+
var_name = array.first.to_sym
|
75
|
+
var_value = array.last
|
76
|
+
param[:scenario][var_name] = var_value
|
77
|
+
end
|
78
|
+
|
79
|
+
param[:converter_hash] = token_converter
|
80
|
+
param[:expected_outcome] = validator.validate(
|
81
|
+
scenario: scenario,
|
82
|
+
fixture: param
|
83
|
+
)
|
84
|
+
|
85
|
+
param
|
86
|
+
end
|
87
|
+
|
88
|
+
def instantiate_spec(spec_config)
|
89
|
+
spec = RastSpec.new(
|
90
|
+
description: spec_config[:description],
|
91
|
+
variables: spec_config['variables'],
|
92
|
+
rule: Rule.new(rules: spec_config['rules'])
|
93
|
+
)
|
94
|
+
|
95
|
+
pair_config = spec_config['pair']
|
96
|
+
spec.init_pair(pair_config: pair_config) unless pair_config.nil?
|
97
|
+
|
98
|
+
converters = if spec_config['converters'].nil?
|
99
|
+
str_converter = StrConverter.new
|
100
|
+
spec_config['variables'].map { |_var| str_converter }
|
101
|
+
else
|
102
|
+
spec_config['converters'].map do |converter|
|
103
|
+
Object.const_get(converter).new
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
spec.init_converters(converters: converters)
|
108
|
+
end
|
109
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# CaseFixture.java, containing an actual and specific combination of variables.
|
4
|
+
class RastSpec
|
5
|
+
attr_reader :variables, :pair, :pair_reversed, :rule, :description,
|
6
|
+
:exempt_rule, :converters
|
7
|
+
|
8
|
+
attr_accessor :exclude
|
9
|
+
|
10
|
+
def initialize(description: '', variables: [][], rule: nil)
|
11
|
+
@description = description
|
12
|
+
@variables = variables
|
13
|
+
@pair = {}
|
14
|
+
@pair_reversed = {}
|
15
|
+
@rule = rule
|
16
|
+
@exempt_rule = nil
|
17
|
+
end
|
18
|
+
|
19
|
+
def init_pair(pair_config: {})
|
20
|
+
@pair[pair_config.keys.first.to_s] = pair_config.values.first.to_s
|
21
|
+
@pair_reversed = [@pair.to_a.first.reverse].to_h
|
22
|
+
self
|
23
|
+
end
|
24
|
+
|
25
|
+
def init_converters(converters: [])
|
26
|
+
@converters = converters
|
27
|
+
self
|
28
|
+
end
|
29
|
+
|
30
|
+
def init_exempt_rule(exempt_rule)
|
31
|
+
@exempt_rule = exempt_rule
|
32
|
+
self
|
33
|
+
end
|
34
|
+
|
35
|
+
def to_s
|
36
|
+
"Class: #{self.class}
|
37
|
+
Description: #{@description}
|
38
|
+
Variables: #{@variables}
|
39
|
+
Rules: #{@rules}
|
40
|
+
Pair: #{@pair}
|
41
|
+
Converters: #{@converters}
|
42
|
+
"
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,132 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Provides logic evaluation functionalities.
|
4
|
+
module LogicHelper
|
5
|
+
# /**
|
6
|
+
# * Custom logical AND/OR evaluator.
|
7
|
+
# *
|
8
|
+
# * @author Royce
|
9
|
+
# */
|
10
|
+
|
11
|
+
TRUE = '|true'
|
12
|
+
FALSE = '|false'
|
13
|
+
|
14
|
+
# /**
|
15
|
+
# * @param scenario list of scenario tokens.
|
16
|
+
# * @param left_subscript left index.
|
17
|
+
# * @param right_subscript right index.
|
18
|
+
# * @param left left token.
|
19
|
+
# * @param right right token.
|
20
|
+
# */
|
21
|
+
def perform_logical_and(scenario: [], left_subscript: -1, right_subscript: -1,
|
22
|
+
left: nil, right: nil)
|
23
|
+
if FALSE == left || FALSE == right
|
24
|
+
FALSE
|
25
|
+
elsif TRUE == left && TRUE == right
|
26
|
+
TRUE
|
27
|
+
elsif TRUE == left
|
28
|
+
if right_subscript.negative?
|
29
|
+
scenario.include?(right).to_s
|
30
|
+
else
|
31
|
+
(scenario[right_subscript] == right).to_s
|
32
|
+
end
|
33
|
+
elsif TRUE == right
|
34
|
+
if left_subscript.negative?
|
35
|
+
scenario.include?(left).to_s
|
36
|
+
else
|
37
|
+
(scenario[left_subscript] == left).to_s
|
38
|
+
end
|
39
|
+
else
|
40
|
+
left_eval = pevaluate(
|
41
|
+
scenario: scenario,
|
42
|
+
subscript: left_subscript,
|
43
|
+
object: left
|
44
|
+
)
|
45
|
+
|
46
|
+
right_eval = pevaluate(
|
47
|
+
scenario: scenario,
|
48
|
+
subscript: right_subscript,
|
49
|
+
object: right
|
50
|
+
)
|
51
|
+
|
52
|
+
(left_eval && right_eval).to_s
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
# /**
|
57
|
+
# * @param scenario list of scenario tokens.
|
58
|
+
# * @param left_subscript left index.
|
59
|
+
# * @param right_subscript right index.
|
60
|
+
# * @param left left token.
|
61
|
+
# * @param right right token.
|
62
|
+
# */
|
63
|
+
def perform_logical_or(scenario: [], left_subscript: -1, right_subscript: -1,
|
64
|
+
left: nil, right: nil)
|
65
|
+
if TRUE == left || TRUE == right
|
66
|
+
TRUE
|
67
|
+
elsif FALSE == left && FALSE == right
|
68
|
+
FALSE
|
69
|
+
elsif FALSE == left
|
70
|
+
if right_subscript.negative?
|
71
|
+
scenario.include?(right).to_s
|
72
|
+
else
|
73
|
+
(scenario[right_subscript] == right).to_s
|
74
|
+
end
|
75
|
+
elsif FALSE == right
|
76
|
+
if left_subscript.negative?
|
77
|
+
scenario.include?(left).to_s
|
78
|
+
else
|
79
|
+
(scenario[left_subscript]).to_s == left
|
80
|
+
end
|
81
|
+
else
|
82
|
+
left_eval = pevaluate(
|
83
|
+
scenario: scenario,
|
84
|
+
subscript: left_subscript,
|
85
|
+
object: left
|
86
|
+
)
|
87
|
+
|
88
|
+
right_eval = pevaluate(
|
89
|
+
scenario: scenario,
|
90
|
+
subscript: right_subscript,
|
91
|
+
object: right
|
92
|
+
)
|
93
|
+
|
94
|
+
(left_eval || right_eval).to_s
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
# /**
|
99
|
+
# * Helper method to evaluate left or right token.
|
100
|
+
# *
|
101
|
+
# * @param scenario list of scenario tokens.
|
102
|
+
# * @param subscript scenario token subscript.
|
103
|
+
# * @param object left or right token.
|
104
|
+
# */
|
105
|
+
def pevaluate(scenario: [], subscript: -1, object: nil)
|
106
|
+
if subscript.negative?
|
107
|
+
scenario.include?(object)
|
108
|
+
else
|
109
|
+
scenario[subscript] == object
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
# /**
|
114
|
+
# * Check if the token is opening bracket.
|
115
|
+
# *
|
116
|
+
# * @param token Input <code>String</code> token
|
117
|
+
# * @return <code>boolean</code> output
|
118
|
+
# */
|
119
|
+
def open_bracket?(token: '')
|
120
|
+
token == '('
|
121
|
+
end
|
122
|
+
|
123
|
+
# /**
|
124
|
+
# * Check if the token is closing bracket.
|
125
|
+
# *
|
126
|
+
# * @param token Input <code>String</code> token
|
127
|
+
# * @return <code>boolean</code> output
|
128
|
+
# */
|
129
|
+
def close_bracket?(token: '')
|
130
|
+
token == ')'
|
131
|
+
end
|
132
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Operator Enum in Java. To be used only internally in RuleEvaluator class.
|
4
|
+
class Operator
|
5
|
+
# Not('!', Byte.MAX_VALUE), And('&', (byte) 2), Or('|', (byte) 1)
|
6
|
+
|
7
|
+
attr_reader :name, :symbol, :precedence
|
8
|
+
|
9
|
+
def initialize(name: '', symbol: '', precedence: -1)
|
10
|
+
@name = name
|
11
|
+
@symbol = symbol
|
12
|
+
@precedence = precedence
|
13
|
+
end
|
14
|
+
|
15
|
+
def to_s
|
16
|
+
@operator.to_s
|
17
|
+
end
|
18
|
+
end
|