rql_parser 0.0.1alpha3 → 0.0.1alpha4

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 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