summaryrefslogtreecommitdiff
path: root/ext/ripper/tools/dsl.rb
diff options
context:
space:
mode:
Diffstat (limited to 'ext/ripper/tools/dsl.rb')
-rw-r--r--ext/ripper/tools/dsl.rb48
1 files changed, 33 insertions, 15 deletions
diff --git a/ext/ripper/tools/dsl.rb b/ext/ripper/tools/dsl.rb
index 49ff51711f..d0002d1ec3 100644
--- a/ext/ripper/tools/dsl.rb
+++ b/ext/ripper/tools/dsl.rb
@@ -1,37 +1,52 @@
+# frozen_string_literal: true
+
# Simple DSL implementation for Ripper code generation
#
-# input: /*% ripper: stmts_add(stmts_new, void_stmt) %*/
+# input: /*% ripper: stmts_add!(stmts_new!, void_stmt!) %*/
# output:
# VALUE v1, v2;
# v1 = dispatch0(stmts_new);
# v2 = dispatch0(void_stmt);
# $$ = dispatch2(stmts_add, v1, v2);
-
-$dollar = "$$"
-alias $$ $dollar
+#
+# - The code must be a single line.
+#
+# - The code is basically Ruby code, even if it appears like in C and
+# the result will be processed as C. e.g., comments need to be in
+# Ruby style.
class DSL
- def initialize(code, options)
+ TAG_PATTERN = /(?><[a-zA-Z0-9_]+>)/.source
+ NAME_PATTERN = /(?>\$|\d+|[a-zA-Z_][a-zA-Z0-9_]*|\[[a-zA-Z_.][-a-zA-Z0-9_.]*\])(?>(?:\.|->)[a-zA-Z_][a-zA-Z0-9_]*)*/.source
+ NOT_REF_PATTERN = /(?>\#.*|[^\"$@]*|"(?>\\.|[^\"])*")/.source
+
+ def self.line?(line, lineno = nil)
+ if %r</\*% *ripper(?:\[(.*?)\])?: *(.*?) *%\*/> =~ line
+ new($2, $1&.split(",") || [], lineno)
+ end
+ end
+
+ def initialize(code, options, lineno = nil)
+ @lineno = lineno
@events = {}
@error = options.include?("error")
@brace = options.include?("brace")
if options.include?("final")
@final = "p->result"
else
- @final = (options.grep(/\A\$(?:\$|\d+)\z/)[0] || "$$")
+ @final = (options.grep(/\A\$#{NAME_PATTERN}\z/o)[0] || "p->s_lvalue")
end
@vars = 0
- # create $1 == "$1", $2 == "$2", ...
- s = (1..20).map {|n| "$#{n}"}
- re = Array.new(s.size, "([^\0]+)")
- /#{re.join("\0")}/ =~ s.join("\0")
-
# struct parser_params *p
p = p = "p"
- @code = ""
+ @code = +""
+ code = code.gsub(%r[\G#{NOT_REF_PATTERN}\K(\$|\$:|@)#{TAG_PATTERN}?#{NAME_PATTERN}]o, '"\&"')
@last_value = eval(code)
+ rescue SyntaxError
+ $stderr.puts "error on line #{@lineno}" if @lineno
+ raise
end
attr_reader :events
@@ -62,11 +77,15 @@ class DSL
vars = []
args.each do |arg|
vars << v = new_var
- @code << "#{ v }=#{ arg };"
+ if arg =~ /\A\$:#{NAME_PATTERN}\z/
+ @code << "#{ v }=get_value(#{arg});"
+ else
+ @code << "#{ v }=#{ arg };"
+ end
end
v = new_var
d = "dispatch#{ args.size }(#{ [event, *vars].join(",") })"
- d = "#{ vars.last }==Qundef ? #{ vars.first } : #{ d }" if qundef_check
+ d = "#{ vars.last }==rb_ripper_none ? #{ vars.first } : #{ d }" if qundef_check
@code << "#{ v }=#{ d };"
v
end
@@ -85,4 +104,3 @@ class DSL
name
end
end
-