rql_parser 0.0.1alpha3 → 0.0.1alpha4

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d59c753d26bd53b0ad5a268acb1ce5b4bcb40f1d4f0682f2834e5dab4bafa968
4
- data.tar.gz: 37c54da788af245b197765af41ec6069cc16b829bf47bed9f3bdc6d8c85a1d21
3
+ metadata.gz: 75d3efb4c2d93963bc05ad192108c57e964d3224b11d5bf0291bd69a2f652ffe
4
+ data.tar.gz: 99270a824bf63557ce93e29b1db68491f971c5189119b8431356b0cb2444cafc
5
5
  SHA512:
6
- metadata.gz: 067bca6a134e1c4e93d4db0bd75a87ad709f25c1d5bc6dbc398d8040a09e4bd6a0396285e8e963add7d828903b65b3303118c64f7224025dfc07fddafc2be490
7
- data.tar.gz: 4fd670220b3f9694d70d5bc42c30a957b2e740ce17f1d648bee1349a274863de6c9eb0c09fbed016c7863e64316b252a3394793e9fdff3da6c41d9be5f5b6ab2
6
+ metadata.gz: 7598c3cd3007ac838fce30b144f0a3c181313a95855496697d538efbb608b9096779d8a06f6ea2d2fbece42128c65ac4a70aec9b39e6d6cfb8fe3603b079500b
7
+ data.tar.gz: acc40e93395fcbd2012fa7961c291d46bee87eaa75969155f0cfa8797cca99f94fe9a0c1a25e4d5955148acfba0bcd591dbf86a47222bd8bc78201290da38643
data/.rubocop.yml ADDED
@@ -0,0 +1,8 @@
1
+ Metrics/BlockLength:
2
+ Exclude:
3
+ - 'spec/**/*'
4
+ Max: 40
5
+ Metrics/LineLength:
6
+ Max: 120
7
+ Metrics/AbcSize:
8
+ Max: 20
data/CHANGELOG.md CHANGED
@@ -0,0 +1,13 @@
1
+ # Changelog
2
+
3
+ #### 0.0.1alpha4
4
+
5
+ - Restructure gem files
6
+ - Fix some code style issues
7
+ - Rework gem endpoints
8
+
9
+ ---
10
+
11
+ #### 0.0.1alpha3
12
+
13
+ - Release a first working version of a gem
data/Gemfile CHANGED
@@ -1,6 +1,6 @@
1
- source "https://rubygems.org"
1
+ source 'https://rubygems.org'
2
2
 
3
- git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }
3
+ git_source(:github) { |repo_name| "https://github.com/#{repo_name}" }
4
4
 
5
5
  # Specify your gem's dependencies in rql_parser.gemspec
6
6
  gemspec
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- rql_parser (0.0.1alpha1)
4
+ rql_parser (0.0.1alpha3)
5
5
  active_interaction (~> 3.6.0)
6
6
 
7
7
  GEM
@@ -17,10 +17,24 @@ GEM
17
17
  minitest (~> 5.1)
18
18
  tzinfo (~> 1.1)
19
19
  concurrent-ruby (1.1.4)
20
+ diff-lcs (1.3)
20
21
  i18n (1.3.0)
21
22
  concurrent-ruby (~> 1.0)
22
23
  minitest (5.11.3)
23
24
  rake (10.5.0)
25
+ rspec (3.8.0)
26
+ rspec-core (~> 3.8.0)
27
+ rspec-expectations (~> 3.8.0)
28
+ rspec-mocks (~> 3.8.0)
29
+ rspec-core (3.8.0)
30
+ rspec-support (~> 3.8.0)
31
+ rspec-expectations (3.8.2)
32
+ diff-lcs (>= 1.2.0, < 2.0)
33
+ rspec-support (~> 3.8.0)
34
+ rspec-mocks (3.8.0)
35
+ diff-lcs (>= 1.2.0, < 2.0)
36
+ rspec-support (~> 3.8.0)
37
+ rspec-support (3.8.0)
24
38
  thread_safe (0.3.6)
25
39
  tzinfo (1.2.5)
26
40
  thread_safe (~> 0.1)
@@ -32,6 +46,7 @@ DEPENDENCIES
32
46
  bundler (~> 1.17)
33
47
  rake (~> 10.0)
34
48
  rql_parser!
49
+ rspec (~> 3.8.0)
35
50
 
36
51
  BUNDLED WITH
37
52
  1.17.1
data/README.md CHANGED
@@ -18,14 +18,19 @@ Or install it yourself as:
18
18
 
19
19
  ## Usage
20
20
 
21
- See [ActiveInteraction](https://github.com/AaronLasseigne/active_interaction)
21
+ See [ActiveInteraction](https://github.com/AaronLasseigne/active_interaction), as it is used as a base for the gem
22
22
 
23
23
  ```ruby
24
- # in controller
25
- output = RqlParser::FromParams.run(params.to_unsafe_hash)
26
- # or
24
+ # In controller:
25
+ output = RqlParser.from_params(params.to_unsafe_hash)
26
+ # To raise an error instead of returning an object:
27
+ output = RqlParser.from_params!(params.to_unsafe_hash)
28
+
29
+ # Parse RQL instead of params:
27
30
  rql = 'eq(hello,world)&ruby=eq=awesome' # your RQL query here
28
- output = RqlParser::Parse.run(rql)
31
+ output = RqlParser.parse(rql)
32
+ # To raise an error instead of returning an object:
33
+ output = RqlParser.parse!(rql)
29
34
  ```
30
35
 
31
36
  `output.result` yields a binary tree representing the query.
data/Rakefile CHANGED
@@ -1,2 +1,2 @@
1
- require "bundler/gem_tasks"
2
- task :default => :spec
1
+ require 'bundler/gem_tasks'
2
+ task default: :spec
data/bin/console CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- require "bundler/setup"
4
- require "rql_parser"
3
+ require 'bundler/setup'
4
+ require 'rql_parser'
5
5
 
6
6
  # You can add fixtures and/or initialization code here to make experimenting
7
7
  # with your gem easier. You can also use a different console, if you like.
@@ -10,5 +10,5 @@ require "rql_parser"
10
10
  # require "pry"
11
11
  # Pry.start
12
12
 
13
- require "irb"
13
+ require 'irb'
14
14
  IRB.start(__FILE__)
@@ -1,4 +1,5 @@
1
1
  module RqlParser
2
+ # Parent class for all objects
2
3
  class BaseInteraction < ActiveInteraction::Base
3
4
  private
4
5
 
@@ -0,0 +1,46 @@
1
+ module RqlParser
2
+ module Services
3
+ # Formats input into parser-understandable string
4
+ class Format < BaseInteraction
5
+ string :rql
6
+
7
+ RQL_FORMAT = /\A[0-9A-Za-z_()|;&,+\-!=<> ]+\z/.freeze
8
+
9
+ validates :rql, format: { with: RQL_FORMAT, message: 'has invalid format' }
10
+
11
+ def execute
12
+ res = remove_whitespace(rql)
13
+ replace_shorthands(res) unless errors.any?
14
+ end
15
+
16
+ private
17
+
18
+ def remove_whitespace(rql)
19
+ if /[0-9a-zA-Z] [0-9a-zA-Z(]/.match?(rql)
20
+ errors.add(:rql, 'has invalid whitespace')
21
+ else
22
+ rql.delete(' ')
23
+ end
24
+ end
25
+
26
+ def replace_shorthands(rql)
27
+ res = without_shorthands(rql)
28
+ if /[!<>=]/.match?(res)
29
+ errors.add(:rql, 'has invalid shorthands')
30
+ else
31
+ res
32
+ end
33
+ end
34
+
35
+ def without_shorthands(rql)
36
+ rql.gsub(/([0-9A-Za-z_]+)=(eq|ne|lt|le|gt|ge)=([0-9A-Za-z_]+)/, '\2(\1,\3)')
37
+ .gsub(/([0-9A-Za-z_]+)!=([0-9A-Za-z_]+)/, 'ne(\1,\2)')
38
+ .gsub(/([0-9A-Za-z_]+)<([0-9A-Za-z_]+)/, 'lt(\1,\2)')
39
+ .gsub(/([0-9A-Za-z_]+)<=([0-9A-Za-z_]+)/, 'le(\1,\2)')
40
+ .gsub(/([0-9A-Za-z_]+)>([0-9A-Za-z_]+)/, 'gt(\1,\2)')
41
+ .gsub(/([0-9A-Za-z_]+)>=([0-9A-Za-z_]+)/, 'ge(\1,\2)')
42
+ .gsub(/([0-9A-Za-z_]+)=([0-9A-Za-z_]+)/, 'eq(\1,\2)')
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RqlParser
4
+ module Services
5
+ class FromParams < BaseInteraction
6
+ hash :params, strip: false
7
+
8
+ def execute
9
+ perform(Parse.run(rql: rql))
10
+ end
11
+
12
+ private
13
+
14
+ def rql
15
+ params.except(:controller, :action).map do |k, v|
16
+ [k, v].compact.join('=')
17
+ end.join('&')
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,151 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RqlParser
4
+ module Services
5
+ class Parse < BaseInteraction
6
+ string :rql
7
+
8
+ def execute
9
+ formatted = perform(Format.run(inputs))
10
+ expression(formatted) || errors.add(:rql) unless errors.any?
11
+ end
12
+
13
+ private
14
+
15
+ def expression(str)
16
+ group(str) || or_expression(str)
17
+ end
18
+
19
+ def group(str)
20
+ res = false
21
+ if /\A\(.+\)\z/.match?(str)
22
+ res = or_expression(str[1..-2])
23
+ if res
24
+ res = { type: :group, args: res } if res[:args].size > 1
25
+ end
26
+ end
27
+ res
28
+ end
29
+
30
+ def or_expression(str)
31
+ res = []
32
+ split = str.split(/[;|]/)
33
+ temp = ''
34
+ while split.any?
35
+ temp += split.shift
36
+ temp_and_exp = and_expression(temp)
37
+ if temp_and_exp
38
+ res.push(temp_and_exp)
39
+ temp = ''
40
+ else
41
+ temp += '|'
42
+ end
43
+ end
44
+ return false if temp.present?
45
+
46
+ res.size > 1 ? { type: :function, identifier: 'or', args: res } : res.first
47
+ end
48
+
49
+ def and_expression(str)
50
+ res = []
51
+ split = str.split(/,/)
52
+ temp = ''
53
+ while split.any?
54
+ temp += split.shift
55
+ temp_and_exp = function(temp) || group(temp) || and_strict(temp)
56
+ if temp_and_exp
57
+ res.push(temp_and_exp)
58
+ temp = ''
59
+ else
60
+ temp += ','
61
+ end
62
+ end
63
+ return false if temp.present?
64
+
65
+ res.size > 1 ? { type: :function, identifier: 'and', args: res } : res.first
66
+ end
67
+
68
+ def and_strict(str)
69
+ res = []
70
+ split = str.split(/&/)
71
+ temp = ''
72
+ while split.any?
73
+ temp += split.shift
74
+ temp_and_exp = function(temp) || group(temp)
75
+ if temp_and_exp
76
+ res.push(temp_and_exp)
77
+ temp = ''
78
+ else
79
+ temp += ','
80
+ end
81
+ end
82
+ return false if temp.present?
83
+
84
+ res.size > 1 ? { type: :function, identifier: 'and', args: res } : res.first
85
+ end
86
+
87
+ def function(str)
88
+ res = false
89
+ if /\A[a-z]+\(.+\)\z/.match?(str)
90
+ identifier = str.match(/\A([a-z]+)/)[1]
91
+ args = str.match(/\A[a-z]+\((.+)\)\z/)[1]
92
+ temp_args = args(args)
93
+ res = { type: :function, identifier: identifier, args: temp_args } if temp_args
94
+ end
95
+ res
96
+ end
97
+
98
+ def args(str)
99
+ res = []
100
+ split = str.split(',')
101
+ temp = ''
102
+ while split.any?
103
+ temp += split.shift
104
+ temp_arg = arg(temp)
105
+ if temp_arg
106
+ res.push(temp_arg)
107
+ temp = ''
108
+ else
109
+ temp += ','
110
+ end
111
+ end
112
+ return false if temp.present?
113
+
114
+ res
115
+ end
116
+
117
+ def arg(str)
118
+ expression(str) || array_of_values(str) || value(str)
119
+ end
120
+
121
+ def array_of_values(str)
122
+ return false unless /\A\(.+\)\z/.match?(str)
123
+
124
+ res = []
125
+ split = str[1..-2].split(',')
126
+ temp = ''
127
+ while split.any?
128
+ temp += split.shift
129
+ temp_arg = value(temp)
130
+ if temp_arg
131
+ res.push(temp_arg)
132
+ temp = ''
133
+ else
134
+ temp += ','
135
+ end
136
+ end
137
+ return false if temp.present?
138
+
139
+ { arg_array: res }
140
+ end
141
+
142
+ def value(str)
143
+ if str.match?(/\A[_0-9a-zA-Z]+\z/)
144
+ { arg: str }
145
+ else
146
+ false
147
+ end
148
+ end
149
+ end
150
+ end
151
+ end
@@ -1,3 +1,3 @@
1
1
  module RqlParser
2
- VERSION = '0.0.1alpha3'.freeze
2
+ VERSION = '0.0.1alpha4'.freeze
3
3
  end
data/lib/rql_parser.rb CHANGED
@@ -1,5 +1,26 @@
1
1
  require 'active_interaction'
2
2
 
3
- module RqlParser; end
3
+ # Base module of the parser
4
+ module RqlParser
5
+ def self.from_params(params)
6
+ Services::FromParams.run(params)
7
+ end
4
8
 
5
- require "rql_parser/version"
9
+ def self.from_params!(params)
10
+ Services::FromParams.run!(params)
11
+ end
12
+
13
+ def self.parse(rql)
14
+ Services::Parse.run(rql)
15
+ end
16
+
17
+ def self.parse!(rql)
18
+ Services::Parse.run!(rql)
19
+ end
20
+ end
21
+
22
+ require 'rql_parser/version'
23
+ require 'rql_parser/base_interaction'
24
+ require 'rql_parser/services/from_params'
25
+ require 'rql_parser/services/format'
26
+ require 'rql_parser/services/parse'
data/rql_parser.gemspec CHANGED
@@ -1,40 +1,37 @@
1
-
2
- lib = File.expand_path("../lib", __FILE__)
1
+ lib = File.expand_path('lib', __dir__)
3
2
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
- require "rql_parser/version"
3
+ require 'rql_parser/version'
5
4
 
6
5
  Gem::Specification.new do |spec|
7
- spec.name = "rql_parser"
6
+ spec.name = 'rql_parser'
8
7
  spec.version = RqlParser::VERSION
9
- spec.authors = ["Aliaksei Kharkou"]
10
- spec.email = ["Aliaksei.Kharkou@itechart-group.com"]
8
+ spec.authors = ['Aliaksei Kharkou']
9
+ spec.email = ['Aliaksei.Kharkou@itechart-group.com']
11
10
 
12
- spec.summary = %q{RqlParser is a gem for using RQL as valid params}
13
- spec.description = %q{RqlParser is a gem for using RQL as valid params}
14
- spec.homepage = "https://github.com/deorigosa-work/rql-parser"
15
- spec.license = "MIT"
11
+ spec.summary = 'RqlParser is a gem for using RQL as valid params'
12
+ spec.description = 'RqlParser is a gem for using RQL as valid params'
13
+ spec.homepage = 'https://github.com/deorigosa-work/rql-parser'
14
+ spec.license = 'MIT'
16
15
 
17
16
  # Prevent pushing this gem to RubyGems.org. To allow pushes either set the 'allowed_push_host'
18
17
  # to allow pushing to a single host or delete this section to allow pushing to any host.
19
- if spec.respond_to?(:metadata)
20
- spec.metadata["homepage_uri"] = spec.homepage
21
- spec.metadata["source_code_uri"] = "https://github.com/deorigosa-work/rql-parser"
22
- spec.metadata["changelog_uri"] = "https://github.com/deorigosa-work/rql-parser/CHANGELOG.md"
23
- else
24
- raise "RubyGems 2.0 or newer is required to protect against " \
25
- "public gem pushes."
26
- end
18
+ raise 'RubyGems 2.0 or newer is required to protect against public gem pushes.' unless spec.respond_to?(:metadata)
19
+
20
+ spec.metadata['homepage_uri'] = spec.homepage
21
+ spec.metadata['source_code_uri'] = 'https://github.com/deorigosa-work/rql-parser'
22
+ spec.metadata['changelog_uri'] = 'https://github.com/deorigosa-work/rql-parser/CHANGELOG.md'
27
23
 
28
24
  # Specify which files should be added to the gem when it is released.
29
25
  # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
30
- spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
26
+ spec.files = Dir.chdir(File.expand_path(__dir__)) do
31
27
  `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
32
28
  end
33
- spec.bindir = "exe"
29
+ spec.bindir = 'exe'
34
30
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
35
- spec.require_paths = ["lib"]
31
+ spec.require_paths = ['lib']
36
32
 
37
- spec.add_dependency "active_interaction", "~> 3.6.0"
38
- spec.add_development_dependency "bundler", "~> 1.17"
39
- spec.add_development_dependency "rake", "~> 10.0"
33
+ spec.add_dependency 'active_interaction', '~> 3.6.0'
34
+ spec.add_development_dependency 'bundler', '~> 1.17'
35
+ spec.add_development_dependency 'rake', '~> 10.0'
36
+ spec.add_development_dependency 'rspec', '~> 3.8.0'
40
37
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rql_parser
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1alpha3
4
+ version: 0.0.1alpha4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Aliaksei Kharkou
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2018-12-24 00:00:00.000000000 Z
11
+ date: 2018-12-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: active_interaction
@@ -52,6 +52,20 @@ dependencies:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
54
  version: '10.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rspec
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: 3.8.0
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: 3.8.0
55
69
  description: RqlParser is a gem for using RQL as valid params
56
70
  email:
57
71
  - Aliaksei.Kharkou@itechart-group.com
@@ -60,6 +74,7 @@ extensions: []
60
74
  extra_rdoc_files: []
61
75
  files:
62
76
  - ".gitignore"
77
+ - ".rubocop.yml"
63
78
  - CHANGELOG.md
64
79
  - CODE_OF_CONDUCT.md
65
80
  - Gemfile
@@ -70,11 +85,11 @@ files:
70
85
  - bin/console
71
86
  - bin/setup
72
87
  - lib/rql_parser.rb
88
+ - lib/rql_parser/_grammar.ebnf
73
89
  - lib/rql_parser/base_interaction.rb
74
- - lib/rql_parser/format.rb
75
- - lib/rql_parser/from_params.rb
76
- - lib/rql_parser/parse.rb
77
- - lib/rql_parser/rules.ebnf
90
+ - lib/rql_parser/services/format.rb
91
+ - lib/rql_parser/services/from_params.rb
92
+ - lib/rql_parser/services/parse.rb
78
93
  - lib/rql_parser/version.rb
79
94
  - rql_parser.gemspec
80
95
  homepage: https://github.com/deorigosa-work/rql-parser
@@ -1,44 +0,0 @@
1
- module RqlParser
2
- class Format < BaseInteraction
3
- string :rql
4
-
5
- RQL_FORMAT = /\A[0-9A-Za-z_()|&,+\-!=<> ]+\z/.freeze
6
-
7
- validates :rql, format: { with: RQL_FORMAT }
8
-
9
- def execute
10
- res = remove_whitespace(rql)
11
- replace_shorthands(res)
12
- end
13
-
14
- private
15
-
16
- def remove_whitespace(rql)
17
- if /[0-9a-zA-Z] [0-9a-zA-Z(]/.match?(rql)
18
- errors.add(:rql_parser, 'has invalid whitespace')
19
- else
20
- rql.delete(' ')
21
- end
22
- end
23
-
24
- def replace_shorthands(rql)
25
- res = without_shorthands(rql)
26
- if /[!<>=]/.match?(res)
27
- errors.add(:rql_parser, 'has invalid shorthands')
28
- else
29
- res
30
- end
31
- end
32
-
33
- def without_shorthands(rql)
34
- rql.gsub(/([0-9A-Za-z_]+)=(eq|ne|lt|le|gt|ge)=([0-9A-Za-z_]+)/,
35
- '\2(\1,\3)')
36
- .gsub(/([0-9A-Za-z_]+)!=([0-9A-Za-z_]+)/, 'ne(\1,\2)')
37
- .gsub(/([0-9A-Za-z_]+)<([0-9A-Za-z_]+)/, 'lt(\1,\2)')
38
- .gsub(/([0-9A-Za-z_]+)<=([0-9A-Za-z_]+)/, 'le(\1,\2)')
39
- .gsub(/([0-9A-Za-z_]+)>([0-9A-Za-z_]+)/, 'gt(\1,\2)')
40
- .gsub(/([0-9A-Za-z_]+)>=([0-9A-Za-z_]+)/, 'ge(\1,\2)')
41
- .gsub(/([0-9A-Za-z_]+)=([0-9A-Za-z_]+)/, 'eq(\1,\2)')
42
- end
43
- end
44
- end
@@ -1,21 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module RqlParser
4
- #
5
- # some doc
6
- class FromParams < BaseInteraction
7
- hash :params, strip: false
8
-
9
- def execute
10
- perform RqlParser::Parse.run(rql: to_rql(params))
11
- end
12
-
13
- private
14
-
15
- def to_rql(params)
16
- params.except(:controller, :action).map do |k, v|
17
- [k, v].compact.join('=')
18
- end.join('&')
19
- end
20
- end
21
- end
@@ -1,153 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module RqlParser
4
- class Parse < BaseInteraction
5
- string :rql
6
-
7
- def execute
8
- formatted = perform(Format.run(inputs))
9
- expression(formatted) || errors.add(:rql) unless errors.any?
10
- end
11
-
12
- private
13
-
14
- def expression(str)
15
- group(str) || or_expression(str)
16
- end
17
-
18
- def group(str)
19
- res = false
20
- if /\A\(.+\)\z/.match?(str)
21
- res = or_expression(str[1..-2])
22
- if res
23
- res = { type: :group, args: res } if res[:args].size > 1
24
- end
25
- end
26
- res
27
- end
28
-
29
- def or_expression(str)
30
- res = []
31
- split = str.split(/[|;]/)
32
- temp = ''
33
- while split.any?
34
- temp += split.shift
35
- temp_and_exp = and_expression(temp)
36
- if temp_and_exp
37
- res.push(temp_and_exp)
38
- temp = ''
39
- else
40
- temp += ';'
41
- end
42
- end
43
- return false if temp.present?
44
-
45
- res.size > 1 ? { type: :function, identifier: 'or', args: res } : res.first
46
- end
47
-
48
- def and_expression(str)
49
- res = []
50
- split = str.split(/,/)
51
- temp = ''
52
- while split.any?
53
- temp += split.shift
54
- temp_and_exp = function(temp) || group(temp) || and_strict(temp)
55
- if temp_and_exp
56
- res.push(temp_and_exp)
57
- temp = ''
58
- else
59
- temp += ','
60
- end
61
- end
62
- return false if temp.present?
63
-
64
- res.size > 1 ? { type: :function, identifier: 'and', args: res } : res.first
65
- end
66
-
67
- def and_strict(str)
68
- res = []
69
- split = str.split(/&/)
70
- temp = ''
71
- while split.any?
72
- temp += split.shift
73
- temp_and_exp = function(temp) || group(temp)
74
- if temp_and_exp
75
- res.push(temp_and_exp)
76
- temp = ''
77
- else
78
- temp += ','
79
- end
80
- end
81
- return false if temp.present?
82
-
83
- res.size > 1 ? { type: :function, identifier: 'and', args: res } : res.first
84
- end
85
-
86
- def function(str)
87
- res = false
88
- if /\A[a-z]+\(.+\)\z/.match?(str)
89
- identifier = str.match(/\A([a-z]+)/)[1]
90
- args = str.match(/\A[a-z]+\((.+)\)\z/)[1]
91
- temp_args = args(args)
92
- if temp_args
93
- res = { type: :function, identifier: identifier, args: temp_args }
94
- else
95
- false
96
- end
97
- end
98
- res
99
- end
100
-
101
- def args(str)
102
- res = []
103
- split = str.split(',')
104
- temp = ''
105
- while split.any?
106
- temp += split.shift
107
- temp_arg = arg(temp)
108
- if temp_arg
109
- res.push(temp_arg)
110
- temp = ''
111
- else
112
- temp += ','
113
- end
114
- end
115
- return false if temp.present?
116
-
117
- res
118
- end
119
-
120
- def arg(str)
121
- expression(str) || array_of_values(str) || value(str)
122
- end
123
-
124
- def array_of_values(str)
125
- return false unless /\A\(.+\)\z/.match?(str)
126
-
127
- res = []
128
- split = str[1..-2].split(',')
129
- temp = ''
130
- while split.any?
131
- temp += split.shift
132
- temp_arg = value(temp)
133
- if temp_arg
134
- res.push(temp_arg)
135
- temp = ''
136
- else
137
- temp += ','
138
- end
139
- end
140
- return false if temp.present?
141
-
142
- { arg_array: res }
143
- end
144
-
145
- def value(str)
146
- if str.match?(/\A[_0-9a-zA-Z]+\z/)
147
- { arg: str }
148
- else
149
- false
150
- end
151
- end
152
- end
153
- end
File without changes