lamep 0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: fc0ce5e8f408a519a1c060670e476287be1d9f67
4
+ data.tar.gz: c2930b9fbdcdc8c53df84b860f2d331adf53d911
5
+ SHA512:
6
+ metadata.gz: fbf0d01e871e567f1e9fb466512a581c17b10631845611b09e02e1374d338a5c6edfd53a7acd480186b8a7df5e14c23dfc025cd26929441eed5863a4087dd466
7
+ data.tar.gz: 1e0f8b49ed2b77cadc2cb0aa7b10fbebe9a7d21865647a34e25af1e6a47bcb8769a87cf6c5420e44bf86683cbee3f1f89157e68f582a2fa80e6f5d60e36b60f9
@@ -0,0 +1,23 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+ *.bundle
19
+ *.so
20
+ *.o
21
+ *.a
22
+ mkmf.log
23
+ .idea
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in lamep.gemspec
4
+ gemspec
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2015 Miroslav Csonka
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.
@@ -0,0 +1,102 @@
1
+ # LAMEP
2
+
3
+ TODO: Write a gem description
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'lamep'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install lamep
18
+
19
+ ## Usage
20
+
21
+ # Basic Usage
22
+
23
+ You can use lamep for:
24
+
25
+ 1. Parsing expression into array of tokens:
26
+
27
+ ```ruby
28
+ # Splits expression into single tokens
29
+ tokens = TokenParser.new.parse('material = wood && (price > 180 || price <= 250)')
30
+ ```
31
+ Variable `tokens` will be array of tokens:
32
+ ```ruby
33
+ %w{material = wood && ( price > 180 || price <= 250 )}
34
+ ```
35
+
36
+ 2. Converting tokens into postfix notation:
37
+
38
+ ```ruby
39
+ # Converts tokens into postfix notation (also known as RPN)
40
+ postfix = ShuntingYard.new(tokens).posfix
41
+ ```
42
+ Variable `postfix` will be array of tokens in postfix notation:
43
+ ```ruby
44
+ %w{material wood = price 180 > price 250 <= || &&}
45
+ ```
46
+
47
+ 3. Building Abstract Syntax Tree:
48
+
49
+ ```ruby
50
+ # Builds tree from postfix
51
+ ast = AbstractSyntaxTreeBuilder.new(postfix).build_tree
52
+ ```
53
+ Variable `ast` will be containing such structure:
54
+ ```ruby
55
+ And.new(
56
+ Equal.new('material', 'wood'),
57
+ Or.new(
58
+ GreaterThan.new('price', '180'),
59
+ LessThanEqual.new('price', '250')
60
+ )
61
+ )
62
+ ```
63
+ 4. Building SQL WHERE clause:
64
+
65
+ ```ruby
66
+ # Builds SQL WHERE clause
67
+ sql_where = ast.to_sql
68
+ ```
69
+ Variable `sql_where` will be string:
70
+ ```ruby
71
+ '((material = wood) AND ((price > 180) OR (price <= 250)))'
72
+ ```
73
+
74
+ # Supported operators
75
+
76
+ At this point we support following list of operators and their SQL conversion:
77
+
78
+ operator | description
79
+ ---------|--------------
80
+ **=** | *Equal*
81
+ **!=** | *Not Equal*
82
+ **>** | *Greater Than*
83
+ **>=** | *Greater Than Equal*
84
+ **<** | *Less Than*
85
+ **<=** | *Less Than Equal*
86
+ **&&** | *Logical AND*
87
+ **\|\|** | *Logical OR*
88
+ **-** | *Unary Minus*
89
+
90
+ The rest of passed expression is considered as an operand i.e. either variable or a number.
91
+
92
+ # Adding your own operators
93
+ TODO:
94
+
95
+
96
+ ## Contributing
97
+
98
+ 1. Fork it ( https://github.com/forex-kaiz/lamep/fork )
99
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
100
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
101
+ 4. Push to the branch (`git push origin my-new-feature`)
102
+ 5. Create a new Pull Request
@@ -0,0 +1,2 @@
1
+ require 'bundler/gem_tasks'
2
+
@@ -0,0 +1,23 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = 'lamep'
7
+ spec.version = 0.1
8
+ spec.authors = ['Martin Svoboda', 'Miroslav Csonka']
9
+ spec.email = ['miroslav.csonka@gmail.com']
10
+ spec.summary = %q{Logical and mathematical expression parser}
11
+ spec.description = %q{Loads logical or mathematical expression (in string) into Abstract Syntax Tree for later evaluation}
12
+ spec.homepage = ''
13
+ spec.license = 'MIT'
14
+
15
+ spec.files = `git ls-files -z`.split("\x0")
16
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
17
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
18
+ spec.require_paths = ['lib']
19
+
20
+ spec.add_development_dependency 'bundler', '~> 1.6'
21
+ spec.add_development_dependency 'rake'
22
+ spec.add_development_dependency 'rspec'
23
+ end
@@ -0,0 +1,8 @@
1
+ class And < Arity2Operators
2
+ Operator.register('&&', And, 13)
3
+
4
+ def to_sql
5
+ "(#{@left.to_sql} AND #{@right.to_sql})"
6
+ end
7
+
8
+ end
@@ -0,0 +1,16 @@
1
+ class Arity1Operators < Operator
2
+
3
+ attr_reader :operand
4
+ ARITY = 1
5
+
6
+ def ==(other)
7
+ other.class == self.class && other.operand == @operand
8
+ end
9
+
10
+ def initialize(operand)
11
+ @operand = (operand.is_a?(Operator)) ? operand : ValueExpression.new(operand)
12
+ end
13
+
14
+ alias_method :equal?, :==
15
+
16
+ end
@@ -0,0 +1,17 @@
1
+ class Arity2Operators < Operator
2
+
3
+ attr_reader :left, :right
4
+ ARITY = 2
5
+
6
+ def initialize(left, right)
7
+ @left = (left.is_a?(Operator)) ? left : ValueExpression.new(left)
8
+ @right = (right.is_a?(Operator)) ? right : ValueExpression.new(right)
9
+ end
10
+
11
+ def ==(other)
12
+ other.class == self.class && other.left == @left && other.right == @right
13
+ end
14
+
15
+ alias_method :equal?, :==
16
+
17
+ end
@@ -0,0 +1,8 @@
1
+ class Equal < Arity2Operators
2
+ Operator.register('=', Equal, 9)
3
+
4
+ def to_sql
5
+ "(#{@left.to_sql} = #{@right.to_sql})"
6
+ end
7
+
8
+ end
@@ -0,0 +1,8 @@
1
+ class GreaterThan < Arity2Operators
2
+ Operator.register('>', GreaterThan, 8)
3
+
4
+ def to_sql
5
+ "(#{@left.to_sql} > #{@right.to_sql})"
6
+ end
7
+
8
+ end
@@ -0,0 +1,8 @@
1
+ class GreaterThanEqual < Arity2Operators
2
+ Operator.register('>=', GreaterThanEqual, 8)
3
+
4
+ def to_sql
5
+ "(#{@left.to_sql} >= #{@right.to_sql})"
6
+ end
7
+
8
+ end
@@ -0,0 +1,8 @@
1
+ class LessThan < Arity2Operators
2
+ Operator.register('<', LessThan, 8)
3
+
4
+ def to_sql
5
+ "(#{@left.to_sql} < #{@right.to_sql})"
6
+ end
7
+
8
+ end
@@ -0,0 +1,8 @@
1
+ class LessThanEqual < Arity2Operators
2
+ Operator.register('<=', LessThanEqual, 8)
3
+
4
+ def to_sql
5
+ "(#{@left.to_sql} <= #{@right.to_sql})"
6
+ end
7
+
8
+ end
@@ -0,0 +1,8 @@
1
+ class NotEqual < Arity2Operators
2
+ Operator.register('!=', NotEqual, 9)
3
+
4
+ def to_sql
5
+ "(#{@left.to_sql} != #{@right.to_sql})"
6
+ end
7
+
8
+ end
@@ -0,0 +1,30 @@
1
+ class Operator
2
+
3
+ OPERATORS = {}
4
+
5
+ def self.factory!(operator_symbol)
6
+ operator(operator_symbol)[:class_name]
7
+ end
8
+
9
+ def self.precedence!(operator_symbol)
10
+ operator(operator_symbol)[:precedence]
11
+ end
12
+
13
+ def self.operator(operator_symbol)
14
+ fail "Unregistered operator: #{operator_symbol}" unless exists?(operator_symbol)
15
+ OPERATORS[operator_symbol]
16
+ end
17
+
18
+ def self.exists?(operator_symbol)
19
+ OPERATORS.key?(operator_symbol)
20
+ end
21
+
22
+ def self.register(operator_symbol, class_name, precedence)
23
+ OPERATORS[operator_symbol] = { class_name: class_name, precedence: precedence }
24
+ end
25
+
26
+ def to_sql
27
+ raise NotImplementedError
28
+ end
29
+
30
+ end
@@ -0,0 +1,7 @@
1
+ class Or < Arity2Operators
2
+ Operator.register('||', Or, 14)
3
+
4
+ def to_sql
5
+ "(#{@left.to_sql} OR #{@right.to_sql})"
6
+ end
7
+ end
@@ -0,0 +1,10 @@
1
+ class UnaryMinus < Arity1Operators
2
+ Operator.register('-', UnaryMinus, 3)
3
+
4
+ def to_sql
5
+ operand = @operand.to_sql
6
+ fail(ArgumentError, ("#{operand} is not a number")) if operand !~ /^\d+$/
7
+ -operand.to_i
8
+ end
9
+
10
+ end
@@ -0,0 +1,11 @@
1
+ class ValueExpression < Arity1Operators
2
+
3
+ def initialize(operand)
4
+ @operand = operand
5
+ end
6
+
7
+ def to_sql
8
+ operand
9
+ end
10
+
11
+ end
@@ -0,0 +1,32 @@
1
+ class AbstractSyntaxTreeBuilder
2
+
3
+ def initialize(postfix)
4
+ @postfix = postfix
5
+ end
6
+
7
+ def build_tree
8
+ until @postfix.length == 1
9
+ operator_index = first_operator_index
10
+ fail 'Not enough operators' if operator_index.nil?
11
+ exp = Operator.factory!(@postfix.slice!(operator_index))
12
+ most_left_child = operator_index - exp::ARITY
13
+ fail "Not enough operands for operator #{exp}" if most_left_child < 0
14
+ children = @postfix.slice!(most_left_child, exp::ARITY)
15
+ @postfix.insert(most_left_child, exp.new(*children))
16
+ end
17
+ @postfix.first
18
+ end
19
+
20
+ private
21
+
22
+ def first_operator_index
23
+ @postfix.find_index { |token|
24
+ begin
25
+ Operator.factory!(token)
26
+ true
27
+ rescue
28
+ false
29
+ end
30
+ }
31
+ end
32
+ end
@@ -0,0 +1,49 @@
1
+ class ShuntingYard
2
+
3
+ def initialize(tokens)
4
+ fail ArgumentError.new("Expected array: Got #{tokens.class}") unless tokens.is_a?(Array)
5
+ @tokens = tokens
6
+ end
7
+
8
+ def postfix
9
+ @output = []
10
+ @stack = []
11
+ bracket_sum = 0
12
+ @tokens.each do |token|
13
+ case token
14
+ when '('
15
+ bracket_sum += 1
16
+ @stack << token
17
+ when ')'
18
+ bracket_sum -= 1
19
+ fail('Right parentheses mismatch') if bracket_sum < 0
20
+ burn_stack_to_parentheses
21
+ else
22
+ if Operator.exists?(token)
23
+ burn_stack_to_higher_precedence(token)
24
+ @stack << token
25
+ else
26
+ @output << token
27
+ end
28
+ end
29
+ end
30
+ fail('Left parentheses mismatch') if bracket_sum > 0
31
+ @output += @stack.reverse
32
+ @output
33
+ end
34
+
35
+ def burn_stack_to_higher_precedence(token)
36
+ until @stack.empty? || @stack.last == '(' || Operator.precedence!(token) < Operator.precedence!(@stack.last)
37
+ @output << @stack.pop
38
+ end
39
+ end
40
+
41
+ private def burn_stack_to_parentheses
42
+ until @stack.empty?
43
+ popped = @stack.pop
44
+ break if popped == '('
45
+ @output << popped
46
+ end
47
+ end
48
+
49
+ end
@@ -0,0 +1,22 @@
1
+ class TokenParser
2
+
3
+ def parse(input)
4
+ input.scan(/^<
5
+ |(>=)|
6
+ (<=)|
7
+ (!=)|
8
+ ([a-zA-Záäéëěíóöôúůüýčďňřšťžĺľ]+)|
9
+ (=)|
10
+ (>)|
11
+ (<)|
12
+ (\d+)|
13
+ (\()|
14
+ (\))|
15
+ (&&)|
16
+ (\|\|)|
17
+ >+$/x)
18
+ .flatten
19
+ .compact
20
+ end
21
+
22
+ end
@@ -0,0 +1,78 @@
1
+ require './spec/spec_helper'
2
+
3
+ describe Operator do
4
+
5
+ describe 'Generating sql statements' do
6
+ describe UnaryMinus do
7
+ it 'unary minus on int to SQL' do
8
+ expect(UnaryMinus.new('180').to_sql).to be(-180)
9
+ end
10
+
11
+ it 'unary minus on string to SQL' do
12
+ expect { UnaryMinus.new('ahoj').to_sql }.to raise_error(ArgumentError)
13
+ end
14
+ end
15
+
16
+ describe Equal do
17
+ it 'simple case' do
18
+ expect(Equal.new('price', '180').to_sql).to eq '(price = 180)'
19
+ end
20
+ end
21
+
22
+ describe GreaterThan do
23
+ it 'simple case' do
24
+ expect(GreaterThan.new('price', '180').to_sql).to eq '(price > 180)'
25
+ end
26
+ end
27
+
28
+ describe GreaterThanEqual do
29
+ it 'simple case' do
30
+ expect(GreaterThanEqual.new('price', '180').to_sql).to eq '(price >= 180)'
31
+ end
32
+ end
33
+
34
+ describe LessThan do
35
+ it 'simple case' do
36
+ expect(LessThan.new('price', '180').to_sql).to eq '(price < 180)'
37
+ end
38
+ end
39
+
40
+ describe LessThanEqual do
41
+ it 'simple case' do
42
+ expect(LessThan.new('price', '180').to_sql).to eq '(price < 180)'
43
+ end
44
+ end
45
+
46
+ describe NotEqual do
47
+ it 'simple case' do
48
+ expect(NotEqual.new('price', '180').to_sql).to eq '(price != 180)'
49
+ end
50
+ end
51
+
52
+ describe Or do
53
+ it 'Nested case' do
54
+ expression = Or.new(Equal.new('price', UnaryMinus.new('180')), Equal.new('Group', 'Tabák'))
55
+ expect(expression.to_sql).to eq '((price = -180) OR (Group = Tabák))'
56
+ end
57
+ end
58
+
59
+ describe And do
60
+ it 'Nested case' do
61
+ expression = And.new(Equal.new('price', UnaryMinus.new('180')), Equal.new('Group', 'Tabák'))
62
+ expect(expression.to_sql).to eq '((price = -180) AND (Group = Tabák))'
63
+ end
64
+ end
65
+
66
+ it 'Composite case' do
67
+ expect(And.new(
68
+ Equal.new('materiál', 'dřevo'),
69
+ Or.new(
70
+ GreaterThan.new('cena', '180'),
71
+ GreaterThanEqual.new('cena', '250')
72
+ )
73
+ ).to_sql).to eq '((materiál = dřevo) AND ((cena > 180) OR (cena >= 250)))'
74
+ end
75
+
76
+ end
77
+
78
+ end
@@ -0,0 +1,67 @@
1
+ require './spec/spec_helper'
2
+
3
+ describe AbstractSyntaxTreeBuilder do
4
+ def returns(postfix, tree)
5
+ expect(AbstractSyntaxTreeBuilder.new(postfix).build_tree).to be(tree)
6
+ end
7
+
8
+ it 'equal case' do
9
+ returns %w(materiál dřevo =), Equal.new('materiál', 'dřevo')
10
+ end
11
+
12
+ it 'gt case' do
13
+ returns %w(materiál 180 >), GreaterThan.new('materiál', '180')
14
+ end
15
+
16
+ it 'lt case' do
17
+ returns %w(materiál 180 <), LessThan.new('materiál', '180')
18
+ end
19
+
20
+ it 'gte case' do
21
+ returns %w(materiál 180 >=), GreaterThanEqual.new('materiál', '180')
22
+ end
23
+
24
+ it 'lte case' do
25
+ returns %w(materiál 180 <=), LessThanEqual.new('materiál', '180')
26
+ end
27
+
28
+ it '&& case' do
29
+ returns %w(materiál 180 &&), And.new('materiál', '180')
30
+ end
31
+
32
+ it '|| case' do
33
+ returns %w(materiál 180 ||), Or.new('materiál', '180')
34
+ end
35
+
36
+ it '!= case' do
37
+ returns %w(materiál 180 !=), NotEqual.new('materiál', '180')
38
+ end
39
+
40
+ it '- case' do
41
+ returns %w(180 -), UnaryMinus.new('180')
42
+ end
43
+
44
+ it 'composite cases' do
45
+ returns %w(materiál dřevo = cena 180 > &&),
46
+ And.new(Equal.new('materiál', 'dřevo'), GreaterThan.new('cena', '180'))
47
+
48
+ returns %w{materiál dřevo = cena 180 > cena 250 >= || &&},
49
+ And.new(
50
+ Equal.new('materiál', 'dřevo'),
51
+ Or.new(
52
+ GreaterThan.new('cena', '180'),
53
+ GreaterThanEqual.new('cena', '250')
54
+ )
55
+ )
56
+
57
+ end
58
+
59
+ it 'only operands' do
60
+ expect {AbstractSyntaxTreeBuilder.new(%w(materiál cena)).build_tree }.to raise_error(RuntimeError)
61
+ end
62
+
63
+ it 'only operators' do
64
+ expect {AbstractSyntaxTreeBuilder.new(%w(&& -)).build_tree }.to raise_error(RuntimeError)
65
+ end
66
+
67
+ end
@@ -0,0 +1,53 @@
1
+ require './spec/spec_helper'
2
+
3
+ describe ShuntingYard do
4
+ def returns(tokens, postfix)
5
+ expect(ShuntingYard.new(tokens).postfix).to eq(postfix)
6
+ end
7
+
8
+ it 'empty input' do
9
+ returns [], []
10
+ end
11
+
12
+ it 'single operand' do
13
+ returns ['drevo'], ['drevo']
14
+ end
15
+
16
+ it 'wrong input' do
17
+ expect { ShuntingYard.new({}).postfix }.to raise_error(ArgumentError)
18
+ expect { ShuntingYard.new(5).postfix }.to raise_error(ArgumentError)
19
+ expect { ShuntingYard.new(nil).postfix }.to raise_error(ArgumentError)
20
+ expect { ShuntingYard.new('ahoj').postfix }.to raise_error(ArgumentError)
21
+ end
22
+
23
+ it 'private constant' do
24
+ expect { ShuntingYard::OPERATORS }.to raise_error(NameError)
25
+ end
26
+
27
+ it 'simple eq' do
28
+ returns %w(material = drevo), %w(material drevo =)
29
+ end
30
+
31
+ it 'empty brackets' do
32
+ returns %w(( )), []
33
+ end
34
+
35
+ it 'brackets' do
36
+ returns %w(( cena > 180 )), %w(cena 180 >)
37
+ returns %w(( ( cena ) > ( 180 ) )), %w(cena 180 >)
38
+ expect { ShuntingYard.new(%w{( cena ) > 180 )}).postfix }.to raise_error(RuntimeError)
39
+ expect { ShuntingYard.new(%w{((( cena ) > 180 )}).postfix }.to raise_error(RuntimeError)
40
+ end
41
+
42
+ it 'difficult cases' do
43
+ returns %w{material = drevo && ( cena > 180 || cena >= 250 )},
44
+ %w{material drevo = cena 180 > cena 250 >= || &&}
45
+ returns %w{( A || - B ) && C}, %w{A B - || C &&}
46
+ returns %w{( ) ( ( cena = - 150 ) ) ( )}, %w{cena 150 - =}
47
+ returns %w{- A = 150 || B && C}, %w{A - 150 = B C && ||}
48
+ end
49
+
50
+ it 'czech operands' do
51
+ returns %w{dřevo < polička}, %w{dřevo polička <}
52
+ end
53
+ end
@@ -0,0 +1,37 @@
1
+ require './spec/spec_helper'
2
+
3
+ describe TokenParser do
4
+ let(:parser) { TokenParser.new }
5
+
6
+ def returns(string, tokens)
7
+ expect(parser.parse(string)).to eq tokens
8
+ end
9
+
10
+ it 'empty input' do
11
+ returns '', []
12
+ end
13
+
14
+ it 'single token' do
15
+ returns 'attribute', %w(attribute)
16
+ end
17
+
18
+ it 'simple assertions' do
19
+ returns 'weight > 0', %w(weight > 0)
20
+ end
21
+
22
+ it 'simple OR operator' do
23
+ returns ' true || false', %w(true || false)
24
+ end
25
+
26
+ it 'simple AND operator' do
27
+ returns 'true && false', %w(true && false)
28
+ end
29
+
30
+ it 'complex case' do
31
+ returns 'material = dřevo && (cena > 180 || cena >= 250)', %w(material = dřevo && ( cena > 180 || cena >= 250 ))
32
+ returns '(material != ocel || cena = 30 && ( šlahounů >= 2 && šlahounů <= 5 ) ',
33
+ %w{( material != ocel || cena = 30 && ( šlahounů >= 2 && šlahounů <= 5 )}
34
+ end
35
+
36
+
37
+ end
@@ -0,0 +1,90 @@
1
+ require './lib/lamep/Expressions/operator'
2
+ require './lib/lamep/Expressions/arity1_operators'
3
+ require './lib/lamep/Expressions/arity2_operators'
4
+ require './lib/lamep/Expressions/value_expression'
5
+ require './lib/lamep/token_parser'
6
+ require './lib/lamep/shunting_yard'
7
+ require './lib/lamep/Expressions/equal'
8
+ require './lib/lamep/Expressions/greater_than'
9
+ require './lib/lamep/Expressions/less_than'
10
+ require './lib/lamep/Expressions/greater_than_equal'
11
+ require './lib/lamep/Expressions/less_than_equal'
12
+ require './lib/lamep/Expressions/and'
13
+ require './lib/lamep/Expressions/or'
14
+ require './lib/lamep/Expressions/unary_minus'
15
+ require './lib/lamep/Expressions/not_equal'
16
+ require './lib/lamep/abstract_syntax_tree_builder'
17
+
18
+ RSpec.configure do |config|
19
+ # rspec-expectations config goes here. You can use an alternate
20
+ # assertion/expectation library such as wrong or the stdlib/minitest
21
+ # assertions if you prefer.
22
+ config.expect_with :rspec do |expectations|
23
+ # This option will default to `true` in RSpec 4. It makes the `description`
24
+ # and `failure_message` of custom matchers include text for helper methods
25
+ # defined using `chain`, e.g.:
26
+ # be_bigger_than(2).and_smaller_than(4).description
27
+ # # => "be bigger than 2 and smaller than 4"
28
+ # ...rather than:
29
+ # # => "be bigger than 2"
30
+ expectations.include_chain_clauses_in_custom_matcher_descriptions = true
31
+ end
32
+
33
+ # rspec-mocks config goes here. You can use an alternate test double
34
+ # library (such as bogus or mocha) by changing the `mock_with` option here.
35
+ config.mock_with :rspec do |mocks|
36
+ # Prevents you from mocking or stubbing a method that does not exist on
37
+ # a real object. This is generally recommended, and will default to
38
+ # `true` in RSpec 4.
39
+ mocks.verify_partial_doubles = true
40
+ end
41
+
42
+ # The settings below are suggested to provide a good initial experience
43
+ # with RSpec, but feel free to customize to your heart's content.
44
+ =begin
45
+ # These two settings work together to allow you to limit a spec run
46
+ # to individual examples or groups you care about by tagging them with
47
+ # `:focus` metadata. When nothing is tagged with `:focus`, all examples
48
+ # get run.
49
+ config.filter_run :focus
50
+ config.run_all_when_everything_filtered = true
51
+
52
+ # Limits the available syntax to the non-monkey patched syntax that is recommended.
53
+ # For more details, see:
54
+ # - http://myronmars.to/n/dev-blog/2012/06/rspecs-new-expectation-syntax
55
+ # - http://teaisaweso.me/blog/2013/05/27/rspecs-new-message-expectation-syntax/
56
+ # - http://myronmars.to/n/dev-blog/2014/05/notable-changes-in-rspec-3#new__config_option_to_disable_rspeccore_monkey_patching
57
+ config.disable_monkey_patching!
58
+
59
+ # This setting enables warnings. It's recommended, but in some cases may
60
+ # be too noisy due to issues in dependencies.
61
+ config.warnings = true
62
+
63
+ # Many RSpec users commonly either run the entire suite or an individual
64
+ # file, and it's useful to allow more verbose output when running an
65
+ # individual spec file.
66
+ if config.files_to_run.one?
67
+ # Use the documentation formatter for detailed output,
68
+ # unless a formatter has already been configured
69
+ # (e.g. via a command-line flag).
70
+ config.default_formatter = 'doc'
71
+ end
72
+
73
+ # Print the 10 slowest examples and example groups at the
74
+ # end of the spec run, to help surface which specs are running
75
+ # particularly slow.
76
+ config.profile_examples = 10
77
+
78
+ # Run specs in random order to surface order dependencies. If you find an
79
+ # order dependency and want to debug it, you can fix the order by providing
80
+ # the seed, which is printed after each run.
81
+ # --seed 1234
82
+ config.order = :random
83
+
84
+ # Seed global randomization in this process using the `--seed` CLI option.
85
+ # Setting this allows you to use `--seed` to deterministically reproduce
86
+ # test failures related to randomization by passing the same `--seed` value
87
+ # as the one that triggered the failure.
88
+ Kernel.srand config.seed
89
+ =end
90
+ end
metadata ADDED
@@ -0,0 +1,120 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: lamep
3
+ version: !ruby/object:Gem::Version
4
+ version: '0.1'
5
+ platform: ruby
6
+ authors:
7
+ - Martin Svoboda
8
+ - Miroslav Csonka
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2015-01-14 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: bundler
16
+ requirement: !ruby/object:Gem::Requirement
17
+ requirements:
18
+ - - "~>"
19
+ - !ruby/object:Gem::Version
20
+ version: '1.6'
21
+ type: :development
22
+ prerelease: false
23
+ version_requirements: !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - "~>"
26
+ - !ruby/object:Gem::Version
27
+ version: '1.6'
28
+ - !ruby/object:Gem::Dependency
29
+ name: rake
30
+ requirement: !ruby/object:Gem::Requirement
31
+ requirements:
32
+ - - ">="
33
+ - !ruby/object:Gem::Version
34
+ version: '0'
35
+ type: :development
36
+ prerelease: false
37
+ version_requirements: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - ">="
40
+ - !ruby/object:Gem::Version
41
+ version: '0'
42
+ - !ruby/object:Gem::Dependency
43
+ name: rspec
44
+ requirement: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - ">="
47
+ - !ruby/object:Gem::Version
48
+ version: '0'
49
+ type: :development
50
+ prerelease: false
51
+ version_requirements: !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - ">="
54
+ - !ruby/object:Gem::Version
55
+ version: '0'
56
+ description: Loads logical or mathematical expression (in string) into Abstract Syntax
57
+ Tree for later evaluation
58
+ email:
59
+ - miroslav.csonka@gmail.com
60
+ executables: []
61
+ extensions: []
62
+ extra_rdoc_files: []
63
+ files:
64
+ - ".gitignore"
65
+ - Gemfile
66
+ - LICENSE.txt
67
+ - README.md
68
+ - Rakefile
69
+ - lamep.gemspec
70
+ - lib/lamep/Expressions/and.rb
71
+ - lib/lamep/Expressions/arity1_operators.rb
72
+ - lib/lamep/Expressions/arity2_operators.rb
73
+ - lib/lamep/Expressions/equal.rb
74
+ - lib/lamep/Expressions/greater_than.rb
75
+ - lib/lamep/Expressions/greater_than_equal.rb
76
+ - lib/lamep/Expressions/less_than.rb
77
+ - lib/lamep/Expressions/less_than_equal.rb
78
+ - lib/lamep/Expressions/not_equal.rb
79
+ - lib/lamep/Expressions/operator.rb
80
+ - lib/lamep/Expressions/or.rb
81
+ - lib/lamep/Expressions/unary_minus.rb
82
+ - lib/lamep/Expressions/value_expression.rb
83
+ - lib/lamep/abstract_syntax_tree_builder.rb
84
+ - lib/lamep/shunting_yard.rb
85
+ - lib/lamep/token_parser.rb
86
+ - spec/lib/Expressions/operators_spec.rb
87
+ - spec/lib/abstract_syntax_tree_builder_spec.rb
88
+ - spec/lib/shunting_yard_spec.rb
89
+ - spec/lib/token_parser_spec.rb
90
+ - spec/spec_helper.rb
91
+ homepage: ''
92
+ licenses:
93
+ - MIT
94
+ metadata: {}
95
+ post_install_message:
96
+ rdoc_options: []
97
+ require_paths:
98
+ - lib
99
+ required_ruby_version: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ required_rubygems_version: !ruby/object:Gem::Requirement
105
+ requirements:
106
+ - - ">="
107
+ - !ruby/object:Gem::Version
108
+ version: '0'
109
+ requirements: []
110
+ rubyforge_project:
111
+ rubygems_version: 2.2.2
112
+ signing_key:
113
+ specification_version: 4
114
+ summary: Logical and mathematical expression parser
115
+ test_files:
116
+ - spec/lib/Expressions/operators_spec.rb
117
+ - spec/lib/abstract_syntax_tree_builder_spec.rb
118
+ - spec/lib/shunting_yard_spec.rb
119
+ - spec/lib/token_parser_spec.rb
120
+ - spec/spec_helper.rb