jaina 0.0.0 → 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 +4 -4
- data/.gitignore +1 -0
- data/.travis.yml +19 -0
- data/README.md +160 -1
- data/jaina.gemspec +2 -1
- data/lib/jaina/parser/ast/context.rb +98 -0
- data/lib/jaina/parser/ast/evaluator.rb +17 -0
- data/lib/jaina/parser/ast/tree.rb +35 -0
- data/lib/jaina/parser/ast/tree_builder.rb +129 -0
- data/lib/jaina/parser/ast.rb +62 -0
- data/lib/jaina/parser/code_converter/to_postfix_form.rb +167 -0
- data/lib/jaina/parser/code_converter/to_prefix_form.rb +122 -0
- data/lib/jaina/parser/code_converter.rb +28 -0
- data/lib/jaina/parser/expression/operator/abstract/dsl.rb +256 -0
- data/lib/jaina/parser/expression/operator/abstract.rb +67 -0
- data/lib/jaina/parser/expression/operator/and.rb +12 -0
- data/lib/jaina/parser/expression/operator/grouping/dsl.rb +100 -0
- data/lib/jaina/parser/expression/operator/grouping.rb +12 -0
- data/lib/jaina/parser/expression/operator/left_corner.rb +10 -0
- data/lib/jaina/parser/expression/operator/non_terminal.rb +25 -0
- data/lib/jaina/parser/expression/operator/not.rb +12 -0
- data/lib/jaina/parser/expression/operator/or.rb +12 -0
- data/lib/jaina/parser/expression/operator/right_corner.rb +10 -0
- data/lib/jaina/parser/expression/operator/terminal.rb +25 -0
- data/lib/jaina/parser/expression/operator.rb +15 -0
- data/lib/jaina/parser/expression/registry/access_interface_mixin.rb +49 -0
- data/lib/jaina/parser/expression/registry.rb +127 -0
- data/lib/jaina/parser/expression.rb +87 -0
- data/lib/jaina/parser/tokenizer.rb +37 -0
- data/lib/jaina/parser.rb +44 -0
- data/lib/jaina/version.rb +5 -1
- data/lib/jaina.rb +58 -4
- metadata +29 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5b071350b636b4d475d51836639fa20c3b62f5518eddd4d0e71aa70cf9a9a1f9
|
4
|
+
data.tar.gz: eec63665a26dc9de484fd162795332e79762e2b4da24a637753468b06c5cfd8b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 56422133b95ab2bbfdcb720aea41a320d0c147e26ffca1de3fcf1a7cc013af2bb2cc9462634eee9dc4f1296584a6488b9fc63555aafc6bd37814e01d000c6f35
|
7
|
+
data.tar.gz: e5127b38022694809fd58644d86b9434bd4e368d1467b2a13d36ebe22103b5117a29bc2aaa11b6298dae0109f1ae6dea9f0d11983db52e45c3f1b447000ee54b
|
data/.gitignore
CHANGED
data/.travis.yml
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
language: ruby
|
2
|
+
matrix:
|
3
|
+
fast_finish: true
|
4
|
+
include:
|
5
|
+
- rvm: 2.3
|
6
|
+
- rvm: 2.4
|
7
|
+
- rvm: 2.5
|
8
|
+
- rvm: 2.6
|
9
|
+
- rvm: ruby-head
|
10
|
+
- rvm: jruby-head
|
11
|
+
allow_failures:
|
12
|
+
- rvm: ruby-head
|
13
|
+
- rvm: jruby-head
|
14
|
+
sudo: false
|
15
|
+
cache: bundler
|
16
|
+
before_install: gem install bundler
|
17
|
+
script:
|
18
|
+
- bundke exec rubocop
|
19
|
+
- bundle exec rspec
|
data/README.md
CHANGED
@@ -1 +1,160 @@
|
|
1
|
-
# Jaina
|
1
|
+
# Jaina · [](https://badge.fury.io/rb/jaina) [](https://travis-ci.org/0exp/jaina) [](https://coveralls.io/github/0exp/jaina?branch=master)
|
2
|
+
|
3
|
+
Simple programming language builder inspired by interpreter pattern.
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
```ruby
|
8
|
+
gem 'jaina'
|
9
|
+
```
|
10
|
+
|
11
|
+
```shell
|
12
|
+
$ bundle install
|
13
|
+
# --- or ---
|
14
|
+
$ gem install 'jaina'
|
15
|
+
```
|
16
|
+
|
17
|
+
```ruby
|
18
|
+
require 'jaina'
|
19
|
+
```
|
20
|
+
|
21
|
+
## Usage
|
22
|
+
|
23
|
+
- [Registered operators](#registered-operators)
|
24
|
+
- [Register your own operator](#register-your-own-operator)
|
25
|
+
- [Register your own operand](#register-your-own-operand)
|
26
|
+
- [Context API](#context-api)
|
27
|
+
- [Parse your code (build AST)](#parse-your-code-build-ast)
|
28
|
+
- [Evaluate your code](#evaluate-your-code)
|
29
|
+
- [List registered operands and operators](#list-and-fetch-registered-operands-and-operators)
|
30
|
+
|
31
|
+
---
|
32
|
+
|
33
|
+
### Registered operators
|
34
|
+
|
35
|
+
- `AND`
|
36
|
+
- `OR`
|
37
|
+
- `NOT`
|
38
|
+
- `(`, `)` (grouping operators)
|
39
|
+
|
40
|
+
---
|
41
|
+
|
42
|
+
### Register your own operator
|
43
|
+
|
44
|
+
```ruby
|
45
|
+
# step 1: define new operator
|
46
|
+
class But < Jaina::NonTerminalExpr
|
47
|
+
token 'BUT' # use it in your program :)
|
48
|
+
associativity_direction :left # associativity (left or right)
|
49
|
+
acts_as_binary_term # binar or unary
|
50
|
+
precedence_level 4 # for example: AND > OR, NOT > AND, and etc...
|
51
|
+
end
|
52
|
+
|
53
|
+
# step 2: regsiter your operator
|
54
|
+
Jaina.register_expression(But)
|
55
|
+
```
|
56
|
+
|
57
|
+
---
|
58
|
+
|
59
|
+
### Register your own operand
|
60
|
+
|
61
|
+
```ruby
|
62
|
+
# step 1: define new operand
|
63
|
+
class A < Jaina::TerminalExpr
|
64
|
+
token 'A'
|
65
|
+
|
66
|
+
# NOTE: context is a custom data holder that passed from expression to expression
|
67
|
+
def evaluate(context)
|
68
|
+
# your custom evaluation code
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
# step 2: regsiter your operand
|
73
|
+
Jaina.register_expression(A)
|
74
|
+
```
|
75
|
+
|
76
|
+
---
|
77
|
+
|
78
|
+
### Context API
|
79
|
+
|
80
|
+
```ruby
|
81
|
+
class A < Jaina::TerminalExpr
|
82
|
+
# ... some code
|
83
|
+
|
84
|
+
def evaluate(context)
|
85
|
+
... your code ...
|
86
|
+
# ... context ???
|
87
|
+
... your code ...
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
# NOTE: context api
|
92
|
+
|
93
|
+
context.keys # => []
|
94
|
+
context.set(:a, 1) # => 1
|
95
|
+
context.get(:a) # => 1
|
96
|
+
context.keys # => [:a]
|
97
|
+
context.get(:b) # => Jaina::Parser::AST::Contex::UndefinedContextKeyError
|
98
|
+
```
|
99
|
+
|
100
|
+
---
|
101
|
+
|
102
|
+
### Parse your code (build AST)
|
103
|
+
|
104
|
+
```ruby
|
105
|
+
Jaina.parse('A AND B AND (C OR D) OR A AND (C OR E)')
|
106
|
+
# => #<Jaina::Parser::AST:0x00007fd6f424a2e8>
|
107
|
+
```
|
108
|
+
|
109
|
+
---
|
110
|
+
|
111
|
+
### Evaluate your code
|
112
|
+
|
113
|
+
```ruby
|
114
|
+
ast = Jaina.parse('A AND B AND (C OR D) OR A AND (C OR E)')
|
115
|
+
ast.evaluate
|
116
|
+
|
117
|
+
# --- or ---
|
118
|
+
Jaina.evaluate('A AND B AND (C OR D) OR A AND (C OR E)')
|
119
|
+
```
|
120
|
+
|
121
|
+
---
|
122
|
+
|
123
|
+
### List and fetch registered operands and operators
|
124
|
+
|
125
|
+
```ruby
|
126
|
+
A = Class.new(Jaina::TerminalExpr) { token 'A' }
|
127
|
+
B = Class.new(Jaina::TerminalExpr) { token 'B' }
|
128
|
+
C = Class.new(Jaina::TerminalExpr) { token 'C' }
|
129
|
+
|
130
|
+
Jaina.register_expression(A)
|
131
|
+
Jaina.register_expression(B)
|
132
|
+
Jaina.register_expression(C)
|
133
|
+
|
134
|
+
Jaina.expressions
|
135
|
+
# => ["AND", "OR", "NOT", "(", ")", "A", "B", "C"]
|
136
|
+
|
137
|
+
Jaina.fetch_expression("AND") # => Jaina::Parser::Expression::Operator::And
|
138
|
+
Jaina.fetch_expression("A") # => A
|
139
|
+
|
140
|
+
Jaina.fetch_expression("KEK")
|
141
|
+
# => raises Jaina::Parser::Expression::Registry::UnregisteredExpressionError
|
142
|
+
```
|
143
|
+
|
144
|
+
---
|
145
|
+
|
146
|
+
## Contributing
|
147
|
+
|
148
|
+
- Fork it ( https://github.com/0exp/jaina/fork )
|
149
|
+
- Create your feature branch (`git checkout -b feature/my-new-feature`)
|
150
|
+
- Commit your changes (`git commit -am 'Add some feature'`)
|
151
|
+
- Push to the branch (`git push origin feature/my-new-feature`)
|
152
|
+
- Create new Pull Request
|
153
|
+
|
154
|
+
## License
|
155
|
+
|
156
|
+
Released under MIT License.
|
157
|
+
|
158
|
+
## Authors
|
159
|
+
|
160
|
+
[Rustam Ibragimov](https://github.com/0exp)
|
data/jaina.gemspec
CHANGED
@@ -13,7 +13,8 @@ Gem::Specification.new do |spec|
|
|
13
13
|
|
14
14
|
spec.homepage = 'https://github.com/0exp/jaina'
|
15
15
|
spec.summary = 'Simple programming language builder inspired by interpreter pattern.'
|
16
|
-
spec.description = 'Simple programming language builder inspired by interpreter pattern.'
|
16
|
+
spec.description = 'Simple programming language builder inspired by interpreter pattern. ' \
|
17
|
+
'You can build your own langs for any project purposes.'
|
17
18
|
|
18
19
|
spec.bindir = 'bin'
|
19
20
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
@@ -0,0 +1,98 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# @api public
|
4
|
+
# @since 0.1.0
|
5
|
+
class Jaina::Parser::AST::Context
|
6
|
+
# @since 0.1.0
|
7
|
+
Error = Class.new(StandardError)
|
8
|
+
# @since 0.1.0
|
9
|
+
UndefinedContextKeyError = Class.new(Error)
|
10
|
+
|
11
|
+
# @return [void]
|
12
|
+
#
|
13
|
+
# @api private
|
14
|
+
# @since 0.1.0
|
15
|
+
def initialize
|
16
|
+
@data = {}
|
17
|
+
@access_lock = Mutex.new
|
18
|
+
end
|
19
|
+
|
20
|
+
# @param key [Any]
|
21
|
+
# @param value [Any]
|
22
|
+
# @return [Any]
|
23
|
+
#
|
24
|
+
# @api public
|
25
|
+
# @since 0.1.0
|
26
|
+
def set(key, value)
|
27
|
+
thread_safe { apply(key, value) }
|
28
|
+
end
|
29
|
+
|
30
|
+
# @param key [Any]
|
31
|
+
# @return [Any]
|
32
|
+
#
|
33
|
+
# @api public
|
34
|
+
# @since 0.1.0
|
35
|
+
def get(key)
|
36
|
+
thread_safe { get(key) }
|
37
|
+
end
|
38
|
+
|
39
|
+
# @return [Array<Any>]
|
40
|
+
#
|
41
|
+
# @api public
|
42
|
+
# @since 0.1.0
|
43
|
+
def keys
|
44
|
+
thread_safe { registered_data }
|
45
|
+
end
|
46
|
+
|
47
|
+
private
|
48
|
+
|
49
|
+
# @return [Hash<Any,Any>]
|
50
|
+
#
|
51
|
+
# @api private
|
52
|
+
# @since 0.1.0
|
53
|
+
attr_reader :data
|
54
|
+
|
55
|
+
# @return [Mutex]
|
56
|
+
#
|
57
|
+
# @api private
|
58
|
+
# @since 0.1.0
|
59
|
+
attr_reader :access_lock
|
60
|
+
|
61
|
+
# @param block [Proc]
|
62
|
+
# @return [Any]
|
63
|
+
#
|
64
|
+
# @api private
|
65
|
+
# @since 0.1.0
|
66
|
+
def thread_safe(&block)
|
67
|
+
access_lock.synchronize { yield }
|
68
|
+
end
|
69
|
+
|
70
|
+
# @param key [Any]
|
71
|
+
# @param value [Any]
|
72
|
+
# @return [Any]
|
73
|
+
#
|
74
|
+
# @api private
|
75
|
+
# @since 0.1.0
|
76
|
+
def apply(key, value)
|
77
|
+
value.tap { data[key] = value }
|
78
|
+
end
|
79
|
+
|
80
|
+
# @return [Array<Any>]
|
81
|
+
#
|
82
|
+
# @api private
|
83
|
+
# @since 0.1.0
|
84
|
+
def registered_data
|
85
|
+
data.keys
|
86
|
+
end
|
87
|
+
|
88
|
+
# @param key [String]
|
89
|
+
# @return [Any]
|
90
|
+
#
|
91
|
+
# @api private
|
92
|
+
# @since 0.1.0
|
93
|
+
def fetch(key)
|
94
|
+
data.fetch(key)
|
95
|
+
rescue KeyError
|
96
|
+
raise UndefinedContextKeyError, "Data with `#{key}` key does not exist"
|
97
|
+
end
|
98
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# @api private
|
4
|
+
# @since 0.1.0
|
5
|
+
module Jaina::Parser::AST::Evaluator
|
6
|
+
class << self
|
7
|
+
# @param ast [Jaina::Parser::AST]
|
8
|
+
# @return [Any]
|
9
|
+
#
|
10
|
+
# @api private
|
11
|
+
# @since 0.1.0
|
12
|
+
def evaluate(ast)
|
13
|
+
context = Jaina::Parser::AST::Context.new
|
14
|
+
# TODO: traverse the abstract syntax tree
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# @api private
|
4
|
+
# @since 0.1.0
|
5
|
+
class Jaina::Parser::AST::Tree
|
6
|
+
# @return [String]
|
7
|
+
#
|
8
|
+
# @api private
|
9
|
+
# @since 0.1.0
|
10
|
+
attr_reader :initial_program
|
11
|
+
|
12
|
+
# @return [String]
|
13
|
+
#
|
14
|
+
# @api private
|
15
|
+
# @since 0.1.0
|
16
|
+
attr_reader :ast_oriented_program
|
17
|
+
|
18
|
+
# @return [Jaina::Parser::Expression::Operator::Abstract]
|
19
|
+
#
|
20
|
+
# @api private
|
21
|
+
# @since 0.1.0
|
22
|
+
attr_reader :expression
|
23
|
+
|
24
|
+
# @param initial_program [String]
|
25
|
+
# @param expression [Jaina::Parser::Expression::Operator::Abstract]
|
26
|
+
# @return [void]
|
27
|
+
#
|
28
|
+
# @api private
|
29
|
+
# @since 0.1.0
|
30
|
+
def initialize(initial_program:, ast_oriented_program:, expression:)
|
31
|
+
@initial_program = initial_program
|
32
|
+
@ast_oriented_program = ast_oriented_program
|
33
|
+
@expression = expression
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,129 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# @api private
|
4
|
+
# @since 0.1.0
|
5
|
+
class Jaina::Parser::AST::TreeBuilder
|
6
|
+
# @since 0.1.0
|
7
|
+
extend Forwardable
|
8
|
+
|
9
|
+
class << self
|
10
|
+
# @param program [String]
|
11
|
+
# @return [Jaina::Parser::AST::Tree]
|
12
|
+
#
|
13
|
+
# @api private
|
14
|
+
# @since 0.1.0
|
15
|
+
def build(program)
|
16
|
+
new(program).build
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
# @since 0.1.0
|
21
|
+
def_delegators Jaina::Parser::Expression,
|
22
|
+
:terminal?,
|
23
|
+
:non_terminal?,
|
24
|
+
:acts_as_unary_term?,
|
25
|
+
:acts_as_binary_term?
|
26
|
+
|
27
|
+
# @param progrm [String]
|
28
|
+
# @return [void]
|
29
|
+
#
|
30
|
+
# @api private
|
31
|
+
# @since 0.1.0
|
32
|
+
def initialize(program)
|
33
|
+
@program = program.dup.tap(&:freeze)
|
34
|
+
@prefix_form = Jaina::Parser::CodeConverter.to_prefix_form(@program)
|
35
|
+
@tokens = Jaina::Parser::Tokenizer.tokenize(@prefix_form)
|
36
|
+
end
|
37
|
+
|
38
|
+
# @return [Jaina::Parser::AST:Tree]
|
39
|
+
#
|
40
|
+
# @api private
|
41
|
+
# @since 0.1.0
|
42
|
+
def build
|
43
|
+
token_series = tokens.map(&:dup)
|
44
|
+
expression_tree = build_expression_tree(token_series)
|
45
|
+
|
46
|
+
Jaina::Parser::AST::Tree.new(
|
47
|
+
initial_program: program,
|
48
|
+
ast_oriented_program: prefix_form,
|
49
|
+
expression: expression_tree
|
50
|
+
)
|
51
|
+
end
|
52
|
+
|
53
|
+
private
|
54
|
+
|
55
|
+
# @return [String]
|
56
|
+
#
|
57
|
+
# @api private
|
58
|
+
# @since 0.1.0
|
59
|
+
attr_reader :program
|
60
|
+
|
61
|
+
# @return [String]
|
62
|
+
#
|
63
|
+
# @api private
|
64
|
+
# @since 0.1.0
|
65
|
+
attr_reader :prefix_form
|
66
|
+
|
67
|
+
# @return [Array<String>]
|
68
|
+
#
|
69
|
+
# @api private
|
70
|
+
# @since 0.1.0
|
71
|
+
attr_reader :tokens
|
72
|
+
|
73
|
+
# @param token_series [Array<String>]
|
74
|
+
# @return [Array<Jaina::Parser::Expression::Operator::Abstract>]
|
75
|
+
#
|
76
|
+
# @api private
|
77
|
+
# @since 0.1.0
|
78
|
+
def build_expression_tree(token_series)
|
79
|
+
current_token = extract_second_token(token_series)
|
80
|
+
return if current_token.nil?
|
81
|
+
|
82
|
+
case
|
83
|
+
when terminal?(current_token)
|
84
|
+
build_terminal_expression(current_token)
|
85
|
+
when non_terminal?(current_token)
|
86
|
+
build_non_terminal_expression(current_token, token_series)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
# @param token_series [Array<String>]
|
91
|
+
# @return [String, NilClass]
|
92
|
+
#
|
93
|
+
# @api private
|
94
|
+
# @since 0.1.0
|
95
|
+
def extract_second_token(token_series)
|
96
|
+
token_series.shift
|
97
|
+
end
|
98
|
+
|
99
|
+
# @param current_token [String]
|
100
|
+
# @return [Jaina::Parser::Expression::Operator::Abstract]
|
101
|
+
#
|
102
|
+
# @api private
|
103
|
+
# @since 0.1.0
|
104
|
+
def build_terminal_expression(current_token)
|
105
|
+
Jaina::Parser::Expression.build(current_token)
|
106
|
+
end
|
107
|
+
|
108
|
+
# @param current_token [String]
|
109
|
+
# @param token_series [Array<String>]
|
110
|
+
# @return [Jaina::Parser::Expression::Operator::Abstract]
|
111
|
+
#
|
112
|
+
# @api private
|
113
|
+
# @since 0.1.0
|
114
|
+
def build_non_terminal_expression(current_token, token_series)
|
115
|
+
case
|
116
|
+
when acts_as_unary_term?(current_token)
|
117
|
+
Jaina::Parser::Expression.build(
|
118
|
+
current_token,
|
119
|
+
build_expression_tree(token_series)
|
120
|
+
)
|
121
|
+
when acts_as_binary_term?(current_token)
|
122
|
+
Jaina::Parser::Expression.build(
|
123
|
+
current_token,
|
124
|
+
build_expression_tree(token_series),
|
125
|
+
build_expression_tree(token_series)
|
126
|
+
)
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# @api private
|
4
|
+
# @since 0.1.0
|
5
|
+
class Jaina::Parser::AST
|
6
|
+
require_relative './ast/tree'
|
7
|
+
require_relative './ast/tree_builder'
|
8
|
+
require_relative './ast/evaluator'
|
9
|
+
require_relative './ast/context'
|
10
|
+
|
11
|
+
class << self
|
12
|
+
# @param program [String] Program string in prefix form
|
13
|
+
# @return [Jaina::Parser::AST]
|
14
|
+
#
|
15
|
+
# @api private
|
16
|
+
# @since 0.1.0
|
17
|
+
def build(program)
|
18
|
+
ast_tree = Jaina::Parser::AST::TreeBuilder.build(program)
|
19
|
+
new(program, ast_tree)
|
20
|
+
end
|
21
|
+
|
22
|
+
# @param program [String] Program string in prefix form
|
23
|
+
# @return [Any]
|
24
|
+
#
|
25
|
+
# @api private
|
26
|
+
# @since 0.1.0
|
27
|
+
def evaluate(program)
|
28
|
+
build(program).evaluate
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
# @return [Jaina::Pasrer::AST::Tree]
|
33
|
+
#
|
34
|
+
# @api private
|
35
|
+
# @since 0.1.0
|
36
|
+
attr_reader :ast_tree
|
37
|
+
|
38
|
+
# @return [String]
|
39
|
+
#
|
40
|
+
# @api private
|
41
|
+
# @since 0.1.0
|
42
|
+
attr_reader :program
|
43
|
+
|
44
|
+
# @param program [String]
|
45
|
+
# @param ast_tree [Jaina::Parser::AST::Tree]
|
46
|
+
# @return [void]
|
47
|
+
#
|
48
|
+
# @api private
|
49
|
+
# @since 0.1.0
|
50
|
+
def initialize(program, ast_tree)
|
51
|
+
@program = program.dup.tap(&:freeze)
|
52
|
+
@ast_tree = ast_tree
|
53
|
+
end
|
54
|
+
|
55
|
+
# @return [Any]
|
56
|
+
#
|
57
|
+
# @api private
|
58
|
+
# @since 0.1.0
|
59
|
+
def evaluate
|
60
|
+
Jaina::Parser::AST::Evaluator.evaluate(self)
|
61
|
+
end
|
62
|
+
end
|