turmali 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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