turmali 0.0.1

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.
@@ -0,0 +1,156 @@
1
+ require "turmali/parser"
2
+ require "turmali/runtime/object"
3
+ require "turmali/runtime/method"
4
+ require "turmali/runtime/context"
5
+ require "turmali/runtime/class"
6
+ require "turmali/runtime/bootstrap"
7
+
8
+ # First, we create an simple wrapper class to encapsulate the interpretation process.
9
+ # All this does is parse the code and call `eval` on the node at the top of the AST.
10
+ class Interpreter
11
+ def initialize
12
+ @parser = Parser.new
13
+ end
14
+
15
+ def eval(code)
16
+ @parser.parse(code).eval(RootContext)
17
+ end
18
+ end
19
+
20
+ # The `Nodes` class will always be at the top of the AST. Its only purpose it to
21
+ # contain other nodes. It correspond to a block of code or a series of expressions.
22
+ #
23
+ # The `eval` method of every node is the "interpreter" part of our language.
24
+ # All nodes know how to evalualte themselves and return the result of their evaluation.
25
+ # The `context` variable is the `Context` in which the node is evaluated (local
26
+ # variables, current self and current class).
27
+ class Nodes
28
+ def eval(context)
29
+ return_value = nil
30
+ nodes.each do |node|
31
+ return_value = node.eval(context)
32
+ end
33
+ return_value || Constants["nil"] # Last result is return value (or nil if none).
34
+ end
35
+ end
36
+
37
+ # We're using `Constants` that we created before when bootstrapping the runtime to access
38
+ # the objects and classes from inside the runtime.
39
+ #
40
+ # Next, we implement `eval` on other node types. Think of that `eval` method as how the
41
+ # node bring itself to life inside the runtime.
42
+ class NumberNode
43
+ def eval(context)
44
+ Constants["Number"].new_with_value(value)
45
+ end
46
+ end
47
+
48
+ class StringNode
49
+ def eval(context)
50
+ Constants["String"].new_with_value(value)
51
+ end
52
+ end
53
+
54
+ class TrueNode
55
+ def eval(context)
56
+ Constants["true"]
57
+ end
58
+ end
59
+
60
+ class FalseNode
61
+ def eval(context)
62
+ Constants["false"]
63
+ end
64
+ end
65
+
66
+ class NilNode
67
+ def eval(context)
68
+ Constants["nil"]
69
+ end
70
+ end
71
+
72
+ class GetConstantNode
73
+ def eval(context)
74
+ Constants[name]
75
+ end
76
+ end
77
+
78
+ class GetLocalNode
79
+ def eval(context)
80
+ context.locals[name]
81
+ end
82
+ end
83
+
84
+ # When setting the value of a constant or a local variable, the `value` attribute
85
+ # is a node, created by the parser. We need to evaluate the node first, to convert
86
+ # it to an object, before storing it into a variable or constant.
87
+ class SetConstantNode
88
+ def eval(context)
89
+ Constants[name] = value.eval(context)
90
+ end
91
+ end
92
+
93
+ class SetLocalNode
94
+ def eval(context)
95
+ context.locals[name] = value.eval(context)
96
+ end
97
+ end
98
+
99
+ # The `CallNode` for calling a method is a little more complex. It needs to set the receiver
100
+ # first and then evaluate the arguments before calling the method.
101
+ class CallNode
102
+ def eval(context)
103
+ if receiver
104
+ value = receiver.eval(context)
105
+ else
106
+ value = context.current_self # Default to `self` if no receiver.
107
+ end
108
+
109
+ evaluated_arguments = arguments.map { |arg| arg.eval(context) }
110
+ value.call(method, evaluated_arguments)
111
+ end
112
+ end
113
+
114
+ # Defining a method, using the `def` keyword, is done by adding a method to the current class.
115
+ class DefNode
116
+ def eval(context)
117
+ method = TurmaliMethod.new(params, body)
118
+ context.current_class.runtime_methods[name] = method
119
+ end
120
+ end
121
+
122
+ # Defining a class is done in three steps:
123
+ #
124
+ # 1. Reopen or define the class.
125
+ # 2. Create a special context of evaluation (set `current_self` and `current_class` to the new class).
126
+ # 3. Evaluate the body of the class inside that context.
127
+ #
128
+ # Check back how `DefNode` was implemented, adding methods to `context.current_class`. Here is
129
+ # where we set the value of `current_class`.
130
+ class ClassNode
131
+ def eval(context)
132
+ turmali_class = Constants[name] # Check if class is already defined
133
+
134
+ unless turmali_class # Class doesn't exist yet
135
+ turmali_class = TurmaliClass.new
136
+ Constants[name] = turmali_class # Define the class in the runtime
137
+ end
138
+
139
+ class_context = Context.new(turmali_class, turmali_class)
140
+ body.eval(class_context)
141
+
142
+ turmali_class
143
+ end
144
+ end
145
+
146
+ # Finally, to implement `if` in our language,
147
+ # we turn the condition node into a Ruby value to use Ruby's `if`.
148
+ class IfNode
149
+ def eval(context)
150
+ if condition.eval(context).ruby_value
151
+ body.eval(context)
152
+ else # If no body is evaluated, we return nil.
153
+ Constants["nil"]
154
+ end
155
+ end
156
+ end
@@ -0,0 +1,129 @@
1
+ # Our lexer will be used like so: `Lexer.new.tokenize("code")`,
2
+ # and will return an array of tokens (a token being a tuple of `[TOKEN_TYPE, TOKEN_VALUE]`).
3
+ class Lexer
4
+ # First we define the special keywords of our language in a constant.
5
+ # It will be used later on in the tokenizing process to disambiguate
6
+ # an identifier (method name, local variable, etc.) from a keyword.
7
+ KEYWORDS = ["def", "class", "if", "true", "false", "nil"]
8
+
9
+ def tokenize(code)
10
+ code.chomp! # Remove extra line breaks
11
+ tokens = [] # This will hold the generated tokens
12
+
13
+ # We need to know how deep we are in the indentation so
14
+ # we keep track of the current indentation level we are in, and previous ones in the stack
15
+ # so that when we dedent, we can check if we're on the correct level.
16
+ current_indent = 0 # number of spaces in the last indent
17
+ indent_stack = []
18
+
19
+ # Here is how to implement a very simple scanner.
20
+ # Advance one character at the time until you find something to parse.
21
+ # We'll use regular expressions to scan from the current position (`i`)
22
+ # up to the end of the code.
23
+ i = 0 # Current character position
24
+ while i < code.size
25
+ chunk = code[i..-1]
26
+
27
+ # Each of the following `if/elsif`s will test the current code chunk with
28
+ # a regular expression. The order is important as we want to match `if`
29
+ # as a keyword, and not a method name, we'll need to apply it first.
30
+ #
31
+ # First, we'll scan for names: method names and variable names, which we'll call identifiers.
32
+ # Also scanning for special reserved keywords such as `if`, `def`
33
+ # and `true`.
34
+ if identifier = chunk[/\A([a-z]\w*)/, 1]
35
+ if KEYWORDS.include?(identifier) # keywords will generate [:IF, "if"]
36
+ tokens << [identifier.upcase.to_sym, identifier]
37
+ else
38
+ tokens << [:IDENTIFIER, identifier]
39
+ end
40
+ i += identifier.size # skip what we just parsed
41
+
42
+ # Now scanning for constants, names starting with a capital letter.
43
+ # Which means, class names are constants in our language.
44
+ elsif constant = chunk[/\A([A-Z]\w*)/, 1]
45
+ tokens << [:CONSTANT, constant]
46
+ i += constant.size
47
+
48
+ # Next, matching numbers. Our language will only support integers. But to add support for floats,
49
+ # you'd simply need to add a similar rule and adapt the regular expression accordingly.
50
+ elsif number = chunk[/\A([0-9]+)/, 1]
51
+ tokens << [:NUMBER, number.to_i]
52
+ i += number.size
53
+
54
+ # Of course, matching strings too. Anything between `"..."`.
55
+ elsif string = chunk[/\A"([^"]*)"/, 1]
56
+ tokens << [:STRING, string]
57
+ i += string.size + 2 # skip two more to exclude the `"`.
58
+
59
+ # And here's the indentation magic! We have to take care of 3 cases:
60
+ #
61
+ # if true: # 1) The block is created.
62
+ # line 1
63
+ # line 2 # 2) New line inside a block, at the same level.
64
+ # continue # 3) Dedent.
65
+ #
66
+ # This `elsif` takes care of the first case. The number of spaces will determine
67
+ # the indent level.
68
+ elsif indent = chunk[/\A\:\n( +)/m, 1] # Matches ": <newline> <spaces>"
69
+ if indent.size <= current_indent # indent should go up when creating a block
70
+ raise "Bad indent level, got #{indent.size} indents, " +
71
+ "expected > #{current_indent}"
72
+ end
73
+ current_indent = indent.size
74
+ indent_stack.push(current_indent)
75
+ tokens << [:INDENT, indent.size]
76
+ i += indent.size + 2
77
+
78
+ # The next `elsif` takes care of the two last cases:
79
+ #
80
+ # * Case 2: We stay in the same block if the indent level (number of spaces) is the
81
+ # same as `current_indent`.
82
+ # * Case 3: Close the current block, if indent level is lower than `current_indent`.
83
+ elsif indent = chunk[/\A\n( *)/m, 1] # Matches "<newline> <spaces>"
84
+ if indent.size == current_indent # Case 2
85
+ tokens << [:NEWLINE, "\n"] # Nothing to do, we're still in the same block
86
+ elsif indent.size < current_indent # Case 3
87
+ while indent.size < current_indent
88
+ indent_stack.pop
89
+ current_indent = indent_stack.last || 0
90
+ tokens << [:DEDENT, indent.size]
91
+ end
92
+ tokens << [:NEWLINE, "\n"]
93
+ else # indent.size > current_indent, error!
94
+ raise "Missing ':'" # Cannot increase indent level without using ":"
95
+ end
96
+ i += indent.size + 1
97
+
98
+ # Long operators such as `||`, `&&`, `==`, etc.
99
+ # will be matched by the following block.
100
+ # One character long operators are matched by the catch all `else` at the bottom.
101
+ elsif operator = chunk[/\A(\|\||&&|==|!=|<=|>=)/, 1]
102
+ tokens << [operator, operator]
103
+ i += operator.size
104
+
105
+ # We're ignoring spaces. Contrary to line breaks, spaces are meaningless in our language.
106
+ # That's why we don't create tokens for them. They are only used to separate other tokens.
107
+ elsif chunk.match(/\A /)
108
+ i += 1
109
+
110
+ # Finally, catch all single characters, mainly operators.
111
+ # We treat all other single characters as a token. Eg.: `( ) , . ! + - <`.
112
+ else
113
+ value = chunk[0,1]
114
+ tokens << [value, value]
115
+ i += 1
116
+
117
+ end
118
+
119
+ end
120
+
121
+ # Close all open blocks. If the code ends without dedenting, this will take care of
122
+ # balancing the `INDENT`...`DEDENT`s.
123
+ while indent = indent_stack.pop
124
+ tokens << [:DEDENT, indent_stack.first || 0]
125
+ end
126
+
127
+ tokens
128
+ end
129
+ end
@@ -0,0 +1,88 @@
1
+ # The first type is responsible for holding a collection of nodes,
2
+ # each one representing an expression. You can think of it as the internal
3
+ # representation of a block of code.
4
+ #
5
+ # Here we define nodes as Ruby classes that inherit from a `Struct`. This is a
6
+ # simple way, in Ruby, to create a class that holds some attributes (values).
7
+ # It is almost equivalent to:
8
+ #
9
+ # class Nodes
10
+ # def initialize(nodes)
11
+ # @nodes = nodes
12
+ # end
13
+ #
14
+ # def nodes
15
+ # @nodes
16
+ # end
17
+ # end
18
+ #
19
+ # n = Nodes.new("this is stored @nodes")
20
+ # n.nodes # => "this is stored @nodes"
21
+ #
22
+ # But Ruby's `Struct` takes care of overriding the `==` operator for us and a bunch of
23
+ # other things that will make testing easier.
24
+ class Nodes < Struct.new(:nodes)
25
+ def <<(node) # Useful method for adding a node on the fly.
26
+ nodes << node
27
+ self
28
+ end
29
+ end
30
+
31
+ # Literals are static values that have a Ruby representation. For example, a string, a number,
32
+ # `true`, `false`, `nil`, etc. We define a node for each one of those and store their Ruby
33
+ # representation inside their `value` attribute.
34
+ class LiteralNode < Struct.new(:value); end
35
+
36
+ class NumberNode < LiteralNode; end
37
+
38
+ class StringNode < LiteralNode; end
39
+
40
+ class TrueNode < LiteralNode
41
+ def initialize
42
+ super(true)
43
+ end
44
+ end
45
+
46
+ class FalseNode < LiteralNode
47
+ def initialize
48
+ super(false)
49
+ end
50
+ end
51
+
52
+ class NilNode < LiteralNode
53
+ def initialize
54
+ super(nil)
55
+ end
56
+ end
57
+
58
+ # The node for a method call holds the `receiver`,
59
+ # the object on which the method is called, the `method` name and its
60
+ # arguments, which are other nodes.
61
+ class CallNode < Struct.new(:receiver, :method, :arguments); end
62
+
63
+ # Retrieving the value of a constant by its `name` is done by the following node.
64
+ class GetConstantNode < Struct.new(:name); end
65
+
66
+ # And setting its value is done by this one. The `value` will be a node. If we're
67
+ # storing a number inside a constant, for example, `value` would contain an instance
68
+ # of `NumberNode`.
69
+ class SetConstantNode < Struct.new(:name, :value); end
70
+
71
+ # Similar to the previous nodes, the next ones are for dealing with local variables.
72
+ class GetLocalNode < Struct.new(:name); end
73
+
74
+ class SetLocalNode < Struct.new(:name, :value); end
75
+
76
+ # Each method definition will be stored into the following node. It holds the `name` of the method,
77
+ # the name of its parameters (`params`) and the `body` to evaluate when the method is called, which
78
+ # is a tree of node, the root one being a `Nodes` instance.
79
+ class DefNode < Struct.new(:name, :params, :body); end
80
+
81
+ # Class definitions are stored into the following node. Once again, the `name` of the class and
82
+ # its `body`, a tree of nodes.
83
+ class ClassNode < Struct.new(:name, :body); end
84
+
85
+ # `if` control structures are stored in a node of their own. The `condition` and `body` will also
86
+ # be nodes that need to be evaluated at some point.
87
+ # Look at this node if you want to implement other control structures like `while`, `for`, `loop`, etc.
88
+ class IfNode < Struct.new(:condition, :body); end
@@ -0,0 +1,683 @@
1
+ #
2
+ # DO NOT MODIFY!!!!
3
+ # This file is automatically generated by Racc 1.4.6
4
+ # from Racc grammer file "".
5
+ #
6
+
7
+ require 'racc/parser.rb'
8
+
9
+ require "turmali/lexer"
10
+ require "turmali/nodes"
11
+
12
+ class Parser < Racc::Parser
13
+
14
+ module_eval(<<'...end grammar.y/module_eval...', 'grammar.y', 220)
15
+ def parse(code, show_tokens=false)
16
+ @tokens = Lexer.new.tokenize(code) # Tokenize the code using our lexer
17
+ puts @tokens.inspect if show_tokens
18
+ do_parse # Kickoff the parsing process
19
+ end
20
+
21
+ def next_token
22
+ @tokens.shift
23
+ end
24
+ ...end grammar.y/module_eval...
25
+ ##### State transition tables begin ###
26
+
27
+ racc_action_table = [
28
+ 27, 25, 26, 16, 18, 19, 20, 21, 22, 23,
29
+ 24, 27, 25, 26, 16, 18, 19, 20, 21, 22,
30
+ 23, 24, 30, 72, 41, 42, 39, 40, 53, 15,
31
+ 30, 17, 41, 42, 39, 40, 30, 16, 16, 30,
32
+ 15, 74, 17, 27, 25, 26, 84, 18, 19, 20,
33
+ 21, 22, 23, 24, 27, 25, 26, 45, 18, 19,
34
+ 20, 21, 22, 23, 24, 17, 17, 30, 72, 41,
35
+ 42, 47, 15, 68, 30, 82, 41, 42, 39, 40,
36
+ 27, 25, 26, 15, 18, 19, 20, 21, 22, 23,
37
+ 24, 27, 25, 26, 48, 18, 19, 20, 21, 22,
38
+ 23, 24, 30, 28, 41, 42, 27, 25, 26, 15,
39
+ 18, 19, 20, 21, 22, 23, 24, 27, 25, 26,
40
+ 15, 18, 19, 20, 21, 22, 23, 24, 86, 79,
41
+ 85, 78, 27, 25, 26, 15, 18, 19, 20, 21,
42
+ 22, 23, 24, 27, 25, 26, 15, 18, 19, 20,
43
+ 21, 22, 23, 24, 46, 49, 45, 51, 27, 25,
44
+ 26, 15, 18, 19, 20, 21, 22, 23, 24, 27,
45
+ 25, 26, 15, 18, 19, 20, 21, 22, 23, 24,
46
+ 72, 88, nil, nil, 27, 25, 26, 15, 18, 19,
47
+ 20, 21, 22, 23, 24, 27, 25, 26, 15, 18,
48
+ 19, 20, 21, 22, 23, 24, nil, nil, nil, nil,
49
+ 27, 25, 26, 15, 18, 19, 20, 21, 22, 23,
50
+ 24, 27, 25, 26, 15, 18, 19, 20, 21, 22,
51
+ 23, 24, nil, nil, nil, nil, 27, 25, 26, 15,
52
+ 18, 19, 20, 21, 22, 23, 24, 27, 25, 26,
53
+ 15, 18, 19, 20, 21, 22, 23, 24, nil, nil,
54
+ nil, nil, 27, 25, 26, 15, 18, 19, 20, 21,
55
+ 22, 23, 24, 27, 25, 26, 15, 18, 19, 20,
56
+ 21, 22, 23, 24, nil, nil, nil, nil, 27, 25,
57
+ 26, 15, 18, 19, 20, 21, 22, 23, 24, nil,
58
+ nil, 30, 15, 41, 42, 39, 40, 35, 36, 37,
59
+ 38, 33, 34, 32, 31, nil, nil, 15, 66, 72,
60
+ nil, 30, nil, 41, 42, 39, 40, 35, 36, 37,
61
+ 38, 33, 34, 32, 31, 30, nil, 41, 42, 39,
62
+ 40, 35, 36, 37, 38, 33, 34, 32, 31, 30,
63
+ nil, 41, 42, 39, 40, 35, 36, 37, 38, 33,
64
+ 34, 32, 31, 30, nil, 41, 42, 39, 40, 35,
65
+ 36, 37, 38, 33, 34, 32, 31, 30, nil, 41,
66
+ 42, 39, 40, 35, 36, 37, 38, 33, 34, 32,
67
+ 31, 30, nil, 41, 42, 39, 40, 35, 36, 37,
68
+ 38, 33, 34, 32, 31, 30, nil, 41, 42, 39,
69
+ 40, 35, 36, 37, 38, 33, 34, 32, 31, 30,
70
+ nil, 41, 42, 39, 40, 35, 36, 37, 38, 33,
71
+ 34, 32, 30, nil, 41, 42, 39, 40, 35, 36,
72
+ 37, 38, 33, 34, 30, nil, 41, 42, 39, 40,
73
+ 35, 36, 37, 38, 30, nil, 41, 42, 39, 40,
74
+ 35, 36, 37, 38, 30, nil, 41, 42, 39, 40 ]
75
+
76
+ racc_action_check = [
77
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
78
+ 0, 72, 72, 72, 72, 72, 72, 72, 72, 72,
79
+ 72, 72, 61, 48, 61, 61, 61, 61, 30, 0,
80
+ 60, 0, 60, 60, 60, 60, 64, 80, 2, 65,
81
+ 72, 48, 72, 45, 45, 45, 80, 45, 45, 45,
82
+ 45, 45, 45, 45, 29, 29, 29, 53, 29, 29,
83
+ 29, 29, 29, 29, 29, 80, 2, 62, 49, 62,
84
+ 62, 24, 45, 45, 58, 74, 58, 58, 58, 58,
85
+ 15, 15, 15, 29, 15, 15, 15, 15, 15, 15,
86
+ 15, 40, 40, 40, 25, 40, 40, 40, 40, 40,
87
+ 40, 40, 63, 1, 63, 63, 41, 41, 41, 15,
88
+ 41, 41, 41, 41, 41, 41, 41, 47, 47, 47,
89
+ 40, 47, 47, 47, 47, 47, 47, 47, 81, 69,
90
+ 81, 69, 46, 46, 46, 41, 46, 46, 46, 46,
91
+ 46, 46, 46, 27, 27, 27, 47, 27, 27, 27,
92
+ 27, 27, 27, 27, 23, 26, 23, 28, 39, 39,
93
+ 39, 46, 39, 39, 39, 39, 39, 39, 39, 79,
94
+ 79, 79, 27, 79, 79, 79, 79, 79, 79, 79,
95
+ 85, 86, nil, nil, 42, 42, 42, 39, 42, 42,
96
+ 42, 42, 42, 42, 42, 38, 38, 38, 79, 38,
97
+ 38, 38, 38, 38, 38, 38, nil, nil, nil, nil,
98
+ 32, 32, 32, 42, 32, 32, 32, 32, 32, 32,
99
+ 32, 33, 33, 33, 38, 33, 33, 33, 33, 33,
100
+ 33, 33, nil, nil, nil, nil, 34, 34, 34, 32,
101
+ 34, 34, 34, 34, 34, 34, 34, 35, 35, 35,
102
+ 33, 35, 35, 35, 35, 35, 35, 35, nil, nil,
103
+ nil, nil, 36, 36, 36, 34, 36, 36, 36, 36,
104
+ 36, 36, 36, 37, 37, 37, 35, 37, 37, 37,
105
+ 37, 37, 37, 37, nil, nil, nil, nil, 31, 31,
106
+ 31, 36, 31, 31, 31, 31, 31, 31, 31, nil,
107
+ nil, 43, 37, 43, 43, 43, 43, 43, 43, 43,
108
+ 43, 43, 43, 43, 43, nil, nil, 31, 43, 50,
109
+ nil, 50, nil, 50, 50, 50, 50, 50, 50, 50,
110
+ 50, 50, 50, 50, 50, 3, nil, 3, 3, 3,
111
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 52,
112
+ nil, 52, 52, 52, 52, 52, 52, 52, 52, 52,
113
+ 52, 52, 52, 83, nil, 83, 83, 83, 83, 83,
114
+ 83, 83, 83, 83, 83, 83, 83, 70, nil, 70,
115
+ 70, 70, 70, 70, 70, 70, 70, 70, 70, 70,
116
+ 70, 71, nil, 71, 71, 71, 71, 71, 71, 71,
117
+ 71, 71, 71, 71, 71, 67, nil, 67, 67, 67,
118
+ 67, 67, 67, 67, 67, 67, 67, 67, 67, 54,
119
+ nil, 54, 54, 54, 54, 54, 54, 54, 54, 54,
120
+ 54, 54, 55, nil, 55, 55, 55, 55, 55, 55,
121
+ 55, 55, 55, 55, 57, nil, 57, 57, 57, 57,
122
+ 57, 57, 57, 57, 56, nil, 56, 56, 56, 56,
123
+ 56, 56, 56, 56, 59, nil, 59, 59, 59, 59 ]
124
+
125
+ racc_action_pointer = [
126
+ -2, 103, 33, 320, nil, nil, nil, nil, nil, nil,
127
+ nil, nil, nil, nil, nil, 78, nil, nil, nil, nil,
128
+ nil, nil, nil, 125, 42, 83, 143, 141, 157, 52,
129
+ 17, 286, 208, 219, 234, 245, 260, 271, 193, 156,
130
+ 89, 104, 182, 286, nil, 41, 130, 115, 10, 55,
131
+ 306, nil, 334, 26, 404, 417, 439, 429, 59, 449,
132
+ 15, 7, 52, 87, 21, 24, nil, 390, nil, 99,
133
+ 362, 376, 9, nil, 64, nil, nil, nil, nil, 167,
134
+ 32, 98, nil, 348, nil, 167, 170, nil, nil ]
135
+
136
+ racc_action_default = [
137
+ -1, -56, -2, -3, -6, -7, -8, -9, -10, -11,
138
+ -12, -13, -14, -15, -16, -56, -18, -19, -20, -21,
139
+ -22, -23, -24, -46, -44, -56, -56, -56, -56, -5,
140
+ -56, -56, -56, -56, -56, -56, -56, -56, -56, -56,
141
+ -56, -56, -56, -56, -25, -56, -56, -56, -56, -56,
142
+ -56, 89, -4, -27, -32, -33, -34, -35, -36, -37,
143
+ -38, -39, -40, -41, -42, -43, -17, -30, -28, -56,
144
+ -47, -45, -56, -49, -51, -54, -55, -26, -29, -56,
145
+ -56, -56, -52, -31, -48, -56, -56, -50, -53 ]
146
+
147
+ racc_goto_table = [
148
+ 29, 2, 43, 73, 75, 76, 44, 1, 69, 81,
149
+ nil, nil, nil, nil, 50, nil, 52, nil, 54, 55,
150
+ 56, 57, 58, 59, 60, 61, 62, 63, 64, 65,
151
+ nil, nil, 67, 70, 71, nil, 77, nil, nil, nil,
152
+ 87, nil, nil, nil, nil, nil, nil, nil, nil, nil,
153
+ nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
154
+ nil, nil, nil, nil, nil, nil, 83, nil, nil, nil,
155
+ nil, nil, nil, 80, nil, nil, nil, nil, 29 ]
156
+
157
+ racc_goto_check = [
158
+ 4, 2, 3, 17, 17, 17, 15, 1, 16, 18,
159
+ nil, nil, nil, nil, 3, nil, 3, nil, 3, 3,
160
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
161
+ nil, nil, 3, 3, 3, nil, 15, nil, nil, nil,
162
+ 17, nil, nil, nil, nil, nil, nil, nil, nil, nil,
163
+ nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
164
+ nil, nil, nil, nil, nil, nil, 3, nil, nil, nil,
165
+ nil, nil, nil, 2, nil, nil, nil, nil, 4 ]
166
+
167
+ racc_goto_pointer = [
168
+ nil, 7, 1, -13, -2, nil, nil, nil, nil, nil,
169
+ nil, nil, nil, nil, nil, -17, -37, -45, -65 ]
170
+
171
+ racc_goto_default = [
172
+ nil, nil, nil, 3, 4, 5, 6, 7, 8, 9,
173
+ 10, 11, 12, 13, 14, nil, nil, nil, nil ]
174
+
175
+ racc_reduce_table = [
176
+ 0, 0, :racc_error,
177
+ 0, 35, :_reduce_1,
178
+ 1, 35, :_reduce_2,
179
+ 1, 36, :_reduce_3,
180
+ 3, 36, :_reduce_4,
181
+ 2, 36, :_reduce_5,
182
+ 1, 36, :_reduce_6,
183
+ 1, 37, :_reduce_none,
184
+ 1, 37, :_reduce_none,
185
+ 1, 37, :_reduce_none,
186
+ 1, 37, :_reduce_none,
187
+ 1, 37, :_reduce_none,
188
+ 1, 37, :_reduce_none,
189
+ 1, 37, :_reduce_none,
190
+ 1, 37, :_reduce_none,
191
+ 1, 37, :_reduce_none,
192
+ 1, 37, :_reduce_none,
193
+ 3, 37, :_reduce_17,
194
+ 1, 38, :_reduce_none,
195
+ 1, 38, :_reduce_none,
196
+ 1, 39, :_reduce_20,
197
+ 1, 39, :_reduce_21,
198
+ 1, 39, :_reduce_22,
199
+ 1, 39, :_reduce_23,
200
+ 1, 39, :_reduce_24,
201
+ 2, 40, :_reduce_25,
202
+ 4, 40, :_reduce_26,
203
+ 3, 40, :_reduce_27,
204
+ 2, 49, :_reduce_28,
205
+ 3, 49, :_reduce_29,
206
+ 1, 50, :_reduce_30,
207
+ 3, 50, :_reduce_31,
208
+ 3, 41, :_reduce_32,
209
+ 3, 41, :_reduce_33,
210
+ 3, 41, :_reduce_34,
211
+ 3, 41, :_reduce_35,
212
+ 3, 41, :_reduce_36,
213
+ 3, 41, :_reduce_37,
214
+ 3, 41, :_reduce_38,
215
+ 3, 41, :_reduce_39,
216
+ 3, 41, :_reduce_40,
217
+ 3, 41, :_reduce_41,
218
+ 3, 41, :_reduce_42,
219
+ 3, 41, :_reduce_43,
220
+ 1, 42, :_reduce_44,
221
+ 3, 43, :_reduce_45,
222
+ 1, 44, :_reduce_46,
223
+ 3, 45, :_reduce_47,
224
+ 3, 51, :_reduce_48,
225
+ 3, 46, :_reduce_49,
226
+ 6, 46, :_reduce_50,
227
+ 0, 52, :_reduce_51,
228
+ 1, 52, :_reduce_52,
229
+ 3, 52, :_reduce_53,
230
+ 3, 47, :_reduce_54,
231
+ 3, 48, :_reduce_55 ]
232
+
233
+ racc_reduce_n = 56
234
+
235
+ racc_shift_n = 89
236
+
237
+ racc_token_table = {
238
+ false => 0,
239
+ :error => 1,
240
+ :IF => 2,
241
+ :DEF => 3,
242
+ :CLASS => 4,
243
+ :NEWLINE => 5,
244
+ :NUMBER => 6,
245
+ :STRING => 7,
246
+ :TRUE => 8,
247
+ :FALSE => 9,
248
+ :NIL => 10,
249
+ :IDENTIFIER => 11,
250
+ :CONSTANT => 12,
251
+ :INDENT => 13,
252
+ :DEDENT => 14,
253
+ "." => 15,
254
+ "!" => 16,
255
+ "*" => 17,
256
+ "/" => 18,
257
+ "+" => 19,
258
+ "-" => 20,
259
+ ">" => 21,
260
+ ">=" => 22,
261
+ "<" => 23,
262
+ "<=" => 24,
263
+ "==" => 25,
264
+ "!=" => 26,
265
+ "&&" => 27,
266
+ "||" => 28,
267
+ "=" => 29,
268
+ "," => 30,
269
+ "(" => 31,
270
+ ")" => 32,
271
+ ";" => 33 }
272
+
273
+ racc_nt_base = 34
274
+
275
+ racc_use_result_var = true
276
+
277
+ Racc_arg = [
278
+ racc_action_table,
279
+ racc_action_check,
280
+ racc_action_default,
281
+ racc_action_pointer,
282
+ racc_goto_table,
283
+ racc_goto_check,
284
+ racc_goto_default,
285
+ racc_goto_pointer,
286
+ racc_nt_base,
287
+ racc_reduce_table,
288
+ racc_token_table,
289
+ racc_shift_n,
290
+ racc_reduce_n,
291
+ racc_use_result_var ]
292
+
293
+ Racc_token_to_s_table = [
294
+ "$end",
295
+ "error",
296
+ "IF",
297
+ "DEF",
298
+ "CLASS",
299
+ "NEWLINE",
300
+ "NUMBER",
301
+ "STRING",
302
+ "TRUE",
303
+ "FALSE",
304
+ "NIL",
305
+ "IDENTIFIER",
306
+ "CONSTANT",
307
+ "INDENT",
308
+ "DEDENT",
309
+ "\".\"",
310
+ "\"!\"",
311
+ "\"*\"",
312
+ "\"/\"",
313
+ "\"+\"",
314
+ "\"-\"",
315
+ "\">\"",
316
+ "\">=\"",
317
+ "\"<\"",
318
+ "\"<=\"",
319
+ "\"==\"",
320
+ "\"!=\"",
321
+ "\"&&\"",
322
+ "\"||\"",
323
+ "\"=\"",
324
+ "\",\"",
325
+ "\"(\"",
326
+ "\")\"",
327
+ "\";\"",
328
+ "$start",
329
+ "Program",
330
+ "Expressions",
331
+ "Expression",
332
+ "Terminator",
333
+ "Literal",
334
+ "Call",
335
+ "Operator",
336
+ "GetConstant",
337
+ "SetConstant",
338
+ "GetLocal",
339
+ "SetLocal",
340
+ "Def",
341
+ "Class",
342
+ "If",
343
+ "Arguments",
344
+ "ArgList",
345
+ "Block",
346
+ "ParamList" ]
347
+
348
+ Racc_debug_parser = false
349
+
350
+ ##### State transition tables end #####
351
+
352
+ # reduce 0 omitted
353
+
354
+ module_eval(<<'.,.,', 'grammar.y', 49)
355
+ def _reduce_1(val, _values, result)
356
+ result = Nodes.new([])
357
+ result
358
+ end
359
+ .,.,
360
+
361
+ module_eval(<<'.,.,', 'grammar.y', 50)
362
+ def _reduce_2(val, _values, result)
363
+ result = val[0]
364
+ result
365
+ end
366
+ .,.,
367
+
368
+ module_eval(<<'.,.,', 'grammar.y', 67)
369
+ def _reduce_3(val, _values, result)
370
+ result = Nodes.new(val)
371
+ result
372
+ end
373
+ .,.,
374
+
375
+ module_eval(<<'.,.,', 'grammar.y', 68)
376
+ def _reduce_4(val, _values, result)
377
+ result = val[0] << val[2]
378
+ result
379
+ end
380
+ .,.,
381
+
382
+ module_eval(<<'.,.,', 'grammar.y', 69)
383
+ def _reduce_5(val, _values, result)
384
+ result = val[0]
385
+ result
386
+ end
387
+ .,.,
388
+
389
+ module_eval(<<'.,.,', 'grammar.y', 70)
390
+ def _reduce_6(val, _values, result)
391
+ result = Nodes.new([])
392
+ result
393
+ end
394
+ .,.,
395
+
396
+ # reduce 7 omitted
397
+
398
+ # reduce 8 omitted
399
+
400
+ # reduce 9 omitted
401
+
402
+ # reduce 10 omitted
403
+
404
+ # reduce 11 omitted
405
+
406
+ # reduce 12 omitted
407
+
408
+ # reduce 13 omitted
409
+
410
+ # reduce 14 omitted
411
+
412
+ # reduce 15 omitted
413
+
414
+ # reduce 16 omitted
415
+
416
+ module_eval(<<'.,.,', 'grammar.y', 85)
417
+ def _reduce_17(val, _values, result)
418
+ result = val[1]
419
+ result
420
+ end
421
+ .,.,
422
+
423
+ # reduce 18 omitted
424
+
425
+ # reduce 19 omitted
426
+
427
+ module_eval(<<'.,.,', 'grammar.y', 103)
428
+ def _reduce_20(val, _values, result)
429
+ result = NumberNode.new(val[0])
430
+ result
431
+ end
432
+ .,.,
433
+
434
+ module_eval(<<'.,.,', 'grammar.y', 104)
435
+ def _reduce_21(val, _values, result)
436
+ result = StringNode.new(val[0])
437
+ result
438
+ end
439
+ .,.,
440
+
441
+ module_eval(<<'.,.,', 'grammar.y', 105)
442
+ def _reduce_22(val, _values, result)
443
+ result = TrueNode.new
444
+ result
445
+ end
446
+ .,.,
447
+
448
+ module_eval(<<'.,.,', 'grammar.y', 106)
449
+ def _reduce_23(val, _values, result)
450
+ result = FalseNode.new
451
+ result
452
+ end
453
+ .,.,
454
+
455
+ module_eval(<<'.,.,', 'grammar.y', 107)
456
+ def _reduce_24(val, _values, result)
457
+ result = NilNode.new
458
+ result
459
+ end
460
+ .,.,
461
+
462
+ module_eval(<<'.,.,', 'grammar.y', 119)
463
+ def _reduce_25(val, _values, result)
464
+ result = CallNode.new(nil, val[0], val[1])
465
+ result
466
+ end
467
+ .,.,
468
+
469
+ module_eval(<<'.,.,', 'grammar.y', 121)
470
+ def _reduce_26(val, _values, result)
471
+ result = CallNode.new(val[0], val[2], val[3])
472
+ result
473
+ end
474
+ .,.,
475
+
476
+ module_eval(<<'.,.,', 'grammar.y', 122)
477
+ def _reduce_27(val, _values, result)
478
+ result = CallNode.new(val[0], val[2], [])
479
+ result
480
+ end
481
+ .,.,
482
+
483
+ module_eval(<<'.,.,', 'grammar.y', 126)
484
+ def _reduce_28(val, _values, result)
485
+ result = []
486
+ result
487
+ end
488
+ .,.,
489
+
490
+ module_eval(<<'.,.,', 'grammar.y', 127)
491
+ def _reduce_29(val, _values, result)
492
+ result = val[1]
493
+ result
494
+ end
495
+ .,.,
496
+
497
+ module_eval(<<'.,.,', 'grammar.y', 131)
498
+ def _reduce_30(val, _values, result)
499
+ result = val
500
+ result
501
+ end
502
+ .,.,
503
+
504
+ module_eval(<<'.,.,', 'grammar.y', 132)
505
+ def _reduce_31(val, _values, result)
506
+ result = val[0] << val[2]
507
+ result
508
+ end
509
+ .,.,
510
+
511
+ module_eval(<<'.,.,', 'grammar.y', 143)
512
+ def _reduce_32(val, _values, result)
513
+ result = CallNode.new(val[0], val[1], [val[2]])
514
+ result
515
+ end
516
+ .,.,
517
+
518
+ module_eval(<<'.,.,', 'grammar.y', 144)
519
+ def _reduce_33(val, _values, result)
520
+ result = CallNode.new(val[0], val[1], [val[2]])
521
+ result
522
+ end
523
+ .,.,
524
+
525
+ module_eval(<<'.,.,', 'grammar.y', 145)
526
+ def _reduce_34(val, _values, result)
527
+ result = CallNode.new(val[0], val[1], [val[2]])
528
+ result
529
+ end
530
+ .,.,
531
+
532
+ module_eval(<<'.,.,', 'grammar.y', 146)
533
+ def _reduce_35(val, _values, result)
534
+ result = CallNode.new(val[0], val[1], [val[2]])
535
+ result
536
+ end
537
+ .,.,
538
+
539
+ module_eval(<<'.,.,', 'grammar.y', 147)
540
+ def _reduce_36(val, _values, result)
541
+ result = CallNode.new(val[0], val[1], [val[2]])
542
+ result
543
+ end
544
+ .,.,
545
+
546
+ module_eval(<<'.,.,', 'grammar.y', 148)
547
+ def _reduce_37(val, _values, result)
548
+ result = CallNode.new(val[0], val[1], [val[2]])
549
+ result
550
+ end
551
+ .,.,
552
+
553
+ module_eval(<<'.,.,', 'grammar.y', 149)
554
+ def _reduce_38(val, _values, result)
555
+ result = CallNode.new(val[0], val[1], [val[2]])
556
+ result
557
+ end
558
+ .,.,
559
+
560
+ module_eval(<<'.,.,', 'grammar.y', 150)
561
+ def _reduce_39(val, _values, result)
562
+ result = CallNode.new(val[0], val[1], [val[2]])
563
+ result
564
+ end
565
+ .,.,
566
+
567
+ module_eval(<<'.,.,', 'grammar.y', 151)
568
+ def _reduce_40(val, _values, result)
569
+ result = CallNode.new(val[0], val[1], [val[2]])
570
+ result
571
+ end
572
+ .,.,
573
+
574
+ module_eval(<<'.,.,', 'grammar.y', 152)
575
+ def _reduce_41(val, _values, result)
576
+ result = CallNode.new(val[0], val[1], [val[2]])
577
+ result
578
+ end
579
+ .,.,
580
+
581
+ module_eval(<<'.,.,', 'grammar.y', 153)
582
+ def _reduce_42(val, _values, result)
583
+ result = CallNode.new(val[0], val[1], [val[2]])
584
+ result
585
+ end
586
+ .,.,
587
+
588
+ module_eval(<<'.,.,', 'grammar.y', 154)
589
+ def _reduce_43(val, _values, result)
590
+ result = CallNode.new(val[0], val[1], [val[2]])
591
+ result
592
+ end
593
+ .,.,
594
+
595
+ module_eval(<<'.,.,', 'grammar.y', 159)
596
+ def _reduce_44(val, _values, result)
597
+ result = GetConstantNode.new(val[0])
598
+ result
599
+ end
600
+ .,.,
601
+
602
+ module_eval(<<'.,.,', 'grammar.y', 163)
603
+ def _reduce_45(val, _values, result)
604
+ result = SetConstantNode.new(val[0], val[2])
605
+ result
606
+ end
607
+ .,.,
608
+
609
+ module_eval(<<'.,.,', 'grammar.y', 167)
610
+ def _reduce_46(val, _values, result)
611
+ result = GetLocalNode.new(val[0])
612
+ result
613
+ end
614
+ .,.,
615
+
616
+ module_eval(<<'.,.,', 'grammar.y', 171)
617
+ def _reduce_47(val, _values, result)
618
+ result = SetLocalNode.new(val[0], val[2])
619
+ result
620
+ end
621
+ .,.,
622
+
623
+ module_eval(<<'.,.,', 'grammar.y', 183)
624
+ def _reduce_48(val, _values, result)
625
+ result = val[1]
626
+ result
627
+ end
628
+ .,.,
629
+
630
+ module_eval(<<'.,.,', 'grammar.y', 189)
631
+ def _reduce_49(val, _values, result)
632
+ result = DefNode.new(val[1], [], val[2])
633
+ result
634
+ end
635
+ .,.,
636
+
637
+ module_eval(<<'.,.,', 'grammar.y', 191)
638
+ def _reduce_50(val, _values, result)
639
+ result = DefNode.new(val[1], val[3], val[5])
640
+ result
641
+ end
642
+ .,.,
643
+
644
+ module_eval(<<'.,.,', 'grammar.y', 195)
645
+ def _reduce_51(val, _values, result)
646
+ result = []
647
+ result
648
+ end
649
+ .,.,
650
+
651
+ module_eval(<<'.,.,', 'grammar.y', 196)
652
+ def _reduce_52(val, _values, result)
653
+ result = val
654
+ result
655
+ end
656
+ .,.,
657
+
658
+ module_eval(<<'.,.,', 'grammar.y', 197)
659
+ def _reduce_53(val, _values, result)
660
+ result = val[0] << val[2]
661
+ result
662
+ end
663
+ .,.,
664
+
665
+ module_eval(<<'.,.,', 'grammar.y', 203)
666
+ def _reduce_54(val, _values, result)
667
+ result = ClassNode.new(val[1], val[2])
668
+ result
669
+ end
670
+ .,.,
671
+
672
+ module_eval(<<'.,.,', 'grammar.y', 208)
673
+ def _reduce_55(val, _values, result)
674
+ result = IfNode.new(val[1], val[2])
675
+ result
676
+ end
677
+ .,.,
678
+
679
+ def _reduce_none(val, _values, result)
680
+ val[0]
681
+ end
682
+
683
+ end # class Parser