diff options
Diffstat (limited to 'ext/ripper')
| -rw-r--r-- | ext/ripper/README | 29 | ||||
| -rw-r--r-- | ext/ripper/depend | 841 | ||||
| -rw-r--r-- | ext/ripper/eventids2.c | 303 | ||||
| -rw-r--r-- | ext/ripper/eventids2.h | 8 | ||||
| -rw-r--r-- | ext/ripper/extconf.rb | 18 | ||||
| -rw-r--r-- | ext/ripper/lib/ripper.rb | 74 | ||||
| -rw-r--r-- | ext/ripper/lib/ripper/core.rb | 74 | ||||
| -rw-r--r-- | ext/ripper/lib/ripper/filter.rb | 86 | ||||
| -rw-r--r-- | ext/ripper/lib/ripper/lexer.rb | 379 | ||||
| -rw-r--r-- | ext/ripper/lib/ripper/sexp.rb | 187 | ||||
| -rw-r--r-- | ext/ripper/ripper_init.c.tmpl | 680 | ||||
| -rw-r--r-- | ext/ripper/ripper_init.h | 6 | ||||
| -rw-r--r-- | ext/ripper/tools/dsl.rb | 181 | ||||
| -rw-r--r-- | ext/ripper/tools/generate-param-macros.rb | 15 | ||||
| -rw-r--r-- | ext/ripper/tools/generate.rb | 194 | ||||
| -rw-r--r-- | ext/ripper/tools/preproc.rb | 124 | ||||
| -rw-r--r-- | ext/ripper/tools/strip.rb | 12 |
17 files changed, 3211 insertions, 0 deletions
diff --git a/ext/ripper/README b/ext/ripper/README new file mode 100644 index 0000000000..70fa208920 --- /dev/null +++ b/ext/ripper/README @@ -0,0 +1,29 @@ +Ripper README +============= + + Ripper is a Ruby script parser. You can get information + by event-based style from the parser. + + !! WARNING !! + + Ripper is still early-alpha version. + I never assure any kind of backward compatibility. + +Requirements +------------ + + * ruby 1.9 (support CVS HEAD only) + +Usage +----- + + See test/ripper/* and sample/ripper/*. + +License +------- + + Ruby License. + + Minero Aoki + aamine@loveruby.net + http://i.loveruby.net diff --git a/ext/ripper/depend b/ext/ripper/depend new file mode 100644 index 0000000000..db83378a1d --- /dev/null +++ b/ext/ripper/depend @@ -0,0 +1,841 @@ +GEN = $(srcdir)/tools/generate.rb +SRC1 = $(top_srcdir)/parse.y +SRC2 = $(srcdir)/eventids2.c +LRAMA = $(BASERUBY) $(top_srcdir)/tool/lrama/exe/lrama + +.SUFFIXES: .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 + +ripper.o: ripper.c + +.y.c: + $(ECHO) compiling compiler $< + $(Q) $(LRAMA) -o$@ - $< < $< + +all: check +static: check + +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 + +check: .eventids2-check + +.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 + $(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 new file mode 100644 index 0000000000..87f2f588ec --- /dev/null +++ b/ext/ripper/eventids2.c @@ -0,0 +1,303 @@ +#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" + +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; + + 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 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) +{ +#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); + + 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_ASSERT(k__END___range, k__END__ < SHRT_MAX); +STATIC_ASSERT(ripper_scanner_ids_size, sizeof(ripper_scanner_ids) < SHRT_MAX); + +ID +ripper_token2eventid(enum yytokentype tok) +{ +#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 + + int i = (int)tok; + if (i >= 0 && i < numberof(offsets) && (i = offsets[i]) > 0) { + return *(const ID *)((const char *)&ripper_scanner_ids-1+i); + } + /* 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 new file mode 100644 index 0000000000..c3c56c27c5 --- /dev/null +++ b/ext/ripper/extconf.rb @@ -0,0 +1,18 @@ +#!ruby -s +# frozen_string_literal: true + +require 'mkmf' +require 'rbconfig' + +def main + $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 + +main diff --git a/ext/ripper/lib/ripper.rb b/ext/ripper/lib/ripper.rb new file mode 100644 index 0000000000..e937d65217 --- /dev/null +++ b/ext/ripper/lib/ripper.rb @@ -0,0 +1,74 @@ +# frozen_string_literal: true +require 'ripper/core' +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 new file mode 100644 index 0000000000..fa075da5b9 --- /dev/null +++ b/ext/ripper/lib/ripper/core.rb @@ -0,0 +1,74 @@ +# frozen_string_literal: true +# +# $Id$ +# +# Copyright (c) 2003-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.so' + +class Ripper + + # 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 array contains name of parser events. + PARSER_EVENTS = PARSER_EVENT_TABLE.keys + + # This array contains name of scanner events. + SCANNER_EVENTS = SCANNER_EVENT_TABLE.keys + + # This array contains name of all ripper events. + EVENTS = PARSER_EVENTS + SCANNER_EVENTS + + private + + # :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 + # + + PARSER_EVENT_TABLE.each do |id, arity| + alias_method "on_#{id}", "_dispatch_#{arity}" + end + + # 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 + + # + # Scanner Events + # + + SCANNER_EVENTS.each do |id| + alias_method "on_#{id}", :_dispatch_1 + end + +end diff --git a/ext/ripper/lib/ripper/filter.rb b/ext/ripper/lib/ripper/filter.rb new file mode 100644 index 0000000000..9955d30550 --- /dev/null +++ b/ext/ripper/lib/ripper/filter.rb @@ -0,0 +1,86 @@ +# 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/lexer' + +class Ripper + + # This class handles only scanner events, + # 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) + @__lexer = Lexer.new(src, filename, lineno) + @__line = nil + @__col = nil + @__state = nil + end + + # The file name of the input. + def filename + @__lexer.filename + end + + # The line number of the current token. + # This value starts from 1. + # This method is valid only in event handlers. + def lineno + @__line + end + + # The column number of the current token. + # This value starts from 0. + # This method is valid only in event handlers. + def column + @__col + end + + # 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 + @__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) + end + end + data + end + + private + + # 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 + + end + +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/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/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-param-macros.rb b/ext/ripper/tools/generate-param-macros.rb new file mode 100644 index 0000000000..f0de55a5f2 --- /dev/null +++ b/ext/ripper/tools/generate-param-macros.rb @@ -0,0 +1,15 @@ +# frozen_string_literal: true +off = true +ARGF.each do |line| + case line + when /RIPPER_PARAMS_DECL_BEGIN/ + off = false + when /RIPPER_PARAMS_DECL_END/ + exit + when /ripper/ + next if off + var = line.scan(/\w+/).last or next + base = var.sub(/ripper_/, '') + puts %"\#define #{base}\t\t(parser->ripper_#{base})" + end +end 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/preproc.rb b/ext/ripper/tools/preproc.rb new file mode 100644 index 0000000000..5e8a6e0cb5 --- /dev/null +++ b/ext/ripper/tools/preproc.rb @@ -0,0 +1,124 @@ +# frozen_string_literal: true +# $Id$ + +require 'optparse' + +def main + 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 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 + 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(f, out) + generate_line(f, out) do |line| + case line + when %r</\*%%%\*/> + "#if 0\n" + when %r</\*%> + "#endif\n" + when %r<%\*/> + "\n" + else + line + end + end +end + +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 new file mode 100644 index 0000000000..23102f797a --- /dev/null +++ b/ext/ripper/tools/strip.rb @@ -0,0 +1,12 @@ +# frozen_string_literal: true +last_is_void = false +ARGF.each do |line| + case line + when /\A\s*\z/, /\A\#/ + puts unless last_is_void + last_is_void = true + else + print line + last_is_void = false + end +end |
