rast 0.1.0.pre
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 +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
|