post_in_fix 0.9.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +17 -0
- data/.rspec +2 -0
- data/.travis.yml +3 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +61 -0
- data/Rakefile +7 -0
- data/lib/post_in_fix/infix.rb +79 -0
- data/lib/post_in_fix/operator.rb +34 -0
- data/lib/post_in_fix/postfix.rb +23 -0
- data/lib/post_in_fix/version.rb +3 -0
- data/lib/post_in_fix.rb +7 -0
- data/post_in_fix.gemspec +24 -0
- data/spec/post_in_fix_spec.rb +98 -0
- data/spec/spec_helper.rb +2 -0
- metadata +103 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 141c73950a277258239cdebbe299021544b6892a
|
4
|
+
data.tar.gz: 54fcff947195752fd4cf3cfa3b973592f2baa4be
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 6df564bc9735b2f4903c991a79aa15e3135419070a79376cbb99d9c84d737324a23bacd11801224ba61de8590794f05ab08bdedf105ce37d122263f7a2cf896b
|
7
|
+
data.tar.gz: 52d69d2adca12583777ff2180af98864a52be657dcb1c13f670035a5ae04a359c649e6019dd7788bf386983dc65d0ca64f5968031e84f283931cdae8b4a2acf8
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2015 Stefan Berndtsson
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,61 @@
|
|
1
|
+
# PostInFix
|
2
|
+
|
3
|
+
Parse an expression in infix format using the Infix class, and obtain a stack based
|
4
|
+
notation from it (RPN). The stack output can also be converted into a Postfix object,
|
5
|
+
for further translation into other forms.
|
6
|
+
|
7
|
+
The only use so far for this has been to convert infix notated Solr boost expressions
|
8
|
+
into a form Solr can understand. Therefor to_solr() is the only output of the Postfix
|
9
|
+
class.
|
10
|
+
|
11
|
+
## Installation
|
12
|
+
|
13
|
+
Add this line to your application's Gemfile:
|
14
|
+
|
15
|
+
```ruby
|
16
|
+
gem 'post_in_fix'
|
17
|
+
```
|
18
|
+
|
19
|
+
And then execute:
|
20
|
+
|
21
|
+
$ bundle
|
22
|
+
|
23
|
+
Or install it yourself as:
|
24
|
+
|
25
|
+
$ gem install post_in_fix
|
26
|
+
|
27
|
+
## Usage
|
28
|
+
|
29
|
+
Stack from a simple expression:
|
30
|
+
```ruby
|
31
|
+
infix = PostInFix::Infix.new("1+2")
|
32
|
+
infix.to_stack # => [1, 2, OP<+>]
|
33
|
+
```
|
34
|
+
|
35
|
+
```OP<+>``` here is an object of the class PostInFix::Operator
|
36
|
+
|
37
|
+
Stack from a slightly more complex expression:
|
38
|
+
```ruby
|
39
|
+
infix = PostInFix::Infix.new("(33.73+9.2)*7")
|
40
|
+
infix.to_stack # => [33.73, 9.2, OP<+>, 7, OP<*>]
|
41
|
+
```
|
42
|
+
|
43
|
+
Stack from an expression where variables (non-values) are included:
|
44
|
+
```ruby
|
45
|
+
infix = PostInFix::Infix.new("foo/(3.2*(bar-baz))")
|
46
|
+
infix.to_stack # => ["foo", 3.2, "bar", "baz", OP<->, OP<*>, OP</>]
|
47
|
+
```
|
48
|
+
|
49
|
+
Output a Solr compatible expression from that last expression:
|
50
|
+
```ruby
|
51
|
+
infix = PostInFix::Infix.new("foo/(3.2*(bar-baz))")
|
52
|
+
infix.to_postfix.to_solr # => "div(foo,product(3.2,sub(bar,baz)))"
|
53
|
+
```
|
54
|
+
|
55
|
+
## Contributing
|
56
|
+
|
57
|
+
1. Fork it ( https://github.com/stefanberndtsson/post_in_fix/fork )
|
58
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
59
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
60
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
61
|
+
5. Create a new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1,79 @@
|
|
1
|
+
require 'post_in_fix/postfix'
|
2
|
+
require 'post_in_fix/operator'
|
3
|
+
|
4
|
+
module PostInFix
|
5
|
+
class Infix
|
6
|
+
def initialize(str)
|
7
|
+
@str = str
|
8
|
+
end
|
9
|
+
|
10
|
+
def to_stack
|
11
|
+
pflist = []
|
12
|
+
pfstack = []
|
13
|
+
last_chr = false
|
14
|
+
sign_next_value = nil
|
15
|
+
|
16
|
+
@str.split("").each do |chr|
|
17
|
+
if chr[/[a-z0-9_.]/]
|
18
|
+
if !last_chr
|
19
|
+
pflist << ""
|
20
|
+
end
|
21
|
+
if sign_next_value == "-"
|
22
|
+
pflist.last << "-"
|
23
|
+
end
|
24
|
+
pflist.last << chr
|
25
|
+
last_chr = true
|
26
|
+
sign_next_value = nil
|
27
|
+
elsif chr[/[+-]/]
|
28
|
+
if !value_near_top?(pflist)
|
29
|
+
sign_next_value = chr
|
30
|
+
else
|
31
|
+
while pfstack.last && pfstack.last[/[*\/+-]/]
|
32
|
+
pflist << pfstack.pop
|
33
|
+
end
|
34
|
+
pfstack.push(Operator.new(chr))
|
35
|
+
end
|
36
|
+
last_chr = false
|
37
|
+
elsif chr[/[*\/]/]
|
38
|
+
pfstack.push(Operator.new(chr))
|
39
|
+
last_chr = false
|
40
|
+
elsif chr[/[(]/]
|
41
|
+
pfstack.push(Operator.new(chr))
|
42
|
+
last_chr = false
|
43
|
+
elsif chr[/[)]/]
|
44
|
+
while pfstack.last && !pfstack.last[/[(]/]
|
45
|
+
pflist << pfstack.pop
|
46
|
+
end
|
47
|
+
if pfstack.last && pfstack.last[/[(]/]
|
48
|
+
pfstack.pop
|
49
|
+
end
|
50
|
+
last_chr = false
|
51
|
+
end
|
52
|
+
end
|
53
|
+
while pfstack.last
|
54
|
+
pflist << pfstack.pop
|
55
|
+
end
|
56
|
+
pflist.map do |entry|
|
57
|
+
if entry.is_a?(String)
|
58
|
+
if entry[/^[-+]?[0-9]+$/]
|
59
|
+
entry = entry.to_i
|
60
|
+
elsif entry[/^[-+]?[0-9]*\.?[0-9]+$/]
|
61
|
+
entry = entry.to_f
|
62
|
+
end
|
63
|
+
end
|
64
|
+
entry
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def to_postfix
|
69
|
+
Postfix.new(to_stack)
|
70
|
+
end
|
71
|
+
|
72
|
+
def value_near_top?(stack)
|
73
|
+
stack_value = stack.reverse.first
|
74
|
+
return false if stack_value.is_a?(Operator)
|
75
|
+
return false if stack_value.nil?
|
76
|
+
true
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module PostInFix
|
2
|
+
class Operator
|
3
|
+
SOLR_OPERNAMES={
|
4
|
+
"+" => "add",
|
5
|
+
"-" => "sub",
|
6
|
+
"/" => "div",
|
7
|
+
"*" => "product"
|
8
|
+
}
|
9
|
+
|
10
|
+
def initialize(sign)
|
11
|
+
@sign = sign
|
12
|
+
end
|
13
|
+
|
14
|
+
def solr_apply(left, right)
|
15
|
+
"#{SOLR_OPERNAMES[@sign]}(#{left},#{right})"
|
16
|
+
end
|
17
|
+
|
18
|
+
def [](value)
|
19
|
+
@sign[value]
|
20
|
+
end
|
21
|
+
|
22
|
+
def sign
|
23
|
+
@sign
|
24
|
+
end
|
25
|
+
|
26
|
+
def inspect
|
27
|
+
"OP<#{@sign}>"
|
28
|
+
end
|
29
|
+
|
30
|
+
def is_operator?
|
31
|
+
["+", "-", "/", "*"].include?(@sign)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'post_in_fix/operator'
|
2
|
+
|
3
|
+
module PostInFix
|
4
|
+
class Postfix
|
5
|
+
def initialize(postfix_array)
|
6
|
+
@pf = postfix_array
|
7
|
+
end
|
8
|
+
|
9
|
+
def to_solr
|
10
|
+
stack = []
|
11
|
+
@pf.each do |entry|
|
12
|
+
if entry.is_a?(Operator)
|
13
|
+
right = stack.pop
|
14
|
+
left = stack.pop
|
15
|
+
stack.push(entry.solr_apply(left, right))
|
16
|
+
else
|
17
|
+
stack.push(entry)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
stack.pop
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
data/lib/post_in_fix.rb
ADDED
data/post_in_fix.gemspec
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'post_in_fix/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "post_in_fix"
|
8
|
+
spec.version = PostInFix::VERSION
|
9
|
+
spec.authors = ["Stefan Berndtsson"]
|
10
|
+
spec.email = ["stefan.berndtsson@gmail.com"]
|
11
|
+
spec.summary = %q{Infix expression parser}
|
12
|
+
spec.description = %q{Parse expressions in Infix format, and produce Postfix}
|
13
|
+
spec.homepage = "https://github.com/stefanberndtsson/post_in_fix"
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files -z`.split("\x0")
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_development_dependency "bundler", "~> 1.7"
|
22
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
23
|
+
spec.add_development_dependency "rspec", "~> 3.0"
|
24
|
+
end
|
@@ -0,0 +1,98 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'pp'
|
3
|
+
|
4
|
+
describe PostInFix do
|
5
|
+
context "Infix" do
|
6
|
+
it 'has a version number' do
|
7
|
+
expect(PostInFix::VERSION).not_to be nil
|
8
|
+
end
|
9
|
+
|
10
|
+
it "handles single positive integer" do
|
11
|
+
stack = PostInFix::Infix.new("10").to_stack
|
12
|
+
expect(stack[0]).to eq(10)
|
13
|
+
stack = PostInFix::Infix.new("+10").to_stack
|
14
|
+
expect(stack[0]).to eq(10)
|
15
|
+
end
|
16
|
+
|
17
|
+
it "handles single positive float" do
|
18
|
+
stack = PostInFix::Infix.new("10.03").to_stack
|
19
|
+
expect(stack[0]).to eq(10.03)
|
20
|
+
stack = PostInFix::Infix.new("+10.03").to_stack
|
21
|
+
expect(stack[0]).to eq(10.03)
|
22
|
+
end
|
23
|
+
|
24
|
+
it "handles single negative integer" do
|
25
|
+
stack = PostInFix::Infix.new("-10").to_stack
|
26
|
+
expect(stack[0]).to eq(-10)
|
27
|
+
end
|
28
|
+
|
29
|
+
it "handles single negative float" do
|
30
|
+
stack = PostInFix::Infix.new("-10.03").to_stack
|
31
|
+
expect(stack[0]).to eq(-10.03)
|
32
|
+
end
|
33
|
+
|
34
|
+
it 'handles 1+2' do
|
35
|
+
stack = PostInFix::Infix.new("1+2").to_stack
|
36
|
+
expect(stack[0]).to eq(1)
|
37
|
+
expect(stack[1]).to eq(2)
|
38
|
+
expect(stack[2]).to be_a(PostInFix::Operator)
|
39
|
+
expect(stack[2].sign).to eq("+")
|
40
|
+
end
|
41
|
+
|
42
|
+
it 'handles (1+2)*3' do
|
43
|
+
stack = PostInFix::Infix.new("(1+2)*3").to_stack
|
44
|
+
expect(stack[0]).to eq(1)
|
45
|
+
expect(stack[1]).to eq(2)
|
46
|
+
expect(stack[2]).to be_a(PostInFix::Operator)
|
47
|
+
expect(stack[2].sign).to eq("+")
|
48
|
+
expect(stack[3]).to eq(3)
|
49
|
+
expect(stack[4]).to be_a(PostInFix::Operator)
|
50
|
+
expect(stack[4].sign).to eq("*")
|
51
|
+
end
|
52
|
+
|
53
|
+
it 'handles ((1+2)*3)/(4+5)' do
|
54
|
+
stack = PostInFix::Infix.new("((1+2)*3)/(4+5)").to_stack
|
55
|
+
expect(stack[0]).to eq(1)
|
56
|
+
expect(stack[1]).to eq(2)
|
57
|
+
expect(stack[2]).to be_a(PostInFix::Operator)
|
58
|
+
expect(stack[2].sign).to eq("+")
|
59
|
+
expect(stack[3]).to eq(3)
|
60
|
+
expect(stack[4]).to be_a(PostInFix::Operator)
|
61
|
+
expect(stack[4].sign).to eq("*")
|
62
|
+
expect(stack[5]).to eq(4)
|
63
|
+
expect(stack[6]).to eq(5)
|
64
|
+
expect(stack[7]).to be_a(PostInFix::Operator)
|
65
|
+
expect(stack[7].sign).to eq("+")
|
66
|
+
expect(stack[8]).to be_a(PostInFix::Operator)
|
67
|
+
expect(stack[8].sign).to eq("/")
|
68
|
+
end
|
69
|
+
|
70
|
+
it 'handles variables: (foo+bar)*(3-baz)' do
|
71
|
+
stack = PostInFix::Infix.new("(foo+bar)*(3-baz)").to_stack
|
72
|
+
expect(stack[0]).to eq("foo")
|
73
|
+
expect(stack[1]).to eq("bar")
|
74
|
+
expect(stack[2]).to be_a(PostInFix::Operator)
|
75
|
+
expect(stack[2].sign).to eq("+")
|
76
|
+
expect(stack[3]).to eq(3)
|
77
|
+
expect(stack[4]).to eq("baz")
|
78
|
+
expect(stack[5]).to be_a(PostInFix::Operator)
|
79
|
+
expect(stack[5].sign).to eq("-")
|
80
|
+
expect(stack[6]).to be_a(PostInFix::Operator)
|
81
|
+
expect(stack[6].sign).to eq("*")
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
context "Postfix" do
|
86
|
+
context "Solr" do
|
87
|
+
it "compatible expression from: 1+2" do
|
88
|
+
solr = PostInFix::Infix.new("1+2").to_postfix.to_solr
|
89
|
+
expect(solr).to eq("add(1,2)")
|
90
|
+
end
|
91
|
+
|
92
|
+
it "compatible expression from: (foo*(3+bar))/(baz-9)" do
|
93
|
+
solr = PostInFix::Infix.new("(foo*(3+bar))/(baz-9)").to_postfix.to_solr
|
94
|
+
expect(solr).to eq("div(product(foo,add(3,bar)),sub(baz,9))")
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
data/spec/spec_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,103 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: post_in_fix
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.9.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Stefan Berndtsson
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2015-11-29 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.7'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.7'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '10.0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '10.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rspec
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '3.0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '3.0'
|
55
|
+
description: Parse expressions in Infix format, and produce Postfix
|
56
|
+
email:
|
57
|
+
- stefan.berndtsson@gmail.com
|
58
|
+
executables: []
|
59
|
+
extensions: []
|
60
|
+
extra_rdoc_files: []
|
61
|
+
files:
|
62
|
+
- ".gitignore"
|
63
|
+
- ".rspec"
|
64
|
+
- ".travis.yml"
|
65
|
+
- Gemfile
|
66
|
+
- LICENSE.txt
|
67
|
+
- README.md
|
68
|
+
- Rakefile
|
69
|
+
- lib/post_in_fix.rb
|
70
|
+
- lib/post_in_fix/infix.rb
|
71
|
+
- lib/post_in_fix/operator.rb
|
72
|
+
- lib/post_in_fix/postfix.rb
|
73
|
+
- lib/post_in_fix/version.rb
|
74
|
+
- post_in_fix.gemspec
|
75
|
+
- spec/post_in_fix_spec.rb
|
76
|
+
- spec/spec_helper.rb
|
77
|
+
homepage: https://github.com/stefanberndtsson/post_in_fix
|
78
|
+
licenses:
|
79
|
+
- MIT
|
80
|
+
metadata: {}
|
81
|
+
post_install_message:
|
82
|
+
rdoc_options: []
|
83
|
+
require_paths:
|
84
|
+
- lib
|
85
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
91
|
+
requirements:
|
92
|
+
- - ">="
|
93
|
+
- !ruby/object:Gem::Version
|
94
|
+
version: '0'
|
95
|
+
requirements: []
|
96
|
+
rubyforge_project:
|
97
|
+
rubygems_version: 2.4.3
|
98
|
+
signing_key:
|
99
|
+
specification_version: 4
|
100
|
+
summary: Infix expression parser
|
101
|
+
test_files:
|
102
|
+
- spec/post_in_fix_spec.rb
|
103
|
+
- spec/spec_helper.rb
|