summaryrefslogtreecommitdiff
path: root/ext/ripper
diff options
context:
space:
mode:
Diffstat (limited to 'ext/ripper')
-rw-r--r--ext/ripper/.cvsignore4
-rw-r--r--ext/ripper/MANIFEST23
-rw-r--r--ext/ripper/README4
-rw-r--r--ext/ripper/depend854
-rw-r--r--ext/ripper/eventids2.c540
-rw-r--r--ext/ripper/eventids2.h8
-rw-r--r--ext/ripper/extconf.rb24
-rw-r--r--ext/ripper/lib/ripper.rb73
-rw-r--r--ext/ripper/lib/ripper/core.rb869
-rw-r--r--ext/ripper/lib/ripper/core.rb.in69
-rw-r--r--ext/ripper/lib/ripper/filter.rb42
-rw-r--r--ext/ripper/lib/ripper/lexer.rb379
-rw-r--r--ext/ripper/lib/ripper/sexp.rb187
-rw-r--r--ext/ripper/lib/ripper/tokenizer.rb64
-rw-r--r--ext/ripper/ripper_init.c.tmpl680
-rw-r--r--ext/ripper/ripper_init.h6
-rw-r--r--ext/ripper/test/check-event-arity.rb24
-rwxr-xr-xext/ripper/test/check-event-coverage.sh15
-rw-r--r--ext/ripper/test/check-scanner-event-coverage.rb18
-rw-r--r--ext/ripper/test/list-called-events.rb12
-rw-r--r--ext/ripper/test/src_rb363
-rw-r--r--ext/ripper/test/validate.rb68
-rw-r--r--ext/ripper/tools/dsl.rb181
-rwxr-xr-xext/ripper/tools/generate-eventids1.rb16
-rw-r--r--[-rwxr-xr-x]ext/ripper/tools/generate-param-macros.rb1
-rwxr-xr-xext/ripper/tools/generate-ripper_rb.rb60
-rw-r--r--ext/ripper/tools/generate.rb194
-rwxr-xr-xext/ripper/tools/list-parse-event-ids.rb33
-rwxr-xr-xext/ripper/tools/list-scan-event-ids.rb23
-rw-r--r--[-rwxr-xr-x]ext/ripper/tools/preproc.rb139
-rw-r--r--[-rwxr-xr-x]ext/ripper/tools/strip.rb8
31 files changed, 3002 insertions, 1979 deletions
diff --git a/ext/ripper/.cvsignore b/ext/ripper/.cvsignore
deleted file mode 100644
index 184a72c8ce..0000000000
--- a/ext/ripper/.cvsignore
+++ /dev/null
@@ -1,4 +0,0 @@
-Makefile
-eventids1.c
-ripper.c
-ripper.y
diff --git a/ext/ripper/MANIFEST b/ext/ripper/MANIFEST
deleted file mode 100644
index 9ca4fa82ca..0000000000
--- a/ext/ripper/MANIFEST
+++ /dev/null
@@ -1,23 +0,0 @@
-MANIFEST
-README
-depend
-eventids2.c
-extconf.rb
-lib/ripper.rb
-lib/ripper/core.rb
-lib/ripper/core.rb.in
-lib/ripper/filter.rb
-lib/ripper/tokenizer.rb
-test/check-event-arity.rb
-test/check-event-coverage.sh
-test/check-scanner-event-coverage.rb
-test/list-called-events.rb
-test/src.rb
-test/validate.rb
-tools/generate-eventids1.rb
-tools/generate-param-macros.rb
-tools/generate-ripper_rb.rb
-tools/list-parse-event-ids.rb
-tools/list-scan-event-ids.rb
-tools/preproc.rb
-tools/strip.rb
diff --git a/ext/ripper/README b/ext/ripper/README
index 5242c4256d..70fa208920 100644
--- a/ext/ripper/README
+++ b/ext/ripper/README
@@ -8,18 +8,16 @@ Ripper README
Ripper is still early-alpha version.
I never assure any kind of backward compatibility.
-
+
Requirements
------------
* ruby 1.9 (support CVS HEAD only)
- * bison 1.28 or later (You MUST use bison)
Usage
-----
See test/ripper/* and sample/ripper/*.
- To know thrown events, see lib/ripper.rb.
License
-------
diff --git a/ext/ripper/depend b/ext/ripper/depend
index 3cfc4ab404..db83378a1d 100644
--- a/ext/ripper/depend
+++ b/ext/ripper/depend
@@ -1,35 +1,841 @@
-ripper.o: $(hdrdir)/lex.c eventids1.c eventids2.c
+GEN = $(srcdir)/tools/generate.rb
+SRC1 = $(top_srcdir)/parse.y
+SRC2 = $(srcdir)/eventids2.c
+LRAMA = $(BASERUBY) $(top_srcdir)/tool/lrama/exe/lrama
-ripper.c: ripper.y
- bison -t -v -o$@ ripper.y
+.SUFFIXES: .y
-ripper.y: $(hdrdir)/parse.y $(srcdir)/tools/preproc.rb
- $(RUBY) $(srcdir)/tools/preproc.rb $(hdrdir)/parse.y > $@
+src: ripper.c ripper_init.c eventids1.c eventids1.h eventids2table.c
+ripper.c ripper_init.c eventids1.c eventids1.h eventids2table.c: depend
-eventids1.c: $(hdrdir)/parse.y $(srcdir)/tools/generate-eventids1.rb ids1
- $(RUBY) $(srcdir)/tools/generate-eventids1.rb ids1 > $@
+ripper.o: ripper.c
-ids1: $(srcdir)/tools/list-parse-event-ids.rb $(hdrdir)/parse.y
- $(RUBY) $(srcdir)/tools/list-parse-event-ids.rb -a $(hdrdir)/parse.y > $@
+.y.c:
+ $(ECHO) compiling compiler $<
+ $(Q) $(LRAMA) -o$@ - $< < $<
-ids2: $(srcdir)/tools/list-scan-event-ids.rb $(srcdir)/eventids2.c
- $(RUBY) $(srcdir)/tools/list-scan-event-ids.rb -a $(srcdir)/eventids2.c > $@
+all: check
+static: check
-rb: $(srcdir)/lib/ripper/core.rb
-$(srcdir)/lib/ripper/core.rb: $(srcdir)/lib/ripper/core.rb.in ids1 ids2 $(srcdir)/tools/generate-ripper_rb.rb
- $(RUBY) $(srcdir)/tools/generate-ripper_rb.rb $(srcdir)/lib/ripper/core.rb.in ids1 ids2 > $@
+ripper.y: $(srcdir)/tools/preproc.rb $(srcdir)/tools/dsl.rb $(top_srcdir)/parse.y $(top_srcdir)/defs/id.def
+ $(ECHO) extracting $@ from $(top_srcdir)/parse.y
+ $(Q) $(RUBY) $(top_srcdir)/tool/id2token.rb $(top_srcdir)/parse.y | \
+ $(RUBY) $(srcdir)/tools/preproc.rb --output=$@ - ripper.y
-#
-# Entries for only ripper developpers: DO NOT USE
-#
+check: .eventids2-check
-test:
- $(RUBY) test/check-event-arity.rb $(hdrdir)/parse.y
- sh test/check-event-coverage.sh
- $(RUBY) test/check-scanner-event-coverage.rb
- $(RUBY) test/validate.rb > /dev/null
- @echo OK
+.eventids2-check: $(GEN) $(SRC1) $(SRC2)
+ $(ECHO) checking $(SRC1) and $(SRC2)
+ $(Q) $(RUBY) $(GEN) --mode=check --ids1src=$(SRC1) --ids2src=$(SRC2)
+ @exit > $@
+
+eventids1.h: $(GEN) $(srcdir)/tools/dsl.rb $(SRC1)
+ $(ECHO) generating $@ from $(SRC1)
+ $(Q) $(RUBY) $(GEN) --mode=eventids1_h --ids1src=$(SRC1) --output=$@
+
+eventids1.c: $(GEN) $(srcdir)/tools/dsl.rb $(SRC1)
+ $(ECHO) generating $@ from $(SRC1)
+ $(Q) $(RUBY) $(GEN) --mode=eventids1 --ids1src=$(SRC1) --output=$@
+
+eventids2table.c: $(GEN) $(srcdir)/tools/dsl.rb $(SRC2)
+ $(ECHO) generating $@ from $(SRC2)
+ $(Q) $(RUBY) $(GEN) --mode=eventids2table --ids2src=$(SRC2) --output=$@
+
+ripper_init.c: $(srcdir)/ripper_init.c.tmpl ripper.y $(srcdir)/tools/preproc.rb $(top_srcdir)/internal/ruby_parser.h
+ $(ECHO) generating $@ from $(srcdir)/ripper_init.c.tmpl
+ $(Q) $(RUBY) $(srcdir)/tools/preproc.rb --output=$@ --template=$(srcdir)/ripper_init.c.tmpl $(top_srcdir)/internal/ruby_parser.h
+
+# Entries for Ripper maintainer
preproc: ripper.E
ripper.E: ripper.c
- $(CC) -E $(CPPFLAGS) ripper.c | $(RUBY) $(srcdir)/tools/strip.rb > $@
+ $(ECHO) preprocessing ripper.c
+ $(Q) $(CC) -E $(INCFLAGS) $(CPPFLAGS) $< | $(RUBY) $(srcdir)/tools/strip.rb > $@
+
+# AUTOGENERATED DEPENDENCIES START
+eventids1.o: $(RUBY_EXTCONF_H)
+eventids1.o: $(arch_hdrdir)/ruby/config.h
+eventids1.o: $(hdrdir)/ruby/assert.h
+eventids1.o: $(hdrdir)/ruby/backward.h
+eventids1.o: $(hdrdir)/ruby/backward/2/assume.h
+eventids1.o: $(hdrdir)/ruby/backward/2/attributes.h
+eventids1.o: $(hdrdir)/ruby/backward/2/bool.h
+eventids1.o: $(hdrdir)/ruby/backward/2/inttypes.h
+eventids1.o: $(hdrdir)/ruby/backward/2/limits.h
+eventids1.o: $(hdrdir)/ruby/backward/2/long_long.h
+eventids1.o: $(hdrdir)/ruby/backward/2/stdalign.h
+eventids1.o: $(hdrdir)/ruby/backward/2/stdarg.h
+eventids1.o: $(hdrdir)/ruby/defines.h
+eventids1.o: $(hdrdir)/ruby/intern.h
+eventids1.o: $(hdrdir)/ruby/internal/abi.h
+eventids1.o: $(hdrdir)/ruby/internal/anyargs.h
+eventids1.o: $(hdrdir)/ruby/internal/arithmetic.h
+eventids1.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+eventids1.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+eventids1.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+eventids1.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+eventids1.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+eventids1.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+eventids1.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+eventids1.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+eventids1.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+eventids1.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+eventids1.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+eventids1.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+eventids1.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+eventids1.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+eventids1.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+eventids1.o: $(hdrdir)/ruby/internal/assume.h
+eventids1.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+eventids1.o: $(hdrdir)/ruby/internal/attr/artificial.h
+eventids1.o: $(hdrdir)/ruby/internal/attr/cold.h
+eventids1.o: $(hdrdir)/ruby/internal/attr/const.h
+eventids1.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+eventids1.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+eventids1.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+eventids1.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+eventids1.o: $(hdrdir)/ruby/internal/attr/error.h
+eventids1.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+eventids1.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+eventids1.o: $(hdrdir)/ruby/internal/attr/format.h
+eventids1.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+eventids1.o: $(hdrdir)/ruby/internal/attr/noalias.h
+eventids1.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+eventids1.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+eventids1.o: $(hdrdir)/ruby/internal/attr/noinline.h
+eventids1.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+eventids1.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+eventids1.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+eventids1.o: $(hdrdir)/ruby/internal/attr/pure.h
+eventids1.o: $(hdrdir)/ruby/internal/attr/restrict.h
+eventids1.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+eventids1.o: $(hdrdir)/ruby/internal/attr/warning.h
+eventids1.o: $(hdrdir)/ruby/internal/attr/weakref.h
+eventids1.o: $(hdrdir)/ruby/internal/cast.h
+eventids1.o: $(hdrdir)/ruby/internal/compiler_is.h
+eventids1.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+eventids1.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+eventids1.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+eventids1.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+eventids1.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+eventids1.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+eventids1.o: $(hdrdir)/ruby/internal/compiler_since.h
+eventids1.o: $(hdrdir)/ruby/internal/config.h
+eventids1.o: $(hdrdir)/ruby/internal/constant_p.h
+eventids1.o: $(hdrdir)/ruby/internal/core.h
+eventids1.o: $(hdrdir)/ruby/internal/core/rarray.h
+eventids1.o: $(hdrdir)/ruby/internal/core/rbasic.h
+eventids1.o: $(hdrdir)/ruby/internal/core/rbignum.h
+eventids1.o: $(hdrdir)/ruby/internal/core/rclass.h
+eventids1.o: $(hdrdir)/ruby/internal/core/rdata.h
+eventids1.o: $(hdrdir)/ruby/internal/core/rfile.h
+eventids1.o: $(hdrdir)/ruby/internal/core/rhash.h
+eventids1.o: $(hdrdir)/ruby/internal/core/robject.h
+eventids1.o: $(hdrdir)/ruby/internal/core/rregexp.h
+eventids1.o: $(hdrdir)/ruby/internal/core/rstring.h
+eventids1.o: $(hdrdir)/ruby/internal/core/rstruct.h
+eventids1.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+eventids1.o: $(hdrdir)/ruby/internal/ctype.h
+eventids1.o: $(hdrdir)/ruby/internal/dllexport.h
+eventids1.o: $(hdrdir)/ruby/internal/dosish.h
+eventids1.o: $(hdrdir)/ruby/internal/error.h
+eventids1.o: $(hdrdir)/ruby/internal/eval.h
+eventids1.o: $(hdrdir)/ruby/internal/event.h
+eventids1.o: $(hdrdir)/ruby/internal/fl_type.h
+eventids1.o: $(hdrdir)/ruby/internal/gc.h
+eventids1.o: $(hdrdir)/ruby/internal/glob.h
+eventids1.o: $(hdrdir)/ruby/internal/globals.h
+eventids1.o: $(hdrdir)/ruby/internal/has/attribute.h
+eventids1.o: $(hdrdir)/ruby/internal/has/builtin.h
+eventids1.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+eventids1.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+eventids1.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+eventids1.o: $(hdrdir)/ruby/internal/has/extension.h
+eventids1.o: $(hdrdir)/ruby/internal/has/feature.h
+eventids1.o: $(hdrdir)/ruby/internal/has/warning.h
+eventids1.o: $(hdrdir)/ruby/internal/intern/array.h
+eventids1.o: $(hdrdir)/ruby/internal/intern/bignum.h
+eventids1.o: $(hdrdir)/ruby/internal/intern/class.h
+eventids1.o: $(hdrdir)/ruby/internal/intern/compar.h
+eventids1.o: $(hdrdir)/ruby/internal/intern/complex.h
+eventids1.o: $(hdrdir)/ruby/internal/intern/cont.h
+eventids1.o: $(hdrdir)/ruby/internal/intern/dir.h
+eventids1.o: $(hdrdir)/ruby/internal/intern/enum.h
+eventids1.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+eventids1.o: $(hdrdir)/ruby/internal/intern/error.h
+eventids1.o: $(hdrdir)/ruby/internal/intern/eval.h
+eventids1.o: $(hdrdir)/ruby/internal/intern/file.h
+eventids1.o: $(hdrdir)/ruby/internal/intern/hash.h
+eventids1.o: $(hdrdir)/ruby/internal/intern/io.h
+eventids1.o: $(hdrdir)/ruby/internal/intern/load.h
+eventids1.o: $(hdrdir)/ruby/internal/intern/marshal.h
+eventids1.o: $(hdrdir)/ruby/internal/intern/numeric.h
+eventids1.o: $(hdrdir)/ruby/internal/intern/object.h
+eventids1.o: $(hdrdir)/ruby/internal/intern/parse.h
+eventids1.o: $(hdrdir)/ruby/internal/intern/proc.h
+eventids1.o: $(hdrdir)/ruby/internal/intern/process.h
+eventids1.o: $(hdrdir)/ruby/internal/intern/random.h
+eventids1.o: $(hdrdir)/ruby/internal/intern/range.h
+eventids1.o: $(hdrdir)/ruby/internal/intern/rational.h
+eventids1.o: $(hdrdir)/ruby/internal/intern/re.h
+eventids1.o: $(hdrdir)/ruby/internal/intern/ruby.h
+eventids1.o: $(hdrdir)/ruby/internal/intern/select.h
+eventids1.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+eventids1.o: $(hdrdir)/ruby/internal/intern/set.h
+eventids1.o: $(hdrdir)/ruby/internal/intern/signal.h
+eventids1.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+eventids1.o: $(hdrdir)/ruby/internal/intern/string.h
+eventids1.o: $(hdrdir)/ruby/internal/intern/struct.h
+eventids1.o: $(hdrdir)/ruby/internal/intern/thread.h
+eventids1.o: $(hdrdir)/ruby/internal/intern/time.h
+eventids1.o: $(hdrdir)/ruby/internal/intern/variable.h
+eventids1.o: $(hdrdir)/ruby/internal/intern/vm.h
+eventids1.o: $(hdrdir)/ruby/internal/interpreter.h
+eventids1.o: $(hdrdir)/ruby/internal/iterator.h
+eventids1.o: $(hdrdir)/ruby/internal/memory.h
+eventids1.o: $(hdrdir)/ruby/internal/method.h
+eventids1.o: $(hdrdir)/ruby/internal/module.h
+eventids1.o: $(hdrdir)/ruby/internal/newobj.h
+eventids1.o: $(hdrdir)/ruby/internal/scan_args.h
+eventids1.o: $(hdrdir)/ruby/internal/special_consts.h
+eventids1.o: $(hdrdir)/ruby/internal/static_assert.h
+eventids1.o: $(hdrdir)/ruby/internal/stdalign.h
+eventids1.o: $(hdrdir)/ruby/internal/stdbool.h
+eventids1.o: $(hdrdir)/ruby/internal/stdckdint.h
+eventids1.o: $(hdrdir)/ruby/internal/symbol.h
+eventids1.o: $(hdrdir)/ruby/internal/value.h
+eventids1.o: $(hdrdir)/ruby/internal/value_type.h
+eventids1.o: $(hdrdir)/ruby/internal/variable.h
+eventids1.o: $(hdrdir)/ruby/internal/warning_push.h
+eventids1.o: $(hdrdir)/ruby/internal/xmalloc.h
+eventids1.o: $(hdrdir)/ruby/missing.h
+eventids1.o: $(hdrdir)/ruby/ruby.h
+eventids1.o: $(hdrdir)/ruby/st.h
+eventids1.o: $(hdrdir)/ruby/subst.h
+eventids1.o: eventids1.h
+eventids1.o: {$(VPATH)}eventids1.c
+eventids1.o: {$(VPATH)}eventids1.h
+eventids2.o: $(RUBY_EXTCONF_H)
+eventids2.o: $(arch_hdrdir)/ruby/config.h
+eventids2.o: $(hdrdir)/ruby/assert.h
+eventids2.o: $(hdrdir)/ruby/backward.h
+eventids2.o: $(hdrdir)/ruby/backward/2/assume.h
+eventids2.o: $(hdrdir)/ruby/backward/2/attributes.h
+eventids2.o: $(hdrdir)/ruby/backward/2/bool.h
+eventids2.o: $(hdrdir)/ruby/backward/2/inttypes.h
+eventids2.o: $(hdrdir)/ruby/backward/2/limits.h
+eventids2.o: $(hdrdir)/ruby/backward/2/long_long.h
+eventids2.o: $(hdrdir)/ruby/backward/2/stdalign.h
+eventids2.o: $(hdrdir)/ruby/backward/2/stdarg.h
+eventids2.o: $(hdrdir)/ruby/defines.h
+eventids2.o: $(hdrdir)/ruby/encoding.h
+eventids2.o: $(hdrdir)/ruby/intern.h
+eventids2.o: $(hdrdir)/ruby/internal/abi.h
+eventids2.o: $(hdrdir)/ruby/internal/anyargs.h
+eventids2.o: $(hdrdir)/ruby/internal/arithmetic.h
+eventids2.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+eventids2.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+eventids2.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+eventids2.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+eventids2.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+eventids2.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+eventids2.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+eventids2.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+eventids2.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+eventids2.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+eventids2.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+eventids2.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+eventids2.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+eventids2.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+eventids2.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+eventids2.o: $(hdrdir)/ruby/internal/assume.h
+eventids2.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+eventids2.o: $(hdrdir)/ruby/internal/attr/artificial.h
+eventids2.o: $(hdrdir)/ruby/internal/attr/cold.h
+eventids2.o: $(hdrdir)/ruby/internal/attr/const.h
+eventids2.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+eventids2.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+eventids2.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+eventids2.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+eventids2.o: $(hdrdir)/ruby/internal/attr/error.h
+eventids2.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+eventids2.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+eventids2.o: $(hdrdir)/ruby/internal/attr/format.h
+eventids2.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+eventids2.o: $(hdrdir)/ruby/internal/attr/noalias.h
+eventids2.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+eventids2.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+eventids2.o: $(hdrdir)/ruby/internal/attr/noinline.h
+eventids2.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+eventids2.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+eventids2.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+eventids2.o: $(hdrdir)/ruby/internal/attr/pure.h
+eventids2.o: $(hdrdir)/ruby/internal/attr/restrict.h
+eventids2.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+eventids2.o: $(hdrdir)/ruby/internal/attr/warning.h
+eventids2.o: $(hdrdir)/ruby/internal/attr/weakref.h
+eventids2.o: $(hdrdir)/ruby/internal/cast.h
+eventids2.o: $(hdrdir)/ruby/internal/compiler_is.h
+eventids2.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+eventids2.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+eventids2.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+eventids2.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+eventids2.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+eventids2.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+eventids2.o: $(hdrdir)/ruby/internal/compiler_since.h
+eventids2.o: $(hdrdir)/ruby/internal/config.h
+eventids2.o: $(hdrdir)/ruby/internal/constant_p.h
+eventids2.o: $(hdrdir)/ruby/internal/core.h
+eventids2.o: $(hdrdir)/ruby/internal/core/rarray.h
+eventids2.o: $(hdrdir)/ruby/internal/core/rbasic.h
+eventids2.o: $(hdrdir)/ruby/internal/core/rbignum.h
+eventids2.o: $(hdrdir)/ruby/internal/core/rclass.h
+eventids2.o: $(hdrdir)/ruby/internal/core/rdata.h
+eventids2.o: $(hdrdir)/ruby/internal/core/rfile.h
+eventids2.o: $(hdrdir)/ruby/internal/core/rhash.h
+eventids2.o: $(hdrdir)/ruby/internal/core/robject.h
+eventids2.o: $(hdrdir)/ruby/internal/core/rregexp.h
+eventids2.o: $(hdrdir)/ruby/internal/core/rstring.h
+eventids2.o: $(hdrdir)/ruby/internal/core/rstruct.h
+eventids2.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+eventids2.o: $(hdrdir)/ruby/internal/ctype.h
+eventids2.o: $(hdrdir)/ruby/internal/dllexport.h
+eventids2.o: $(hdrdir)/ruby/internal/dosish.h
+eventids2.o: $(hdrdir)/ruby/internal/encoding/coderange.h
+eventids2.o: $(hdrdir)/ruby/internal/encoding/ctype.h
+eventids2.o: $(hdrdir)/ruby/internal/encoding/encoding.h
+eventids2.o: $(hdrdir)/ruby/internal/encoding/pathname.h
+eventids2.o: $(hdrdir)/ruby/internal/encoding/re.h
+eventids2.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
+eventids2.o: $(hdrdir)/ruby/internal/encoding/string.h
+eventids2.o: $(hdrdir)/ruby/internal/encoding/symbol.h
+eventids2.o: $(hdrdir)/ruby/internal/encoding/transcode.h
+eventids2.o: $(hdrdir)/ruby/internal/error.h
+eventids2.o: $(hdrdir)/ruby/internal/eval.h
+eventids2.o: $(hdrdir)/ruby/internal/event.h
+eventids2.o: $(hdrdir)/ruby/internal/fl_type.h
+eventids2.o: $(hdrdir)/ruby/internal/gc.h
+eventids2.o: $(hdrdir)/ruby/internal/glob.h
+eventids2.o: $(hdrdir)/ruby/internal/globals.h
+eventids2.o: $(hdrdir)/ruby/internal/has/attribute.h
+eventids2.o: $(hdrdir)/ruby/internal/has/builtin.h
+eventids2.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+eventids2.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+eventids2.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+eventids2.o: $(hdrdir)/ruby/internal/has/extension.h
+eventids2.o: $(hdrdir)/ruby/internal/has/feature.h
+eventids2.o: $(hdrdir)/ruby/internal/has/warning.h
+eventids2.o: $(hdrdir)/ruby/internal/intern/array.h
+eventids2.o: $(hdrdir)/ruby/internal/intern/bignum.h
+eventids2.o: $(hdrdir)/ruby/internal/intern/class.h
+eventids2.o: $(hdrdir)/ruby/internal/intern/compar.h
+eventids2.o: $(hdrdir)/ruby/internal/intern/complex.h
+eventids2.o: $(hdrdir)/ruby/internal/intern/cont.h
+eventids2.o: $(hdrdir)/ruby/internal/intern/dir.h
+eventids2.o: $(hdrdir)/ruby/internal/intern/enum.h
+eventids2.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+eventids2.o: $(hdrdir)/ruby/internal/intern/error.h
+eventids2.o: $(hdrdir)/ruby/internal/intern/eval.h
+eventids2.o: $(hdrdir)/ruby/internal/intern/file.h
+eventids2.o: $(hdrdir)/ruby/internal/intern/hash.h
+eventids2.o: $(hdrdir)/ruby/internal/intern/io.h
+eventids2.o: $(hdrdir)/ruby/internal/intern/load.h
+eventids2.o: $(hdrdir)/ruby/internal/intern/marshal.h
+eventids2.o: $(hdrdir)/ruby/internal/intern/numeric.h
+eventids2.o: $(hdrdir)/ruby/internal/intern/object.h
+eventids2.o: $(hdrdir)/ruby/internal/intern/parse.h
+eventids2.o: $(hdrdir)/ruby/internal/intern/proc.h
+eventids2.o: $(hdrdir)/ruby/internal/intern/process.h
+eventids2.o: $(hdrdir)/ruby/internal/intern/random.h
+eventids2.o: $(hdrdir)/ruby/internal/intern/range.h
+eventids2.o: $(hdrdir)/ruby/internal/intern/rational.h
+eventids2.o: $(hdrdir)/ruby/internal/intern/re.h
+eventids2.o: $(hdrdir)/ruby/internal/intern/ruby.h
+eventids2.o: $(hdrdir)/ruby/internal/intern/select.h
+eventids2.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+eventids2.o: $(hdrdir)/ruby/internal/intern/set.h
+eventids2.o: $(hdrdir)/ruby/internal/intern/signal.h
+eventids2.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+eventids2.o: $(hdrdir)/ruby/internal/intern/string.h
+eventids2.o: $(hdrdir)/ruby/internal/intern/struct.h
+eventids2.o: $(hdrdir)/ruby/internal/intern/thread.h
+eventids2.o: $(hdrdir)/ruby/internal/intern/time.h
+eventids2.o: $(hdrdir)/ruby/internal/intern/variable.h
+eventids2.o: $(hdrdir)/ruby/internal/intern/vm.h
+eventids2.o: $(hdrdir)/ruby/internal/interpreter.h
+eventids2.o: $(hdrdir)/ruby/internal/iterator.h
+eventids2.o: $(hdrdir)/ruby/internal/memory.h
+eventids2.o: $(hdrdir)/ruby/internal/method.h
+eventids2.o: $(hdrdir)/ruby/internal/module.h
+eventids2.o: $(hdrdir)/ruby/internal/newobj.h
+eventids2.o: $(hdrdir)/ruby/internal/scan_args.h
+eventids2.o: $(hdrdir)/ruby/internal/special_consts.h
+eventids2.o: $(hdrdir)/ruby/internal/static_assert.h
+eventids2.o: $(hdrdir)/ruby/internal/stdalign.h
+eventids2.o: $(hdrdir)/ruby/internal/stdbool.h
+eventids2.o: $(hdrdir)/ruby/internal/stdckdint.h
+eventids2.o: $(hdrdir)/ruby/internal/symbol.h
+eventids2.o: $(hdrdir)/ruby/internal/value.h
+eventids2.o: $(hdrdir)/ruby/internal/value_type.h
+eventids2.o: $(hdrdir)/ruby/internal/variable.h
+eventids2.o: $(hdrdir)/ruby/internal/warning_push.h
+eventids2.o: $(hdrdir)/ruby/internal/xmalloc.h
+eventids2.o: $(hdrdir)/ruby/missing.h
+eventids2.o: $(hdrdir)/ruby/onigmo.h
+eventids2.o: $(hdrdir)/ruby/oniguruma.h
+eventids2.o: $(hdrdir)/ruby/ruby.h
+eventids2.o: $(hdrdir)/ruby/st.h
+eventids2.o: $(hdrdir)/ruby/subst.h
+eventids2.o: $(top_srcdir)/internal.h
+eventids2.o: $(top_srcdir)/internal/static_assert.h
+eventids2.o: $(top_srcdir)/rubyparser.h
+eventids2.o: eventids2.c
+eventids2.o: eventids2.h
+eventids2.o: {$(VPATH)}eventids2table.c
+eventids2.o: {$(VPATH)}parse.h
+ripper.o: $(RUBY_EXTCONF_H)
+ripper.o: $(arch_hdrdir)/ruby/config.h
+ripper.o: $(hdrdir)/ruby.h
+ripper.o: $(hdrdir)/ruby/assert.h
+ripper.o: $(hdrdir)/ruby/atomic.h
+ripper.o: $(hdrdir)/ruby/backward.h
+ripper.o: $(hdrdir)/ruby/backward/2/assume.h
+ripper.o: $(hdrdir)/ruby/backward/2/attributes.h
+ripper.o: $(hdrdir)/ruby/backward/2/bool.h
+ripper.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+ripper.o: $(hdrdir)/ruby/backward/2/inttypes.h
+ripper.o: $(hdrdir)/ruby/backward/2/limits.h
+ripper.o: $(hdrdir)/ruby/backward/2/long_long.h
+ripper.o: $(hdrdir)/ruby/backward/2/stdalign.h
+ripper.o: $(hdrdir)/ruby/backward/2/stdarg.h
+ripper.o: $(hdrdir)/ruby/defines.h
+ripper.o: $(hdrdir)/ruby/encoding.h
+ripper.o: $(hdrdir)/ruby/intern.h
+ripper.o: $(hdrdir)/ruby/internal/abi.h
+ripper.o: $(hdrdir)/ruby/internal/anyargs.h
+ripper.o: $(hdrdir)/ruby/internal/arithmetic.h
+ripper.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+ripper.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+ripper.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+ripper.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+ripper.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+ripper.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+ripper.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+ripper.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+ripper.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+ripper.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+ripper.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+ripper.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+ripper.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+ripper.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+ripper.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+ripper.o: $(hdrdir)/ruby/internal/assume.h
+ripper.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+ripper.o: $(hdrdir)/ruby/internal/attr/artificial.h
+ripper.o: $(hdrdir)/ruby/internal/attr/cold.h
+ripper.o: $(hdrdir)/ruby/internal/attr/const.h
+ripper.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+ripper.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+ripper.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+ripper.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+ripper.o: $(hdrdir)/ruby/internal/attr/error.h
+ripper.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+ripper.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+ripper.o: $(hdrdir)/ruby/internal/attr/format.h
+ripper.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+ripper.o: $(hdrdir)/ruby/internal/attr/noalias.h
+ripper.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+ripper.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+ripper.o: $(hdrdir)/ruby/internal/attr/noinline.h
+ripper.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+ripper.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+ripper.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+ripper.o: $(hdrdir)/ruby/internal/attr/pure.h
+ripper.o: $(hdrdir)/ruby/internal/attr/restrict.h
+ripper.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+ripper.o: $(hdrdir)/ruby/internal/attr/warning.h
+ripper.o: $(hdrdir)/ruby/internal/attr/weakref.h
+ripper.o: $(hdrdir)/ruby/internal/cast.h
+ripper.o: $(hdrdir)/ruby/internal/compiler_is.h
+ripper.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+ripper.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+ripper.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+ripper.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+ripper.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+ripper.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+ripper.o: $(hdrdir)/ruby/internal/compiler_since.h
+ripper.o: $(hdrdir)/ruby/internal/config.h
+ripper.o: $(hdrdir)/ruby/internal/constant_p.h
+ripper.o: $(hdrdir)/ruby/internal/core.h
+ripper.o: $(hdrdir)/ruby/internal/core/rarray.h
+ripper.o: $(hdrdir)/ruby/internal/core/rbasic.h
+ripper.o: $(hdrdir)/ruby/internal/core/rbignum.h
+ripper.o: $(hdrdir)/ruby/internal/core/rclass.h
+ripper.o: $(hdrdir)/ruby/internal/core/rdata.h
+ripper.o: $(hdrdir)/ruby/internal/core/rfile.h
+ripper.o: $(hdrdir)/ruby/internal/core/rhash.h
+ripper.o: $(hdrdir)/ruby/internal/core/rmatch.h
+ripper.o: $(hdrdir)/ruby/internal/core/robject.h
+ripper.o: $(hdrdir)/ruby/internal/core/rregexp.h
+ripper.o: $(hdrdir)/ruby/internal/core/rstring.h
+ripper.o: $(hdrdir)/ruby/internal/core/rstruct.h
+ripper.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+ripper.o: $(hdrdir)/ruby/internal/ctype.h
+ripper.o: $(hdrdir)/ruby/internal/dllexport.h
+ripper.o: $(hdrdir)/ruby/internal/dosish.h
+ripper.o: $(hdrdir)/ruby/internal/encoding/coderange.h
+ripper.o: $(hdrdir)/ruby/internal/encoding/ctype.h
+ripper.o: $(hdrdir)/ruby/internal/encoding/encoding.h
+ripper.o: $(hdrdir)/ruby/internal/encoding/pathname.h
+ripper.o: $(hdrdir)/ruby/internal/encoding/re.h
+ripper.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
+ripper.o: $(hdrdir)/ruby/internal/encoding/string.h
+ripper.o: $(hdrdir)/ruby/internal/encoding/symbol.h
+ripper.o: $(hdrdir)/ruby/internal/encoding/transcode.h
+ripper.o: $(hdrdir)/ruby/internal/error.h
+ripper.o: $(hdrdir)/ruby/internal/eval.h
+ripper.o: $(hdrdir)/ruby/internal/event.h
+ripper.o: $(hdrdir)/ruby/internal/fl_type.h
+ripper.o: $(hdrdir)/ruby/internal/gc.h
+ripper.o: $(hdrdir)/ruby/internal/glob.h
+ripper.o: $(hdrdir)/ruby/internal/globals.h
+ripper.o: $(hdrdir)/ruby/internal/has/attribute.h
+ripper.o: $(hdrdir)/ruby/internal/has/builtin.h
+ripper.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+ripper.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+ripper.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+ripper.o: $(hdrdir)/ruby/internal/has/extension.h
+ripper.o: $(hdrdir)/ruby/internal/has/feature.h
+ripper.o: $(hdrdir)/ruby/internal/has/warning.h
+ripper.o: $(hdrdir)/ruby/internal/intern/array.h
+ripper.o: $(hdrdir)/ruby/internal/intern/bignum.h
+ripper.o: $(hdrdir)/ruby/internal/intern/class.h
+ripper.o: $(hdrdir)/ruby/internal/intern/compar.h
+ripper.o: $(hdrdir)/ruby/internal/intern/complex.h
+ripper.o: $(hdrdir)/ruby/internal/intern/cont.h
+ripper.o: $(hdrdir)/ruby/internal/intern/dir.h
+ripper.o: $(hdrdir)/ruby/internal/intern/enum.h
+ripper.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+ripper.o: $(hdrdir)/ruby/internal/intern/error.h
+ripper.o: $(hdrdir)/ruby/internal/intern/eval.h
+ripper.o: $(hdrdir)/ruby/internal/intern/file.h
+ripper.o: $(hdrdir)/ruby/internal/intern/hash.h
+ripper.o: $(hdrdir)/ruby/internal/intern/io.h
+ripper.o: $(hdrdir)/ruby/internal/intern/load.h
+ripper.o: $(hdrdir)/ruby/internal/intern/marshal.h
+ripper.o: $(hdrdir)/ruby/internal/intern/numeric.h
+ripper.o: $(hdrdir)/ruby/internal/intern/object.h
+ripper.o: $(hdrdir)/ruby/internal/intern/parse.h
+ripper.o: $(hdrdir)/ruby/internal/intern/proc.h
+ripper.o: $(hdrdir)/ruby/internal/intern/process.h
+ripper.o: $(hdrdir)/ruby/internal/intern/random.h
+ripper.o: $(hdrdir)/ruby/internal/intern/range.h
+ripper.o: $(hdrdir)/ruby/internal/intern/rational.h
+ripper.o: $(hdrdir)/ruby/internal/intern/re.h
+ripper.o: $(hdrdir)/ruby/internal/intern/ruby.h
+ripper.o: $(hdrdir)/ruby/internal/intern/select.h
+ripper.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+ripper.o: $(hdrdir)/ruby/internal/intern/set.h
+ripper.o: $(hdrdir)/ruby/internal/intern/signal.h
+ripper.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+ripper.o: $(hdrdir)/ruby/internal/intern/string.h
+ripper.o: $(hdrdir)/ruby/internal/intern/struct.h
+ripper.o: $(hdrdir)/ruby/internal/intern/thread.h
+ripper.o: $(hdrdir)/ruby/internal/intern/time.h
+ripper.o: $(hdrdir)/ruby/internal/intern/variable.h
+ripper.o: $(hdrdir)/ruby/internal/intern/vm.h
+ripper.o: $(hdrdir)/ruby/internal/interpreter.h
+ripper.o: $(hdrdir)/ruby/internal/iterator.h
+ripper.o: $(hdrdir)/ruby/internal/memory.h
+ripper.o: $(hdrdir)/ruby/internal/method.h
+ripper.o: $(hdrdir)/ruby/internal/module.h
+ripper.o: $(hdrdir)/ruby/internal/newobj.h
+ripper.o: $(hdrdir)/ruby/internal/scan_args.h
+ripper.o: $(hdrdir)/ruby/internal/special_consts.h
+ripper.o: $(hdrdir)/ruby/internal/static_assert.h
+ripper.o: $(hdrdir)/ruby/internal/stdalign.h
+ripper.o: $(hdrdir)/ruby/internal/stdbool.h
+ripper.o: $(hdrdir)/ruby/internal/stdckdint.h
+ripper.o: $(hdrdir)/ruby/internal/symbol.h
+ripper.o: $(hdrdir)/ruby/internal/value.h
+ripper.o: $(hdrdir)/ruby/internal/value_type.h
+ripper.o: $(hdrdir)/ruby/internal/variable.h
+ripper.o: $(hdrdir)/ruby/internal/warning_push.h
+ripper.o: $(hdrdir)/ruby/internal/xmalloc.h
+ripper.o: $(hdrdir)/ruby/io.h
+ripper.o: $(hdrdir)/ruby/missing.h
+ripper.o: $(hdrdir)/ruby/onigmo.h
+ripper.o: $(hdrdir)/ruby/oniguruma.h
+ripper.o: $(hdrdir)/ruby/ractor.h
+ripper.o: $(hdrdir)/ruby/re.h
+ripper.o: $(hdrdir)/ruby/regex.h
+ripper.o: $(hdrdir)/ruby/ruby.h
+ripper.o: $(hdrdir)/ruby/st.h
+ripper.o: $(hdrdir)/ruby/subst.h
+ripper.o: $(hdrdir)/ruby/thread_native.h
+ripper.o: $(hdrdir)/ruby/util.h
+ripper.o: $(hdrdir)/ruby/version.h
+ripper.o: $(top_srcdir)/ccan/check_type/check_type.h
+ripper.o: $(top_srcdir)/ccan/container_of/container_of.h
+ripper.o: $(top_srcdir)/ccan/list/list.h
+ripper.o: $(top_srcdir)/ccan/str/str.h
+ripper.o: $(top_srcdir)/constant.h
+ripper.o: $(top_srcdir)/encindex.h
+ripper.o: $(top_srcdir)/id_table.h
+ripper.o: $(top_srcdir)/internal.h
+ripper.o: $(top_srcdir)/internal/array.h
+ripper.o: $(top_srcdir)/internal/basic_operators.h
+ripper.o: $(top_srcdir)/internal/bignum.h
+ripper.o: $(top_srcdir)/internal/bits.h
+ripper.o: $(top_srcdir)/internal/box.h
+ripper.o: $(top_srcdir)/internal/compar.h
+ripper.o: $(top_srcdir)/internal/compile.h
+ripper.o: $(top_srcdir)/internal/compilers.h
+ripper.o: $(top_srcdir)/internal/complex.h
+ripper.o: $(top_srcdir)/internal/encoding.h
+ripper.o: $(top_srcdir)/internal/error.h
+ripper.o: $(top_srcdir)/internal/fixnum.h
+ripper.o: $(top_srcdir)/internal/gc.h
+ripper.o: $(top_srcdir)/internal/hash.h
+ripper.o: $(top_srcdir)/internal/imemo.h
+ripper.o: $(top_srcdir)/internal/io.h
+ripper.o: $(top_srcdir)/internal/numeric.h
+ripper.o: $(top_srcdir)/internal/parse.h
+ripper.o: $(top_srcdir)/internal/rational.h
+ripper.o: $(top_srcdir)/internal/re.h
+ripper.o: $(top_srcdir)/internal/ruby_parser.h
+ripper.o: $(top_srcdir)/internal/sanitizers.h
+ripper.o: $(top_srcdir)/internal/serial.h
+ripper.o: $(top_srcdir)/internal/set_table.h
+ripper.o: $(top_srcdir)/internal/static_assert.h
+ripper.o: $(top_srcdir)/internal/string.h
+ripper.o: $(top_srcdir)/internal/struct.h
+ripper.o: $(top_srcdir)/internal/symbol.h
+ripper.o: $(top_srcdir)/internal/thread.h
+ripper.o: $(top_srcdir)/internal/variable.h
+ripper.o: $(top_srcdir)/internal/vm.h
+ripper.o: $(top_srcdir)/internal/warnings.h
+ripper.o: $(top_srcdir)/method.h
+ripper.o: $(top_srcdir)/node.h
+ripper.o: $(top_srcdir)/parser_node.h
+ripper.o: $(top_srcdir)/parser_st.h
+ripper.o: $(top_srcdir)/regenc.h
+ripper.o: $(top_srcdir)/ruby_assert.h
+ripper.o: $(top_srcdir)/ruby_atomic.h
+ripper.o: $(top_srcdir)/rubyparser.h
+ripper.o: $(top_srcdir)/shape.h
+ripper.o: $(top_srcdir)/symbol.h
+ripper.o: $(top_srcdir)/thread_pthread.h
+ripper.o: $(top_srcdir)/vm_core.h
+ripper.o: $(top_srcdir)/vm_opts.h
+ripper.o: ../../probes.h
+ripper.o: eventids1.h
+ripper.o: eventids2.c
+ripper.o: eventids2.h
+ripper.o: ripper.y
+ripper.o: ripper_init.h
+ripper.o: {$(VPATH)}eventids1.c
+ripper.o: {$(VPATH)}eventids2table.c
+ripper.o: {$(VPATH)}id.h
+ripper.o: {$(VPATH)}lex.c
+ripper.o: {$(VPATH)}parse.h
+ripper.o: {$(VPATH)}probes.dmyh
+ripper.o: {$(VPATH)}ripper.c
+ripper_init.o: $(RUBY_EXTCONF_H)
+ripper_init.o: $(arch_hdrdir)/ruby/config.h
+ripper_init.o: $(hdrdir)/ruby/assert.h
+ripper_init.o: $(hdrdir)/ruby/backward.h
+ripper_init.o: $(hdrdir)/ruby/backward/2/assume.h
+ripper_init.o: $(hdrdir)/ruby/backward/2/attributes.h
+ripper_init.o: $(hdrdir)/ruby/backward/2/bool.h
+ripper_init.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+ripper_init.o: $(hdrdir)/ruby/backward/2/inttypes.h
+ripper_init.o: $(hdrdir)/ruby/backward/2/limits.h
+ripper_init.o: $(hdrdir)/ruby/backward/2/long_long.h
+ripper_init.o: $(hdrdir)/ruby/backward/2/stdalign.h
+ripper_init.o: $(hdrdir)/ruby/backward/2/stdarg.h
+ripper_init.o: $(hdrdir)/ruby/defines.h
+ripper_init.o: $(hdrdir)/ruby/encoding.h
+ripper_init.o: $(hdrdir)/ruby/intern.h
+ripper_init.o: $(hdrdir)/ruby/internal/abi.h
+ripper_init.o: $(hdrdir)/ruby/internal/anyargs.h
+ripper_init.o: $(hdrdir)/ruby/internal/arithmetic.h
+ripper_init.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+ripper_init.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+ripper_init.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+ripper_init.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+ripper_init.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+ripper_init.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+ripper_init.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+ripper_init.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+ripper_init.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+ripper_init.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+ripper_init.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+ripper_init.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+ripper_init.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+ripper_init.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+ripper_init.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+ripper_init.o: $(hdrdir)/ruby/internal/assume.h
+ripper_init.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+ripper_init.o: $(hdrdir)/ruby/internal/attr/artificial.h
+ripper_init.o: $(hdrdir)/ruby/internal/attr/cold.h
+ripper_init.o: $(hdrdir)/ruby/internal/attr/const.h
+ripper_init.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+ripper_init.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+ripper_init.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+ripper_init.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+ripper_init.o: $(hdrdir)/ruby/internal/attr/error.h
+ripper_init.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+ripper_init.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+ripper_init.o: $(hdrdir)/ruby/internal/attr/format.h
+ripper_init.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+ripper_init.o: $(hdrdir)/ruby/internal/attr/noalias.h
+ripper_init.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+ripper_init.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+ripper_init.o: $(hdrdir)/ruby/internal/attr/noinline.h
+ripper_init.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+ripper_init.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+ripper_init.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+ripper_init.o: $(hdrdir)/ruby/internal/attr/pure.h
+ripper_init.o: $(hdrdir)/ruby/internal/attr/restrict.h
+ripper_init.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+ripper_init.o: $(hdrdir)/ruby/internal/attr/warning.h
+ripper_init.o: $(hdrdir)/ruby/internal/attr/weakref.h
+ripper_init.o: $(hdrdir)/ruby/internal/cast.h
+ripper_init.o: $(hdrdir)/ruby/internal/compiler_is.h
+ripper_init.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+ripper_init.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+ripper_init.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+ripper_init.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+ripper_init.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+ripper_init.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+ripper_init.o: $(hdrdir)/ruby/internal/compiler_since.h
+ripper_init.o: $(hdrdir)/ruby/internal/config.h
+ripper_init.o: $(hdrdir)/ruby/internal/constant_p.h
+ripper_init.o: $(hdrdir)/ruby/internal/core.h
+ripper_init.o: $(hdrdir)/ruby/internal/core/rarray.h
+ripper_init.o: $(hdrdir)/ruby/internal/core/rbasic.h
+ripper_init.o: $(hdrdir)/ruby/internal/core/rbignum.h
+ripper_init.o: $(hdrdir)/ruby/internal/core/rclass.h
+ripper_init.o: $(hdrdir)/ruby/internal/core/rdata.h
+ripper_init.o: $(hdrdir)/ruby/internal/core/rfile.h
+ripper_init.o: $(hdrdir)/ruby/internal/core/rhash.h
+ripper_init.o: $(hdrdir)/ruby/internal/core/robject.h
+ripper_init.o: $(hdrdir)/ruby/internal/core/rregexp.h
+ripper_init.o: $(hdrdir)/ruby/internal/core/rstring.h
+ripper_init.o: $(hdrdir)/ruby/internal/core/rstruct.h
+ripper_init.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+ripper_init.o: $(hdrdir)/ruby/internal/ctype.h
+ripper_init.o: $(hdrdir)/ruby/internal/dllexport.h
+ripper_init.o: $(hdrdir)/ruby/internal/dosish.h
+ripper_init.o: $(hdrdir)/ruby/internal/encoding/coderange.h
+ripper_init.o: $(hdrdir)/ruby/internal/encoding/ctype.h
+ripper_init.o: $(hdrdir)/ruby/internal/encoding/encoding.h
+ripper_init.o: $(hdrdir)/ruby/internal/encoding/pathname.h
+ripper_init.o: $(hdrdir)/ruby/internal/encoding/re.h
+ripper_init.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
+ripper_init.o: $(hdrdir)/ruby/internal/encoding/string.h
+ripper_init.o: $(hdrdir)/ruby/internal/encoding/symbol.h
+ripper_init.o: $(hdrdir)/ruby/internal/encoding/transcode.h
+ripper_init.o: $(hdrdir)/ruby/internal/error.h
+ripper_init.o: $(hdrdir)/ruby/internal/eval.h
+ripper_init.o: $(hdrdir)/ruby/internal/event.h
+ripper_init.o: $(hdrdir)/ruby/internal/fl_type.h
+ripper_init.o: $(hdrdir)/ruby/internal/gc.h
+ripper_init.o: $(hdrdir)/ruby/internal/glob.h
+ripper_init.o: $(hdrdir)/ruby/internal/globals.h
+ripper_init.o: $(hdrdir)/ruby/internal/has/attribute.h
+ripper_init.o: $(hdrdir)/ruby/internal/has/builtin.h
+ripper_init.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+ripper_init.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+ripper_init.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+ripper_init.o: $(hdrdir)/ruby/internal/has/extension.h
+ripper_init.o: $(hdrdir)/ruby/internal/has/feature.h
+ripper_init.o: $(hdrdir)/ruby/internal/has/warning.h
+ripper_init.o: $(hdrdir)/ruby/internal/intern/array.h
+ripper_init.o: $(hdrdir)/ruby/internal/intern/bignum.h
+ripper_init.o: $(hdrdir)/ruby/internal/intern/class.h
+ripper_init.o: $(hdrdir)/ruby/internal/intern/compar.h
+ripper_init.o: $(hdrdir)/ruby/internal/intern/complex.h
+ripper_init.o: $(hdrdir)/ruby/internal/intern/cont.h
+ripper_init.o: $(hdrdir)/ruby/internal/intern/dir.h
+ripper_init.o: $(hdrdir)/ruby/internal/intern/enum.h
+ripper_init.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+ripper_init.o: $(hdrdir)/ruby/internal/intern/error.h
+ripper_init.o: $(hdrdir)/ruby/internal/intern/eval.h
+ripper_init.o: $(hdrdir)/ruby/internal/intern/file.h
+ripper_init.o: $(hdrdir)/ruby/internal/intern/hash.h
+ripper_init.o: $(hdrdir)/ruby/internal/intern/io.h
+ripper_init.o: $(hdrdir)/ruby/internal/intern/load.h
+ripper_init.o: $(hdrdir)/ruby/internal/intern/marshal.h
+ripper_init.o: $(hdrdir)/ruby/internal/intern/numeric.h
+ripper_init.o: $(hdrdir)/ruby/internal/intern/object.h
+ripper_init.o: $(hdrdir)/ruby/internal/intern/parse.h
+ripper_init.o: $(hdrdir)/ruby/internal/intern/proc.h
+ripper_init.o: $(hdrdir)/ruby/internal/intern/process.h
+ripper_init.o: $(hdrdir)/ruby/internal/intern/random.h
+ripper_init.o: $(hdrdir)/ruby/internal/intern/range.h
+ripper_init.o: $(hdrdir)/ruby/internal/intern/rational.h
+ripper_init.o: $(hdrdir)/ruby/internal/intern/re.h
+ripper_init.o: $(hdrdir)/ruby/internal/intern/ruby.h
+ripper_init.o: $(hdrdir)/ruby/internal/intern/select.h
+ripper_init.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+ripper_init.o: $(hdrdir)/ruby/internal/intern/set.h
+ripper_init.o: $(hdrdir)/ruby/internal/intern/signal.h
+ripper_init.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+ripper_init.o: $(hdrdir)/ruby/internal/intern/string.h
+ripper_init.o: $(hdrdir)/ruby/internal/intern/struct.h
+ripper_init.o: $(hdrdir)/ruby/internal/intern/thread.h
+ripper_init.o: $(hdrdir)/ruby/internal/intern/time.h
+ripper_init.o: $(hdrdir)/ruby/internal/intern/variable.h
+ripper_init.o: $(hdrdir)/ruby/internal/intern/vm.h
+ripper_init.o: $(hdrdir)/ruby/internal/interpreter.h
+ripper_init.o: $(hdrdir)/ruby/internal/iterator.h
+ripper_init.o: $(hdrdir)/ruby/internal/memory.h
+ripper_init.o: $(hdrdir)/ruby/internal/method.h
+ripper_init.o: $(hdrdir)/ruby/internal/module.h
+ripper_init.o: $(hdrdir)/ruby/internal/newobj.h
+ripper_init.o: $(hdrdir)/ruby/internal/scan_args.h
+ripper_init.o: $(hdrdir)/ruby/internal/special_consts.h
+ripper_init.o: $(hdrdir)/ruby/internal/static_assert.h
+ripper_init.o: $(hdrdir)/ruby/internal/stdalign.h
+ripper_init.o: $(hdrdir)/ruby/internal/stdbool.h
+ripper_init.o: $(hdrdir)/ruby/internal/stdckdint.h
+ripper_init.o: $(hdrdir)/ruby/internal/symbol.h
+ripper_init.o: $(hdrdir)/ruby/internal/value.h
+ripper_init.o: $(hdrdir)/ruby/internal/value_type.h
+ripper_init.o: $(hdrdir)/ruby/internal/variable.h
+ripper_init.o: $(hdrdir)/ruby/internal/warning_push.h
+ripper_init.o: $(hdrdir)/ruby/internal/xmalloc.h
+ripper_init.o: $(hdrdir)/ruby/missing.h
+ripper_init.o: $(hdrdir)/ruby/onigmo.h
+ripper_init.o: $(hdrdir)/ruby/oniguruma.h
+ripper_init.o: $(hdrdir)/ruby/ruby.h
+ripper_init.o: $(hdrdir)/ruby/st.h
+ripper_init.o: $(hdrdir)/ruby/subst.h
+ripper_init.o: $(top_srcdir)/internal.h
+ripper_init.o: $(top_srcdir)/internal/array.h
+ripper_init.o: $(top_srcdir)/internal/basic_operators.h
+ripper_init.o: $(top_srcdir)/internal/bignum.h
+ripper_init.o: $(top_srcdir)/internal/bits.h
+ripper_init.o: $(top_srcdir)/internal/compar.h
+ripper_init.o: $(top_srcdir)/internal/compilers.h
+ripper_init.o: $(top_srcdir)/internal/complex.h
+ripper_init.o: $(top_srcdir)/internal/fixnum.h
+ripper_init.o: $(top_srcdir)/internal/imemo.h
+ripper_init.o: $(top_srcdir)/internal/numeric.h
+ripper_init.o: $(top_srcdir)/internal/parse.h
+ripper_init.o: $(top_srcdir)/internal/rational.h
+ripper_init.o: $(top_srcdir)/internal/ruby_parser.h
+ripper_init.o: $(top_srcdir)/internal/serial.h
+ripper_init.o: $(top_srcdir)/internal/static_assert.h
+ripper_init.o: $(top_srcdir)/internal/vm.h
+ripper_init.o: $(top_srcdir)/node.h
+ripper_init.o: $(top_srcdir)/ruby_assert.h
+ripper_init.o: $(top_srcdir)/rubyparser.h
+ripper_init.o: eventids1.h
+ripper_init.o: eventids2.h
+ripper_init.o: ripper_init.h
+ripper_init.o: {$(VPATH)}parse.h
+ripper_init.o: {$(VPATH)}ripper_init.c
+# AUTOGENERATED DEPENDENCIES END
diff --git a/ext/ripper/eventids2.c b/ext/ripper/eventids2.c
index 0ce96a12d3..87f2f588ec 100644
--- a/ext/ripper/eventids2.c
+++ b/ext/ripper/eventids2.c
@@ -1,265 +1,303 @@
-#define tIGNORED_NL (tLAST_TOKEN + 1)
-#define tCOMMENT (tLAST_TOKEN + 2)
-#define tEMBDOC_BEG (tLAST_TOKEN + 3)
-#define tEMBDOC (tLAST_TOKEN + 4)
-#define tEMBDOC_END (tLAST_TOKEN + 5)
-#define tSP (tLAST_TOKEN + 6)
-#define tHEREDOC_BEG (tLAST_TOKEN + 7)
-#define tHEREDOC_END (tLAST_TOKEN + 8)
-#define k__END__ (tLAST_TOKEN + 9)
-#define tCHAR (tLAST_TOKEN + 10)
+#include "ruby/ruby.h"
+#include "rubyparser.h"
+#define YYSTYPE_IS_DECLARED
+#include "parse.h"
+#include "eventids2.h"
+#include "internal.h"
+#include "internal/static_assert.h"
-static ID ripper_id_backref;
-static ID ripper_id_backtick;
-static ID ripper_id_comma;
-static ID ripper_id_const;
-static ID ripper_id_cvar;
-static ID ripper_id_embexpr_beg;
-static ID ripper_id_embexpr_end;
-static ID ripper_id_embvar;
-static ID ripper_id_float;
-static ID ripper_id_gvar;
-static ID ripper_id_ident;
-static ID ripper_id_int;
-static ID ripper_id_ivar;
-static ID ripper_id_kw;
-static ID ripper_id_lbrace;
-static ID ripper_id_lbracket;
-static ID ripper_id_lparen;
-static ID ripper_id_nl;
-static ID ripper_id_op;
-static ID ripper_id_period;
-static ID ripper_id_rbrace;
-static ID ripper_id_rbracket;
-static ID ripper_id_rparen;
-static ID ripper_id_semicolon;
-static ID ripper_id_symbeg;
-static ID ripper_id_tstring_beg;
-static ID ripper_id_tstring_content;
-static ID ripper_id_tstring_end;
-static ID ripper_id_words_beg;
-static ID ripper_id_qwords_beg;
-static ID ripper_id_words_sep;
-static ID ripper_id_regexp_beg;
-static ID ripper_id_regexp_end;
+typedef struct {
+ ID ripper_id_backref;
+ ID ripper_id_backtick;
+ ID ripper_id_comma;
+ ID ripper_id_const;
+ ID ripper_id_cvar;
+ ID ripper_id_embexpr_beg;
+ ID ripper_id_embexpr_end;
+ ID ripper_id_embvar;
+ ID ripper_id_float;
+ ID ripper_id_gvar;
+ ID ripper_id_ident;
+ ID ripper_id_imaginary;
+ ID ripper_id_int;
+ ID ripper_id_ivar;
+ ID ripper_id_kw;
+ ID ripper_id_lbrace;
+ ID ripper_id_lbracket;
+ ID ripper_id_lparen;
+ ID ripper_id_nl;
+ ID ripper_id_op;
+ ID ripper_id_period;
+ ID ripper_id_rbrace;
+ ID ripper_id_rbracket;
+ ID ripper_id_rparen;
+ ID ripper_id_semicolon;
+ ID ripper_id_symbeg;
+ ID ripper_id_tstring_beg;
+ ID ripper_id_tstring_content;
+ ID ripper_id_tstring_end;
+ ID ripper_id_words_beg;
+ ID ripper_id_qwords_beg;
+ ID ripper_id_qsymbols_beg;
+ ID ripper_id_symbols_beg;
+ ID ripper_id_words_sep;
+ ID ripper_id_rational;
+ ID ripper_id_regexp_beg;
+ ID ripper_id_regexp_end;
+ ID ripper_id_label;
+ ID ripper_id_label_end;
+ ID ripper_id_tlambda;
+ ID ripper_id_tlambeg;
-static ID ripper_id_ignored_nl;
-static ID ripper_id_comment;
-static ID ripper_id_embdoc_beg;
-static ID ripper_id_embdoc;
-static ID ripper_id_embdoc_end;
-static ID ripper_id_sp;
-static ID ripper_id_heredoc_beg;
-static ID ripper_id_heredoc_end;
-static ID ripper_id___end__;
-static ID ripper_id_CHAR;
+ ID ripper_id_ignored_nl;
+ ID ripper_id_comment;
+ ID ripper_id_embdoc_beg;
+ ID ripper_id_embdoc;
+ ID ripper_id_embdoc_end;
+ ID ripper_id_sp;
+ ID ripper_id_heredoc_beg;
+ ID ripper_id_heredoc_end;
+ ID ripper_id___end__;
+ ID ripper_id_CHAR;
+} ripper_scanner_ids_t;
-static void
-ripper_init_eventids2()
+static ripper_scanner_ids_t ripper_scanner_ids;
+
+#include "eventids2table.c"
+
+STATIC_ASSERT(eventids2_table_size, RIPPER_EVENTIDS2_TABLE_SIZE == sizeof(ripper_scanner_ids)/sizeof(ID));
+
+void
+ripper_init_eventids2(void)
{
- ripper_id_backref = rb_intern("on_backref");
- ripper_id_backtick = rb_intern("on_backtick");
- ripper_id_comma = rb_intern("on_comma");
- ripper_id_const = rb_intern("on_const");
- ripper_id_cvar = rb_intern("on_cvar");
- ripper_id_embexpr_beg = rb_intern("on_embexpr_beg");
- ripper_id_embexpr_end = rb_intern("on_embexpr_end");
- ripper_id_embvar = rb_intern("on_embvar");
- ripper_id_float = rb_intern("on_float");
- ripper_id_gvar = rb_intern("on_gvar");
- ripper_id_ident = rb_intern("on_ident");
- ripper_id_int = rb_intern("on_int");
- ripper_id_ivar = rb_intern("on_ivar");
- ripper_id_kw = rb_intern("on_kw");
- ripper_id_lbrace = rb_intern("on_lbrace");
- ripper_id_lbracket = rb_intern("on_lbracket");
- ripper_id_lparen = rb_intern("on_lparen");
- ripper_id_nl = rb_intern("on_nl");
- ripper_id_op = rb_intern("on_op");
- ripper_id_period = rb_intern("on_period");
- ripper_id_rbrace = rb_intern("on_rbrace");
- ripper_id_rbracket = rb_intern("on_rbracket");
- ripper_id_rparen = rb_intern("on_rparen");
- ripper_id_semicolon = rb_intern("on_semicolon");
- ripper_id_symbeg = rb_intern("on_symbeg");
- ripper_id_tstring_beg = rb_intern("on_tstring_beg");
- ripper_id_tstring_content = rb_intern("on_tstring_content");
- ripper_id_tstring_end = rb_intern("on_tstring_end");
- ripper_id_words_beg = rb_intern("on_words_beg");
- ripper_id_qwords_beg = rb_intern("on_qwords_beg");
- ripper_id_words_sep = rb_intern("on_words_sep");
- ripper_id_regexp_beg = rb_intern("on_regexp_beg");
- ripper_id_regexp_end = rb_intern("on_regexp_end");
+#define set_id2(name) ripper_scanner_ids.ripper_id_##name = rb_intern_const("on_"#name)
+ set_id2(backref);
+ set_id2(backtick);
+ set_id2(comma);
+ set_id2(const);
+ set_id2(cvar);
+ set_id2(embexpr_beg);
+ set_id2(embexpr_end);
+ set_id2(embvar);
+ set_id2(float);
+ set_id2(gvar);
+ set_id2(ident);
+ set_id2(imaginary);
+ set_id2(int);
+ set_id2(ivar);
+ set_id2(kw);
+ set_id2(lbrace);
+ set_id2(lbracket);
+ set_id2(lparen);
+ set_id2(nl);
+ set_id2(op);
+ set_id2(period);
+ set_id2(rbrace);
+ set_id2(rbracket);
+ set_id2(rparen);
+ set_id2(semicolon);
+ set_id2(symbeg);
+ set_id2(tstring_beg);
+ set_id2(tstring_content);
+ set_id2(tstring_end);
+ set_id2(words_beg);
+ set_id2(qwords_beg);
+ set_id2(qsymbols_beg);
+ set_id2(symbols_beg);
+ set_id2(words_sep);
+ set_id2(rational);
+ set_id2(regexp_beg);
+ set_id2(regexp_end);
+ set_id2(label);
+ set_id2(label_end);
+ set_id2(tlambda);
+ set_id2(tlambeg);
- ripper_id_ignored_nl = rb_intern("on_ignored_nl");
- ripper_id_comment = rb_intern("on_comment");
- ripper_id_embdoc_beg = rb_intern("on_embdoc_beg");
- ripper_id_embdoc = rb_intern("on_embdoc");
- ripper_id_embdoc_end = rb_intern("on_embdoc_end");
- ripper_id_sp = rb_intern("on_sp");
- ripper_id_heredoc_beg = rb_intern("on_heredoc_beg");
- ripper_id_heredoc_end = rb_intern("on_heredoc_end");
- ripper_id___end__ = rb_intern("on___end__");
- ripper_id_CHAR = rb_intern("on_CHAR");
+ set_id2(ignored_nl);
+ set_id2(comment);
+ set_id2(embdoc_beg);
+ set_id2(embdoc);
+ set_id2(embdoc_end);
+ set_id2(sp);
+ set_id2(heredoc_beg);
+ set_id2(heredoc_end);
+ set_id2(__end__);
+ set_id2(CHAR);
}
-static struct token_assoc {
- int token;
- ID *id;
-} token_to_eventid[] = {
- {' ', &ripper_id_words_sep},
- {'!', &ripper_id_op},
- {'%', &ripper_id_op},
- {'&', &ripper_id_op},
- {'*', &ripper_id_op},
- {'+', &ripper_id_op},
- {'-', &ripper_id_op},
- {'/', &ripper_id_op},
- {'<', &ripper_id_op},
- {'=', &ripper_id_op},
- {'>', &ripper_id_op},
- {'?', &ripper_id_op},
- {'^', &ripper_id_op},
- {'|', &ripper_id_op},
- {'~', &ripper_id_op},
- {':', &ripper_id_op},
- {',', &ripper_id_comma},
- {'.', &ripper_id_period},
- {';', &ripper_id_semicolon},
- {'`', &ripper_id_backtick},
- {'\n', &ripper_id_nl},
- {kALIAS, &ripper_id_kw},
- {kAND, &ripper_id_kw},
- {kBEGIN, &ripper_id_kw},
- {kBREAK, &ripper_id_kw},
- {kCASE, &ripper_id_kw},
- {kCLASS, &ripper_id_kw},
- {kDEF, &ripper_id_kw},
- {kDEFINED, &ripper_id_kw},
- {kDO, &ripper_id_kw},
- {kDO_BLOCK, &ripper_id_kw},
- {kDO_COND, &ripper_id_kw},
- {kELSE, &ripper_id_kw},
- {kELSIF, &ripper_id_kw},
- {kEND, &ripper_id_kw},
- {kENSURE, &ripper_id_kw},
- {kFALSE, &ripper_id_kw},
- {kFOR, &ripper_id_kw},
- {kIF, &ripper_id_kw},
- {kIF_MOD, &ripper_id_kw},
- {kIN, &ripper_id_kw},
- {kMODULE, &ripper_id_kw},
- {kNEXT, &ripper_id_kw},
- {kNIL, &ripper_id_kw},
- {kNOT, &ripper_id_kw},
- {kOR, &ripper_id_kw},
- {kREDO, &ripper_id_kw},
- {kRESCUE, &ripper_id_kw},
- {kRESCUE_MOD, &ripper_id_kw},
- {kRETRY, &ripper_id_kw},
- {kRETURN, &ripper_id_kw},
- {kSELF, &ripper_id_kw},
- {kSUPER, &ripper_id_kw},
- {kTHEN, &ripper_id_kw},
- {kTRUE, &ripper_id_kw},
- {kUNDEF, &ripper_id_kw},
- {kUNLESS, &ripper_id_kw},
- {kUNLESS_MOD, &ripper_id_kw},
- {kUNTIL, &ripper_id_kw},
- {kUNTIL_MOD, &ripper_id_kw},
- {kWHEN, &ripper_id_kw},
- {kWHILE, &ripper_id_kw},
- {kWHILE_MOD, &ripper_id_kw},
- {kYIELD, &ripper_id_kw},
- {k__FILE__, &ripper_id_kw},
- {k__LINE__, &ripper_id_kw},
- {klBEGIN, &ripper_id_kw},
- {klEND, &ripper_id_kw},
- {tAMPER, &ripper_id_op},
- {tANDOP, &ripper_id_op},
- {tAREF, &ripper_id_op},
- {tASET, &ripper_id_op},
- {tASSOC, &ripper_id_op},
- {tBACK_REF, &ripper_id_backref},
- {tCMP, &ripper_id_op},
- {tCOLON2, &ripper_id_op},
- {tCOLON3, &ripper_id_op},
- {tCONSTANT, &ripper_id_const},
- {tCVAR, &ripper_id_cvar},
- {tDOT2, &ripper_id_op},
- {tDOT3, &ripper_id_op},
- {tEQ, &ripper_id_op},
- {tEQQ, &ripper_id_op},
- {tFID, &ripper_id_ident},
- {tFLOAT, &ripper_id_float},
- {tGEQ, &ripper_id_op},
- {tGVAR, &ripper_id_gvar},
- {tIDENTIFIER, &ripper_id_ident},
- {tINTEGER, &ripper_id_int},
- {tIVAR, &ripper_id_ivar},
- {tLBRACE, &ripper_id_lbrace},
- {tLBRACE_ARG, &ripper_id_lbrace},
- {'{', &ripper_id_lbrace},
- {'}', &ripper_id_rbrace},
- {tLBRACK, &ripper_id_lbracket},
- {'[', &ripper_id_lbracket},
- {']', &ripper_id_rbracket},
- {tLEQ, &ripper_id_op},
- {tLPAREN, &ripper_id_lparen},
- {tLPAREN_ARG, &ripper_id_lparen},
- {'(', &ripper_id_lparen},
- {')', &ripper_id_rparen},
- {tLSHFT, &ripper_id_op},
- {tMATCH, &ripper_id_op},
- {tNEQ, &ripper_id_op},
- {tNMATCH, &ripper_id_op},
- {tNTH_REF, &ripper_id_backref},
- {tOP_ASGN, &ripper_id_op},
- {tOROP, &ripper_id_op},
- {tPOW, &ripper_id_op},
- {tQWORDS_BEG, &ripper_id_qwords_beg},
- {tREGEXP_BEG, &ripper_id_regexp_beg},
- {tREGEXP_END, &ripper_id_regexp_end},
- {tRPAREN, &ripper_id_rparen},
- {tRSHFT, &ripper_id_op},
- {tSTAR, &ripper_id_op},
- {tSTRING_BEG, &ripper_id_tstring_beg},
- {tSTRING_CONTENT, &ripper_id_tstring_content},
- {tSTRING_DBEG, &ripper_id_embexpr_beg},
- {tSTRING_DVAR, &ripper_id_embvar},
- {tSTRING_END, &ripper_id_tstring_end},
- {tSYMBEG, &ripper_id_symbeg},
- {tUMINUS, &ripper_id_op},
- {tUMINUS_NUM, &ripper_id_op},
- {tUPLUS, &ripper_id_op},
- {tWORDS_BEG, &ripper_id_words_beg},
- {tXSTRING_BEG, &ripper_id_backtick},
+STATIC_ASSERT(k__END___range, k__END__ < SHRT_MAX);
+STATIC_ASSERT(ripper_scanner_ids_size, sizeof(ripper_scanner_ids) < SHRT_MAX);
- /* ripper specific tokens */
- {tIGNORED_NL, &ripper_id_ignored_nl},
- {tCOMMENT, &ripper_id_comment},
- {tEMBDOC_BEG, &ripper_id_embdoc_beg},
- {tEMBDOC, &ripper_id_embdoc},
- {tEMBDOC_END, &ripper_id_embdoc_end},
- {tSP, &ripper_id_sp},
- {tHEREDOC_BEG, &ripper_id_heredoc_beg},
- {tHEREDOC_END, &ripper_id_heredoc_end},
- {k__END__, &ripper_id___end__},
- {0, NULL}
-};
-
-static ID
-ripper_token2eventid(tok)
- int tok;
+ID
+ripper_token2eventid(enum yytokentype tok)
{
- struct token_assoc *a;
+#define O(member) (int)offsetof(ripper_scanner_ids_t, ripper_id_##member)+1
+ static const unsigned short offsets[] = {
+ [' '] = O(words_sep),
+ ['!'] = O(op),
+ ['%'] = O(op),
+ ['&'] = O(op),
+ ['*'] = O(op),
+ ['+'] = O(op),
+ ['-'] = O(op),
+ ['/'] = O(op),
+ ['<'] = O(op),
+ ['='] = O(op),
+ ['>'] = O(op),
+ ['?'] = O(op),
+ ['^'] = O(op),
+ ['|'] = O(op),
+ ['~'] = O(op),
+ [':'] = O(op),
+ [','] = O(comma),
+ ['.'] = O(period),
+ [';'] = O(semicolon),
+ ['`'] = O(backtick),
+ ['\n'] = O(nl),
+ [keyword_alias] = O(kw),
+ [keyword_and] = O(kw),
+ [keyword_begin] = O(kw),
+ [keyword_break] = O(kw),
+ [keyword_case] = O(kw),
+ [keyword_class] = O(kw),
+ [keyword_def] = O(kw),
+ [keyword_defined] = O(kw),
+ [keyword_do] = O(kw),
+ [keyword_do_block] = O(kw),
+ [keyword_do_cond] = O(kw),
+ [keyword_else] = O(kw),
+ [keyword_elsif] = O(kw),
+ [keyword_end] = O(kw),
+ [keyword_ensure] = O(kw),
+ [keyword_false] = O(kw),
+ [keyword_for] = O(kw),
+ [keyword_if] = O(kw),
+ [modifier_if] = O(kw),
+ [keyword_in] = O(kw),
+ [keyword_module] = O(kw),
+ [keyword_next] = O(kw),
+ [keyword_nil] = O(kw),
+ [keyword_not] = O(kw),
+ [keyword_or] = O(kw),
+ [keyword_redo] = O(kw),
+ [keyword_rescue] = O(kw),
+ [modifier_rescue] = O(kw),
+ [keyword_retry] = O(kw),
+ [keyword_return] = O(kw),
+ [keyword_self] = O(kw),
+ [keyword_super] = O(kw),
+ [keyword_then] = O(kw),
+ [keyword_true] = O(kw),
+ [keyword_undef] = O(kw),
+ [keyword_unless] = O(kw),
+ [modifier_unless] = O(kw),
+ [keyword_until] = O(kw),
+ [modifier_until] = O(kw),
+ [keyword_when] = O(kw),
+ [keyword_while] = O(kw),
+ [modifier_while] = O(kw),
+ [keyword_yield] = O(kw),
+ [keyword__FILE__] = O(kw),
+ [keyword__LINE__] = O(kw),
+ [keyword__ENCODING__] = O(kw),
+ [keyword_BEGIN] = O(kw),
+ [keyword_END] = O(kw),
+ [keyword_do_LAMBDA] = O(kw),
+ [tAMPER] = O(op),
+ [tANDOP] = O(op),
+ [tAREF] = O(op),
+ [tASET] = O(op),
+ [tASSOC] = O(op),
+ [tBACK_REF] = O(backref),
+ [tCHAR] = O(CHAR),
+ [tCMP] = O(op),
+ [tCOLON2] = O(op),
+ [tCOLON3] = O(op),
+ [tCONSTANT] = O(const),
+ [tCVAR] = O(cvar),
+ [tDOT2] = O(op),
+ [tDOT3] = O(op),
+ [tBDOT2] = O(op),
+ [tBDOT3] = O(op),
+ [tEQ] = O(op),
+ [tEQQ] = O(op),
+ [tFID] = O(ident),
+ [tFLOAT] = O(float),
+ [tGEQ] = O(op),
+ [tGVAR] = O(gvar),
+ [tIDENTIFIER] = O(ident),
+ [tIMAGINARY] = O(imaginary),
+ [tINTEGER] = O(int),
+ [tIVAR] = O(ivar),
+ [tLBRACE] = O(lbrace),
+ [tLBRACE_ARG] = O(lbrace),
+ ['{'] = O(lbrace),
+ ['}'] = O(rbrace),
+ [tLBRACK] = O(lbracket),
+ ['['] = O(lbracket),
+ [']'] = O(rbracket),
+ [tLEQ] = O(op),
+ [tLPAREN] = O(lparen),
+ [tLPAREN_ARG] = O(lparen),
+ ['('] = O(lparen),
+ [')'] = O(rparen),
+ [tLSHFT] = O(op),
+ [tMATCH] = O(op),
+ [tNEQ] = O(op),
+ [tNMATCH] = O(op),
+ [tNTH_REF] = O(backref),
+ [tOP_ASGN] = O(op),
+ [tOROP] = O(op),
+ [tPOW] = O(op),
+ [tQWORDS_BEG] = O(qwords_beg),
+ [tQSYMBOLS_BEG] = O(qsymbols_beg),
+ [tSYMBOLS_BEG] = O(symbols_beg),
+ [tRATIONAL] = O(rational),
+ [tREGEXP_BEG] = O(regexp_beg),
+ [tREGEXP_END] = O(regexp_end),
+ [tRSHFT] = O(op),
+ [tSTAR] = O(op),
+ [tDSTAR] = O(op),
+ [tANDDOT] = O(op),
+ [tSTRING_BEG] = O(tstring_beg),
+ [tSTRING_CONTENT] = O(tstring_content),
+ [tSTRING_DBEG] = O(embexpr_beg),
+ [tSTRING_DEND] = O(embexpr_end),
+ [tSTRING_DVAR] = O(embvar),
+ [tSTRING_END] = O(tstring_end),
+ [tSYMBEG] = O(symbeg),
+ [tUMINUS] = O(op),
+ [tUMINUS_NUM] = O(op),
+ [tUPLUS] = O(op),
+ [tWORDS_BEG] = O(words_beg),
+ [tXSTRING_BEG] = O(backtick),
+ [tLABEL] = O(label),
+ [tLABEL_END] = O(label_end),
+ [tLAMBDA] = O(tlambda),
+ [tLAMBEG] = O(tlambeg),
+
+ /* ripper specific tokens */
+ [tIGNORED_NL] = O(ignored_nl),
+ [tCOMMENT] = O(comment),
+ [tEMBDOC_BEG] = O(embdoc_beg),
+ [tEMBDOC] = O(embdoc),
+ [tEMBDOC_END] = O(embdoc_end),
+ [tSP] = O(sp),
+ [tHEREDOC_BEG] = O(heredoc_beg),
+ [tHEREDOC_END] = O(heredoc_end),
+ [k__END__] = O(__end__),
+ };
+#undef O
- for (a = token_to_eventid; a->id != NULL; a++) {
- if (a->token == tok)
- return *a->id;
+ int i = (int)tok;
+ if (i >= 0 && i < numberof(offsets) && (i = offsets[i]) > 0) {
+ return *(const ID *)((const char *)&ripper_scanner_ids-1+i);
}
- if (tok < 256) {
- return ripper_id_CHAR;
+ /* 128..256 are used as operator tokens */
+ if (tok < 128) {
+ return ripper_scanner_ids.ripper_id_CHAR;
}
rb_raise(rb_eRuntimeError, "[Ripper FATAL] unknown token %d", tok);
+
+ UNREACHABLE_RETURN(0);
}
diff --git a/ext/ripper/eventids2.h b/ext/ripper/eventids2.h
new file mode 100644
index 0000000000..49e46432b9
--- /dev/null
+++ b/ext/ripper/eventids2.h
@@ -0,0 +1,8 @@
+#ifndef RIPPER_EVENTIDS2
+#define RIPPER_EVENTIDS2
+
+void ripper_init_eventids2(void);
+void ripper_init_eventids2_table(VALUE self);
+ID ripper_token2eventid(enum yytokentype tok);
+
+#endif /* RIPPER_EVENTIDS2 */
diff --git a/ext/ripper/extconf.rb b/ext/ripper/extconf.rb
index f1716b84c0..c3c56c27c5 100644
--- a/ext/ripper/extconf.rb
+++ b/ext/ripper/extconf.rb
@@ -1,26 +1,18 @@
#!ruby -s
+# frozen_string_literal: true
require 'mkmf'
require 'rbconfig'
def main
- unless have_command('bison')
- $stderr.puts 'Ripper requires bison; abort'
- exit 1
- end
- $objs = %w(ripper.o)
- $cleanfiles.concat %w(ripper.y ripper.c ripper.E ripper.output eventids1.c ids1 ids2)
- $CPPFLAGS += ' -DRIPPER'
- $CPPFLAGS += ' -DRIPPER_DEBUG' if $debug
+ $objs = %w(eventids1.o eventids2.o ripper.o ripper_init.o)
+ $distcleanfiles.concat %w(ripper.y ripper.c eventids1.c eventids1.h eventids2table.c ripper_init.c)
+ $cleanfiles.concat %w(ripper.E ripper.output y.output .eventids2-check)
+ $defs << '-DRIPPER'
+ $defs << '-DRIPPER_DEBUG' if $debug
+ $VPATH << '$(topdir)' << '$(top_srcdir)'
+ $INCFLAGS << ' -I$(topdir) -I$(top_srcdir)'
create_makefile 'ripper'
end
-def have_command(cmd)
- checking_for(cmd) {
- ENV['PATH'].split(File::PATH_SEPARATOR).any? {|path|
- File.executable?("#{path}/#{cmd}#{Config::CONFIG['EXEEXT']}")
- }
- }
-end
-
main
diff --git a/ext/ripper/lib/ripper.rb b/ext/ripper/lib/ripper.rb
index 38a5a2bd19..e937d65217 100644
--- a/ext/ripper/lib/ripper.rb
+++ b/ext/ripper/lib/ripper.rb
@@ -1,3 +1,74 @@
+# frozen_string_literal: true
require 'ripper/core'
-require 'ripper/tokenizer'
+require 'ripper/lexer'
require 'ripper/filter'
+require 'ripper/sexp'
+
+# Ripper is a Ruby script parser.
+#
+# You can get information from the parser with event-based style.
+# Information such as abstract syntax trees or simple lexical analysis of the
+# Ruby program.
+#
+# == Usage
+#
+# Ripper provides an easy interface for parsing your program into a symbolic
+# expression tree (or S-expression).
+#
+# Understanding the output of the parser may come as a challenge, it's
+# recommended you use PP to format the output for legibility.
+#
+# require 'ripper'
+# require 'pp'
+#
+# pp Ripper.sexp('def hello(world) "Hello, #{world}!"; end')
+# #=> [:program,
+# [[:def,
+# [:@ident, "hello", [1, 4]],
+# [:paren,
+# [:params, [[:@ident, "world", [1, 10]]], nil, nil, nil, nil, nil, nil]],
+# [:bodystmt,
+# [[:string_literal,
+# [:string_content,
+# [:@tstring_content, "Hello, ", [1, 18]],
+# [:string_embexpr, [[:var_ref, [:@ident, "world", [1, 27]]]]],
+# [:@tstring_content, "!", [1, 33]]]]],
+# nil,
+# nil,
+# nil]]]]
+#
+# You can see in the example above, the expression starts with +:program+.
+#
+# From here, a method definition at +:def+, followed by the method's identifier
+# <code>:@ident</code>. After the method's identifier comes the parentheses
+# +:paren+ and the method parameters under +:params+.
+#
+# Next is the method body, starting at +:bodystmt+ (+stmt+ meaning statement),
+# which contains the full definition of the method.
+#
+# In our case, we're simply returning a String, so next we have the
+# +:string_literal+ expression.
+#
+# Within our +:string_literal+ you'll notice two <code>@tstring_content</code>,
+# this is the literal part for <code>Hello, </code> and <code>!</code>. Between
+# the two <code>@tstring_content</code> statements is a +:string_embexpr+,
+# where _embexpr_ is an embedded expression. Our expression consists of a local
+# variable, or +var_ref+, with the identifier (<code>@ident</code>) of +world+.
+#
+# == Resources
+#
+# * {Ruby Inside}[http://www.rubyinside.com/using-ripper-to-see-how-ruby-is-parsing-your-code-5270.html]
+#
+# == Requirements
+#
+# * ruby 1.9 (support CVS HEAD only)
+# * bison 1.28 or later (Other yaccs do not work)
+#
+# == License
+#
+# Ruby License.
+#
+# - Minero Aoki
+# - aamine@loveruby.net
+# - http://i.loveruby.net
+class Ripper; end
diff --git a/ext/ripper/lib/ripper/core.rb b/ext/ripper/lib/ripper/core.rb
index e936783698..fa075da5b9 100644
--- a/ext/ripper/lib/ripper/core.rb
+++ b/ext/ripper/lib/ripper/core.rb
@@ -1,10 +1,8 @@
-# This file is automatically generated from core.rb.in and parse.y.
-# DO NOT MODIFY!!!!!!
-
+# frozen_string_literal: true
#
-# ripper/core.rb
+# $Id$
#
-# Copyright (C) 2003,2004 Minero Aoki
+# Copyright (c) 2003-2005 Minero Aoki
#
# This program is free software.
# You can distribute and/or modify this program under the Ruby License.
@@ -14,870 +12,63 @@
require 'ripper.so'
class Ripper
- # Parses Ruby program read from _src_.
- # _src_ must be a String or a IO or a object which has #gets method.
+
+ # Parses the given Ruby program read from +src+.
+ # +src+ must be a String or an IO or a object with a #gets method.
def Ripper.parse(src, filename = '(ripper)', lineno = 1)
new(src, filename, lineno).parse
end
- # This table contains name of parser events and its arity.
- PARSER_EVENT_TABLE = {
- :BEGIN => 1,
- :END => 1,
- :alias => 2,
- :alias_error => 1,
- :aref => 2,
- :aref_field => 2,
- :arg_ambiguous => 0,
- :arg_paren => 1,
- :arglist_add => 2,
- :arglist_add_block => 2,
- :arglist_add_star => 2,
- :arglist_new => 0,
- :arglist_prepend => 2,
- :array => 1,
- :assign => 2,
- :assign_error => 1,
- :assoc_new => 2,
- :assoclist_from_args => 1,
- :bare_assoc_hash => 1,
- :begin => 1,
- :binary => 3,
- :blockvar_add_block => 2,
- :blockvar_add_star => 2,
- :blockvar_new => 1,
- :bodystmt => 4,
- :brace_block => 2,
- :break => 1,
- :call => 3,
- :case => 2,
- :class => 3,
- :class_name_error => 1,
- :command => 2,
- :command_call => 4,
- :const_ref => 1,
- :constpath_field => 2,
- :constpath_ref => 2,
- :def => 3,
- :defined => 1,
- :defs => 5,
- :do_block => 2,
- :dot2 => 2,
- :dot3 => 2,
- :dyna_symbol => 1,
- :else => 1,
- :elsif => 3,
- :ensure => 1,
- :fcall => 1,
- :field => 3,
- :for => 3,
- :hash => 1,
- :if => 3,
- :if_mod => 2,
- :ifop => 3,
- :iter_block => 2,
- :massign => 2,
- :method_add_arg => 2,
- :mlhs_add => 2,
- :mlhs_add_star => 2,
- :mlhs_new => 0,
- :mlhs_paren => 1,
- :module => 2,
- :mrhs_add => 2,
- :mrhs_add_star => 2,
- :mrhs_new => 0,
- :mrhs_new_from_arglist => 1,
- :next => 1,
- :opassign => 3,
- :param_error => 1,
- :params => 4,
- :paren => 1,
- :parse_error => 1,
- :program => 1,
- :qwords_add => 2,
- :qwords_new => 0,
- :redo => 0,
- :regexp_literal => 1,
- :rescue => 4,
- :rescue_mod => 2,
- :restparam => 1,
- :retry => 0,
- :return => 1,
- :return0 => 0,
- :sclass => 2,
- :space => 1,
- :stmts_add => 2,
- :stmts_new => 0,
- :string_add => 2,
- :string_concat => 2,
- :string_content => 0,
- :string_dvar => 1,
- :string_embexpr => 1,
- :string_literal => 1,
- :super => 1,
- :symbol => 1,
- :symbol_literal => 1,
- :topconst_field => 1,
- :topconst_ref => 1,
- :unary => 2,
- :undef => 1,
- :unless => 3,
- :unless_mod => 2,
- :until => 2,
- :until_mod => 2,
- :var_alias => 2,
- :var_field => 1,
- :var_ref => 1,
- :void_stmt => 0,
- :when => 3,
- :while => 2,
- :while_mod => 2,
- :word_add => 2,
- :word_new => 0,
- :words_add => 2,
- :words_new => 0,
- :xstring_add => 2,
- :xstring_literal => 1,
- :xstring_new => 0,
- :yield => 1,
- :yield0 => 0,
- :zsuper => 0
- }
-
# This array contains name of parser events.
PARSER_EVENTS = PARSER_EVENT_TABLE.keys
- # This table contains name of scanner events and its arity
- # (arity is always 1 for all scanner events).
- SCANNER_EVENT_TABLE = {
- :CHAR => 1,
- :__end__ => 1,
- :backref => 1,
- :backtick => 1,
- :comma => 1,
- :comment => 1,
- :const => 1,
- :cvar => 1,
- :embdoc => 1,
- :embdoc_beg => 1,
- :embdoc_end => 1,
- :embexpr_beg => 1,
- :embexpr_end => 1,
- :embvar => 1,
- :float => 1,
- :gvar => 1,
- :heredoc_beg => 1,
- :heredoc_end => 1,
- :ident => 1,
- :ignored_nl => 1,
- :int => 1,
- :ivar => 1,
- :kw => 1,
- :lbrace => 1,
- :lbracket => 1,
- :lparen => 1,
- :nl => 1,
- :op => 1,
- :period => 1,
- :qwords_beg => 1,
- :rbrace => 1,
- :rbracket => 1,
- :regexp_beg => 1,
- :regexp_end => 1,
- :rparen => 1,
- :semicolon => 1,
- :sp => 1,
- :symbeg => 1,
- :tstring_beg => 1,
- :tstring_content => 1,
- :tstring_end => 1,
- :words_beg => 1,
- :words_sep => 1
- }
-
# This array contains name of scanner events.
SCANNER_EVENTS = SCANNER_EVENT_TABLE.keys
- # This table contains name of all ripper events.
+ # This array contains name of all ripper events.
EVENTS = PARSER_EVENTS + SCANNER_EVENTS
- ### ###
- ### Event Handlers ###
- ### ###
-
private
- # This method is called when weak warning is produced by the parser.
- # _fmt_ and _args_ is printf style.
- def warn(fmt, *args)
- end
-
- # This method is called when strong warning is produced by the parser.
- # _fmt_ and _args_ is printf style.
- def warning(fmt, *args)
- end
-
- # This method is called when the parser found syntax error.
- def compile_error(msg)
- end
+ # :stopdoc:
+ def _dispatch_0() nil end
+ def _dispatch_1(a) a end
+ def _dispatch_2(a, b) a end
+ def _dispatch_3(a, b, c) a end
+ def _dispatch_4(a, b, c, d) a end
+ def _dispatch_5(a, b, c, d, e) a end
+ def _dispatch_6(a, b, c, d, e, f) a end
+ def _dispatch_7(a, b, c, d, e, f, g) a end
+ # :startdoc:
#
# Parser Events
#
- def on_BEGIN(a)
- a
- end
-
- def on_END(a)
- a
- end
-
- def on_alias(a, b)
- a
- end
-
- def on_alias_error(a)
- a
+ PARSER_EVENT_TABLE.each do |id, arity|
+ alias_method "on_#{id}", "_dispatch_#{arity}"
end
- def on_aref(a, b)
- a
- end
-
- def on_aref_field(a, b)
- a
- end
-
- def on_arg_ambiguous
- nil
- end
-
- def on_arg_paren(a)
- a
- end
-
- def on_arglist_add(a, b)
- a
- end
-
- def on_arglist_add_block(a, b)
- a
- end
-
- def on_arglist_add_star(a, b)
- a
- end
-
- def on_arglist_new
- nil
- end
-
- def on_arglist_prepend(a, b)
- a
- end
-
- def on_array(a)
- a
- end
-
- def on_assign(a, b)
- a
- end
-
- def on_assign_error(a)
- a
- end
-
- def on_assoc_new(a, b)
- a
- end
-
- def on_assoclist_from_args(a)
- a
- end
-
- def on_bare_assoc_hash(a)
- a
- end
-
- def on_begin(a)
- a
- end
-
- def on_binary(a, b, c)
- a
- end
-
- def on_blockvar_add_block(a, b)
- a
- end
-
- def on_blockvar_add_star(a, b)
- a
- end
-
- def on_blockvar_new(a)
- a
- end
-
- def on_bodystmt(a, b, c, d)
- a
- end
-
- def on_brace_block(a, b)
- a
- end
-
- def on_break(a)
- a
- end
-
- def on_call(a, b, c)
- a
- end
-
- def on_case(a, b)
- a
- end
-
- def on_class(a, b, c)
- a
- end
-
- def on_class_name_error(a)
- a
- end
-
- def on_command(a, b)
- a
- end
-
- def on_command_call(a, b, c, d)
- a
- end
-
- def on_const_ref(a)
- a
- end
-
- def on_constpath_field(a, b)
- a
- end
-
- def on_constpath_ref(a, b)
- a
- end
-
- def on_def(a, b, c)
- a
- end
-
- def on_defined(a)
- a
- end
-
- def on_defs(a, b, c, d, e)
- a
- end
-
- def on_do_block(a, b)
- a
- end
-
- def on_dot2(a, b)
- a
- end
-
- def on_dot3(a, b)
- a
- end
-
- def on_dyna_symbol(a)
- a
- end
-
- def on_else(a)
- a
- end
-
- def on_elsif(a, b, c)
- a
- end
-
- def on_ensure(a)
- a
- end
-
- def on_fcall(a)
- a
- end
-
- def on_field(a, b, c)
- a
- end
-
- def on_for(a, b, c)
- a
- end
-
- def on_hash(a)
- a
- end
-
- def on_if(a, b, c)
- a
- end
-
- def on_if_mod(a, b)
- a
- end
-
- def on_ifop(a, b, c)
- a
- end
-
- def on_iter_block(a, b)
- a
- end
-
- def on_massign(a, b)
- a
- end
-
- def on_method_add_arg(a, b)
- a
- end
-
- def on_mlhs_add(a, b)
- a
- end
-
- def on_mlhs_add_star(a, b)
- a
- end
-
- def on_mlhs_new
- nil
- end
-
- def on_mlhs_paren(a)
- a
- end
-
- def on_module(a, b)
- a
- end
-
- def on_mrhs_add(a, b)
- a
- end
-
- def on_mrhs_add_star(a, b)
- a
- end
-
- def on_mrhs_new
- nil
- end
-
- def on_mrhs_new_from_arglist(a)
- a
- end
-
- def on_next(a)
- a
- end
-
- def on_opassign(a, b, c)
- a
- end
-
- def on_param_error(a)
- a
- end
-
- def on_params(a, b, c, d)
- a
- end
-
- def on_paren(a)
- a
- end
-
- def on_parse_error(a)
- a
- end
-
- def on_program(a)
- a
- end
-
- def on_qwords_add(a, b)
- a
- end
-
- def on_qwords_new
- nil
- end
-
- def on_redo
- nil
- end
-
- def on_regexp_literal(a)
- a
- end
-
- def on_rescue(a, b, c, d)
- a
- end
-
- def on_rescue_mod(a, b)
- a
- end
-
- def on_restparam(a)
- a
- end
-
- def on_retry
- nil
- end
-
- def on_return(a)
- a
- end
-
- def on_return0
- nil
- end
-
- def on_sclass(a, b)
- a
- end
-
- def on_space(a)
- a
- end
-
- def on_stmts_add(a, b)
- a
- end
-
- def on_stmts_new
- nil
- end
-
- def on_string_add(a, b)
- a
- end
-
- def on_string_concat(a, b)
- a
- end
-
- def on_string_content
- nil
- end
-
- def on_string_dvar(a)
- a
- end
-
- def on_string_embexpr(a)
- a
- end
-
- def on_string_literal(a)
- a
- end
-
- def on_super(a)
- a
- end
-
- def on_symbol(a)
- a
- end
-
- def on_symbol_literal(a)
- a
- end
-
- def on_topconst_field(a)
- a
- end
-
- def on_topconst_ref(a)
- a
- end
-
- def on_unary(a, b)
- a
- end
-
- def on_undef(a)
- a
- end
-
- def on_unless(a, b, c)
- a
- end
-
- def on_unless_mod(a, b)
- a
- end
-
- def on_until(a, b)
- a
- end
-
- def on_until_mod(a, b)
- a
- end
-
- def on_var_alias(a, b)
- a
- end
-
- def on_var_field(a)
- a
- end
-
- def on_var_ref(a)
- a
- end
-
- def on_void_stmt
- nil
- end
-
- def on_when(a, b, c)
- a
- end
-
- def on_while(a, b)
- a
- end
-
- def on_while_mod(a, b)
- a
- end
-
- def on_word_add(a, b)
- a
- end
-
- def on_word_new
- nil
- end
-
- def on_words_add(a, b)
- a
- end
-
- def on_words_new
- nil
- end
-
- def on_xstring_add(a, b)
- a
- end
-
- def on_xstring_literal(a)
- a
- end
-
- def on_xstring_new
- nil
- end
-
- def on_yield(a)
- a
+ # This method is called when weak warning is produced by the parser.
+ # +fmt+ and +args+ is printf style.
+ def warn(fmt, *args)
end
- def on_yield0
- nil
+ # This method is called when strong warning is produced by the parser.
+ # +fmt+ and +args+ is printf style.
+ def warning(fmt, *args)
end
- def on_zsuper
- nil
+ # This method is called when the parser found syntax error.
+ def compile_error(msg)
end
#
- # Lexer Events
+ # Scanner Events
#
- def on_CHAR(token)
- token
- end
-
- def on___end__(token)
- token
- end
-
- def on_backref(token)
- token
- end
-
- def on_backtick(token)
- token
- end
-
- def on_comma(token)
- token
- end
-
- def on_comment(token)
- token
- end
-
- def on_const(token)
- token
- end
-
- def on_cvar(token)
- token
- end
-
- def on_embdoc(token)
- token
- end
-
- def on_embdoc_beg(token)
- token
- end
-
- def on_embdoc_end(token)
- token
- end
-
- def on_embexpr_beg(token)
- token
- end
-
- def on_embexpr_end(token)
- token
- end
-
- def on_embvar(token)
- token
- end
-
- def on_float(token)
- token
- end
-
- def on_gvar(token)
- token
- end
-
- def on_heredoc_beg(token)
- token
- end
-
- def on_heredoc_end(token)
- token
- end
-
- def on_ident(token)
- token
- end
-
- def on_ignored_nl(token)
- token
- end
-
- def on_int(token)
- token
- end
-
- def on_ivar(token)
- token
- end
-
- def on_kw(token)
- token
- end
-
- def on_lbrace(token)
- token
- end
-
- def on_lbracket(token)
- token
- end
-
- def on_lparen(token)
- token
- end
-
- def on_nl(token)
- token
- end
-
- def on_op(token)
- token
- end
-
- def on_period(token)
- token
- end
-
- def on_qwords_beg(token)
- token
- end
-
- def on_rbrace(token)
- token
- end
-
- def on_rbracket(token)
- token
+ SCANNER_EVENTS.each do |id|
+ alias_method "on_#{id}", :_dispatch_1
end
- def on_regexp_beg(token)
- token
- end
-
- def on_regexp_end(token)
- token
- end
-
- def on_rparen(token)
- token
- end
-
- def on_semicolon(token)
- token
- end
-
- def on_sp(token)
- token
- end
-
- def on_symbeg(token)
- token
- end
-
- def on_tstring_beg(token)
- token
- end
-
- def on_tstring_content(token)
- token
- end
-
- def on_tstring_end(token)
- token
- end
-
- def on_words_beg(token)
- token
- end
-
- def on_words_sep(token)
- token
- end
end
diff --git a/ext/ripper/lib/ripper/core.rb.in b/ext/ripper/lib/ripper/core.rb.in
deleted file mode 100644
index 7e6d51ab8f..0000000000
--- a/ext/ripper/lib/ripper/core.rb.in
+++ /dev/null
@@ -1,69 +0,0 @@
-#
-# ripper/core.rb
-#
-# Copyright (C) 2003,2004 Minero Aoki
-#
-# This program is free software.
-# You can distribute and/or modify this program under the Ruby License.
-# For details of Ruby License, see ruby/COPYING.
-#
-
-require 'ripper.so'
-
-class Ripper
- # Parses Ruby program read from _src_.
- # _src_ must be a String or a IO or a object which has #gets method.
- def Ripper.parse(src, filename = '(ripper)', lineno = 1)
- new(src, filename, lineno).parse
- end
-
- # This table contains name of parser events and its arity.
- PARSER_EVENT_TABLE = {
-#include ids1
- }
-
- # This array contains name of parser events.
- PARSER_EVENTS = PARSER_EVENT_TABLE.keys
-
- # This table contains name of scanner events and its arity
- # (arity is always 1 for all scanner events).
- SCANNER_EVENT_TABLE = {
-#include ids2
- }
-
- # This array contains name of scanner events.
- SCANNER_EVENTS = SCANNER_EVENT_TABLE.keys
-
- # This table contains name of all ripper events.
- EVENTS = PARSER_EVENTS + SCANNER_EVENTS
-
- ### ###
- ### Event Handlers ###
- ### ###
-
- private
-
- # This method is called when weak warning is produced by the parser.
- # _fmt_ and _args_ is printf style.
- def warn(fmt, *args)
- end
-
- # This method is called when strong warning is produced by the parser.
- # _fmt_ and _args_ is printf style.
- def warning(fmt, *args)
- end
-
- # This method is called when the parser found syntax error.
- def compile_error(msg)
- end
-
- #
- # Parser Events
- #
-#include handlers1
-
- #
- # Lexer Events
- #
-#include handlers2
-end
diff --git a/ext/ripper/lib/ripper/filter.rb b/ext/ripper/lib/ripper/filter.rb
index 061bf109d0..9955d30550 100644
--- a/ext/ripper/lib/ripper/filter.rb
+++ b/ext/ripper/lib/ripper/filter.rb
@@ -1,30 +1,36 @@
+# frozen_string_literal: true
#
-# ripper/filter.rb
+# $Id$
#
-# Copyright (C) 2004 Minero Aoki
+# Copyright (c) 2004,2005 Minero Aoki
#
# This program is free software.
# You can distribute and/or modify this program under the Ruby License.
# For details of Ruby License, see ruby/COPYING.
#
-require 'ripper/tokenizer'
+require 'ripper/lexer'
class Ripper
# This class handles only scanner events,
- # and they are dispatched in the `right' order (same with input).
+ # which are dispatched in the 'right' order (same with input).
class Filter
+ # Creates a new Ripper::Filter instance, passes parameters +src+,
+ # +filename+, and +lineno+ to Ripper::Lexer.new
+ #
+ # The lexer is for internal use only.
def initialize(src, filename = '-', lineno = 1)
- @__parser = Tokenizer.new(src, filename, lineno)
+ @__lexer = Lexer.new(src, filename, lineno)
@__line = nil
@__col = nil
+ @__state = nil
end
# The file name of the input.
def filename
- @__parser.filename
+ @__lexer.filename
end
# The line number of the current token.
@@ -41,12 +47,20 @@ class Ripper
@__col
end
- # Starts parsing. _init_ is a data accumulator.
- # It is passed to the next event handler (as of Enumerable#inject).
+ # The scanner's state of the current token.
+ # This value is the bitwise OR of zero or more of the +Ripper::EXPR_*+ constants.
+ def state
+ @__state
+ end
+
+ # Starts the parser.
+ # +init+ is a data accumulator and is passed to the next event handler (as
+ # of Enumerable#inject).
def parse(init = nil)
data = init
- @__parser.parse.each do |pos, event, tok|
+ @__lexer.lex.each do |pos, event, tok, state|
@__line, @__col = *pos
+ @__state = state
data = if respond_to?(event, true)
then __send__(event, tok, data)
else on_default(event, tok, data)
@@ -57,10 +71,12 @@ class Ripper
private
- # This method is called when some event handler have not defined.
- # _event_ is :on_XXX, _token_ is scanned token, _data_ is a data
- # accumulator. The return value of this method is passed to the
- # next event handler (as of Enumerable#inject).
+ # This method is called when some event handler is undefined.
+ # +event+ is :on_XXX, +token+ is the scanned token, and +data+ is a data
+ # accumulator.
+ #
+ # The return value of this method is passed to the next event handler (as
+ # of Enumerable#inject).
def on_default(event, token, data)
data
end
diff --git a/ext/ripper/lib/ripper/lexer.rb b/ext/ripper/lib/ripper/lexer.rb
new file mode 100644
index 0000000000..9b849dfeae
--- /dev/null
+++ b/ext/ripper/lib/ripper/lexer.rb
@@ -0,0 +1,379 @@
+# frozen_string_literal: true
+#
+# $Id$
+#
+# Copyright (c) 2004,2005 Minero Aoki
+#
+# This program is free software.
+# You can distribute and/or modify this program under the Ruby License.
+# For details of Ruby License, see ruby/COPYING.
+#
+
+require 'ripper/core'
+
+class Ripper
+
+ # Tokenizes the Ruby program and returns an array of strings.
+ # The +filename+ and +lineno+ arguments are mostly ignored, since the
+ # return value is just the tokenized input.
+ # By default, this method does not handle syntax errors in +src+,
+ # use the +raise_errors+ keyword to raise a SyntaxError for an error in +src+.
+ #
+ # p Ripper.tokenize("def m(a) nil end")
+ # # => ["def", " ", "m", "(", "a", ")", " ", "nil", " ", "end"]
+ #
+ def Ripper.tokenize(src, filename = '-', lineno = 1, **kw)
+ Lexer.new(src, filename, lineno).tokenize(**kw)
+ end
+
+ # Tokenizes the Ruby program and returns an array of an array,
+ # which is formatted like
+ # <code>[[lineno, column], type, token, state]</code>.
+ # The +filename+ argument is mostly ignored.
+ # By default, this method does not handle syntax errors in +src+,
+ # use the +raise_errors+ keyword to raise a SyntaxError for an error in +src+.
+ #
+ # require 'ripper'
+ # require 'pp'
+ #
+ # pp Ripper.lex("def m(a) nil end")
+ # #=> [[[1, 0], :on_kw, "def", FNAME ],
+ # [[1, 3], :on_sp, " ", FNAME ],
+ # [[1, 4], :on_ident, "m", ENDFN ],
+ # [[1, 5], :on_lparen, "(", BEG|LABEL],
+ # [[1, 6], :on_ident, "a", ARG ],
+ # [[1, 7], :on_rparen, ")", ENDFN ],
+ # [[1, 8], :on_sp, " ", BEG ],
+ # [[1, 9], :on_kw, "nil", END ],
+ # [[1, 12], :on_sp, " ", END ],
+ # [[1, 13], :on_kw, "end", END ]]
+ #
+ def Ripper.lex(src, filename = '-', lineno = 1, **kw)
+ Lexer.new(src, filename, lineno).lex(**kw)
+ end
+
+ class Lexer < ::Ripper #:nodoc: internal use only
+ # :stopdoc:
+ class State
+ attr_reader :to_int, :to_s
+
+ def initialize(i)
+ @to_int = i
+ @to_s = Ripper.lex_state_name(i)
+ freeze
+ end
+
+ def [](index)
+ case index
+ when 0, :to_int
+ @to_int
+ when 1, :to_s
+ @to_s
+ else
+ nil
+ end
+ end
+
+ alias to_i to_int
+ alias inspect to_s
+ def pretty_print(q) q.text(to_s) end
+ def ==(i) super or to_int == i end
+ def &(i) self.class.new(to_int & i) end
+ def |(i) self.class.new(to_int | i) end
+ def allbits?(i) to_int.allbits?(i) end
+ def anybits?(i) to_int.anybits?(i) end
+ def nobits?(i) to_int.nobits?(i) end
+ end
+
+ class Elem
+ attr_accessor :pos, :event, :tok, :state, :message
+
+ def initialize(pos, event, tok, state, message = nil)
+ @pos = pos
+ @event = event
+ @tok = tok
+ @state = State.new(state)
+ @message = message
+ end
+
+ def [](index)
+ case index
+ when 0, :pos
+ @pos
+ when 1, :event
+ @event
+ when 2, :tok
+ @tok
+ when 3, :state
+ @state
+ when 4, :message
+ @message
+ else
+ nil
+ end
+ end
+
+ def inspect
+ "#<#{self.class}: #{event}@#{pos[0]}:#{pos[1]}:#{state}: #{tok.inspect}#{": " if message}#{message}>"
+ end
+
+ alias to_s inspect
+
+ def pretty_print(q)
+ q.group(2, "#<#{self.class}:", ">") {
+ q.breakable
+ q.text("#{event}@#{pos[0]}:#{pos[1]}")
+ q.breakable
+ state.pretty_print(q)
+ q.breakable
+ q.text("token: ")
+ tok.pretty_print(q)
+ if message
+ q.breakable
+ q.text("message: ")
+ q.text(message)
+ end
+ }
+ end
+
+ def to_a
+ if @message
+ [@pos, @event, @tok, @state, @message]
+ else
+ [@pos, @event, @tok, @state]
+ end
+ end
+ end
+
+ attr_reader :errors
+
+ def tokenize(**kw)
+ parse(**kw).sort_by(&:pos).map(&:tok)
+ end
+
+ def lex(**kw)
+ parse(**kw).sort_by(&:pos).map(&:to_a)
+ end
+
+ # parse the code and returns elements including errors.
+ def scan(**kw)
+ result = (parse(**kw) + errors + @stack.flatten).uniq.sort_by {|e| [*e.pos, (e.message ? -1 : 0)]}
+ result.each_with_index do |e, i|
+ if e.event == :on_parse_error and e.tok.empty? and (pre = result[i-1]) and
+ pre.pos[0] == e.pos[0] and (pre.pos[1] + pre.tok.size) == e.pos[1]
+ e.tok = pre.tok
+ e.pos[1] = pre.pos[1]
+ result[i-1] = e
+ result[i] = pre
+ end
+ end
+ result
+ end
+
+ def parse(raise_errors: false)
+ @errors = []
+ @buf = []
+ @stack = []
+ super()
+ @buf = @stack.pop unless @stack.empty?
+ if raise_errors and !@errors.empty?
+ raise SyntaxError, @errors.map(&:message).join(' ;')
+ end
+ @buf.flatten!
+ unless (result = @buf).empty?
+ result.concat(@buf) until (@buf = []; super(); @buf.flatten!; @buf.empty?)
+ end
+ result
+ end
+
+ private
+
+ unless SCANNER_EVENT_TABLE.key?(:ignored_sp)
+ SCANNER_EVENT_TABLE[:ignored_sp] = 1
+ SCANNER_EVENTS << :ignored_sp
+ EVENTS << :ignored_sp
+ end
+
+ def on_heredoc_dedent(v, w)
+ ignored_sp = []
+ heredoc = @buf.last
+ if Array === heredoc
+ heredoc.each_with_index do |e, i|
+ if Elem === e and e.event == :on_tstring_content and e.pos[1].zero?
+ tok = e.tok.dup if w > 0 and /\A\s/ =~ e.tok
+ if (n = dedent_string(e.tok, w)) > 0
+ if e.tok.empty?
+ e.tok = tok[0, n]
+ e.event = :on_ignored_sp
+ next
+ end
+ ignored_sp << [i, Elem.new(e.pos.dup, :on_ignored_sp, tok[0, n], e.state)]
+ e.pos[1] += n
+ end
+ end
+ end
+ end
+ ignored_sp.reverse_each do |i, e|
+ heredoc[i, 0] = [e]
+ end
+ v
+ end
+
+ def on_heredoc_beg(tok)
+ @stack.push @buf
+ buf = []
+ @buf.push buf
+ @buf = buf
+ @buf.push Elem.new([lineno(), column()], __callee__, tok, state())
+ end
+
+ def on_heredoc_end(tok)
+ @buf.push Elem.new([lineno(), column()], __callee__, tok, state())
+ @buf = @stack.pop unless @stack.empty?
+ end
+
+ def _push_token(tok)
+ e = Elem.new([lineno(), column()], __callee__, tok, state())
+ @buf.push(e)
+ e
+ end
+
+ def on_error1(mesg)
+ @errors.push Elem.new([lineno(), column()], __callee__, token(), state(), mesg)
+ end
+
+ def on_error2(mesg, elem)
+ if elem
+ elem = Elem.new(elem.pos, __callee__, elem.tok, elem.state, mesg)
+ else
+ elem = Elem.new([lineno(), column()], __callee__, token(), state(), mesg)
+ end
+ @errors.push elem
+ end
+ PARSER_EVENTS.grep(/_error\z/) do |e|
+ arity = PARSER_EVENT_TABLE.fetch(e)
+ alias_method "on_#{e}", "on_error#{arity}"
+ end
+ alias compile_error on_error1
+
+ (SCANNER_EVENTS.map {|event|:"on_#{event}"} - private_instance_methods(false)).each do |event|
+ alias_method event, :_push_token
+ end
+ # :startdoc:
+ end
+
+ # [EXPERIMENTAL]
+ # Parses +src+ and return a string which was matched to +pattern+.
+ # +pattern+ should be described as Regexp.
+ #
+ # require 'ripper'
+ #
+ # p Ripper.slice('def m(a) nil end', 'ident') #=> "m"
+ # p Ripper.slice('def m(a) nil end', '[ident lparen rparen]+') #=> "m(a)"
+ # p Ripper.slice("<<EOS\nstring\nEOS",
+ # 'heredoc_beg nl $(tstring_content*) heredoc_end', 1)
+ # #=> "string\n"
+ #
+ def Ripper.slice(src, pattern, n = 0)
+ if m = token_match(src, pattern)
+ then m.string(n)
+ else nil
+ end
+ end
+
+ def Ripper.token_match(src, pattern) #:nodoc:
+ TokenPattern.compile(pattern).match(src)
+ end
+
+ class TokenPattern #:nodoc:
+
+ class Error < ::StandardError # :nodoc:
+ end
+ class CompileError < Error # :nodoc:
+ end
+ class MatchError < Error # :nodoc:
+ end
+
+ class << self
+ alias compile new
+ end
+
+ def initialize(pattern)
+ @source = pattern
+ @re = compile(pattern)
+ end
+
+ def match(str)
+ match_list(::Ripper.lex(str))
+ end
+
+ def match_list(tokens)
+ if m = @re.match(map_tokens(tokens))
+ then MatchData.new(tokens, m)
+ else nil
+ end
+ end
+
+ private
+
+ def compile(pattern)
+ if m = /[^\w\s$()\[\]{}?*+\.]/.match(pattern)
+ raise CompileError, "invalid char in pattern: #{m[0].inspect}"
+ end
+ buf = +''
+ pattern.scan(/(?:\w+|\$\(|[()\[\]\{\}?*+\.]+)/) do |tok|
+ case tok
+ when /\w/
+ buf.concat map_token(tok)
+ when '$('
+ buf.concat '('
+ when '('
+ buf.concat '(?:'
+ when /[?*\[\])\.]/
+ buf.concat tok
+ else
+ raise 'must not happen'
+ end
+ end
+ Regexp.compile(buf)
+ rescue RegexpError => err
+ raise CompileError, err.message
+ end
+
+ def map_tokens(tokens)
+ tokens.map {|pos,type,str| map_token(type.to_s.delete_prefix('on_')) }.join
+ end
+
+ MAP = {}
+ seed = ('a'..'z').to_a + ('A'..'Z').to_a + ('0'..'9').to_a
+ SCANNER_EVENT_TABLE.each do |ev, |
+ raise CompileError, "[RIPPER FATAL] too many system token" if seed.empty?
+ MAP[ev.to_s.delete_prefix('on_')] = seed.shift
+ end
+
+ def map_token(tok)
+ MAP[tok] or raise CompileError, "unknown token: #{tok}"
+ end
+
+ class MatchData # :nodoc:
+ def initialize(tokens, match)
+ @tokens = tokens
+ @match = match
+ end
+
+ def string(n = 0)
+ return nil unless @match
+ match(n).join
+ end
+
+ private
+
+ def match(n = 0)
+ return [] unless @match
+ @tokens[@match.begin(n)...@match.end(n)].map {|pos,type,str| str }
+ end
+ end
+
+ end
+
+end
diff --git a/ext/ripper/lib/ripper/sexp.rb b/ext/ripper/lib/ripper/sexp.rb
new file mode 100644
index 0000000000..b1d553b1da
--- /dev/null
+++ b/ext/ripper/lib/ripper/sexp.rb
@@ -0,0 +1,187 @@
+# frozen_string_literal: true
+#
+# $Id$
+#
+# Copyright (c) 2004,2005 Minero Aoki
+#
+# This program is free software.
+# You can distribute and/or modify this program under the Ruby License.
+# For details of Ruby License, see ruby/COPYING.
+#
+
+require 'ripper/core'
+
+class Ripper
+
+ # [EXPERIMENTAL]
+ # Parses +src+ and create S-exp tree.
+ # Returns more readable tree rather than Ripper.sexp_raw.
+ # This method is mainly for developer use.
+ # The +filename+ argument is mostly ignored.
+ # By default, this method does not handle syntax errors in +src+,
+ # returning +nil+ in such cases. Use the +raise_errors+ keyword
+ # to raise a SyntaxError for an error in +src+.
+ #
+ # require 'ripper'
+ # require 'pp'
+ #
+ # pp Ripper.sexp("def m(a) nil end")
+ # #=> [:program,
+ # [[:def,
+ # [:@ident, "m", [1, 4]],
+ # [:paren, [:params, [[:@ident, "a", [1, 6]]], nil, nil, nil, nil, nil, nil]],
+ # [:bodystmt, [[:var_ref, [:@kw, "nil", [1, 9]]]], nil, nil, nil]]]]
+ #
+ def Ripper.sexp(src, filename = '-', lineno = 1, raise_errors: false)
+ builder = SexpBuilderPP.new(src, filename, lineno)
+ sexp = builder.parse
+ if builder.error?
+ if raise_errors
+ raise SyntaxError, builder.error
+ end
+ else
+ sexp
+ end
+ end
+
+ # [EXPERIMENTAL]
+ # Parses +src+ and create S-exp tree.
+ # This method is mainly for developer use.
+ # The +filename+ argument is mostly ignored.
+ # By default, this method does not handle syntax errors in +src+,
+ # returning +nil+ in such cases. Use the +raise_errors+ keyword
+ # to raise a SyntaxError for an error in +src+.
+ #
+ # require 'ripper'
+ # require 'pp'
+ #
+ # pp Ripper.sexp_raw("def m(a) nil end")
+ # #=> [:program,
+ # [:stmts_add,
+ # [:stmts_new],
+ # [:def,
+ # [:@ident, "m", [1, 4]],
+ # [:paren, [:params, [[:@ident, "a", [1, 6]]], nil, nil, nil]],
+ # [:bodystmt,
+ # [:stmts_add, [:stmts_new], [:var_ref, [:@kw, "nil", [1, 9]]]],
+ # nil,
+ # nil,
+ # nil]]]]
+ #
+ def Ripper.sexp_raw(src, filename = '-', lineno = 1, raise_errors: false)
+ builder = SexpBuilder.new(src, filename, lineno)
+ sexp = builder.parse
+ if builder.error?
+ if raise_errors
+ raise SyntaxError, builder.error
+ end
+ else
+ sexp
+ end
+ end
+
+ class SexpBuilder < ::Ripper #:nodoc:
+ attr_reader :error
+
+ private
+
+ def dedent_element(e, width)
+ if (n = dedent_string(e[1], width)) > 0
+ e[2][1] += n
+ end
+ e
+ end
+
+ def on_heredoc_dedent(val, width)
+ sub = proc do |cont|
+ cont.map! do |e|
+ if Array === e
+ case e[0]
+ when :@tstring_content
+ e = dedent_element(e, width)
+ when /_add\z/
+ e[1] = sub[e[1]]
+ end
+ elsif String === e
+ dedent_string(e, width)
+ end
+ e
+ end
+ end
+ sub[val]
+ val
+ end
+
+ events = private_instance_methods(false).grep(/\Aon_/) {$'.to_sym}
+ (PARSER_EVENTS - events).each do |event|
+ module_eval(<<-End, __FILE__, __LINE__ + 1)
+ def on_#{event}(*args)
+ args.unshift :#{event}
+ args
+ end
+ End
+ end
+
+ SCANNER_EVENTS.each do |event|
+ module_eval(<<-End, __FILE__, __LINE__ + 1)
+ def on_#{event}(tok)
+ [:@#{event}, tok, [lineno(), column()]]
+ end
+ End
+ end
+
+ def on_error(mesg)
+ @error = mesg
+ end
+ remove_method :on_parse_error
+ alias on_parse_error on_error
+ alias compile_error on_error
+ end
+
+ class SexpBuilderPP < SexpBuilder #:nodoc:
+ private
+
+ def on_heredoc_dedent(val, width)
+ val.map! do |e|
+ next e if Symbol === e and /_content\z/ =~ e
+ if Array === e and e[0] == :@tstring_content
+ e = dedent_element(e, width)
+ elsif String === e
+ dedent_string(e, width)
+ end
+ e
+ end
+ val
+ end
+
+ def _dispatch_event_new
+ []
+ end
+
+ def _dispatch_event_push(list, item)
+ list.push item
+ list
+ end
+
+ def on_mlhs_paren(list)
+ [:mlhs, *list]
+ end
+
+ def on_mlhs_add_star(list, star)
+ list.push([:rest_param, star])
+ end
+
+ def on_mlhs_add_post(list, post)
+ list.concat(post)
+ end
+
+ PARSER_EVENT_TABLE.each do |event, arity|
+ if /_new\z/ =~ event and arity == 0
+ alias_method "on_#{event}", :_dispatch_event_new
+ elsif /_add\z/ =~ event
+ alias_method "on_#{event}", :_dispatch_event_push
+ end
+ end
+ end
+
+end
diff --git a/ext/ripper/lib/ripper/tokenizer.rb b/ext/ripper/lib/ripper/tokenizer.rb
deleted file mode 100644
index 4209903ba7..0000000000
--- a/ext/ripper/lib/ripper/tokenizer.rb
+++ /dev/null
@@ -1,64 +0,0 @@
-#
-# ripper/tokenizer.rb
-#
-# Copyright (C) 2004 Minero Aoki
-#
-# This program is free software.
-# You can distribute and/or modify this program under the Ruby License.
-# For details of Ruby License, see ruby/COPYING.
-#
-
-require 'ripper/core'
-
-class Ripper
-
- # Tokenizes Ruby program and returns an Array of String.
- def Ripper.tokenize(src, filename = '-', lineno = 1)
- Tokenizer.new(src, filename, lineno).tokenize
- end
-
- # Tokenizes Ruby program and returns an Array of Array,
- # which is formatted like [[lineno, column], type, token].
- #
- # require 'ripper'
- # require 'pp'
- #
- # p Ripper.scan("def m(a) nil end")
- # #=> [[[1, 0], :on_kw, "def"],
- # [[1, 3], :on_sp, " " ],
- # [[1, 4], :on_ident, "m" ],
- # [[1, 5], :on_lparen, "(" ],
- # [[1, 6], :on_ident, "a" ],
- # [[1, 7], :on_rparen, ")" ],
- # [[1, 8], :on_sp, " " ],
- # [[1, 9], :on_kw, "nil"],
- # [[1, 12], :on_sp, " " ],
- # [[1, 13], :on_kw, "end"]]
- #
- def Ripper.scan(src, filename = '-', lineno = 1)
- Tokenizer.new(src, filename, lineno).parse
- end
-
- class Tokenizer < ::Ripper #:nodoc: internal use only
- def tokenize
- parse().map {|pos, event, tok| tok }
- end
-
- def parse
- @buf = []
- super
- @buf.sort_by {|pos, event, tok| pos }
- end
-
- private
-
- SCANNER_EVENTS.each do |event|
- module_eval(<<-End)
- def on_#{event}(tok)
- @buf.push [[lineno(), column()], :on_#{event}, tok]
- end
- End
- end
- end
-
-end
diff --git a/ext/ripper/ripper_init.c.tmpl b/ext/ripper/ripper_init.c.tmpl
new file mode 100644
index 0000000000..11e432423d
--- /dev/null
+++ b/ext/ripper/ripper_init.c.tmpl
@@ -0,0 +1,680 @@
+%# -*- c -*-
+#include "ruby/ruby.h"
+#include "ruby/encoding.h"
+#include "internal.h"
+#include "rubyparser.h"
+#define YYSTYPE_IS_DECLARED
+#include "parse.h"
+#include "internal/parse.h"
+#include "internal/ruby_parser.h"
+#include "node.h"
+#include "eventids1.h"
+#include "eventids2.h"
+#include "ripper_init.h"
+
+#define STR_NEW2(ptr) rb_enc_str_new((ptr),strlen(ptr),rb_ruby_parser_enc(p))
+#define RIPPER_VERSION "0.1.0"
+
+ID id_warn, id_warning, id_gets, id_assoc;
+
+enum lex_type {
+ lex_type_str,
+ lex_type_io,
+ lex_type_generic,
+};
+
+struct ripper {
+ rb_parser_t *p;
+ enum lex_type type;
+ union {
+ struct lex_pointer_string ptr_str;
+ VALUE val;
+ } data;
+};
+
+static void
+ripper_parser_mark2(void *ptr)
+{
+ struct ripper *r = (struct ripper*)ptr;
+ if (r->p) {
+ ripper_parser_mark(r->p);
+
+ switch (r->type) {
+ case lex_type_str:
+ rb_gc_mark(r->data.ptr_str.str);
+ break;
+ case lex_type_io:
+ rb_gc_mark(r->data.val);
+ break;
+ case lex_type_generic:
+ rb_gc_mark(r->data.val);
+ break;
+ }
+ }
+}
+
+static void
+ripper_parser_free2(void *ptr)
+{
+ struct ripper *r = (struct ripper*)ptr;
+ if (r->p) ripper_parser_free(r->p);
+ xfree(r);
+}
+
+static size_t
+ripper_parser_memsize2(const void *ptr)
+{
+ struct ripper *r = (struct ripper*)ptr;
+ return (r->p) ? ripper_parser_memsize(r->p) : 0;
+}
+
+static const rb_data_type_t parser_data_type = {
+ "ripper",
+ {
+ ripper_parser_mark2,
+ ripper_parser_free2,
+ ripper_parser_memsize2,
+ },
+ 0, 0, RUBY_TYPED_FREE_IMMEDIATELY
+};
+
+static rb_parser_string_t *
+ripper_lex_get_generic(struct parser_params *p, rb_parser_input_data input, int line_count)
+{
+ VALUE src = (VALUE)input;
+ VALUE line = rb_funcallv_public(src, id_gets, 0, 0);
+ if (NIL_P(line)) return 0;
+ if (!RB_TYPE_P(line, T_STRING)) {
+ rb_raise(rb_eTypeError,
+ "gets returned %"PRIsVALUE" (expected String or nil)",
+ rb_obj_class(line));
+ }
+ return rb_str_to_parser_string(p, line);
+}
+
+void
+ripper_compile_error(struct parser_params *p, const char *fmt, ...)
+{
+ VALUE str;
+ va_list args;
+
+ va_start(args, fmt);
+ str = rb_vsprintf(fmt, args);
+ va_end(args);
+ rb_funcall(ripper_value(p), rb_intern("compile_error"), 1, str);
+ ripper_error(p);
+}
+
+static rb_parser_string_t *
+ripper_lex_io_get(struct parser_params *p, rb_parser_input_data input, int line_count)
+{
+ VALUE src = (VALUE)input;
+ VALUE line = rb_io_gets(src);
+ if (NIL_P(line)) return 0;
+ return rb_str_to_parser_string(p, line);
+}
+
+static rb_parser_string_t *
+ripper_lex_get_str(struct parser_params *p, rb_parser_input_data input, int line_count)
+{
+ return rb_parser_lex_get_str(p, (struct lex_pointer_string *)input);
+}
+
+static VALUE
+ripper_s_allocate(VALUE klass)
+{
+ struct ripper *r;
+
+ VALUE self = TypedData_Make_Struct(klass, struct ripper,
+ &parser_data_type, r);
+
+#ifdef UNIVERSAL_PARSER
+ const rb_parser_config_t *config = rb_ruby_parser_config();
+ r->p = rb_ripper_parser_params_allocate(config);
+#else
+ r->p = rb_ruby_ripper_parser_allocate();
+#endif
+ rb_ruby_parser_set_value(r->p, self);
+ return self;
+}
+
+static struct parser_params *
+ripper_parser_params(VALUE self, bool initialized)
+{
+ struct ripper *r;
+ struct parser_params *p;
+
+ TypedData_Get_Struct(self, struct ripper, &parser_data_type, r);
+ p = r->p;
+ if (initialized && !rb_ruby_ripper_initialized_p(p)) {
+ rb_raise(rb_eArgError, "method called for uninitialized object");
+ }
+ return p;
+}
+
+/*
+ * call-seq:
+ * ripper.error? -> Boolean
+ *
+ * Return true if parsed source has errors.
+ */
+static VALUE
+ripper_error_p(VALUE vparser)
+{
+ struct parser_params *p = ripper_parser_params(vparser, false);
+
+ return RBOOL(rb_ruby_parser_error_p(p));
+}
+
+/*
+ * call-seq:
+ * ripper.end_seen? -> Boolean
+ *
+ * Return true if parsed source ended by +\_\_END\_\_+.
+ */
+static VALUE
+ripper_parser_end_seen_p(VALUE vparser)
+{
+ struct parser_params *p = ripper_parser_params(vparser, false);
+
+ return RBOOL(rb_ruby_parser_end_seen_p(p));
+}
+
+/*
+ * call-seq:
+ * ripper.encoding -> encoding
+ *
+ * Return encoding of the source.
+ */
+static VALUE
+ripper_parser_encoding(VALUE vparser)
+{
+ struct parser_params *p = ripper_parser_params(vparser, false);
+
+ return rb_enc_from_encoding(rb_ruby_parser_encoding(p));
+}
+
+/*
+ * call-seq:
+ * ripper.yydebug -> true or false
+ *
+ * Get yydebug.
+ */
+static VALUE
+ripper_parser_get_yydebug(VALUE self)
+{
+ struct parser_params *p = ripper_parser_params(self, false);
+
+ return RBOOL(rb_ruby_parser_get_yydebug(p));
+}
+
+/*
+ * call-seq:
+ * ripper.yydebug = flag
+ *
+ * Set yydebug.
+ */
+static VALUE
+ripper_parser_set_yydebug(VALUE self, VALUE flag)
+{
+ struct parser_params *p = ripper_parser_params(self, false);
+
+ rb_ruby_parser_set_yydebug(p, RTEST(flag));
+ return flag;
+}
+
+/*
+ * call-seq:
+ * ripper.debug_output -> obj
+ *
+ * Get debug output.
+ */
+static VALUE
+ripper_parser_get_debug_output(VALUE self)
+{
+ struct parser_params *p = ripper_parser_params(self, false);
+
+ return rb_ruby_parser_debug_output(p);
+}
+
+/*
+ * call-seq:
+ * ripper.debug_output = obj
+ *
+ * Set debug output.
+ */
+static VALUE
+ripper_parser_set_debug_output(VALUE self, VALUE output)
+{
+ struct parser_params *p = ripper_parser_params(self, false);
+
+ rb_ruby_parser_set_debug_output(p, output);
+ return output;
+}
+
+static int
+ripper_parser_dedent_string(struct parser_params *p, VALUE string, int width)
+{
+ int col;
+ rb_parser_string_t *str;
+ str = rb_str_to_parser_string(p, string);
+ col = rb_ruby_ripper_dedent_string(p, str, width);
+ rb_str_replace(string, rb_str_new_parser_string(str));
+ rb_parser_string_free(p, str);
+ return col;
+}
+
+#ifdef UNIVERSAL_PARSER
+struct dedent_string_arg {
+ struct parser_params *p;
+ VALUE input;
+ VALUE width;
+};
+
+static VALUE
+parser_dedent_string0(VALUE a)
+{
+ struct dedent_string_arg *arg = (void *)a;
+ int wid, col;
+
+ StringValue(arg->input);
+ wid = NUM2UINT(arg->width);
+ col = ripper_parser_dedent_string(arg->p, arg->input, wid);
+ return INT2NUM(col);
+}
+
+static VALUE
+parser_free(VALUE a)
+{
+ struct parser_params *p = (void *)a;
+
+ rb_ruby_parser_free(p);
+ return Qnil;
+}
+#endif
+
+/*
+ * call-seq:
+ * Ripper.dedent_string(input, width) -> Integer
+ *
+ * USE OF RIPPER LIBRARY ONLY.
+ *
+ * Strips up to +width+ leading whitespaces from +input+,
+ * and returns the stripped column width.
+ */
+#ifdef UNIVERSAL_PARSER
+static VALUE
+parser_dedent_string(VALUE self, VALUE input, VALUE width)
+{
+ struct parser_params *p;
+ struct dedent_string_arg args;
+
+ p = rb_parser_params_new();
+
+ args.p = p;
+ args.input = input;
+ args.width = width;
+ return rb_ensure(parser_dedent_string0, (VALUE)&args, parser_free, (VALUE)p);
+}
+#else
+static VALUE
+parser_dedent_string(VALUE self, VALUE input, VALUE width)
+{
+ int wid, col;
+
+ StringValue(input);
+ wid = NUM2UINT(width);
+ col = ripper_parser_dedent_string(0, input, wid);
+ return INT2NUM(col);
+}
+#endif
+
+/*
+ * call-seq:
+ * Ripper.new(src, filename="(ripper)", lineno=1) -> ripper
+ *
+ * Create a new Ripper object.
+ * _src_ must be a String, an IO, or an Object which has #gets method.
+ *
+ * This method does not starts parsing.
+ * See also Ripper#parse and Ripper.parse.
+ */
+static VALUE
+ripper_initialize(int argc, VALUE *argv, VALUE self)
+{
+ struct ripper *r;
+ struct parser_params *p;
+ VALUE src, fname, lineno;
+ rb_parser_lex_gets_func *gets;
+ VALUE sourcefile_string;
+ const char *sourcefile;
+ int sourceline;
+ rb_parser_input_data input;
+
+ p = ripper_parser_params(self, false);
+ TypedData_Get_Struct(self, struct ripper, &parser_data_type, r);
+ rb_scan_args(argc, argv, "12", &src, &fname, &lineno);
+ if (RB_TYPE_P(src, T_FILE)) {
+ gets = ripper_lex_io_get;
+ r->type = lex_type_io;
+ r->data.val = src;
+ input = (rb_parser_input_data)src;
+ }
+ else if (rb_respond_to(src, id_gets)) {
+ gets = ripper_lex_get_generic;
+ r->type = lex_type_generic;
+ r->data.val = src;
+ input = (rb_parser_input_data)src;
+ }
+ else {
+ StringValue(src);
+ gets = ripper_lex_get_str;
+ r->type = lex_type_str;
+ r->data.ptr_str.str = src;
+ r->data.ptr_str.ptr = 0;
+ input = (rb_parser_input_data)&r->data.ptr_str;
+ }
+ if (NIL_P(fname)) {
+ fname = STR_NEW2("(ripper)");
+ OBJ_FREEZE(fname);
+ }
+ else {
+ StringValueCStr(fname);
+ fname = rb_str_new_frozen(fname);
+ }
+ rb_ruby_ripper_parser_initialize(p);
+
+ sourcefile_string = fname;
+ sourcefile = RSTRING_PTR(fname);
+ sourceline = NIL_P(lineno) ? 0 : NUM2INT(lineno) - 1;
+
+ rb_ruby_parser_ripper_initialize(p, gets, input, sourcefile_string, sourcefile, sourceline);
+
+ return Qnil;
+}
+
+static VALUE
+ripper_parse0(VALUE vparser)
+{
+ struct parser_params *p = ripper_parser_params(vparser, false);
+
+ rb_ruby_ripper_parse0(p);
+ return rb_ruby_parser_result(p);
+}
+
+static VALUE
+ripper_ensure(VALUE vparser)
+{
+ struct parser_params *p = ripper_parser_params(vparser, false);
+
+ rb_ruby_parser_set_parsing_thread(p, Qnil);
+ return Qnil;
+}
+
+/*
+ * call-seq:
+ * ripper.parse
+ *
+ * Start parsing and returns the value of the root action.
+ */
+static VALUE
+ripper_parse(VALUE self)
+{
+ struct parser_params *p = ripper_parser_params(self, true);
+ VALUE result;
+
+ if (!NIL_P(rb_ruby_parser_parsing_thread(p))) {
+ if (rb_ruby_parser_parsing_thread(p) == rb_thread_current())
+ rb_raise(rb_eArgError, "Ripper#parse is not reentrant");
+ else
+ rb_raise(rb_eArgError, "Ripper#parse is not multithread-safe");
+ }
+ rb_ruby_parser_set_parsing_thread(p, rb_thread_current());
+ result = rb_ensure(ripper_parse0, self, ripper_ensure, self);
+ RB_GC_GUARD(self);
+
+ return result;
+}
+
+/*
+ * call-seq:
+ * ripper.column -> Integer
+ *
+ * Return column number of current parsing line.
+ * This number starts from 0.
+ */
+static VALUE
+ripper_column(VALUE self)
+{
+ struct parser_params *p = ripper_parser_params(self, true);
+ long col;
+
+ if (NIL_P(rb_ruby_parser_parsing_thread(p))) return Qnil;
+ col = rb_ruby_ripper_column(p);
+ return LONG2NUM(col);
+}
+
+/*
+ * call-seq:
+ * ripper.filename -> String
+ *
+ * Return current parsing filename.
+ */
+static VALUE
+ripper_filename(VALUE self)
+{
+ struct parser_params *p = ripper_parser_params(self, true);
+
+ return rb_ruby_parser_ruby_sourcefile_string(p);
+}
+
+/*
+ * call-seq:
+ * ripper.lineno -> Integer
+ *
+ * Return line number of current parsing line.
+ * This number starts from 1.
+ */
+static VALUE
+ripper_lineno(VALUE self)
+{
+ struct parser_params *p = ripper_parser_params(self, true);
+
+ if (NIL_P(rb_ruby_parser_parsing_thread(p))) return Qnil;
+ return INT2NUM(rb_ruby_parser_ruby_sourceline(p));
+}
+
+/*
+ * call-seq:
+ * ripper.state -> Integer
+ *
+ * Return scanner state of current token.
+ */
+static VALUE
+ripper_state(VALUE self)
+{
+ struct parser_params *p = ripper_parser_params(self, true);
+
+ if (NIL_P(rb_ruby_parser_parsing_thread(p))) return Qnil;
+ return INT2NUM(rb_ruby_parser_lex_state(p));
+}
+
+/*
+ * call-seq:
+ * ripper.token -> String
+ *
+ * Return the current token string.
+ */
+static VALUE
+ripper_token(VALUE self)
+{
+ struct parser_params *p = ripper_parser_params(self, true);
+ long pos, len;
+ VALUE str;
+
+ if (NIL_P(rb_ruby_parser_parsing_thread(p))) return Qnil;
+ pos = rb_ruby_ripper_column(p);
+ len = rb_ruby_ripper_token_len(p);
+ str = rb_str_new_parser_string(rb_ruby_ripper_lex_lastline(p));
+ return rb_str_subseq(str, pos, len);
+}
+
+#ifdef RIPPER_DEBUG
+/* :nodoc: */
+static VALUE
+ripper_assert_Qundef(VALUE self, VALUE obj, VALUE msg)
+{
+ StringValue(msg);
+ if (UNDEF_P(obj)) {
+ rb_raise(rb_eArgError, "%"PRIsVALUE, msg);
+ }
+ return Qnil;
+}
+
+/* :nodoc: */
+static VALUE
+ripper_raw_value(VALUE self, VALUE obj)
+{
+ return ULONG2NUM(obj);
+}
+
+/* :nodoc: */
+static VALUE
+ripper_validate_object(VALUE self, VALUE x)
+{
+ if (x == Qfalse) return x;
+ if (x == Qtrue) return x;
+ if (NIL_P(x)) return x;
+ if (UNDEF_P(x))
+ rb_raise(rb_eArgError, "Qundef given");
+ if (FIXNUM_P(x)) return x;
+ if (SYMBOL_P(x)) return x;
+ switch (BUILTIN_TYPE(x)) {
+ case T_STRING:
+ case T_OBJECT:
+ case T_ARRAY:
+ case T_BIGNUM:
+ case T_FLOAT:
+ case T_COMPLEX:
+ case T_RATIONAL:
+ break;
+ default:
+ rb_raise(rb_eArgError, "wrong type of ruby object: %p (%s)",
+ (void *)x, rb_obj_classname(x));
+ }
+ if (!RBASIC_CLASS(x)) {
+ rb_raise(rb_eArgError, "hidden ruby object: %p (%s)",
+ (void *)x, rb_builtin_type_name(TYPE(x)));
+ }
+ return x;
+}
+#endif
+
+#ifdef UNIVERSAL_PARSER
+struct lex_state_name_arg {
+ struct parser_params *p;
+ VALUE state;
+};
+
+static VALUE
+lex_state_name0(VALUE a)
+{
+ struct lex_state_name_arg *arg = (void *)a;
+
+ return rb_ruby_ripper_lex_state_name(arg->p, NUM2INT(arg->state));
+}
+#endif
+
+/*
+ * call-seq:
+ * Ripper.lex_state_name(integer) -> string
+ *
+ * Returns a string representation of lex_state.
+ */
+#ifdef UNIVERSAL_PARSER
+static VALUE
+ripper_lex_state_name(VALUE self, VALUE state)
+{
+ struct parser_params *p;
+ struct lex_state_name_arg args;
+
+ p = rb_parser_params_new();
+
+ args.p = p;
+ args.state = state;
+
+ return rb_ensure(lex_state_name0, (VALUE)&args, parser_free, (VALUE)p);
+}
+#else
+static VALUE
+ripper_lex_state_name(VALUE self, VALUE state)
+{
+ return rb_ruby_ripper_lex_state_name(0, NUM2INT(state));
+}
+#endif
+
+void
+Init_ripper(void)
+{
+ ripper_init_eventids1();
+ ripper_init_eventids2();
+ id_warn = rb_intern_const("warn");
+ id_warning = rb_intern_const("warning");
+ id_gets = rb_intern_const("gets");
+ id_assoc = rb_intern_const("=>");
+
+ InitVM(ripper);
+}
+
+void
+InitVM_ripper(void)
+{
+ VALUE Ripper;
+
+ Ripper = rb_define_class("Ripper", rb_cObject);
+ /* version of Ripper */
+ rb_define_const(Ripper, "Version", rb_usascii_str_new2(RIPPER_VERSION));
+ rb_define_alloc_func(Ripper, ripper_s_allocate);
+ rb_define_method(Ripper, "initialize", ripper_initialize, -1);
+ rb_define_method(Ripper, "parse", ripper_parse, 0);
+ rb_define_method(Ripper, "column", ripper_column, 0);
+ rb_define_method(Ripper, "filename", ripper_filename, 0);
+ rb_define_method(Ripper, "lineno", ripper_lineno, 0);
+ rb_define_method(Ripper, "state", ripper_state, 0);
+ rb_define_method(Ripper, "token", ripper_token, 0);
+ rb_define_method(Ripper, "end_seen?", ripper_parser_end_seen_p, 0);
+ rb_define_method(Ripper, "encoding", ripper_parser_encoding, 0);
+ rb_define_method(Ripper, "yydebug", ripper_parser_get_yydebug, 0);
+ rb_define_method(Ripper, "yydebug=", ripper_parser_set_yydebug, 1);
+ rb_define_method(Ripper, "debug_output", ripper_parser_get_debug_output, 0);
+ rb_define_method(Ripper, "debug_output=", ripper_parser_set_debug_output, 1);
+ rb_define_method(Ripper, "error?", ripper_error_p, 0);
+#ifdef RIPPER_DEBUG
+ rb_define_method(Ripper, "assert_Qundef", ripper_assert_Qundef, 2);
+ rb_define_method(Ripper, "rawVALUE", ripper_raw_value, 1);
+ rb_define_method(Ripper, "validate_object", ripper_validate_object, 1);
+#endif
+
+ rb_define_singleton_method(Ripper, "dedent_string", parser_dedent_string, 2);
+ rb_define_private_method(Ripper, "dedent_string", parser_dedent_string, 2);
+
+ rb_define_singleton_method(Ripper, "lex_state_name", ripper_lex_state_name, 1);
+
+<% @exprs.each do |expr, desc| -%>
+ /* <%=desc%> */
+ rb_define_const(Ripper, "<%=expr%>", INT2NUM(<%=expr%>));
+<% end %>
+ ripper_init_eventids1_table(Ripper);
+ ripper_init_eventids2_table(Ripper);
+
+# if 0
+ /* Hack to let RDoc document SCRIPT_LINES__ */
+
+ /*
+ * When a Hash is assigned to +SCRIPT_LINES__+ the contents of files loaded
+ * after the assignment will be added as an Array of lines with the file
+ * name as the key.
+ */
+ rb_define_global_const("SCRIPT_LINES__", Qnil);
+#endif
+}
diff --git a/ext/ripper/ripper_init.h b/ext/ripper/ripper_init.h
new file mode 100644
index 0000000000..9d228107d1
--- /dev/null
+++ b/ext/ripper/ripper_init.h
@@ -0,0 +1,6 @@
+#ifndef RIPPER_INIT_H
+#define RIPPER_INIT_H
+
+PRINTF_ARGS(void ripper_compile_error(struct parser_params*, const char *fmt, ...), 2, 3);
+
+#endif /* RIPPER_INIT_H */
diff --git a/ext/ripper/test/check-event-arity.rb b/ext/ripper/test/check-event-arity.rb
deleted file mode 100644
index 00e1b98dbc..0000000000
--- a/ext/ripper/test/check-event-arity.rb
+++ /dev/null
@@ -1,24 +0,0 @@
-def main
- invalid = false
- table = {}
- ARGF.each do |line|
- next if /\A\#\s*define\s+s?dispatch\d/ === line
- next if /ripper_dispatch\d/ === line
- line.scan(/dispatch(\d)\((\w+)/) do |num, ev|
- num = num.to_i
- if data = table[ev]
- locations, arity = data
- unless num == arity
- invalid = true
- puts "arity differ [#{ev}]: #{ARGF.lineno}->#{num}; #{locations.join(',')}->#{arity}"
- end
- locations.push ARGF.lineno
- else
- table[ev] = [[ARGF.lineno], num.to_i]
- end
- end
- end
- exit 1 if invalid
-end
-
-main
diff --git a/ext/ripper/test/check-event-coverage.sh b/ext/ripper/test/check-event-coverage.sh
deleted file mode 100755
index 727c3b9837..0000000000
--- a/ext/ripper/test/check-event-coverage.sh
+++ /dev/null
@@ -1,15 +0,0 @@
-# $Id$
-
-RUBY=${RUBY:-ruby}
-status=0
-
-$RUBY tools/list-parse-event-ids.rb parse.y | awk '{print "on__" $1}' > list_a
-$RUBY test/list-called-events.rb | sort -u > list_b
-diff -u list_a list_b | grep '^-on' | sed 's/^-on__//' > list_diff
-if [ -s list_diff ]
-then
- cat list_diff
- status=1
-fi
-rm -f list_a list_b list_diff
-exit $status
diff --git a/ext/ripper/test/check-scanner-event-coverage.rb b/ext/ripper/test/check-scanner-event-coverage.rb
deleted file mode 100644
index 4de01e35f4..0000000000
--- a/ext/ripper/test/check-scanner-event-coverage.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-def main
- not_tested = eventids() - tested_ids()
- unless not_tested.empty?
- puts not_tested
- exit 1
- end
- exit 0
-end
-
-def eventids
- File.read('eventids2.c').scan(/on__(\w+)/).flatten.uniq
-end
-
-def tested_ids
- File.read('test/test_scanner_events.rb').scan(/def test_(\S+)/).flatten.uniq
-end
-
-main
diff --git a/ext/ripper/test/list-called-events.rb b/ext/ripper/test/list-called-events.rb
deleted file mode 100644
index d799efc979..0000000000
--- a/ext/ripper/test/list-called-events.rb
+++ /dev/null
@@ -1,12 +0,0 @@
-require 'ripper.so'
-
-class R < Ripper
- def method_missing(mid, *args)
- puts mid
- args[0]
- end
- undef :warn
-end
-
-fname = (ARGV[0] || 'test/src_rb')
-R.new(File.read(fname), fname, 1).parse
diff --git a/ext/ripper/test/src_rb b/ext/ripper/test/src_rb
deleted file mode 100644
index e7894362f3..0000000000
--- a/ext/ripper/test/src_rb
+++ /dev/null
@@ -1,363 +0,0 @@
-# comment
-=begin
- embedded document
-=end
-
-# literal
-1
-1000000000000000000000
-1.0
-1.234e5
-1..2
-1...3
-:symbol
-:"dynamic #{sym_embexpr} symbol"
-[1,2,3]
-{1 => 2}
-'string'
-"string"
-"before #{str_embexpr} after"
-"str #@ivar str"
-"str #$gvar str"
-"string" "concat"
-`/bin/true`
-{1, 2, 3, 4}
-/regexp/
-/regexp_with_opt/mioe
-/regexp #{regexp_embexpr} after/
-%q[string]
-%Q[str#{str_embexpr}ing]
-%r[regexp]
-%w( a b c )
-%W( a#{w_emb}b c d )
-<<HERE
-heredoc line 1
-heredoc line 2
-heredoc line 3
-HERE
-
-# special variables
-true
-false
-nil
-self
-
-# def
-def a
-end
-def b()
-end
-def c(a)
-end
-def d(a,*rest)
-end
-def e(a,&block)
-end
-def f(a,*rest,&block)
-end
-def g(*rest)
-end
-def h(&block)
-end
-def i(*rest,&block)
-end
-def j(CONST)
-end
-def k(@ivar)
-end
-def l($gvar)
-end
-def n(@@cvar)
-end
-
-# alias
-alias x b
-alias $rest $' # error
-alias $nth $1 # error
-
-# undef
-undef warn
-
-# class, module
-class C
-end
-module M
-end
-class cname
-end
-class << Object.new
- def self.a
- end
-end
-
-# field
-$a = 1
-$' = 0 # error
-$1 = 0 # error
-@a = 2
-@@a = 3
-a = 4
-a += 1
-a -= 1
-a *= 1
-a /= 1
-a &&= 1
-a ||= 1
-m.a = 5
-m.a += 1
-m.a &&= 1
-m.a ||= 1
-a[1] = 2
-a[1] += 1
-a[1] &&= 1
-a[1] ||= 1
-C = 1
-C::C = 1
-::C = 1
-def m
- C = 1 # dynamic const assignment
- C::C = 1 # dynamic const assignment
- ::C = 1 # dynamic const assignment
-end
-
-# ref
-lvar = $a
-lvar = @a
-lvar = @@a
-lvar = Object
-lvar = C
-lvar = C::C
-lvar = ::C
-lvar = a[1]
-
-# unary operator
-+1
--1
-not 1
-!1
-~str
-
-# binary operator
-1 + 1
-1 - 1
-1 * 1
-1 / 1
-1 ** 1
-1 ^ 1
-1 & 1
-1 | 1
-1 && 1
-1 || 1
-
-# mlhs, mrhs
-a, b, c = list
-a, = list
-a, * = list
-a, *b = list
-a, (b, c), d, *e = list
-mlhs = 1, 2
-mlhs = 1, 2, 3, *list
-mlhs = *list
-
-# method call
-m
-m()
-m(a)
-m(a,a)
-m(*a)
-m(&b)
-m(a,*a)
-m(a,&b)
-m(a,*a,&b)
-m(1=>2)
-m(1=>2,*a)
-m(1=>2,&b)
-m(1=>2,*a,&b)
-m ()
-m (a)
-m (a,a)
-m (*a)
-m (&b)
-m (a,*a)
-m (a,&b)
-m (a,*a,&b)
-m (1=>2)
-m (1=>2,*a)
-m (1=>2,&b)
-m (1=>2,*a,&b)
-m a
-m a,a
-m *a
-m &b
-m a,*a
-m a,&b
-m a,*a,&b
-m 1=>2
-m 1=>2,*a
-m 1=>2,&b
-m 1=>2,*a,&b
-obj.m
-obj.m()
-obj.m(a)
-obj.m(a,a)
-obj.m(*a)
-obj.m(&b)
-obj.m(a,*a)
-obj.m(a,&b)
-obj.m(a,*a,&b)
-obj.m(1=>2)
-obj.m(1=>2,*a)
-obj.m(1=>2,&b)
-obj.m(1=>2,*a,&b)
-obj.m ()
-obj.m (a)
-obj.m (a,a)
-obj.m (*a)
-obj.m (&b)
-obj.m (a,*a)
-obj.m (a,&b)
-obj.m (a,*a,&b)
-obj.m (1=>2)
-obj.m (1=>2)
-obj.m (1=>2,*a)
-obj.m (1=>2,&b)
-obj.m (1=>2,*a,&b)
-obj.m a
-obj.m a,a
-obj.m *a
-obj.m &b
-obj.m a,*a
-obj.m a,&b
-obj.m a,*a,&b
-obj.m 1=>2
-obj.m 1=>2,*a
-obj.m 1=>2,&b
-obj.m 1=>2,*a,&b
-
-# ambiguous argument
-m +1
-m /r/
-
-# iterator
-[1,2,3].each do |i|
- print i
-end
-{1=>true}.each do |k,v|
- puts k
-end
-[1,2,3].each {|i| print i }
-[1].each {|a,| }
-[1].each {|*b| }
-[1].each {|a,*b| }
-[1].each {|&block| }
-[1].each {|a,&block| }
-[1].each {|a,*b,&block| }
-a = lambda() {|n| n * n }
-a = lambda () {|n| n * n }
-a = lambda (a) {|n| n * n }
-a = lambda (a,b) {|n| n * n }
-
-# BEGIN, END
-BEGIN { }
-END { }
-
-# if, unless
-1 if true
-2 unless false
-if false
- 5
-elsif false
- 6
-elsif false then 7
-else
- 8
-end
-if m
-end
-unless 1
- 2
-end
-unless m
-end
-0 ? 1 : 2
-
-# case
-case 'a'
-when 'b'
- ;
-when 'c' then 1
-else
- 2
-end
-case
-when 1
-when 2
-when 3
-else
-end
-case 1
-else
-end
-case
-else
-end
-
-# while, until, for
-while true
- break
- next
- redo
-end
-begin
- break
-end while true
-until false
- break
- next
- redo
-end
-begin
- break
-end until false
-for x in m()
- break
- next
- redo
-end
-0 until true
-1 while false
-
-# begin, rescue, else, ensure
-begin
- 1
-rescue StandardError => er
- 2
-rescue => er
- 3
- retry
-else
- 4
-ensure
- 5
-end
-a = 1 rescue 2
-
-# jumps
-def m
- redo
- yield
- yield nil
- super
- super 1
- return
- return nil
-end
-
-# defined
-defined? f
-defined?(f)
-
-n = 1 \
-+ 1
-
-__END__
diff --git a/ext/ripper/test/validate.rb b/ext/ripper/test/validate.rb
deleted file mode 100644
index 808d321043..0000000000
--- a/ext/ripper/test/validate.rb
+++ /dev/null
@@ -1,68 +0,0 @@
-require 'ripper.so'
-
-class R < Ripper
- def initialize(*args)
- super
- @lineno = 0
- end
-
- def parse
- result = super
- puts "#{@lineno}:result: #{rawVALUE(result)}"
- validate_object result
- p result
- result
- end
-
- def on__nl(str)
- @lineno += 1
- end
-
- def on__ignored_nl(str)
- @lineno += 1
- end
-
- def on__comment(cmt)
- @lineno += 1
- end
-
- def on__embdoc_beg(str)
- @lineno += 1
- end
-
- def on__embdoc(str)
- @lineno += 1
- end
-
- def on__embdoc_end(str)
- @lineno += 1
- end
-
- def method_missing(mid, *args)
- puts mid
- args.each_with_index do |a,idx|
- puts "#{@lineno}:#{mid}\##{idx+1}: #{rawVALUE(a)}"
- validate_object a
- p a
- end
- args[0]
- end
-
- def warn(*args)
- end
-
- def warning(*args)
- end
-
- unless respond_to?(:validate_object)
- def validate_object(x)
- x
- end
- def rawVALUE(x)
- x.object_id
- end
- end
-end
-
-fname = (ARGV[0] || 'test/src_rb')
-R.new(File.read(fname), fname, 1).parse
diff --git a/ext/ripper/tools/dsl.rb b/ext/ripper/tools/dsl.rb
new file mode 100644
index 0000000000..38f859dd97
--- /dev/null
+++ b/ext/ripper/tools/dsl.rb
@@ -0,0 +1,181 @@
+# frozen_string_literal: true
+
+# Simple DSL implementation for Ripper code generation
+#
+# 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);
+#
+# - 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
+ 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, indent: nil)
+ if %r<(?<space>\s*)/\*% *ripper(?:\[(?<option>.*?)\])?: *(?<code>.*?) *%\*/> =~ line
+ new(code, comma_split(option), lineno, indent: indent || space)
+ end
+ end
+
+ def self.comma_split(str)
+ str or return []
+ str.scan(/(([^(,)]+|\((?:,|\g<0>)*\))+)/).map(&:first)
+ end
+
+ using Module.new {
+ refine Array do
+ def to_s
+ if empty?
+ "rb_ary_new()"
+ else
+ "rb_ary_new_from_args(#{size}, #{map(&:to_s).join(', ')})"
+ end
+ end
+ end
+ }
+
+ class Var
+ class Table < Hash
+ def initialize(&block)
+ super() {|tbl, arg|
+ tbl.fetch(arg, &block)
+ }
+ end
+
+ def fetch(arg, &block)
+ super {
+ self[arg] = Var.new(self, arg, &block)
+ }
+ end
+
+ def add(&block)
+ v = new_var
+ self[v] = Var.new(self, v, &block)
+ end
+
+ def defined?(name)
+ name = name.to_s
+ any? {|_, v| v.var == name}
+ end
+
+ def new_var
+ "v#{size+1}"
+ end
+ end
+
+ attr_reader :var, :value
+
+ PRETTY_PRINT_INSTANCE_VARIABLES = instance_methods(false).freeze
+
+ def pretty_print_instance_variables
+ PRETTY_PRINT_INSTANCE_VARIABLES
+ end
+
+ alias to_s var
+
+ def initialize(table, arg, &block)
+ @var = table.new_var
+ @value = yield arg
+ @table = table
+ end
+
+ # Indexing.
+ #
+ # $:1 -> v1=get_value($:1)
+ # $:1[0] -> rb_ary_entry(v1, 0)
+ # $:1[0..1] -> [rb_ary_entry(v1, 0), rb_ary_entry(v1, 1)]
+ # *$:1[0..1] -> rb_ary_entry(v1, 0), rb_ary_entry(v1, 1)
+ #
+ # Splat needs `[range]` because `Var` does not have the length info.
+ def [](idx)
+ if ::Range === idx
+ idx.map {|i| self[i]}
+ else
+ @table.fetch("#@var[#{idx}]") {"rb_ary_entry(#{@var}, #{idx})"}
+ end
+ end
+ end
+
+ def initialize(code, options, lineno = nil, indent: "\t\t\t")
+ @lineno = lineno
+ @indent = indent
+ @events = {}
+ @error = options.include?("error")
+ if options.include?("final")
+ @final = "p->result"
+ else
+ @final = (options.grep(/\A\$#{NAME_PATTERN}\z/o)[0] || "p->s_lvalue")
+ end
+
+ bind = dsl_binding
+ @var_table = Var::Table.new {|arg| "get_value(#{arg})"}
+ code = code.gsub(%r[\G#{NOT_REF_PATTERN}\K(\$|\$:|@)#{TAG_PATTERN}?#{NAME_PATTERN}]o) {
+ if (arg = $&) == "$:$"
+ '"p->s_lvalue"'
+ elsif arg.start_with?("$:")
+ "(#{@var_table[arg]}=@var_table[#{arg.dump}])"
+ else
+ arg.dump
+ end
+ }
+ @last_value = bind.eval(code)
+ rescue SyntaxError
+ $stderr.puts "error on line #{@lineno}" if @lineno
+ raise
+ end
+
+ def dsl_binding(p = "p")
+ # struct parser_params *p
+ binding
+ end
+
+ attr_reader :events
+
+ undef lambda
+ undef hash
+ undef :class
+
+ def generate
+ s = "#@final=#@last_value;"
+ s << "ripper_error(p);" if @error
+ unless @var_table.empty?
+ vars = @var_table.map {|_, v| "#{v.var}=#{v.value}"}.join(", ")
+ s = "VALUE #{ vars }; #{ s }"
+ end
+ "#{@indent}{#{s}}"
+ end
+
+ def add_event(event, args)
+ event = event.to_s.sub(/!\z/, "")
+ @events[event] = args.size
+ vars = []
+ args.each do |arg|
+ arg = @var_table.add {arg} unless Var === arg
+ vars << arg
+ end
+ @var_table.add {"dispatch#{ args.size }(#{ [event, *vars].join(",") })"}
+ end
+
+ def method_missing(event, *args)
+ if event.to_s =~ /!\z/
+ add_event(event, args)
+ elsif args.empty? and (/\Aid[A-Z_]/ =~ event or @var_table.defined?(event))
+ event
+ else
+ "#{ event }(#{ args.map(&:to_s).join(", ") })"
+ end
+ end
+
+ def self.const_missing(name)
+ name
+ end
+end
diff --git a/ext/ripper/tools/generate-eventids1.rb b/ext/ripper/tools/generate-eventids1.rb
deleted file mode 100755
index ec7ec4949a..0000000000
--- a/ext/ripper/tools/generate-eventids1.rb
+++ /dev/null
@@ -1,16 +0,0 @@
-# $Id$
-
-ids = File.readlines(ARGV[0]).map {|s| s.split[0] }
-
-ids.each do |id|
- puts "static ID ripper_id_#{id};"
-end
-
-puts
-puts 'static void'
-puts 'ripper_init_eventids1()'
-puts '{'
-ids.each do |id|
- puts %Q[ ripper_id_#{id} = rb_intern("on_#{id}");]
-end
-puts '}'
diff --git a/ext/ripper/tools/generate-param-macros.rb b/ext/ripper/tools/generate-param-macros.rb
index b19f6e8d5c..f0de55a5f2 100755..100644
--- a/ext/ripper/tools/generate-param-macros.rb
+++ b/ext/ripper/tools/generate-param-macros.rb
@@ -1,3 +1,4 @@
+# frozen_string_literal: true
off = true
ARGF.each do |line|
case line
diff --git a/ext/ripper/tools/generate-ripper_rb.rb b/ext/ripper/tools/generate-ripper_rb.rb
deleted file mode 100755
index 5c06ca40a4..0000000000
--- a/ext/ripper/tools/generate-ripper_rb.rb
+++ /dev/null
@@ -1,60 +0,0 @@
-# $Id$
-
-def main
- template, ids1, ids2 = *ARGV
- print <<header
-# This file is automatically generated from #{File.basename(template)} and parse.y.
-# DO NOT MODIFY!!!!!!
-
-header
- File.foreach(template) do |line|
- case line
- when /\A\#include ids1/
- print_items read_ids(ids1)
- when /\A\#include ids2/
- print_items read_ids(ids2)
- when /\A\#include handlers1/
- File.foreach(ids1) do |line|
- id, arity = line.split
- arity = arity.to_i
- puts
- puts " def on_#{id}#{paramdecl(arity)}"
- puts " #{arity == 0 ? 'nil' : 'a'}"
- puts " end"
- end
- when /\A\#include handlers2/
- File.foreach(ids2) do |line|
- id, arity = line.split
- arity = arity.to_i
- puts
- puts " def on_#{id}(token)"
- puts " token"
- puts " end"
- end
- when /\A\#include (.*)/
- raise "unknown operation: #include #{$1}"
- else
- print line
- end
- end
-end
-
-def print_items(ids)
- comma = ''
- ids.each do |id, arity|
- print comma; comma = ",\n"
- print " #{id.intern.inspect} => #{arity}"
- end
- puts
-end
-
-def read_ids(path)
- File.readlines(path).map {|line| line.split }
-end
-
-def paramdecl(n)
- return '' if n == 0
- '(' + %w(a b c d e f g h i j k l m)[0, n].join(', ') + ')'
-end
-
-main
diff --git a/ext/ripper/tools/generate.rb b/ext/ripper/tools/generate.rb
new file mode 100644
index 0000000000..57ecac0b39
--- /dev/null
+++ b/ext/ripper/tools/generate.rb
@@ -0,0 +1,194 @@
+# frozen_string_literal: true
+# $Id$
+
+require 'optparse'
+
+def main
+ mode = nil
+ ids1src = nil
+ ids2src = nil
+ output = nil
+
+ parser = @parser = OptionParser.new
+ parser.banner = "Usage: #{File.basename($0)} --mode=MODE [--ids1src=PATH] [--ids2src=PATH] [--output=PATH]"
+ parser.on('--mode=MODE', 'check, eventids1_h, eventids1, or eventids2table.') {|m|
+ mode = m
+ }
+ parser.on('--ids1src=PATH', 'A source file of event-IDs 1 (parse.y).') {|path|
+ ids1src = path
+ }
+ parser.on('--ids2src=PATH', 'A source file of event-IDs 2 (eventids2.c).') {|path|
+ ids2src = path
+ }
+ parser.on('--output=PATH', 'An output file.') {|path|
+ output = path
+ }
+ parser.on('--help', 'Prints this message and quit.') {
+ puts parser.help
+ exit true
+ }
+ begin
+ parser.parse!
+ rescue OptionParser::ParseError => err
+ usage err.message
+ end
+ usage 'no mode given' unless mode
+ case mode
+ when 'check'
+ usage 'no --ids1src' unless ids1src
+ usage 'no --ids2src' unless ids2src
+ h = read_ids1_with_locations(ids1src)
+ check_arity h
+ ids2 = read_ids2(ids2src)
+ common = h.keys & ids2
+ unless common.empty?
+ abort "event crash: #{common.join(' ')}"
+ end
+ exit 0
+ when 'eventids1_h'
+ usage 'no --ids1src' unless ids1src
+ result = generate_eventids1_h(read_ids1(ids1src))
+ when 'eventids1'
+ usage 'no --ids1src' unless ids1src
+ result = generate_eventids1(read_ids1(ids1src))
+ when 'eventids2table'
+ usage 'no --ids2src' unless ids2src
+ result = generate_eventids2_table(read_ids2(ids2src))
+ end
+ if output
+ File.open(output, 'w') {|f|
+ f.write result
+ }
+ else
+ puts result
+ end
+end
+
+def usage(msg)
+ $stderr.puts msg
+ $stderr.puts @parser.help
+ exit false
+end
+
+def generate_eventids1_h(ids)
+ buf = "".dup
+ buf << %Q[#ifndef RIPPER_EVENTIDS1\n]
+ buf << %Q[#define RIPPER_EVENTIDS1\n]
+ buf << %Q[\n]
+ buf << %Q[#define RIPPER_ID(n) ripper_parser_ids.id_ ## n\n]
+ buf << %Q[void ripper_init_eventids1(void);\n]
+ buf << %Q[void ripper_init_eventids1_table(VALUE self);\n]
+ buf << %Q[\n]
+ buf << %Q[struct ripper_parser_ids {\n]
+ ids.each do |id, arity|
+ buf << %Q[ ID id_#{id};\n]
+ end
+ buf << %Q[};\n]
+ buf << %Q[\n]
+ buf << %Q[#endif /* RIPPER_EVENTIDS1 */\n]
+ buf << %Q[\n]
+end
+
+def generate_eventids1(ids)
+ buf = "".dup
+ buf << %Q[#include "ruby/ruby.h"\n]
+ buf << %Q[#include "eventids1.h"\n]
+ buf << %Q[\n]
+ buf << %Q[struct ripper_parser_ids ripper_parser_ids;\n]
+ buf << %Q[\n]
+ buf << %Q[void\n]
+ buf << %Q[ripper_init_eventids1(void)\n]
+ buf << %Q[{\n]
+ buf << %Q[#define set_id1(name) RIPPER_ID(name) = rb_intern_const("on_"#name)\n]
+ ids.each do |id, arity|
+ buf << %Q[ set_id1(#{id});\n]
+ end
+ buf << %Q[}\n]
+ buf << %Q[\n]
+ buf << %Q[#define intern_sym(name) ID2SYM(rb_intern_const(name))\n]
+ buf << %Q[\n]
+ buf << %Q[void\n]
+ buf << %Q[ripper_init_eventids1_table(VALUE self)\n]
+ buf << %Q[{\n]
+ buf << %Q[ VALUE h = rb_hash_new();\n]
+ buf << %Q[ rb_define_const(self, "PARSER_EVENT_TABLE", h);\n]
+ ids.each do |id, arity|
+ buf << %Q[ rb_hash_aset(h, intern_sym("#{id}"), INT2FIX(#{arity}));\n]
+ end
+ buf << %Q[}\n]
+ buf
+end
+
+def generate_eventids2_table(ids)
+ buf = "".dup
+ buf << %Q[#include "ruby/ruby.h"\n]
+ buf << %Q[\n]
+ buf << %Q[#define intern_sym(name) ID2SYM(rb_intern_const(name))\n]
+ buf << %Q[\n]
+ buf << %Q[void\n]
+ buf << %Q[ripper_init_eventids2_table(VALUE self)\n]
+ buf << %Q[{\n]
+ buf << %Q[ VALUE h = rb_hash_new();\n]
+ buf << %Q[ rb_define_const(self, "SCANNER_EVENT_TABLE", h);\n]
+ ids.each do |id|
+ buf << %Q[ rb_hash_aset(h, intern_sym("#{id}"), INT2FIX(1));\n]
+ end
+ buf << %Q[}\n]
+ buf << %Q[\n]
+ buf << %Q[#define RIPPER_EVENTIDS2_TABLE_SIZE #{ids.size}\n]
+ buf
+end
+
+def read_ids1(path)
+ strip_locations(read_ids1_with_locations(path))
+end
+
+def strip_locations(h)
+ h.map {|event, list| [event, list.first[1]] }\
+ .sort_by {|event, arity| event.to_s }
+end
+
+def check_arity(h)
+ invalid = false
+ h.each do |event, list|
+ unless list.map {|line, arity| arity }.uniq.size == 1
+ invalid = true
+ locations = list.map {|line, a| "#{line}:#{a}" }.join(', ')
+ $stderr.puts "arity crash [event=#{event}]: #{locations}"
+ end
+ end
+ abort if invalid
+end
+
+require_relative "dsl"
+
+def read_ids1_with_locations(path)
+ h = {}
+ File.open(path) {|f|
+ f.each do |line|
+ next if /\A\#\s*define\s+dispatch/ =~ line
+ next if /ripper_dispatch/ =~ line
+ line.scan(/\bdispatch(\d)\((\w+)/) do |arity, event|
+ (h[event] ||= []).push [f.lineno, arity.to_i]
+ end
+ if gen = DSL.line?(line, f.lineno)
+ gen.events.each do |event, arity|
+ (h[event] ||= []).push [f.lineno, arity.to_i]
+ end
+ end
+ end
+ }
+ h
+end
+
+def read_ids2(path)
+ src = File.open(path) {|f| f.read}
+ ids2 = src.scan(/ID\s+ripper_id_(\w+)/).flatten.uniq.sort
+ diff = src.scan(/set_id2\((\w+)\);/).flatten - ids2
+ unless diff.empty?
+ abort "missing scanner IDs: #{diff}"
+ end
+ return ids2
+end
+
+main
diff --git a/ext/ripper/tools/list-parse-event-ids.rb b/ext/ripper/tools/list-parse-event-ids.rb
deleted file mode 100755
index 84c7e4c445..0000000000
--- a/ext/ripper/tools/list-parse-event-ids.rb
+++ /dev/null
@@ -1,33 +0,0 @@
-# $Id$
-
-def main
- if ARGV[0] == '-a'
- with_arity = true
- ARGV.delete_at 0
- else
- with_arity = false
- end
- extract_ids(ARGF).each do |id, arity|
- if with_arity
- puts "#{id} #{arity}"
- else
- puts id
- end
- end
-end
-
-def extract_ids(f)
- results = []
- f.each do |line|
- next if /\A\#\s*define\s+s?dispatch/ === line
- next if /ripper_dispatch/ === line
- if a = line.scan(/dispatch(\d)\((\w+)/)
- a.each do |arity, event|
- results.push [event, arity.to_i]
- end
- end
- end
- results.uniq.sort
-end
-
-main
diff --git a/ext/ripper/tools/list-scan-event-ids.rb b/ext/ripper/tools/list-scan-event-ids.rb
deleted file mode 100755
index 670ae9ed09..0000000000
--- a/ext/ripper/tools/list-scan-event-ids.rb
+++ /dev/null
@@ -1,23 +0,0 @@
-# $Id$
-
-def main
- if ARGV.first == '-a'
- with_arity = true
- ARGV.delete_at 0
- else
- with_arity = false
- end
- extract_ids(ARGF).sort.each do |id|
- if with_arity
- puts "#{id} 1"
- else
- puts id
- end
- end
-end
-
-def extract_ids(f)
- f.read.scan(/ripper_id_(\w+)/).flatten.uniq
-end
-
-main
diff --git a/ext/ripper/tools/preproc.rb b/ext/ripper/tools/preproc.rb
index a2dba36e02..5e8a6e0cb5 100755..100644
--- a/ext/ripper/tools/preproc.rb
+++ b/ext/ripper/tools/preproc.rb
@@ -1,57 +1,124 @@
+# frozen_string_literal: true
+# $Id$
+
+require 'optparse'
+
def main
- prelude
- grammar
- usercode
+ output = nil
+ template = nil
+ parser = OptionParser.new
+ parser.banner = "Usage: #{File.basename($0)} [--output=PATH] [--template=PATH] <parse.y>"
+ parser.on('--output=PATH', 'An output file.') {|path|
+ output = path
+ }
+ parser.on('--template=PATH', 'An template file.') {|path|
+ template = path
+ }
+ parser.on('--help', 'Prints this message and quit.') {
+ puts parser.help
+ exit true
+ }
+ begin
+ parser.parse!
+ rescue OptionParser::ParseError => err
+ warn err.message
+ abort parser.help
+ end
+ out = "".dup
+ if ARGV[0] == "-"
+ unless ARGV.size == 2
+ abort "wrong number of arguments (#{ARGV.size} for 2)"
+ end
+ process STDIN, out, ARGV[1], template
+ else
+ unless ARGV.size == 1
+ abort "wrong number of arguments (#{ARGV.size} for 1)"
+ end
+ File.open(ARGV[0]) {|f|
+ process f, out, ARGV[0], template
+ }
+ end
+ if output
+ File.write(output, out)
+ else
+ print out
+ end
end
-def prelude
- while line = ARGF.gets
- case line
- when %r</\*%%%\*/>
- puts '/*'
- when %r</\*%>
- puts '*/'
- when %r<%\*/>
- puts
- when /\A%%/
- puts '%%'
- return
- when /\A%token/
- puts line.sub(/<\w+>/, '<val>')
- when /\A%type/
- puts line.sub(/<\w+>/, '<val>')
+def process(f, out, path, template)
+ prelude f, out
+ grammar f, out
+ usercode f, out, path, template
+end
+
+require_relative 'dsl'
+
+def generate_line(f, out)
+ while line = f.gets
+ case
+ when gen = DSL.line?(line, f.lineno)
+ out << gen.generate << "\n"
+ when line.start_with?("%%")
+ out << "%%\n"
+ break
else
- print line
+ out << yield(line)
+ end
+ end
+end
+
+def prelude(f, out)
+ @exprs = {}
+ generate_line(f, out) do |line|
+ if (/^enum lex_state_(?:bits|e) \{/ =~ line)..(/^\}/ =~ line)
+ case line
+ when /^\s*(EXPR_\w+),\s+\/\*(.+)\*\//
+ @exprs[$1.chomp("_bit")] = $2.strip
+ when /^\s*(EXPR_\w+)\s+=\s+(.+)$/
+ name = $1
+ val = $2.chomp(",")
+ @exprs[name] = "equals to " + (val.start_with?("(") ? "<tt>#{val}</tt>" : "+#{val}+")
+ end
end
+ line
end
end
-def grammar
- while line = ARGF.gets
+def grammar(f, out)
+ generate_line(f, out) do |line|
case line
when %r</\*%%%\*/>
- puts '#if 0'
- when %r</\*%c%\*/>
- puts '/*'
- when %r</\*%c>
- puts '*/'
+ "#if 0\n"
when %r</\*%>
- puts '#endif'
+ "#endif\n"
when %r<%\*/>
- puts
- when /\A%%/
- puts '%%'
- return
+ "\n"
else
- print line
+ line
end
end
end
-def usercode
- while line = ARGF.gets
- print line
+def usercode(f, out, path, template)
+ require 'erb'
+ lineno = nil
+ src = nil
+ compiler = ERB::Compiler.new('%-')
+ compiler.put_cmd = compiler.insert_cmd = "out.<<"
+
+ if template
+ File.open(template) do |f|
+ out.clear
+ lineno = f.lineno
+ src, = compiler.compile(f.read)
+ path = template
+ end
+ else
+ lineno = f.lineno
+ src, = compiler.compile(f.read)
end
+
+ eval(src, binding, path, lineno)
end
main
diff --git a/ext/ripper/tools/strip.rb b/ext/ripper/tools/strip.rb
index 99413c361d..23102f797a 100755..100644
--- a/ext/ripper/tools/strip.rb
+++ b/ext/ripper/tools/strip.rb
@@ -1,10 +1,10 @@
+# frozen_string_literal: true
last_is_void = false
ARGF.each do |line|
- if line.strip.empty?
- #puts() unless last_is_void
+ case line
+ when /\A\s*\z/, /\A\#/
+ puts unless last_is_void
last_is_void = true
- elsif /\A\#/ === line
- ;
else
print line
last_is_void = false