riml 0.1.3 → 0.1.5
Sign up to get free protection for your applications and to get access to all the features.
- data/bin/riml +22 -15
- data/lib/ast_rewriter.rb +6 -5
- data/lib/compiler.rb +85 -39
- data/lib/constants.rb +4 -0
- data/{config → lib}/environment.rb +3 -2
- data/lib/errors.rb +7 -2
- data/lib/grammar.y +143 -125
- data/lib/header.vim +4 -0
- data/lib/lexer.rb +6 -3
- data/lib/nodes.rb +49 -9
- data/lib/parser.rb +1269 -1349
- data/lib/riml.rb +84 -0
- data/version.rb +2 -2
- metadata +7 -6
- data/lib/helper.rb +0 -45
data/bin/riml
CHANGED
@@ -1,12 +1,11 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
# vim: syntax=ruby
|
3
3
|
|
4
|
-
require File.expand_path("../../
|
4
|
+
require File.expand_path("../../lib/environment", __FILE__)
|
5
5
|
|
6
6
|
module Riml
|
7
7
|
include Environment
|
8
|
-
require
|
9
|
-
require File.join(LIBDIR, "helper")
|
8
|
+
require 'riml'
|
10
9
|
|
11
10
|
require 'optparse'
|
12
11
|
require 'ostruct'
|
@@ -16,32 +15,41 @@ module Riml
|
|
16
15
|
|
17
16
|
# defaults
|
18
17
|
options = OpenStruct.new
|
19
|
-
options.
|
20
|
-
options.riml_source_path = Dir.getwd
|
18
|
+
options.compile_files = []
|
21
19
|
|
22
20
|
OptionParser.new do |opts|
|
23
21
|
opts.banner = "Usage: riml [options]"
|
24
22
|
opts.separator ""
|
25
23
|
opts.separator "Specific options:"
|
26
24
|
|
27
|
-
opts.on("-c", "--compile FILE", "Compile riml file to VimL") do |file|
|
25
|
+
opts.on("-c", "--compile FILE", "Compile riml file to VimL.") do |file|
|
28
26
|
if File.exists?(file)
|
29
|
-
options.
|
27
|
+
options.compile_files << file
|
30
28
|
else
|
31
|
-
warn "Couldn't find file #{file.inspect}"
|
29
|
+
warn "Couldn't find file #{file.inspect}."
|
30
|
+
exit 1
|
32
31
|
end
|
33
32
|
end
|
34
33
|
|
35
|
-
opts.on("-
|
34
|
+
opts.on("-t", "--source-path PATH", "Path riml uses for `riml_source` to find files. Defaults to pwd.") do |path|
|
35
|
+
if Dir.exists?(path)
|
36
|
+
Riml.source_path = path
|
37
|
+
else
|
38
|
+
warn "Couldn't find directory #{path.inspect}."
|
39
|
+
exit 1
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
opts.on("-s", "--stdio", "Pipe in riml to STDIN and get back VimL on STDOUT.") do
|
36
44
|
options.stdio = true
|
37
45
|
end
|
38
46
|
|
39
|
-
opts.on_tail("-v", "--version", "Show riml version") do
|
47
|
+
opts.on_tail("-v", "--version", "Show riml version.") do
|
40
48
|
puts VERSION.join('.')
|
41
49
|
exit
|
42
50
|
end
|
43
51
|
|
44
|
-
opts.on_tail("-h", "--help", "Show this message") do
|
52
|
+
opts.on_tail("-h", "--help", "Show this message.") do
|
45
53
|
puts opts
|
46
54
|
exit
|
47
55
|
end
|
@@ -55,12 +63,11 @@ module Riml
|
|
55
63
|
class << self
|
56
64
|
def start
|
57
65
|
options = Options.parse(ARGV)
|
66
|
+
|
58
67
|
if options.stdio
|
59
68
|
puts Riml.compile($stdin.gets)
|
60
|
-
elsif options.
|
61
|
-
options.
|
62
|
-
Riml.compile_file(file)
|
63
|
-
end
|
69
|
+
elsif options.compile_files.any?
|
70
|
+
Riml.compile_files(*options.compile_files)
|
64
71
|
end
|
65
72
|
end
|
66
73
|
end
|
data/lib/ast_rewriter.rb
CHANGED
@@ -6,8 +6,8 @@ module Riml
|
|
6
6
|
class AST_Rewriter
|
7
7
|
include Riml::Constants
|
8
8
|
|
9
|
-
|
10
|
-
def initialize(ast)
|
9
|
+
attr_accessor :ast
|
10
|
+
def initialize(ast = nil)
|
11
11
|
@ast = ast
|
12
12
|
end
|
13
13
|
|
@@ -134,11 +134,12 @@ module Riml
|
|
134
134
|
def replace(node)
|
135
135
|
def_node = node.to_def_node
|
136
136
|
node.parent_node = ast.expressions
|
137
|
+
def_node.parent_node = ast.expressions
|
137
138
|
node.remove
|
138
139
|
def_node.name.insert(0, "#{dict_name}.")
|
139
140
|
def_node.parent_node = constructor.expressions
|
140
141
|
constructor.expressions << def_node
|
141
|
-
reestablish_parents(
|
142
|
+
reestablish_parents(def_node)
|
142
143
|
end
|
143
144
|
end
|
144
145
|
|
@@ -259,8 +260,8 @@ module Riml
|
|
259
260
|
end
|
260
261
|
|
261
262
|
def replace(node)
|
262
|
-
node.replace_with(ExplicitCallNode.new(node[0], node[1], node[2]))
|
263
|
-
reestablish_parents(
|
263
|
+
explicit = node.replace_with(ExplicitCallNode.new(node[0], node[1], node[2]))
|
264
|
+
reestablish_parents(explicit)
|
264
265
|
end
|
265
266
|
end
|
266
267
|
|
data/lib/compiler.rb
CHANGED
@@ -14,7 +14,6 @@ module Riml
|
|
14
14
|
end
|
15
15
|
|
16
16
|
def visit(node)
|
17
|
-
node.compiled_output.clear
|
18
17
|
@value = compile(node)
|
19
18
|
@value << "\n" if node.force_newline and @value[-1] != "\n"
|
20
19
|
propagate_up_tree(node, @value)
|
@@ -33,12 +32,11 @@ module Riml
|
|
33
32
|
def compile(node)
|
34
33
|
condition_visitor = visitor_for_node(node.condition)
|
35
34
|
node.condition.parent_node = node
|
36
|
-
node.
|
37
|
-
node.compiled_output = "if
|
35
|
+
node.condition.force_newline = true
|
36
|
+
node.compiled_output = "if "
|
38
37
|
node.compiled_output << "!" if UnlessNode === node
|
39
38
|
|
40
39
|
node.condition.accept(condition_visitor)
|
41
|
-
node.compiled_output << ")\n"
|
42
40
|
node.body.accept(NodesVisitor.new(:propagate_up_tree => false))
|
43
41
|
|
44
42
|
node.body.compiled_output.each_line do |line|
|
@@ -69,12 +67,10 @@ module Riml
|
|
69
67
|
|
70
68
|
class WhileNodeVisitor < Visitor
|
71
69
|
def compile(node)
|
72
|
-
node.condition.
|
73
|
-
node.compiled_output = "while
|
70
|
+
node.condition.force_newline = true
|
71
|
+
node.compiled_output = "while "
|
74
72
|
node.compiled_output << "!" if UntilNode === node
|
75
|
-
|
76
73
|
node.condition.accept visitor_for_node(node.condition)
|
77
|
-
node.compiled_output << ")\n"
|
78
74
|
|
79
75
|
node.body.accept NodesVisitor.new(:propagate_up_tree => false)
|
80
76
|
|
@@ -92,19 +88,18 @@ module Riml
|
|
92
88
|
class ElseNodeVisitor < Visitor
|
93
89
|
def compile(node)
|
94
90
|
node.compiled_output = "else\n"
|
95
|
-
|
96
|
-
node.expressions.
|
97
|
-
node.expressions.accept(expressions_visitor)
|
91
|
+
node.expressions.parent = node
|
92
|
+
node.expressions.accept(visitor_for_node(node.expressions))
|
98
93
|
node.compiled_output
|
99
94
|
end
|
100
95
|
end
|
101
96
|
|
102
97
|
class ElseifNodeVisitor < Visitor
|
103
98
|
def compile(node)
|
104
|
-
node.compiled_output = "elseif
|
99
|
+
node.compiled_output = "elseif "
|
105
100
|
node.condition.parent_node = node
|
101
|
+
node.condition.force_newline = true
|
106
102
|
node.condition.accept(visitor_for_node(node.condition))
|
107
|
-
node.compiled_output << ")\n"
|
108
103
|
node.expressions.parent_node = node
|
109
104
|
node.expressions.accept(visitor_for_node(node.expressions))
|
110
105
|
node.force_newline = true
|
@@ -127,6 +122,8 @@ module Riml
|
|
127
122
|
end
|
128
123
|
end
|
129
124
|
|
125
|
+
SublistNodeVisitor = NodesVisitor
|
126
|
+
|
130
127
|
class LiteralNodeVisitor < Visitor
|
131
128
|
def compile(node)
|
132
129
|
value = case node.value
|
@@ -208,6 +205,15 @@ module Riml
|
|
208
205
|
end
|
209
206
|
end
|
210
207
|
|
208
|
+
class WrapInParensNodeVisitor < Visitor
|
209
|
+
def compile(node)
|
210
|
+
node.compiled_output << "("
|
211
|
+
node.expression.parent_node = node
|
212
|
+
node.expression.accept(visitor_for_node(node.expression))
|
213
|
+
node.compiled_output << ")"
|
214
|
+
end
|
215
|
+
end
|
216
|
+
|
211
217
|
# common visiting methods for nodes that are scope modified with variable
|
212
218
|
# name prefixes
|
213
219
|
class ScopedVisitor < Visitor
|
@@ -305,19 +311,15 @@ module Riml
|
|
305
311
|
class BinaryOperatorNodeVisitor < Visitor
|
306
312
|
def compile(node)
|
307
313
|
op1, op2 = node.operand1, node.operand2
|
308
|
-
|
309
|
-
|
310
|
-
op1.accept(op1_visitor)
|
311
|
-
op2_visitor.propagate_up_tree = false
|
312
|
-
op2.accept(op2_visitor)
|
314
|
+
[op1, op2].each {|n| n.parent = node}
|
315
|
+
op1.accept(visitor_for_node(op1))
|
313
316
|
if node.ignorecase_capable_operator?(node.operator)
|
314
317
|
operator_suffix = "# "
|
315
318
|
else
|
316
319
|
operator_suffix = " "
|
317
320
|
end
|
318
321
|
node.compiled_output << " #{node.operator}#{operator_suffix}"
|
319
|
-
|
320
|
-
op2.accept(op2_visitor)
|
322
|
+
op2.accept(visitor_for_node(op2))
|
321
323
|
node.compiled_output
|
322
324
|
end
|
323
325
|
end
|
@@ -405,34 +407,40 @@ module Riml
|
|
405
407
|
|
406
408
|
class CallNodeVisitor < ScopedVisitor
|
407
409
|
def compile(node)
|
408
|
-
set_modifier(node)
|
410
|
+
set_modifier(node) if node.name && !node.builtin_function?
|
409
411
|
node.compiled_output =
|
410
|
-
|
411
|
-
|
412
|
-
|
413
|
-
|
414
|
-
|
415
|
-
|
416
|
-
|
417
|
-
|
418
|
-
|
419
|
-
|
412
|
+
if node.name.respond_to?(:variable)
|
413
|
+
node.name.accept(visitor_for_node(node.name))
|
414
|
+
node.scope_modifier + node.name.compiled_output
|
415
|
+
elsif DictGetDotNode === node.name
|
416
|
+
node.name.accept(visitor_for_node(node.name))
|
417
|
+
node.name.compiled_output
|
418
|
+
else
|
419
|
+
"#{node.full_name}"
|
420
|
+
end
|
421
|
+
compile_arguments(node)
|
422
|
+
node.compiled_output
|
423
|
+
end
|
424
|
+
|
425
|
+
def compile_arguments(node)
|
426
|
+
node.compiled_output << (node.builtin_command? ? " " : "(")
|
420
427
|
node.arguments.each_with_index do |arg, i|
|
421
428
|
arg.parent_node = node
|
422
429
|
arg_visitor = visitor_for_node(arg)
|
423
430
|
arg.accept(arg_visitor)
|
424
431
|
node.compiled_output << ", " unless last_arg?(node.arguments, i)
|
425
432
|
end
|
426
|
-
node.compiled_output << ")" unless node.
|
433
|
+
node.compiled_output << ")" unless node.builtin_command?
|
427
434
|
|
428
435
|
unless node.descendant_of_control_structure? ||
|
429
436
|
node.descendant_of_call_node? ||
|
430
437
|
node.descendant_of_list_node? ||
|
431
438
|
node.descendant_of_list_or_dict_get_node? ||
|
432
|
-
node.descendant_of_operator_node?
|
439
|
+
node.descendant_of_operator_node? ||
|
440
|
+
node.descendant_of_wrap_in_parens_node? ||
|
441
|
+
node.descendant_of_sublist_node?
|
433
442
|
node.force_newline = true
|
434
443
|
end
|
435
|
-
node.compiled_output
|
436
444
|
end
|
437
445
|
|
438
446
|
private
|
@@ -443,9 +451,36 @@ module Riml
|
|
443
451
|
|
444
452
|
class ExplicitCallNodeVisitor < CallNodeVisitor
|
445
453
|
def compile(node)
|
446
|
-
|
447
|
-
|
448
|
-
|
454
|
+
if node.scope_modifier || node.name
|
455
|
+
node.compiled_output = "call " << super
|
456
|
+
else
|
457
|
+
node.compiled_output = "call"
|
458
|
+
compile_arguments(node)
|
459
|
+
end
|
460
|
+
node.compiled_output
|
461
|
+
end
|
462
|
+
end
|
463
|
+
|
464
|
+
class RimlCommandNodeVisitor < CallNodeVisitor
|
465
|
+
def compile(node)
|
466
|
+
if node.name == 'riml_source'
|
467
|
+
node.arguments.map(&:value).each do |file|
|
468
|
+
unless File.exists?(File.join(Riml.source_path, file))
|
469
|
+
raise Riml::FileNotFound, "#{file.inspect} could not be found in " \
|
470
|
+
"source path (#{Riml.source_path.inspect})"
|
471
|
+
end
|
472
|
+
|
473
|
+
root_node(node).current_compiler.compile_queue << file
|
474
|
+
end
|
475
|
+
node.compiled_output << 'source'
|
476
|
+
compile_arguments(node)
|
477
|
+
node.compiled_output.gsub(/['"]/, '').gsub('.riml', '.vim')
|
478
|
+
end
|
479
|
+
end
|
480
|
+
|
481
|
+
def root_node(node)
|
482
|
+
node = node.parent until node.parent.nil?
|
483
|
+
node
|
449
484
|
end
|
450
485
|
end
|
451
486
|
|
@@ -568,10 +603,21 @@ module Riml
|
|
568
603
|
end
|
569
604
|
end
|
570
605
|
|
606
|
+
module CompilerAccessible
|
607
|
+
attr_accessor :current_compiler
|
608
|
+
end
|
609
|
+
|
610
|
+
def compile_queue
|
611
|
+
@compile_queue ||= []
|
612
|
+
end
|
613
|
+
|
571
614
|
# compiles nodes into output code
|
572
615
|
def compile(root_node)
|
573
|
-
|
574
|
-
|
616
|
+
# so we can compile concurrently, as some nodes have access to the
|
617
|
+
# compiler instance itself
|
618
|
+
root_node.extend CompilerAccessible
|
619
|
+
root_node.current_compiler = self
|
620
|
+
root_node.accept(NodesVisitor.new)
|
575
621
|
root_node.compiled_output
|
576
622
|
end
|
577
623
|
|
data/lib/constants.rb
CHANGED
@@ -11,10 +11,14 @@ module Riml
|
|
11
11
|
class new)
|
12
12
|
DEFINE_KEYWORDS = %w(def def! defm defm! function function!)
|
13
13
|
KEYWORDS = VIML_KEYWORDS + VIML_END_KEYWORDS + RIML_KEYWORDS
|
14
|
+
|
14
15
|
SPECIAL_VARIABLE_PREFIXES =
|
15
16
|
%w(& @ $)
|
16
17
|
BUILTIN_COMMANDS =
|
17
18
|
%w(echo echon echohl execute sleep)
|
19
|
+
RIML_COMMANDS =
|
20
|
+
%w(riml_source)
|
21
|
+
|
18
22
|
IGNORECASE_CAPABLE_OPERATORS =
|
19
23
|
%w(== != >= > <= < =~ !~)
|
20
24
|
COMPARISON_OPERATORS = IGNORECASE_CAPABLE_OPERATORS.map do |o|
|
@@ -1,9 +1,10 @@
|
|
1
1
|
module Riml
|
2
2
|
module Environment
|
3
3
|
ROOTDIR = File.expand_path('../../', __FILE__)
|
4
|
+
require File.join(ROOTDIR, 'version')
|
4
5
|
|
5
|
-
LIBDIR = File.join(ROOTDIR,
|
6
|
-
BINDIR = File.join(ROOTDIR,
|
6
|
+
LIBDIR = File.join(ROOTDIR, 'lib')
|
7
|
+
BINDIR = File.join(ROOTDIR, 'bin')
|
7
8
|
|
8
9
|
$:.unshift(LIBDIR) unless $:.include? LIBDIR
|
9
10
|
end
|
data/lib/errors.rb
CHANGED
@@ -1,4 +1,9 @@
|
|
1
1
|
module Riml
|
2
|
-
|
3
|
-
|
2
|
+
RimlError = Class.new(StandardError)
|
3
|
+
|
4
|
+
SyntaxError = Class.new(RimlError)
|
5
|
+
ParseError = Class.new(RimlError)
|
6
|
+
CompileError = Class.new(RimlError)
|
7
|
+
|
8
|
+
FileNotFound = Class.new(RimlError)
|
4
9
|
end
|
data/lib/grammar.y
CHANGED
@@ -5,7 +5,7 @@ token WHILE UNTIL BREAK CONTINUE
|
|
5
5
|
token TRY CATCH ENSURE
|
6
6
|
token FOR IN
|
7
7
|
token DEF DEF_BANG SPLAT CALL BUILTIN_COMMAND # such as echo "hi"
|
8
|
-
token CLASS NEW DEFM DEFM_BANG SUPER
|
8
|
+
token CLASS NEW DEFM DEFM_BANG SUPER RIML_COMMAND
|
9
9
|
token RETURN
|
10
10
|
token NEWLINE
|
11
11
|
token NUMBER
|
@@ -21,14 +21,14 @@ token FINISH
|
|
21
21
|
prechigh
|
22
22
|
right '!'
|
23
23
|
left '*' '/' '%'
|
24
|
-
left '+' '
|
24
|
+
left '+' '-' '.'
|
25
25
|
left '>' '>#' '>?' '<' '<#' '<?' '>=' '>=#' '>=?' '<=' '<=#' '<=?'
|
26
26
|
left '==' '==?' '==#' '=~' '=~?' '=~#' '!~' '!~?' '!~#' '!=' '!=?' '!=#'
|
27
27
|
left IS ISNOT
|
28
28
|
left '&&'
|
29
29
|
left '||'
|
30
30
|
right '?'
|
31
|
-
right '='
|
31
|
+
right '=' '+=' '-=' '.='
|
32
32
|
left ','
|
33
33
|
left IF UNLESS
|
34
34
|
preclow
|
@@ -43,40 +43,47 @@ rule
|
|
43
43
|
|
44
44
|
# any list of expressions
|
45
45
|
Expressions:
|
46
|
-
|
47
|
-
| Expressions Terminator
|
46
|
+
AnyExpression { result = Nodes.new([ val[0] ]) }
|
47
|
+
| Expressions Terminator AnyExpression { result = val[0] << val[2] }
|
48
48
|
| Expressions Terminator { result = val[0] }
|
49
49
|
| Terminator { result = Nodes.new([]) }
|
50
50
|
;
|
51
51
|
|
52
52
|
# All types of expressions in Riml
|
53
|
-
|
54
|
-
|
55
|
-
| UnaryOperator { result = val[0] }
|
56
|
-
| Call { result = val[0] }
|
57
|
-
| Assign { result = val[0] }
|
58
|
-
| DictGet { result = val[0] }
|
59
|
-
| ListOrDictGet { result = val[0] }
|
53
|
+
AnyExpression:
|
54
|
+
ExplicitCall { result = val[0] }
|
60
55
|
| Def { result = val[0] }
|
61
56
|
| Return { result = val[0] }
|
62
|
-
| VariableRetrieval { result = val[0] }
|
63
57
|
| UnletVariable { result = val[0] }
|
64
|
-
| Literal { result = val[0] }
|
65
58
|
| ExLiteral { result = val[0] }
|
66
|
-
| Heredoc { result = val[0] }
|
67
59
|
| If { result = val[0] }
|
68
60
|
| Unless { result = val[0] }
|
69
|
-
|
|
61
|
+
| For { result = val[0] }
|
70
62
|
| While { result = val[0] }
|
71
63
|
| Until { result = val[0] }
|
72
|
-
| For { result = val[0] }
|
73
64
|
| Try { result = val[0] }
|
74
65
|
| ClassDefinition { result = val[0] }
|
75
|
-
| ObjectInstantiation { result = val[0] }
|
76
66
|
| Super { result = val[0] }
|
77
67
|
| LoopKeyword { result = val[0] }
|
78
68
|
| EndScript { result = val[0] }
|
79
|
-
|
|
69
|
+
| ValueExpression { result = val[0] }
|
70
|
+
| RimlCommand { result = val[0] }
|
71
|
+
;
|
72
|
+
|
73
|
+
# Expressions that evaluate to a value
|
74
|
+
ValueExpression:
|
75
|
+
UnaryOperator { result = val[0] }
|
76
|
+
| Assign { result = val[0] }
|
77
|
+
| DictGet { result = val[0] }
|
78
|
+
| ListOrDictGet { result = val[0] }
|
79
|
+
| VariableRetrieval { result = val[0] }
|
80
|
+
| Literal { result = val[0] }
|
81
|
+
| Call { result = val[0] }
|
82
|
+
| Heredoc { result = val[0] }
|
83
|
+
| Ternary { result = val[0] }
|
84
|
+
| ObjectInstantiation { result = val[0] }
|
85
|
+
| BinaryOperator { result = val[0] }
|
86
|
+
| '(' ValueExpression ')' { result = WrapInParensNode.new(val[1]) }
|
80
87
|
;
|
81
88
|
|
82
89
|
Terminator:
|
@@ -100,8 +107,6 @@ rule
|
|
100
107
|
|
101
108
|
Number:
|
102
109
|
NUMBER { result = NumberNode.new(val[0]) }
|
103
|
-
| '-' NUMBER { result = NumberNode.new(val[1].insert(0, val[0])) }
|
104
|
-
| '+' NUMBER { result = NumberNode.new(val[1].insert(0, val[0])) }
|
105
110
|
;
|
106
111
|
|
107
112
|
String:
|
@@ -132,8 +137,8 @@ rule
|
|
132
137
|
|
133
138
|
ListItems:
|
134
139
|
/* nothing */ { result = [] }
|
135
|
-
|
|
136
|
-
| ListItems ','
|
140
|
+
| ValueExpression { result = [val[0]] }
|
141
|
+
| ListItems ',' ValueExpression { result = val[0] << val[2] }
|
137
142
|
;
|
138
143
|
|
139
144
|
Dictionary:
|
@@ -159,30 +164,27 @@ rule
|
|
159
164
|
;
|
160
165
|
|
161
166
|
DictGet:
|
162
|
-
Dictionary
|
163
|
-
| Dictionary DictGetWithDotLiteral { result = DictGetDotNode.new(val[0], val[1]) }
|
167
|
+
Dictionary DictGetWithDotLiteral { result = DictGetDotNode.new(val[0], val[1]) }
|
164
168
|
| VariableRetrieval DictGetWithDot { result = DictGetDotNode.new(val[0], val[1]) }
|
165
169
|
| ListOrDictGet DictGetWithDot { result = DictGetDotNode.new(val[0], val[1]) }
|
166
170
|
;
|
167
171
|
|
168
172
|
ListOrDictGet:
|
169
|
-
|
170
|
-
| DictGet ListOrDictGetWithBrackets { result = ListOrDictGetNode.new(val[0], val[1]) }
|
171
|
-
| Call ListOrDictGetWithBrackets { result = ListOrDictGetNode.new(val[0], val[1]) }
|
173
|
+
ValueExpression ListOrDictGetWithBrackets { result = ListOrDictGetNode.new(val[0], val[1]) }
|
172
174
|
;
|
173
175
|
|
174
176
|
ListOrDictGetWithBrackets:
|
175
|
-
'['
|
176
|
-
| '[' SubList ']'
|
177
|
-
| ListOrDictGetWithBrackets '['
|
178
|
-
| ListOrDictGetWithBrackets '[' SubList ']'
|
177
|
+
'[' ValueExpression ']' { result = [val[1]] }
|
178
|
+
| '[' SubList ']' { result = [val[1]] }
|
179
|
+
| ListOrDictGetWithBrackets '[' ValueExpression ']' { result = val[0] << val[2] }
|
180
|
+
| ListOrDictGetWithBrackets '[' SubList ']' { result = val[0] << val[2] }
|
179
181
|
;
|
180
182
|
|
181
183
|
SubList:
|
182
|
-
|
183
|
-
|
|
184
|
-
| ':'
|
185
|
-
| ':' { result =
|
184
|
+
ValueExpression ':' ValueExpression { result = SublistNode.new([val[0], LiteralNode.new(' : '), val[2]]) }
|
185
|
+
| ValueExpression ':' { result = SublistNode.new([val[0], LiteralNode.new(' :')]) }
|
186
|
+
| ':' ValueExpression { result = SublistNode.new([LiteralNode.new(': '), val[1]]) }
|
187
|
+
| ':' { result = SublistNode.new([LiteralNode.new(':')]) }
|
186
188
|
;
|
187
189
|
|
188
190
|
DictGetWithDot:
|
@@ -198,10 +200,19 @@ rule
|
|
198
200
|
Call:
|
199
201
|
Scope DefCallIdentifier '(' ArgList ')' { result = CallNode.new(val[0], val[1], val[3]) }
|
200
202
|
| DictGet '(' ArgList ')' { result = CallNode.new(nil, val[0], val[2]) }
|
201
|
-
| CALL Scope DefCallIdentifier '(' ArgList ')' { result = ExplicitCallNode.new(val[1], val[2], val[4]) }
|
202
|
-
| CALL DictGet '(' ArgList ')' { result = ExplicitCallNode.new(nil, val[1], val[3]) }
|
203
203
|
| BUILTIN_COMMAND '(' ArgList ')' { result = CallNode.new(nil, val[0], val[2]) }
|
204
204
|
| BUILTIN_COMMAND ArgList { result = CallNode.new(nil, val[0], val[1]) }
|
205
|
+
| CALL '(' ArgList ')' { result = ExplicitCallNode.new(nil, nil, val[2]) }
|
206
|
+
;
|
207
|
+
|
208
|
+
RimlCommand:
|
209
|
+
RIML_COMMAND '(' ArgList ')' { result = RimlCommandNode.new(nil, val[0], val[2]) }
|
210
|
+
| RIML_COMMAND ArgList { result = RimlCommandNode.new(nil, val[0], val[1]) }
|
211
|
+
;
|
212
|
+
|
213
|
+
ExplicitCall:
|
214
|
+
CALL Scope DefCallIdentifier '(' ArgList ')' { result = ExplicitCallNode.new(val[1], val[2], val[4]) }
|
215
|
+
| CALL DictGet '(' ArgList ')' { result = ExplicitCallNode.new(nil, val[1], val[3]) }
|
205
216
|
;
|
206
217
|
|
207
218
|
Scope:
|
@@ -211,101 +222,103 @@ rule
|
|
211
222
|
|
212
223
|
ArgList:
|
213
224
|
/* nothing */ { result = [] }
|
214
|
-
|
|
215
|
-
| ArgList ","
|
225
|
+
| ValueExpression { result = val }
|
226
|
+
| ArgList "," ValueExpression { result = val[0] << val[2] }
|
216
227
|
;
|
217
228
|
|
218
229
|
BinaryOperator:
|
219
|
-
|
220
|
-
|
|
230
|
+
ValueExpression '||' ValueExpression { result = BinaryOperatorNode.new(val[1], [val[0], val[2]]) }
|
231
|
+
| ValueExpression '&&' ValueExpression { result = BinaryOperatorNode.new(val[1], [val[0], val[2]]) }
|
221
232
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
233
|
+
| ValueExpression '==' ValueExpression { result = BinaryOperatorNode.new(val[1], [val[0], val[2]]) }
|
234
|
+
| ValueExpression '==#' ValueExpression { result = BinaryOperatorNode.new(val[1], [val[0], val[2]]) }
|
235
|
+
| ValueExpression '==?' ValueExpression { result = BinaryOperatorNode.new(val[1], [val[0], val[2]]) }
|
225
236
|
|
226
237
|
# added by riml
|
227
|
-
|
|
238
|
+
| ValueExpression '===' ValueExpression { result = BinaryOperatorNode.new(val[1], [val[0], val[2]]) }
|
228
239
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
240
|
+
| ValueExpression '!=' ValueExpression { result = BinaryOperatorNode.new(val[1], [val[0], val[2]]) }
|
241
|
+
| ValueExpression '!=#' ValueExpression { result = BinaryOperatorNode.new(val[1], [val[0], val[2]]) }
|
242
|
+
| ValueExpression '!=?' ValueExpression { result = BinaryOperatorNode.new(val[1], [val[0], val[2]]) }
|
232
243
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
244
|
+
| ValueExpression '=~' ValueExpression { result = BinaryOperatorNode.new(val[1], [val[0], val[2]]) }
|
245
|
+
| ValueExpression '=~#' ValueExpression { result = BinaryOperatorNode.new(val[1], [val[0], val[2]]) }
|
246
|
+
| ValueExpression '=~?' ValueExpression { result = BinaryOperatorNode.new(val[1], [val[0], val[2]]) }
|
236
247
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
248
|
+
| ValueExpression '!~' ValueExpression { result = BinaryOperatorNode.new(val[1], [val[0], val[2]]) }
|
249
|
+
| ValueExpression '!~#' ValueExpression { result = BinaryOperatorNode.new(val[1], [val[0], val[2]]) }
|
250
|
+
| ValueExpression '!~?' ValueExpression { result = BinaryOperatorNode.new(val[1], [val[0], val[2]]) }
|
240
251
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
252
|
+
| ValueExpression '>' ValueExpression { result = BinaryOperatorNode.new(val[1], [val[0], val[2]]) }
|
253
|
+
| ValueExpression '>#' ValueExpression { result = BinaryOperatorNode.new(val[1], [val[0], val[2]]) }
|
254
|
+
| ValueExpression '>?' ValueExpression { result = BinaryOperatorNode.new(val[1], [val[0], val[2]]) }
|
244
255
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
256
|
+
| ValueExpression '>=' ValueExpression { result = BinaryOperatorNode.new(val[1], [val[0], val[2]]) }
|
257
|
+
| ValueExpression '>=#' ValueExpression { result = BinaryOperatorNode.new(val[1], [val[0], val[2]]) }
|
258
|
+
| ValueExpression '>=?' ValueExpression { result = BinaryOperatorNode.new(val[1], [val[0], val[2]]) }
|
248
259
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
260
|
+
| ValueExpression '<' ValueExpression { result = BinaryOperatorNode.new(val[1], [val[0], val[2]]) }
|
261
|
+
| ValueExpression '<#' ValueExpression { result = BinaryOperatorNode.new(val[1], [val[0], val[2]]) }
|
262
|
+
| ValueExpression '<?' ValueExpression { result = BinaryOperatorNode.new(val[1], [val[0], val[2]]) }
|
252
263
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
264
|
+
| ValueExpression '<=' ValueExpression { result = BinaryOperatorNode.new(val[1], [val[0], val[2]]) }
|
265
|
+
| ValueExpression '<=#' ValueExpression { result = BinaryOperatorNode.new(val[1], [val[0], val[2]]) }
|
266
|
+
| ValueExpression '<=?' ValueExpression { result = BinaryOperatorNode.new(val[1], [val[0], val[2]]) }
|
256
267
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
268
|
+
| ValueExpression '+' ValueExpression { result = BinaryOperatorNode.new(val[1], [val[0], val[2]]) }
|
269
|
+
| ValueExpression '-' ValueExpression { result = BinaryOperatorNode.new(val[1], [val[0], val[2]]) }
|
270
|
+
| ValueExpression '*' ValueExpression { result = BinaryOperatorNode.new(val[1], [val[0], val[2]]) }
|
271
|
+
| ValueExpression '/' ValueExpression { result = BinaryOperatorNode.new(val[1], [val[0], val[2]]) }
|
272
|
+
| ValueExpression '.' ValueExpression { result = BinaryOperatorNode.new(val[1], [val[0], val[2]]) }
|
262
273
|
|
263
|
-
|
|
264
|
-
|
|
274
|
+
| ValueExpression IS ValueExpression { result = BinaryOperatorNode.new(val[1], [val[0], val[2]]) }
|
275
|
+
| ValueExpression ISNOT ValueExpression { result = BinaryOperatorNode.new(val[1], [val[0], val[2]]) }
|
265
276
|
;
|
266
277
|
|
267
278
|
UnaryOperator:
|
268
|
-
'!'
|
279
|
+
'!' ValueExpression { result = UnaryOperatorNode.new(val[0], val[1]) }
|
280
|
+
| '+' ValueExpression { result = UnaryOperatorNode.new(val[0], val[1]) }
|
281
|
+
| '-' ValueExpression { result = UnaryOperatorNode.new(val[0], val[1]) }
|
269
282
|
;
|
270
283
|
|
271
284
|
# ['=', LHS, RHS]
|
272
285
|
Assign:
|
273
|
-
LET AssignExpression
|
274
|
-
| AssignExpression
|
286
|
+
LET AssignExpression { result = AssignNode.new(val[1][0], val[1][1], val[1][2]) }
|
287
|
+
| AssignExpression { result = AssignNode.new(val[0][0], val[0][1], val[0][2]) }
|
275
288
|
;
|
276
289
|
|
277
290
|
# ['=', AssignLHS, Expression]
|
278
291
|
AssignExpression:
|
279
|
-
AssignLHS '='
|
280
|
-
| AssignLHS '+='
|
281
|
-
| AssignLHS '-='
|
282
|
-
| AssignLHS '.='
|
292
|
+
AssignLHS '=' ValueExpression { result = [val[1], val[0], val[2]] }
|
293
|
+
| AssignLHS '+=' ValueExpression { result = [val[1], val[0], val[2]] }
|
294
|
+
| AssignLHS '-=' ValueExpression { result = [val[1], val[0], val[2]] }
|
295
|
+
| AssignLHS '.=' ValueExpression { result = [val[1], val[0], val[2]] }
|
283
296
|
;
|
284
297
|
|
285
298
|
AssignLHS:
|
286
|
-
VariableRetrieval
|
287
|
-
| DictGet
|
288
|
-
| List
|
289
|
-
| ListOrDictGet
|
299
|
+
VariableRetrieval { result = val[0] }
|
300
|
+
| DictGet { result = val[0] }
|
301
|
+
| List { result = val[0] }
|
302
|
+
| ListOrDictGet { result = val[0] }
|
290
303
|
;
|
291
304
|
|
292
305
|
# retrieving the value of a variable
|
293
306
|
VariableRetrieval:
|
294
|
-
Scope IDENTIFIER
|
295
|
-
| SPECIAL_VAR_PREFIX IDENTIFIER
|
296
|
-
| Scope CurlyBraceName
|
307
|
+
Scope IDENTIFIER { result = GetVariableNode.new(val[0], val[1]) }
|
308
|
+
| SPECIAL_VAR_PREFIX IDENTIFIER { result = GetSpecialVariableNode.new(val[0], val[1]) }
|
309
|
+
| Scope CurlyBraceName { result = GetCurlyBraceNameNode.new(val[0], val[1]) }
|
297
310
|
;
|
298
311
|
|
299
312
|
UnletVariable:
|
300
|
-
UNLET VariableRetrieval
|
301
|
-
| UNLET_BANG VariableRetrieval
|
302
|
-
| UnletVariable VariableRetrieval
|
313
|
+
UNLET VariableRetrieval { result = UnletVariableNode.new('!', [ val[1] ]) }
|
314
|
+
| UNLET_BANG VariableRetrieval { result = UnletVariableNode.new('!', [ val[1] ]) }
|
315
|
+
| UnletVariable VariableRetrieval { result = val[0] << val[1] }
|
303
316
|
;
|
304
317
|
|
305
318
|
CurlyBraceName:
|
306
|
-
IDENTIFIER '{' VariableRetrieval '}'
|
307
|
-
| '{' VariableRetrieval '}' IDENTIFIER
|
308
|
-
| CurlyBraceName IDENTIFIER
|
319
|
+
IDENTIFIER '{' VariableRetrieval '}' { result = CurlyBraceVariable.new([ CurlyBracePart.new(val[0]), CurlyBracePart.new(val[2]) ]) }
|
320
|
+
| '{' VariableRetrieval '}' IDENTIFIER { result = CurlyBraceVariable.new([ CurlyBracePart.new(val[1]), CurlyBracePart.new(val[3]) ]) }
|
321
|
+
| CurlyBraceName IDENTIFIER { result = val[0] << CurlyBracePart.new(val[1]) }
|
309
322
|
;
|
310
323
|
|
311
324
|
# Method definition
|
@@ -325,11 +338,11 @@ rule
|
|
325
338
|
|
326
339
|
DefCallIdentifier:
|
327
340
|
# use '' for first argument instead of nil in order to avoid a double scope-modifier
|
328
|
-
CurlyBraceName { result = GetCurlyBraceNameNode.new('', val[0])}
|
341
|
+
CurlyBraceName { result = GetCurlyBraceNameNode.new('', val[0]) }
|
329
342
|
| IDENTIFIER { result = val[0] }
|
330
343
|
;
|
331
344
|
|
332
|
-
# Example: 'range' or '
|
345
|
+
# Example: 'range', 'dict' or 'abort' after function definition
|
333
346
|
Keyword:
|
334
347
|
IDENTIFIER { result = val[0] }
|
335
348
|
| /* nothing */ { result = nil }
|
@@ -342,7 +355,7 @@ rule
|
|
342
355
|
;
|
343
356
|
|
344
357
|
Return:
|
345
|
-
RETURN
|
358
|
+
RETURN ValueExpression { result = ReturnNode.new(val[1]) }
|
346
359
|
| RETURN Terminator { result = ReturnNode.new(nil) }
|
347
360
|
;
|
348
361
|
|
@@ -352,23 +365,23 @@ rule
|
|
352
365
|
|
353
366
|
# [expression, expressions]
|
354
367
|
If:
|
355
|
-
IF
|
356
|
-
| IF
|
357
|
-
|
|
368
|
+
IF ValueExpression IfBlock END { result = IfNode.new(val[1], val[2]) }
|
369
|
+
| IF ValueExpression THEN ValueExpression END { result = IfNode.new(val[1], Nodes.new([val[3]])) }
|
370
|
+
| ValueExpression IF ValueExpression { result = IfNode.new(val[2], Nodes.new([val[0]])) }
|
358
371
|
;
|
359
372
|
|
360
373
|
Unless:
|
361
|
-
UNLESS
|
362
|
-
| UNLESS
|
363
|
-
|
|
374
|
+
UNLESS ValueExpression IfBlock END { result = UnlessNode.new(val[1], val[2]) }
|
375
|
+
| UNLESS ValueExpression THEN ValueExpression END { result = UnlessNode.new(val[1], Nodes.new([val[3]])) }
|
376
|
+
| ValueExpression UNLESS ValueExpression { result = UnlessNode.new(val[2], Nodes.new([val[0]])) }
|
364
377
|
;
|
365
378
|
|
366
379
|
Ternary:
|
367
|
-
|
380
|
+
ValueExpression '?' ValueExpression ':' ValueExpression { result = TernaryOperatorNode.new([val[0], val[2], val[4]]) }
|
368
381
|
;
|
369
382
|
|
370
383
|
While:
|
371
|
-
WHILE
|
384
|
+
WHILE ValueExpression Block END { result = WhileNode.new(val[1], val[2]) }
|
372
385
|
;
|
373
386
|
|
374
387
|
LoopKeyword:
|
@@ -377,12 +390,12 @@ rule
|
|
377
390
|
;
|
378
391
|
|
379
392
|
Until:
|
380
|
-
UNTIL
|
393
|
+
UNTIL ValueExpression Block END { result = UntilNode.new(val[1], val[2]) }
|
381
394
|
;
|
382
395
|
|
383
396
|
For:
|
384
|
-
FOR IDENTIFIER IN
|
385
|
-
| FOR List IN
|
397
|
+
FOR IDENTIFIER IN ValueExpression Block END { result = ForNode.new(val[1], val[3], val[4]) }
|
398
|
+
| FOR List IN ValueExpression Block END { result = ForNode.new(val[1], val[3], val[4]) }
|
386
399
|
;
|
387
400
|
|
388
401
|
Try:
|
@@ -409,17 +422,18 @@ rule
|
|
409
422
|
|
410
423
|
IfBlock:
|
411
424
|
Block { result = val[0] }
|
412
|
-
| NEWLINE Expressions ElseBlock { result = val[1]
|
425
|
+
| NEWLINE Expressions ElseBlock { result = val[1] << val[2] }
|
426
|
+
| NEWLINE Expressions ElseifBlock { result = val[1] << val[2] }
|
427
|
+
| NEWLINE Expressions ElseifBlock ElseBlock { result = val[1] << val[2] << val[3] }
|
413
428
|
;
|
414
429
|
|
415
430
|
ElseBlock:
|
416
|
-
|
431
|
+
ELSE NEWLINE Expressions { result = ElseNode.new(val[2]) }
|
417
432
|
;
|
418
433
|
|
419
434
|
ElseifBlock:
|
420
|
-
ELSEIF
|
421
|
-
| ElseifBlock ELSEIF
|
422
|
-
| /* nothing */ { result = nil }
|
435
|
+
ELSEIF ValueExpression NEWLINE Expressions { result = Nodes.new([ElseifNode.new(val[1], val[3])]) }
|
436
|
+
| ElseifBlock ELSEIF ValueExpression NEWLINE Expressions { result = val[0] << ElseifNode.new(val[2], val[4]) }
|
423
437
|
;
|
424
438
|
|
425
439
|
ClassDefinition:
|
@@ -449,27 +463,31 @@ end
|
|
449
463
|
---- inner
|
450
464
|
# This code will be put as-is in the parser class
|
451
465
|
|
466
|
+
attr_accessor :ast_rewriter
|
467
|
+
|
452
468
|
# parses tokens or code into output nodes
|
453
|
-
def parse(object,
|
469
|
+
def parse(object, ast_rewriter = AST_Rewriter.new)
|
454
470
|
if tokens?(object)
|
455
471
|
@tokens = object
|
456
472
|
elsif code?(object)
|
457
473
|
@lexer = Riml::Lexer.new(object)
|
458
474
|
end
|
459
|
-
ast = do_parse
|
460
|
-
return ast if rewrite_ast == false
|
461
|
-
AST_Rewriter.new(ast).rewrite
|
462
|
-
end
|
463
475
|
|
464
|
-
|
465
|
-
|
466
|
-
|
467
|
-
|
468
|
-
|
469
|
-
|
476
|
+
begin
|
477
|
+
ast = do_parse
|
478
|
+
rescue Racc::ParseError => e
|
479
|
+
raise unless @lexer
|
480
|
+
raise Riml::ParseError, "line #{@lexer.lineno}: #{e.message}"
|
481
|
+
end
|
482
|
+
|
483
|
+
@ast_rewriter = ast_rewriter
|
484
|
+
return ast unless @ast_rewriter
|
485
|
+
@ast_rewriter.ast = ast
|
486
|
+
@ast_rewriter.rewrite
|
470
487
|
end
|
471
|
-
alias do_parse do_parse_with_error_handling
|
472
488
|
|
489
|
+
# get the next token from either the list of tokens provided, or
|
490
|
+
# the lexer getting the next token
|
473
491
|
def next_token
|
474
492
|
return @tokens.shift unless @lexer
|
475
493
|
@lexer.next_token
|