calcula 0.1.0 → 1.0.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 +4 -4
- data/.travis.yml +3 -0
- data/Gemfile +2 -0
- data/LICENSE.txt +1 -1
- data/README.md +5 -8
- data/lib/Expr.rb +32 -12
- data/lib/Exprs/AssignExpr.rb +39 -0
- data/lib/Exprs/BinopExpr.rb +53 -0
- data/lib/Exprs/BracedExpr.rb +48 -0
- data/lib/Exprs/FuncExpr.rb +31 -31
- data/lib/Exprs/IdentExpr.rb +25 -17
- data/lib/Exprs/NumExpr.rb +25 -17
- data/lib/Exprs/ParamsExpr.rb +24 -18
- data/lib/Exprs/RatExpr.rb +37 -0
- data/lib/Exprs/UnaryExpr.rb +84 -0
- data/lib/Lexer.rb +158 -119
- data/lib/Parser.rb +317 -40
- data/lib/Token.rb +23 -4
- data/lib/calcula.rb +79 -4
- data/lib/calcula/version.rb +1 -1
- metadata +7 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 397e946ee023cbfbe15fbd3c78e7fda729e9fa41
|
4
|
+
data.tar.gz: ad9f8f5b4da62221b96e08e4ff3afd2887317f40
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9017478c73db894b546a21bd0563a5e40cbca71281831223fe345b581a0d5c585791195fc1f10c988a413ba81715ddd792967c95882cca31cfe573e573a15817
|
7
|
+
data.tar.gz: f4033ce6ce081fbf36995db752a7f90c96844663949d78abdc5fa7846b4cef0e808728940dcce1a4bc1508f996c6fdb6092f7a69b7d08f9ab0136bca527c9778
|
data/.travis.yml
CHANGED
data/Gemfile
CHANGED
data/LICENSE.txt
CHANGED
data/README.md
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# Calcula [](https://travis-ci.org/plankp/Calcula) [](http://inch-ci.org/github/plankp/Calcula)
|
1
|
+
# Calcula [](https://travis-ci.org/plankp/Calcula) [](https://codeclimate.com/github/plankp/Calcula) [](http://inch-ci.org/github/plankp/Calcula) [](https://badge.fury.io/rb/calcula)
|
2
2
|
|
3
3
|
When mathematics meets programming
|
4
4
|
|
@@ -22,17 +22,14 @@ Or install it yourself as:
|
|
22
22
|
|
23
23
|
## Usage
|
24
24
|
|
25
|
-
|
26
|
-
To do so, type in:
|
25
|
+
To compile Calcula code to ruby, type in:
|
27
26
|
|
28
27
|
```ruby
|
29
28
|
require "calcula"
|
30
29
|
src = <<-'EOS'
|
31
|
-
# Write some
|
30
|
+
# Write some Calcula code here
|
32
31
|
EOS
|
33
|
-
|
34
|
-
puts tokens.collect { |e| e.text }.to_s
|
35
|
-
puts Calcula.parse(tokens).to_tree
|
32
|
+
puts Calcula::compile(src)
|
36
33
|
```
|
37
34
|
|
38
35
|
## Development
|
@@ -47,4 +44,4 @@ Bug reports and pull requests are welcome on GitHub at https://github.com/plankp
|
|
47
44
|
|
48
45
|
## License
|
49
46
|
|
50
|
-
The gem is available as open source under the terms of the [MIT License](
|
47
|
+
The gem is available as open source under the terms of the [MIT License](./LICENSE.txt).
|
data/lib/Expr.rb
CHANGED
@@ -1,20 +1,40 @@
|
|
1
|
+
# @author Paul T.
|
1
2
|
module Calcula
|
2
|
-
class Expr
|
3
|
-
|
4
|
-
def to_s()
|
5
|
-
""
|
6
|
-
end
|
7
3
|
|
8
|
-
|
9
|
-
|
10
|
-
|
4
|
+
# All valid tree expression must be childrens of this class and should be
|
5
|
+
# placed under the module `Calcula::Exprs`
|
6
|
+
#
|
7
|
+
# @see Calcula::Exprs
|
8
|
+
# @abstract
|
9
|
+
# @author Paul T.
|
10
|
+
class Expr
|
11
11
|
|
12
|
-
#
|
13
|
-
|
14
|
-
|
12
|
+
# Converts the expression to a string. If the form is `:src`, then the
|
13
|
+
# resulting string should resemble as much as its source code as possible.
|
14
|
+
# If the form is `:tree`, the result string should resemble in a Lisp like
|
15
|
+
# form. If the form is `:ruby`, the result should be Ruby code that does the
|
16
|
+
# same thing. Otherwise, `nil` should be returned.
|
17
|
+
#
|
18
|
+
# @param form [Optional, Symbol] The type of format being converted into
|
19
|
+
# @return [String, nil] A string that resembles the specify form
|
20
|
+
def to_s(form: :src)
|
21
|
+
case form
|
22
|
+
when :src then
|
23
|
+
""
|
24
|
+
when :tree then
|
25
|
+
"()"
|
26
|
+
when :ruby then
|
27
|
+
""
|
28
|
+
else
|
29
|
+
nil
|
30
|
+
end
|
15
31
|
end
|
16
32
|
|
17
|
-
|
33
|
+
# Returns the child nodes as a list. Child nodes must be transversible
|
34
|
+
# (hence also expressions).
|
35
|
+
#
|
36
|
+
# @return [Array<Calcula::Expr>] A list of transversible child nodes
|
37
|
+
def children
|
18
38
|
[]
|
19
39
|
end
|
20
40
|
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require_relative "../Expr"
|
2
|
+
|
3
|
+
# Expression for assigning value to variables
|
4
|
+
#
|
5
|
+
# @author Paul T.
|
6
|
+
class Calcula::Exprs::AssignExpr < Calcula::Expr
|
7
|
+
|
8
|
+
# @param ident [Calcula::Exprs::IdentExpr]
|
9
|
+
# @param value [Calcula::Expr]
|
10
|
+
def initialize(ident, value)
|
11
|
+
@ident = ident
|
12
|
+
@value = value
|
13
|
+
end
|
14
|
+
|
15
|
+
# @see Calcula::Expr#to_s
|
16
|
+
# @param (see Calcula::Expr#to_s)
|
17
|
+
# @return (see Calcula::Expr#to_s)
|
18
|
+
def to_s(form: :src)
|
19
|
+
identTxt = @ident.to_s(form: form)
|
20
|
+
valueTxt = @value.to_s(form: form)
|
21
|
+
case form
|
22
|
+
when :src then
|
23
|
+
"let #{identTxt}=#{valueTxt}"
|
24
|
+
when :tree then
|
25
|
+
"(let #{identTxt} #{valueTxt})"
|
26
|
+
when :ruby then
|
27
|
+
"#{identTxt} = #{valueTxt}"
|
28
|
+
else
|
29
|
+
nil
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
# @see Calcula::Expr#children
|
34
|
+
# @param (see Calcula::Expr#children)
|
35
|
+
# @return (see Calcula::Expr#children)
|
36
|
+
def children
|
37
|
+
[@ident, @value]
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
require_relative "../Expr"
|
2
|
+
|
3
|
+
# Expression for binary operators. An expression 10(2) is also a binary operator.
|
4
|
+
# Its operator will be `:PAREN_O`
|
5
|
+
#
|
6
|
+
# @author Paul T.
|
7
|
+
class Calcula::Exprs::BinopExpr < Calcula::Expr
|
8
|
+
|
9
|
+
# @param op [Calcula::Token] Should have type prefixed with `OP_`
|
10
|
+
# @param left [Calcula::Expr]
|
11
|
+
# @param right [Calcula::Expr]
|
12
|
+
def initialize(op, left, right)
|
13
|
+
@op = op
|
14
|
+
@left = left
|
15
|
+
@right = right
|
16
|
+
end
|
17
|
+
|
18
|
+
# @see Calcula::Expr#to_s
|
19
|
+
# @param (see Calcula::Expr#to_s)
|
20
|
+
# @return (see Calcula::Expr#to_s)
|
21
|
+
def to_s(form: :src)
|
22
|
+
leftTxt = @left.to_s(form: form)
|
23
|
+
rightTxt = @right.to_s(form: form)
|
24
|
+
case form
|
25
|
+
when :src, :ruby then
|
26
|
+
case @op.id
|
27
|
+
when :PAREN_O then
|
28
|
+
"#{leftTxt}#{"." if form == :ruby}(#{rightTxt})"
|
29
|
+
when :OP_EQ then
|
30
|
+
"#{leftTxt}#{form == :ruby ? "==" : "="}#{rightTxt}"
|
31
|
+
when :AND then
|
32
|
+
"#{leftTxt}#{form == :ruby ? "&&" : " and "}#{rightTxt}"
|
33
|
+
when :OR then
|
34
|
+
"#{leftTxt}#{form == :ruby ? "||" : " or "}#{rightTxt}"
|
35
|
+
when :COMPOSE then
|
36
|
+
"->(*x){#{leftTxt}.(#{rightTxt}.(*x))}"
|
37
|
+
else
|
38
|
+
"#{leftTxt}#{@op.text}#{rightTxt}"
|
39
|
+
end
|
40
|
+
when :tree then
|
41
|
+
"(#{@op.text} #{leftTxt} #{rightTxt})"
|
42
|
+
else
|
43
|
+
nil
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
# @see Calcula::Expr#children
|
48
|
+
# @param (see Calcula::Expr#children)
|
49
|
+
# @return (see Calcula::Expr#children)
|
50
|
+
def children
|
51
|
+
[@left, @right]
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
require_relative "../Expr"
|
2
|
+
|
3
|
+
# Expression for bracket operators. Floor operators also count as bracket
|
4
|
+
# operators.
|
5
|
+
#
|
6
|
+
# @author Paul T.
|
7
|
+
class Calcula::Exprs::BracedExpr < Calcula::Expr
|
8
|
+
|
9
|
+
# @param startTok [Calcula::Token] The starting token of this expression
|
10
|
+
# @param endTok [Calcula::Token] The ending token of this expression
|
11
|
+
# @param inner [Calcula::Expr]
|
12
|
+
def initialize(startTok, endTok, inner)
|
13
|
+
@startTok = startTok
|
14
|
+
@endTok = endTok
|
15
|
+
@inner = inner
|
16
|
+
end
|
17
|
+
|
18
|
+
# @see Calcula::Expr#to_s
|
19
|
+
# @param (see Calcula::Expr#to_s)
|
20
|
+
# @return (see Calcula::Expr#to_s)
|
21
|
+
def to_s(form: :src)
|
22
|
+
innerTxt = @inner.to_s(form: form)
|
23
|
+
case form
|
24
|
+
when :src then
|
25
|
+
"#{@startTok.text}#{innerTxt}#{@endTok.text}"
|
26
|
+
when :tree then
|
27
|
+
"#{@startTok.text} #{innerTxt} #{@endTok.text}"
|
28
|
+
when :ruby then
|
29
|
+
case @startTok.id
|
30
|
+
when :PAREN_O then
|
31
|
+
"(#{innerTxt})"
|
32
|
+
when :SQUARE_O then
|
33
|
+
"(#{innerTxt}).floor.to_r"
|
34
|
+
else
|
35
|
+
raise "Unknown delimiter #{@startTok.id}"
|
36
|
+
end
|
37
|
+
else
|
38
|
+
nil
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
# @see Calcula::Expr#children
|
43
|
+
# @param (see Calcula::Expr#children)
|
44
|
+
# @return (see Calcula::Expr#children)
|
45
|
+
def children
|
46
|
+
[@inner]
|
47
|
+
end
|
48
|
+
end
|
data/lib/Exprs/FuncExpr.rb
CHANGED
@@ -1,39 +1,39 @@
|
|
1
1
|
require_relative "../Expr"
|
2
2
|
|
3
|
-
|
4
|
-
|
3
|
+
# Expression for functions and lambda expression
|
4
|
+
#
|
5
|
+
# @author Paul T.
|
6
|
+
class Calcula::Exprs::FuncExpr < Calcula::Expr
|
5
7
|
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
def to_s()
|
14
|
-
return "\\#{@params.to_s}(#{@action.to_s})" if @name == nil
|
15
|
-
return "#{@name.to_s}(#{@params.to_s})=#{@action.to_s}"
|
16
|
-
end
|
17
|
-
|
18
|
-
def to_tree()
|
19
|
-
return "(lambda #{@params.to_tree} #{@action.to_tree})" if @name == nil
|
20
|
-
return "(func #{@name.to_tree} #{@params.to_tree} #{@action.to_tree})"
|
21
|
-
end
|
22
|
-
|
23
|
-
def exec(binding)
|
24
|
-
if @name == nil then
|
25
|
-
# We return it (its a lambda function afterall...)
|
26
|
-
else
|
27
|
-
# We do not invoke this function. We just add it to the `binding`
|
28
|
-
end
|
29
|
-
end
|
8
|
+
# @param params [Calcula::Exprs::ParamsExpr] Parameters to the function
|
9
|
+
# @param action [Calcula::Expr] The body of the function
|
10
|
+
def initialize(params, action)
|
11
|
+
@params = params
|
12
|
+
@action = action
|
13
|
+
end
|
30
14
|
|
31
|
-
|
32
|
-
|
15
|
+
# @see Calcula::Expr#to_s
|
16
|
+
# @param (see Calcula::Expr#to_s)
|
17
|
+
# @return (see Calcula::Expr#to_s)
|
18
|
+
def to_s(form: :src)
|
19
|
+
paramsTxt = @params.to_s(form: form)
|
20
|
+
actionTxt = @action.to_s(form: form)
|
21
|
+
case form
|
22
|
+
when :src then
|
23
|
+
"\\#{paramsTxt}(#{actionTxt})"
|
24
|
+
when :tree then
|
25
|
+
"(lambda #{paramsTxt} #{actionTxt})"
|
26
|
+
when :ruby then
|
27
|
+
"->#{paramsTxt}{#{actionTxt}}"
|
28
|
+
else
|
29
|
+
nil
|
33
30
|
end
|
31
|
+
end
|
34
32
|
|
35
|
-
|
36
|
-
|
37
|
-
|
33
|
+
# @see Calcula::Expr#children
|
34
|
+
# @param (see Calcula::Expr#children)
|
35
|
+
# @return (see Calcula::Expr#children)
|
36
|
+
def children
|
37
|
+
[@params, @action]
|
38
38
|
end
|
39
39
|
end
|
data/lib/Exprs/IdentExpr.rb
CHANGED
@@ -1,27 +1,35 @@
|
|
1
1
|
require_relative "../Expr"
|
2
2
|
|
3
|
-
|
4
|
-
|
3
|
+
# Expression for identifiers
|
4
|
+
#
|
5
|
+
# @author Paul T.
|
6
|
+
class Calcula::Exprs::IdentExpr < Calcula::Expr
|
5
7
|
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
8
|
+
# @param name [Calcula::Token] This token should have the type ID
|
9
|
+
def initialize(name)
|
10
|
+
@name = name
|
11
|
+
end
|
10
12
|
|
11
|
-
|
13
|
+
# @see Calcula::Expr#to_s
|
14
|
+
# @param (see Calcula::Expr#to_s)
|
15
|
+
# @return (see Calcula::Expr#to_s)
|
16
|
+
def to_s(form: :src)
|
17
|
+
case form
|
18
|
+
when :src then
|
12
19
|
@name.text
|
13
|
-
|
14
|
-
|
15
|
-
def to_tree()
|
20
|
+
when :tree then
|
16
21
|
"(ident #{@name.text})"
|
22
|
+
when :ruby then
|
23
|
+
@name.text.tr("'", "_")
|
24
|
+
else
|
25
|
+
nil
|
17
26
|
end
|
27
|
+
end
|
18
28
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
[]
|
25
|
-
end
|
29
|
+
# @see Calcula::Expr#children
|
30
|
+
# @param (see Calcula::Expr#children)
|
31
|
+
# @return (see Calcula::Expr#children)
|
32
|
+
def children
|
33
|
+
[]
|
26
34
|
end
|
27
35
|
end
|
data/lib/Exprs/NumExpr.rb
CHANGED
@@ -1,27 +1,35 @@
|
|
1
1
|
require_relative "../Expr"
|
2
2
|
|
3
|
-
|
4
|
-
|
3
|
+
# Expression for representing real numbers
|
4
|
+
#
|
5
|
+
# @author Paul T.
|
6
|
+
class Calcula::Exprs::NumExpr < Calcula::Expr
|
5
7
|
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
8
|
+
# @param num [Calcula::Token] The token should have the type of NUM
|
9
|
+
def initialize(num)
|
10
|
+
@num = num
|
11
|
+
end
|
10
12
|
|
11
|
-
|
13
|
+
# @see Calcula::Expr#to_s
|
14
|
+
# @param (see Calcula::Expr#to_s)
|
15
|
+
# @return (see Calcula::Expr#to_s)
|
16
|
+
def to_s(form: :src)
|
17
|
+
case form
|
18
|
+
when :src then
|
12
19
|
@num.text
|
13
|
-
|
14
|
-
|
15
|
-
def to_tree()
|
20
|
+
when :tree then
|
16
21
|
"(num #{@num.text})"
|
22
|
+
when :ruby then
|
23
|
+
"#{@num.text}r"
|
24
|
+
else
|
25
|
+
nil
|
17
26
|
end
|
27
|
+
end
|
18
28
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
[]
|
25
|
-
end
|
29
|
+
# @see Calcula::Expr#children
|
30
|
+
# @param (see Calcula::Expr#children)
|
31
|
+
# @return (see Calcula::Expr#children)
|
32
|
+
def children
|
33
|
+
[]
|
26
34
|
end
|
27
35
|
end
|