quecto_calc 0.1.0

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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 3f56437ed3d312aa5c0508c4e787d2b33cb0ea8f6943fa6198ff201d8fc6f579
4
+ data.tar.gz: c089f9abbc586cada86442f88c6fdbd9c063609613643388bca93ed6e5eb87a3
5
+ SHA512:
6
+ metadata.gz: 3ec5be8c5bcbbba76dcea6a2b13cd75ce58a4f96d67d1cc2861cc909f9194982b25b15762a22200a7cab3ccb312fbecf7b55c6fee219369fcd14898832b2ae51
7
+ data.tar.gz: 41348a16b6f58ecadc075f9e06e74e3f96dbdd1f61b5e1d8b8c10b9bccc8a3b06eb170bfb5e36e61905fe7e580bc25dfb1f6dadd01f24aaba22668870614dcd7
data/.gitignore ADDED
@@ -0,0 +1,8 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /_yardoc/
4
+ /coverage/
5
+ /doc/
6
+ /pkg/
7
+ /spec/reports/
8
+ /tmp/
data/.rubocop.yml ADDED
@@ -0,0 +1,10 @@
1
+ Style/StringLiterals:
2
+ Enabled: true
3
+ EnforcedStyle: double_quotes
4
+
5
+ Style/StringLiteralsInInterpolation:
6
+ Enabled: true
7
+ EnforcedStyle: double_quotes
8
+
9
+ Layout/LineLength:
10
+ Max: 120
data/CHANGELOG.md ADDED
@@ -0,0 +1,3 @@
1
+ ### 0.1.0 / 2023-02-17
2
+
3
+ * Initial release.
data/Gemfile ADDED
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ source "https://rubygems.org"
4
+
5
+ # Specify your gem's dependencies in quecto_calc.gemspec
6
+ gemspec
7
+
8
+ gem "rake", "~> 13.0"
9
+
10
+ gem "minitest", "~> 5.0"
11
+
12
+ gem "rubocop", "~> 0.80"
data/Gemfile.lock ADDED
@@ -0,0 +1,42 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ quecto_calc (0.1.0)
5
+
6
+ GEM
7
+ remote: https://rubygems.org/
8
+ specs:
9
+ ast (2.4.2)
10
+ minitest (5.16.3)
11
+ parallel (1.22.1)
12
+ parser (3.1.3.0)
13
+ ast (~> 2.4.1)
14
+ rainbow (3.1.1)
15
+ rake (13.0.6)
16
+ regexp_parser (2.6.1)
17
+ rexml (3.2.5)
18
+ rubocop (0.93.1)
19
+ parallel (~> 1.10)
20
+ parser (>= 2.7.1.5)
21
+ rainbow (>= 2.2.2, < 4.0)
22
+ regexp_parser (>= 1.8)
23
+ rexml
24
+ rubocop-ast (>= 0.6.0)
25
+ ruby-progressbar (~> 1.7)
26
+ unicode-display_width (>= 1.4.0, < 2.0)
27
+ rubocop-ast (1.24.0)
28
+ parser (>= 3.1.1.0)
29
+ ruby-progressbar (1.11.0)
30
+ unicode-display_width (1.8.0)
31
+
32
+ PLATFORMS
33
+ x86_64-linux
34
+
35
+ DEPENDENCIES
36
+ minitest (~> 5.0)
37
+ quecto_calc!
38
+ rake (~> 13.0)
39
+ rubocop (~> 0.80)
40
+
41
+ BUNDLED WITH
42
+ 2.2.3
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2023 Mate
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,81 @@
1
+ # QuectoCalc
2
+
3
+ A simple calculator that evaluates primitive arithmetic expressions represented in a text form, simular to the Ruby's native method _eval_.
4
+
5
+ Although QuectoCalc could perform only a _very_ limited set of operations, it parses input expressions in a way that resembles a run of a real interpreter. QuectoCalc performs lexical analysis, builds an abstract syntax tree (AST), and then evaluates the expression based on the AST. Thus, it’s functionality could be expanded later on.
6
+
7
+ ## Installation
8
+
9
+ Add this line to your application's Gemfile:
10
+
11
+ ```ruby
12
+ gem 'quecto_calc'
13
+ ```
14
+
15
+ And then execute:
16
+
17
+ $ bundle install
18
+
19
+ Or install it yourself as:
20
+
21
+ $ gem install quecto_calc
22
+
23
+ ## Usage
24
+
25
+ obj.evaluate(expression [, constants]) -> result
26
+
27
+ #### Arguments
28
+
29
+ + _expression_ [String]
30
+
31
+ Expression to evaluate.
32
+
33
+ + _constants_ [Hash{ String => Numeric }]
34
+
35
+ Constant names and their respective values.
36
+
37
+ #### Returns
38
+
39
+ + _result_ [Numeric]
40
+
41
+ ## Supported operators
42
+
43
+ + _-_
44
+
45
+ Subtraction.
46
+
47
+ + _+_
48
+
49
+ Addition.
50
+
51
+ ## Examples:
52
+
53
+ ```ruby
54
+ require "quecto_calc"
55
+
56
+ calc = QuectoCalc.new
57
+
58
+ # Evaluate an expression:
59
+ calc.evaluate("1 + 2 + 3 + 4 + 5 - 6") # => 9
60
+
61
+ # Evaluate an expression with constants:
62
+ foo = 9000
63
+ bar = 1234
64
+ calc.evaluate("foo - bar", { "foo" => foo, "bar" => bar }) # => 7766
65
+ ```
66
+
67
+ ## Development
68
+
69
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
70
+
71
+ ## Contributing
72
+
73
+ Bug reports and pull requests are welcome on GitHub at https://github.com/8bit-mate/quecto_calc.
74
+
75
+ ## Acknowledges
76
+
77
+ The lexer and the parser were inspired by the David Callanan's "[Make Your Own Programming Language](https://github.com/davidcallanan/py-myopl-code)" series.
78
+
79
+ ## License
80
+
81
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
data/Rakefile ADDED
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bundler/gem_tasks"
4
+ require "rake/testtask"
5
+
6
+ Rake::TestTask.new(:test) do |t|
7
+ t.libs << "test"
8
+ t.libs << "lib"
9
+ t.test_files = FileList["test/**/*_test.rb"]
10
+ end
11
+
12
+ require "rubocop/rake_task"
13
+
14
+ RuboCop::RakeTask.new
15
+
16
+ task default: %i[test rubocop]
data/bin/console ADDED
@@ -0,0 +1,15 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require "bundler/setup"
5
+ require "quecto_calc"
6
+
7
+ # You can add fixtures and/or initialization code here to make experimenting
8
+ # with your gem easier. You can also use a different console, if you like.
9
+
10
+ # (If you use this, don't forget to add pry to your Gemfile!)
11
+ # require "pry"
12
+ # Pry.start
13
+
14
+ require "irb"
15
+ IRB.start(__FILE__)
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ #
4
+ # Stores a node with a binary operation (between two numbers).
5
+ #
6
+ class BinOpNode
7
+ attr_reader :left_node, :operator, :right_node
8
+
9
+ def initialize(left_node, operator, right_node)
10
+ @left_node = left_node
11
+ @operator = operator
12
+ @right_node = right_node
13
+ end
14
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ #
4
+ # Provides character rules that are used by the lexer.
5
+ #
6
+ module CharRules
7
+ NUM_CHAR = /[[:digit:]]/.freeze # characters that could form a number: digits only
8
+ CONST_FIRST_CHAR = /[[:alpha:]]/.freeze # characters that could be used as a 1st char. in the constant name
9
+ CONTS_CHAR = /[[:alpha:][:digit:]_]/.freeze # characters that could form a constant: letters, digits, underscore char.
10
+
11
+ ADD_CHAR = "+" # character that marks an addition operator
12
+ SUB_CHAR = "-" # character that marks an subtraction operator
13
+
14
+ IGNOR_CHAR = /\s/.freeze # characters that are ignored: all whitespace
15
+ end
@@ -0,0 +1,86 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "quecto_error"
4
+ require_relative "token_types"
5
+
6
+ #
7
+ # Evaluates expression from the abstract syntax tree.
8
+ #
9
+ class Evaluator
10
+ include TokenTypes
11
+
12
+ #
13
+ # Initialize an evaluator instance.
14
+ #
15
+ # @param [Hash{ String => Numeric }] consts
16
+ # List of constants and their values to put in the expression.
17
+ #
18
+ def initialize(consts = {})
19
+ @consts = consts
20
+ end
21
+
22
+ #
23
+ # @param [BinOpNode, NumberNode] node
24
+ #
25
+ def visit(node)
26
+ send("_visit_#{node.class}", node)
27
+ end
28
+
29
+ private
30
+
31
+ #
32
+ # Retrieve result of a binary operation node.
33
+ #
34
+ # @param [BinOpNode] node
35
+ #
36
+ # @return [Numeric]
37
+ # Result of the binary operation.
38
+ #
39
+ def _visit_BinOpNode(node)
40
+ left = visit(node.left_node)
41
+ right = visit(node.right_node)
42
+
43
+ case node.operator.type
44
+ when TT_PLUS
45
+ left + right
46
+ when TT_MINUS
47
+ left - right
48
+ end
49
+ end
50
+
51
+ #
52
+ # Retrieve value of a number node.
53
+ #
54
+ # @param [NumberNode] node
55
+ #
56
+ # @return [Numeric]
57
+ #
58
+ def _visit_NumberNode(node)
59
+ case node.token.type
60
+ when TT_INT
61
+ node.token.value
62
+ when TT_CONST
63
+ _init_constant(node)
64
+ end
65
+ end
66
+
67
+ #
68
+ # Replace constant with an associated value.
69
+ #
70
+ # @param [NumberNode] node
71
+ # A numeric node with @token of TT_CONST type.
72
+ #
73
+ # @return [Numeric]
74
+ #
75
+ # @raise [CalcError]
76
+ # Raises if constant is not found in the @consts.
77
+ #
78
+ def _init_constant(node)
79
+ if @consts.key?(node.token.value)
80
+ @consts[node.token.value]
81
+ else
82
+ error_msg = "undefined constant '#{node.token.value}'"
83
+ raise CalcError, error_msg
84
+ end
85
+ end
86
+ end
@@ -0,0 +1,111 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "char_rules"
4
+ require_relative "quecto_error"
5
+ require_relative "token"
6
+ require_relative "token_types"
7
+
8
+ #
9
+ # Performs lexical analysis of a given string.
10
+ #
11
+ class Lexer
12
+ include TokenTypes
13
+ include CharRules
14
+
15
+ #
16
+ # Initialize a lexer instance.
17
+ #
18
+ # @param [String] str
19
+ # String to parse.
20
+ #
21
+ def initialize(str)
22
+ @str = str
23
+ @pos = 0
24
+ @cur_char = nil
25
+
26
+ _next_char
27
+ end
28
+
29
+ #
30
+ # Create a list of tokens from a string.
31
+ #
32
+ # @return [Array<Token>] tokens
33
+ #
34
+ # @raise [IllegalCharError]
35
+ # Raises when @str has an unsupported character.
36
+ #
37
+ def build_tokens
38
+ tokens = []
39
+
40
+ until @cur_char.nil?
41
+ if @cur_char == ADD_CHAR
42
+ tokens.append(Token.new(type: TT_PLUS))
43
+ elsif @cur_char == SUB_CHAR
44
+ tokens.append(Token.new(type: TT_MINUS))
45
+ elsif @cur_char.match?(NUM_CHAR)
46
+ num = Token.new(type: TT_INT, value: _build_word(NUM_CHAR).to_i)
47
+ tokens.append(num)
48
+ elsif @cur_char.match?(CONST_FIRST_CHAR)
49
+ num = Token.new(type: TT_CONST, value: _build_word(CONTS_CHAR))
50
+ tokens.append(num)
51
+ elsif @cur_char.match?(IGNOR_CHAR)
52
+ # Ignore whitespace.
53
+ else
54
+ error_msg = "illegal character '#{@cur_char}' at the position: #{@pos - 1}"
55
+ raise IllegalCharError, error_msg
56
+ end
57
+ _next_char
58
+ end
59
+
60
+ tokens.append(Token.new(type: TT_EOF))
61
+
62
+ tokens
63
+ end
64
+
65
+ private
66
+
67
+ #
68
+ # Build a 'word' out of a sequence of characters.
69
+ #
70
+ # A 'word' is a sequence of characters followed one by another without break characters (e.g. a space or a supported
71
+ # math operator: '+', '-', etc).
72
+ #
73
+ # A 'word' could be represented in a form of:
74
+ #
75
+ # 1. a sequence of alphabetical characters optionally mixed with digits and joined into one string using a connective
76
+ # character '_'. Examples:
77
+ # - 'ruby' (a sequence of alphabetical characters only);
78
+ # - 'foobar9000' (a mix of alphabetical characters and digits);
79
+ # - 'this_is_a_3rd_example' (long string joined with a connective character).
80
+ #
81
+ # 2. an integer number, e.g.: '31337' (a sequence of digits without break characters).
82
+ #
83
+ # @param [Regexp] regexp
84
+ # Defines that kind of character sequence the method should be looking for: NUM_CHAR (search for a digit) or
85
+ # CONTS_CHAR (search for a constant).
86
+ #
87
+ # @return [String] word
88
+ #
89
+ def _build_word(regexp)
90
+ word = ""
91
+
92
+ until @cur_char.nil?
93
+ break unless @cur_char.match?(regexp)
94
+
95
+ word += @cur_char
96
+ _next_char
97
+ end
98
+ _next_char
99
+
100
+ @pos -= 1
101
+ word
102
+ end
103
+
104
+ #
105
+ # Process next character in the string.
106
+ #
107
+ def _next_char
108
+ @cur_char = @pos < @str.length ? @str[@pos] : nil
109
+ @pos += 1
110
+ end
111
+ end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ #
4
+ # Stores a node with a numeric value.
5
+ #
6
+ class NumberNode
7
+ attr_reader :token
8
+
9
+ def initialize(token)
10
+ @token = token
11
+ end
12
+ end
@@ -0,0 +1,87 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "bin_op_node"
4
+ require_relative "number_node"
5
+ require_relative "quecto_error"
6
+ require_relative "token_types"
7
+
8
+ #
9
+ # Parses list of tokens to build an abstract syntax tree.
10
+ #
11
+ class Parser
12
+ include TokenTypes
13
+
14
+ #
15
+ # Initialize a parser instance.
16
+ #
17
+ # @param [Array<Token>] tokens
18
+ # List of tokens to parse.
19
+ #
20
+ def initialize(tokens)
21
+ @tokens = tokens
22
+ @cur_token = @tokens[0]
23
+ @idx = 0
24
+ end
25
+
26
+ #
27
+ # Parse list of tokens.
28
+ #
29
+ def parse
30
+ _expr
31
+ end
32
+
33
+ private
34
+
35
+ #
36
+ # Buid a node for the expression.
37
+ #
38
+ # @return [BinOpNode, NumberNode] left
39
+ # Node for an expression. The left.class corresponds to the expression type: a single number or a binary operation
40
+ # (an operation between two numbers).
41
+ #
42
+ def _expr
43
+ # retrieve left part of the expression:
44
+ left = _term
45
+
46
+ while BIN_OPS.include?(@cur_token.type)
47
+ # retrieve operator between two number nodes:
48
+ op_tok = @cur_token
49
+
50
+ # retrieve right part of the expression:
51
+ _next_token
52
+ right = _term
53
+
54
+ left = BinOpNode.new(left, op_tok, right)
55
+ end
56
+
57
+ left
58
+ end
59
+
60
+ #
61
+ # Search for a term in the expression.
62
+ #
63
+ # @return [NumberNode] token
64
+ # Found term.
65
+ #
66
+ # @raise [InvalidSyntaxError]
67
+ #
68
+ def _term
69
+ if TERMS.include?(@cur_token.type)
70
+ token = NumberNode.new(@cur_token)
71
+ else
72
+ error_msg = "expected TT_INT or TT_LBL, but got #{@cur_token.type}"
73
+ raise InvalidSyntaxError, error_msg
74
+ end
75
+
76
+ _next_token
77
+ token
78
+ end
79
+
80
+ #
81
+ # Process next token.
82
+ #
83
+ def _next_token
84
+ @idx += 1
85
+ @cur_token = @tokens[@idx] if @idx < @tokens.length
86
+ end
87
+ end
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+
3
+ #
4
+ # Errors rised by the quecto_calc.
5
+ #
6
+ class QuectoError < ::StandardError
7
+ attr_reader :error_name, :message
8
+
9
+ def initialize(error_name, message)
10
+ @error_name = error_name
11
+ @message = message
12
+ end
13
+ end
14
+
15
+ #
16
+ # Raised by the lexer if an illegal character is found.
17
+ #
18
+ class IllegalCharError < QuectoError
19
+ attr_reader :message
20
+
21
+ def initialize(message = "")
22
+ super("Illegal Character:", message)
23
+ end
24
+ end
25
+
26
+ #
27
+ # Raised by the parser if an illegal syntax is found.
28
+ #
29
+ class InvalidSyntaxError < QuectoError
30
+ attr_reader :message
31
+
32
+ def initialize(message = "")
33
+ super("Syntax Error:", message)
34
+ end
35
+ end
36
+
37
+ #
38
+ # Raised by the evaluator on an illegal operation.
39
+ #
40
+ class CalcError < QuectoError
41
+ attr_reader :message
42
+
43
+ def initialize(message = "")
44
+ super("Runtime Error:", message)
45
+ end
46
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ #
4
+ # Stores a token generated by the lexer.
5
+ #
6
+ class Token
7
+ attr_reader :type, :value
8
+
9
+ def initialize(type:, value: nil)
10
+ @type = type
11
+ @value = value
12
+ end
13
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ #
4
+ # Provides supported token types.
5
+ #
6
+ module TokenTypes
7
+ TT_INT = :TT_INT # integer number
8
+ TT_CONST = :TT_CONST # constant (placeholder for a numeric value)
9
+ TT_PLUS = :TT_PLUS # addition operator
10
+ TT_MINUS = :TT_MINUS # subtraction operator
11
+ TT_EOF = :TT_EOF # end of input
12
+
13
+ TERMS = [TT_INT, TT_CONST].freeze
14
+
15
+ BIN_OPS = [TT_PLUS, TT_MINUS].freeze
16
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ class QuectoCalc
4
+ VERSION = "0.1.0"
5
+ end
@@ -0,0 +1,71 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "quecto_calc/evaluator"
4
+ require_relative "quecto_calc/lexer"
5
+ require_relative "quecto_calc/parser"
6
+ require_relative "quecto_calc/version"
7
+
8
+ #
9
+ # A simple calculator that evaluates primitive arithmetic expressions represented in a text form.
10
+ #
11
+ # Supported operators:
12
+ # + -- add a number
13
+ # - -- subtract a number.
14
+ #
15
+ # Supported types:
16
+ # Integer;
17
+ # Constant (a string placeholder for an Integer).
18
+ #
19
+ # Parser/lexer stuff was inspired by the David Callanan's "Make Your Own Programming Language" series
20
+ # @ https://github.com/davidcallanan/py-myopl-code
21
+ #
22
+ class QuectoCalc
23
+ #
24
+ # Evaluate an expression.
25
+ #
26
+ # @param [String] expr
27
+ # Expression to parse and evaluate.
28
+ #
29
+ # @option [Hash{ String => Numeric }] consts
30
+ # List on constants and their values to put in the expression.
31
+ #
32
+ def evaluate(expr, consts = {})
33
+ tokens = build_tokens(expr)
34
+ ast = build_ast(tokens)
35
+ evaluate_ast(ast, consts)
36
+ rescue QuectoError => e
37
+ puts "#{e.error_name} #{e.message}"
38
+ end
39
+
40
+ #
41
+ # Get a list of tokens from the string.
42
+ #
43
+ # @param [String] expr
44
+ #
45
+ def build_tokens(expr)
46
+ Lexer.new(expr).build_tokens
47
+ end
48
+
49
+ #
50
+ # Build an abstract syntax tree from a list of tokens.
51
+ #
52
+ # @param [Array<Token>] tokens
53
+ #
54
+ def build_ast(tokens)
55
+ Parser.new(tokens).parse
56
+ end
57
+
58
+ #
59
+ # Evaluate expression from the AST.
60
+ #
61
+ # @param [NumberNode, BinOpNode] ast
62
+ # Expression (in a form of AST) to evaluate.
63
+ #
64
+ # @option [Hash{ String => Numeric }] consts
65
+ # List on constants and their values to put in the expression.
66
+ #
67
+ def evaluate_ast(ast, consts = {})
68
+ evaluator = Evaluator.new(consts)
69
+ evaluator.visit(ast)
70
+ end
71
+ end
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "lib/quecto_calc/version"
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = "quecto_calc"
7
+ spec.version = QuectoCalc::VERSION
8
+ spec.authors = ["Mate"]
9
+ #spec.email = ["mate@example.com"]
10
+
11
+ spec.summary = "A very simple calculator."
12
+ spec.description = "Evaluates primitive arithmetic expressions represented in a text form."
13
+ spec.homepage = "https://github.com/8bit-mate/quecto_calc.rb/"
14
+ spec.license = "MIT"
15
+ spec.required_ruby_version = Gem::Requirement.new(">= 3.0.0")
16
+
17
+ spec.metadata["allowed_push_host"] = "https://rubygems.org/"
18
+
19
+ spec.metadata["homepage_uri"] = spec.homepage
20
+ spec.metadata["source_code_uri"] = spec.homepage
21
+ spec.metadata["changelog_uri"] = "https://github.com/8bit-mate/quecto_calc.rb/blob/main/CHANGELOG.md"
22
+
23
+ # Specify which files should be added to the gem when it is released.
24
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
25
+ spec.files = Dir.chdir(File.expand_path(__dir__)) do
26
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{\A(?:test|spec|features)/}) }
27
+ end
28
+ spec.bindir = "exe"
29
+ spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
30
+ spec.require_paths = ["lib"]
31
+
32
+ # Uncomment to register a new dependency of your gem
33
+ # spec.add_dependency "example-gem", "~> 1.0"
34
+
35
+ # For more information and examples about making a new gem, checkout our
36
+ # guide at: https://bundler.io/guides/creating_gem.html
37
+ end
metadata ADDED
@@ -0,0 +1,68 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: quecto_calc
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Mate
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2023-02-17 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: Evaluates primitive arithmetic expressions represented in a text form.
14
+ email:
15
+ executables: []
16
+ extensions: []
17
+ extra_rdoc_files: []
18
+ files:
19
+ - ".gitignore"
20
+ - ".rubocop.yml"
21
+ - CHANGELOG.md
22
+ - Gemfile
23
+ - Gemfile.lock
24
+ - LICENSE.txt
25
+ - README.md
26
+ - Rakefile
27
+ - bin/console
28
+ - bin/setup
29
+ - lib/quecto_calc.rb
30
+ - lib/quecto_calc/bin_op_node.rb
31
+ - lib/quecto_calc/char_rules.rb
32
+ - lib/quecto_calc/evaluator.rb
33
+ - lib/quecto_calc/lexer.rb
34
+ - lib/quecto_calc/number_node.rb
35
+ - lib/quecto_calc/parser.rb
36
+ - lib/quecto_calc/quecto_error.rb
37
+ - lib/quecto_calc/token.rb
38
+ - lib/quecto_calc/token_types.rb
39
+ - lib/quecto_calc/version.rb
40
+ - quecto_calc.gemspec
41
+ homepage: https://github.com/8bit-mate/quecto_calc.rb/
42
+ licenses:
43
+ - MIT
44
+ metadata:
45
+ allowed_push_host: https://rubygems.org/
46
+ homepage_uri: https://github.com/8bit-mate/quecto_calc.rb/
47
+ source_code_uri: https://github.com/8bit-mate/quecto_calc.rb/
48
+ changelog_uri: https://github.com/8bit-mate/quecto_calc.rb/blob/main/CHANGELOG.md
49
+ post_install_message:
50
+ rdoc_options: []
51
+ require_paths:
52
+ - lib
53
+ required_ruby_version: !ruby/object:Gem::Requirement
54
+ requirements:
55
+ - - ">="
56
+ - !ruby/object:Gem::Version
57
+ version: 3.0.0
58
+ required_rubygems_version: !ruby/object:Gem::Requirement
59
+ requirements:
60
+ - - ">="
61
+ - !ruby/object:Gem::Version
62
+ version: '0'
63
+ requirements: []
64
+ rubygems_version: 3.2.3
65
+ signing_key:
66
+ specification_version: 4
67
+ summary: A very simple calculator.
68
+ test_files: []