ragel-6.8/0000775000175000017500000000000012106315065007463 500000000000000ragel-6.8/CREDITS0000664000175000017500000000366412106315036010432 00000000000000 Ragel State Machine Compiler -- CREDITS ======================================= * Ragel was designed and written by Adrian Thurston . Many others have helped out along the way. My apolgies to anyone who has been missed. * Many thanks to Arbor Networks for supporting development of Ragel. * Objective-C output and valuable feedback contributed by Erich Ocean. * D output and many great ideas contributed by Alan West. * Conditionals inspired by David Helder. * Java code generation contributions, bug reports, fixes, test cases and suggestions from Colin Fleming. * Useful discussions and bug reports due to Carlos Antunes. * Ruby code generation contributed by Victor Hugo Borja. * C# code generation contributed by Daniel Tang. * Go code generation contributed by Justine Tunney. Significantly expanded by Anton Ageev * D2 patch from Johannes Pfau. * OCaml patch from ygrek. * Feedback, Packaging, and Fixes provided by: Bob Tennent, Robert Lemmen, Tobias Jahn, Cris Bailiff, Buddy Betts, Scott Dixon, Steven Handerson, Michael Somos, Bob Paddock, Istvan Buki, David Drai, Matthias Rahlf, Zinx Verituse, Markus W. Weissmann, Marc Liyanage, Erich Ocean, Alan West, Steven Kibbler, Laurent Boulard, Jon Oberheide, David Helder, Lexington Luthor, Jason Jobe, Colin Fleming, Carlos Antunes, Steve Horne, Matt Mower, Josef Goettgens, Zed Shaw, Marcus Rueckert, Jeremy Hinegardner, Aaron Campbell, Josh Purinton, Judson Lester, Barry Arthur, Tim Potter, Ryan Phelps, David Waite, Kenny MacDermid, MenTaLguY, Manoj Rajagopalan, Tim Chklovski, Mikkel Fahnøe Jørgensen, Andrei Polushin, Evan Phoenix, David Balmain, Ross Thomas, Mitchell Foral, John D. Mitchell, Diego 'Flameeyes' Pettenò, Jose Quinteiro, William Morgan, _why, Iñaki Baz Castillo, Attila Sztupák, Ismael Luceno, Josh Stern, Denis Naumov, Anton Ageev, Kamil Klimkiewicz ragel-6.8/contrib/0000775000175000017500000000000012106315065011123 500000000000000ragel-6.8/contrib/ragel.make0000664000175000017500000000012512043335171012772 00000000000000# -*- Makefile -*- SUFFIXES = .rl .rl.c: $(RAGEL) $(RAGELFLAGS) -C $< -o $@ ragel-6.8/contrib/unicode2ragel.rb0000664000175000017500000001573012043335171014121 00000000000000#!/usr/bin/env ruby # # This script uses the unicode spec to generate a Ragel state machine # that recognizes unicode alphanumeric characters. It generates 5 # character classes: uupper, ulower, ualpha, udigit, and ualnum. # Currently supported encodings are UTF-8 [default] and UCS-4. # # Usage: unicode2ragel.rb [options] # -e, --encoding [ucs4 | utf8] Data encoding # -h, --help Show this message # # This script was originally written as part of the Ferret search # engine library. # # Author: Rakan El-Khalil require 'optparse' require 'open-uri' ENCODINGS = [ :utf8, :ucs4 ] ALPHTYPES = { :utf8 => "unsigned char", :ucs4 => "unsigned int" } CHART_URL = "http://www.unicode.org/Public/5.1.0/ucd/DerivedCoreProperties.txt" ### # Display vars & default option TOTAL_WIDTH = 80 RANGE_WIDTH = 23 @encoding = :utf8 ### # Option parsing cli_opts = OptionParser.new do |opts| opts.on("-e", "--encoding [ucs4 | utf8]", "Data encoding") do |o| @encoding = o.downcase.to_sym end opts.on("-h", "--help", "Show this message") do puts opts exit end end cli_opts.parse(ARGV) unless ENCODINGS.member? @encoding puts "Invalid encoding: #{@encoding}" puts cli_opts exit end ## # Downloads the document at url and yields every alpha line's hex # range and description. def each_alpha( url, property ) open( url ) do |file| file.each_line do |line| next if line =~ /^#/; next if line !~ /; #{property} #/; range, description = line.split(/;/) range.strip! description.gsub!(/.*#/, '').strip! if range =~ /\.\./ start, stop = range.split '..' else start = stop = range end yield start.hex .. stop.hex, description end end end ### # Formats to hex at minimum width def to_hex( n ) r = "%0X" % n r = "0#{r}" unless (r.length % 2).zero? r end ### # UCS4 is just a straight hex conversion of the unicode codepoint. def to_ucs4( range ) rangestr = "0x" + to_hex(range.begin) rangestr << "..0x" + to_hex(range.end) if range.begin != range.end [ rangestr ] end ## # 0x00 - 0x7f -> 0zzzzzzz[7] # 0x80 - 0x7ff -> 110yyyyy[5] 10zzzzzz[6] # 0x800 - 0xffff -> 1110xxxx[4] 10yyyyyy[6] 10zzzzzz[6] # 0x010000 - 0x10ffff -> 11110www[3] 10xxxxxx[6] 10yyyyyy[6] 10zzzzzz[6] UTF8_BOUNDARIES = [0x7f, 0x7ff, 0xffff, 0x10ffff] def to_utf8_enc( n ) r = 0 if n <= 0x7f r = n elsif n <= 0x7ff y = 0xc0 | (n >> 6) z = 0x80 | (n & 0x3f) r = y << 8 | z elsif n <= 0xffff x = 0xe0 | (n >> 12) y = 0x80 | (n >> 6) & 0x3f z = 0x80 | n & 0x3f r = x << 16 | y << 8 | z elsif n <= 0x10ffff w = 0xf0 | (n >> 18) x = 0x80 | (n >> 12) & 0x3f y = 0x80 | (n >> 6) & 0x3f z = 0x80 | n & 0x3f r = w << 24 | x << 16 | y << 8 | z end to_hex(r) end def from_utf8_enc( n ) n = n.hex r = 0 if n <= 0x7f r = n elsif n <= 0xdfff y = (n >> 8) & 0x1f z = n & 0x3f r = y << 6 | z elsif n <= 0xefffff x = (n >> 16) & 0x0f y = (n >> 8) & 0x3f z = n & 0x3f r = x << 10 | y << 6 | z elsif n <= 0xf7ffffff w = (n >> 24) & 0x07 x = (n >> 16) & 0x3f y = (n >> 8) & 0x3f z = n & 0x3f r = w << 18 | x << 12 | y << 6 | z end r end ### # Given a range, splits it up into ranges that can be continuously # encoded into utf8. Eg: 0x00 .. 0xff => [0x00..0x7f, 0x80..0xff] # This is not strictly needed since the current [5.1] unicode standard # doesn't have ranges that straddle utf8 boundaries. This is included # for completeness as there is no telling if that will ever change. def utf8_ranges( range ) ranges = [] UTF8_BOUNDARIES.each do |max| if range.begin <= max return ranges << range if range.end <= max ranges << range.begin .. max range = (max + 1) .. range.end end end ranges end def build_range( start, stop ) size = start.size/2 left = size - 1 return [""] if size < 1 a = start[0..1] b = stop[0..1] ### # Shared prefix if a == b return build_range(start[2..-1], stop[2..-1]).map do |elt| "0x#{a} " + elt end end ### # Unshared prefix, end of run return ["0x#{a}..0x#{b} "] if left.zero? ### # Unshared prefix, not end of run # Range can be 0x123456..0x56789A # Which is equivalent to: # 0x123456 .. 0x12FFFF # 0x130000 .. 0x55FFFF # 0x560000 .. 0x56789A ret = [] ret << build_range(start, a + "FF" * left) ### # Only generate middle range if need be. if a.hex+1 != b.hex max = to_hex(b.hex - 1) max = "FF" if b == "FF" ret << "0x#{to_hex(a.hex+1)}..0x#{max} " + "0x00..0xFF " * left end ### # Don't generate last range if it is covered by first range ret << build_range(b + "00" * left, stop) unless b == "FF" ret.flatten! end def to_utf8( range ) utf8_ranges( range ).map do |r| build_range to_utf8_enc(r.begin), to_utf8_enc(r.end) end.flatten! end ## # Perform a 3-way comparison of the number of codepoints advertised by # the unicode spec for the given range, the originally parsed range, # and the resulting utf8 encoded range. def count_codepoints( code ) code.split(' ').inject(1) do |acc, elt| if elt =~ /0x(.+)\.\.0x(.+)/ if @encoding == :utf8 acc * (from_utf8_enc($2) - from_utf8_enc($1) + 1) else acc * ($2.hex - $1.hex + 1) end else acc end end end def is_valid?( range, desc, codes ) spec_count = 1 spec_count = $1.to_i if desc =~ /\[(\d+)\]/ range_count = range.end - range.begin + 1 sum = codes.inject(0) { |acc, elt| acc + count_codepoints(elt) } sum == spec_count and sum == range_count end ## # Generate the state maching to stdout def generate_machine( name, property ) pipe = " " puts " #{name} = " each_alpha( CHART_URL, property ) do |range, desc| codes = (@encoding == :ucs4) ? to_ucs4(range) : to_utf8(range) raise "Invalid encoding of range #{range}: #{codes.inspect}" unless is_valid? range, desc, codes range_width = codes.map { |a| a.size }.max range_width = RANGE_WIDTH if range_width < RANGE_WIDTH desc_width = TOTAL_WIDTH - RANGE_WIDTH - 11 desc_width -= (range_width - RANGE_WIDTH) if range_width > RANGE_WIDTH if desc.size > desc_width desc = desc[0..desc_width - 4] + "..." end codes.each_with_index do |r, idx| desc = "" unless idx.zero? code = "%-#{range_width}s" % r puts " #{pipe} #{code} ##{desc}" pipe = "|" end end puts " ;" puts "" end puts <@\.@<:@0-9@:>@\) .*:\1:p'` ragel_version_compare=`echo $ragel_version | tr -d .` ragel_wanted_version=`echo $2 | tr -d .` AS_IF([test $ragel_version_compare -lt $ragel_wanted_version], [AC_MSG_WARN([Found Ragel $ragel_version but Ragel $2 requested]) RAGEL=false ]) ])) dnl Only test the need if not found AS_IF([test x"$RAGEL" = x"false"], [ AC_MSG_CHECKING([whether we need ragel to regenerate sources]) AS_IF([test -a "${srcdir}/$1"], [ragel_needed=no], [ragel_needed=yes]) AC_MSG_RESULT([$ragel_needed]) AS_IF([test x"$ragel_needed" = x"yes"], [AC_MSG_ERROR([dnl You need Ragel to build from development sources. You can find Ragel at http://www.complang.org/ragel/dnl ])]) ]) ]) AC_DEFUN([CHECK_RAGEL_AM], [ CHECK_RAGEL([$1], [$2]) AM_CONDITIONAL([HAVE_RAGEL], [test x"$RAGEL" != x"false"]) ]) ragel-6.8/contrib/Makefile.in0000664000175000017500000002162612106313353013115 00000000000000# Makefile.in generated by automake 1.11.3 from Makefile.am. # @configure_input@ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, # 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software # Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : subdir = contrib DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/configure.in am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/ragel/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = SOURCES = DIST_SOURCES = DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EXEEXT = @EXEEXT@ FIG2DEV = @FIG2DEV@ GDC = @GDC@ GMCS = @GMCS@ GOBIN = @GOBIN@ GOBJC = @GOBJC@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ JAVAC = @JAVAC@ KELBT = @KELBT@ LDFLAGS = @LDFLAGS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LTLIBOBJS = @LTLIBOBJS@ MAKEINFO = @MAKEINFO@ MKDIR_P = @MKDIR_P@ OBJEXT = @OBJEXT@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PDFLATEX = @PDFLATEX@ PUBDATE = @PUBDATE@ RAGEL = @RAGEL@ RANLIB = @RANLIB@ RUBY = @RUBY@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ TXL = @TXL@ VERSION = @VERSION@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build_alias = @build_alias@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host_alias = @host_alias@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ EXTRA_DIST = ragel.make ragel.m4 unicode2ragel.rb all: all-am .SUFFIXES: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign contrib/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign contrib/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): tags: TAGS TAGS: ctags: CTAGS CTAGS: distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile installdirs: install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic mostlyclean-am distclean: distclean-am -rm -f Makefile distclean-am: clean-am distclean-generic dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-generic pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: .MAKE: install-am install-strip .PHONY: all all-am check check-am clean clean-generic distclean \ distclean-generic distdir dvi dvi-am html html-am info info-am \ install install-am install-data install-data-am install-dvi \ install-dvi-am install-exec install-exec-am install-html \ install-html-am install-info install-info-am install-man \ install-pdf install-pdf-am install-ps install-ps-am \ install-strip installcheck installcheck-am installdirs \ maintainer-clean maintainer-clean-generic mostlyclean \ mostlyclean-generic pdf pdf-am ps ps-am uninstall uninstall-am # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: ragel-6.8/test/0000775000175000017500000000000012106315065010442 500000000000000ragel-6.8/test/statechart1.rl0000664000175000017500000000254712043335171013154 00000000000000/* * @LANG: c */ /* * Test in and out state actions. */ #include #include struct state_chart { int cs; }; %%{ machine state_chart; variable cs fsm->cs; action a { printf("a"); } action b { printf("b"); } action hexa { printf("a"); } action hexb { printf("b"); } hex_a = '0x' '0'* '61' @hexa; hex_b = '0x' '0'* '62' @hexb; a = 'a' @a | hex_a; b = 'b' @b | hex_b; ws = ' '+; mach = start: ( a -> st1 | b -> st2 | zlen -> final ), st1: ( a -> st1 | ws -> start | zlen -> final ), st2: ( b -> st2 | ws -> start | zlen -> final ); main := ( mach '\n' )*; }%% %% write data; void state_chart_init( struct state_chart *fsm ) { %% write init; } void state_chart_execute( struct state_chart *fsm, const char *_data, int _len ) { const char *p = _data; const char *pe = _data+_len; %% write exec; } int state_chart_finish( struct state_chart *fsm ) { if ( fsm->cs == state_chart_error ) return -1; if ( fsm->cs >= state_chart_first_final ) return 1; return 0; } struct state_chart sc; void test( char *buf ) { int len = strlen( buf ); state_chart_init( &sc ); state_chart_execute( &sc, buf, len ); state_chart_finish( &sc ); printf("\n"); } int main() { test( "aa0x0061aa b\n" "bbb0x62b 0x61 0x000062\n" ); return 0; } #ifdef _____OUTPUT_____ aaaaabbbbbbab #endif ragel-6.8/test/recdescent1.rl0000664000175000017500000000345012043335171013123 00000000000000/* * @LANG: c * Test growable stack. */ #include #include #include %%{ machine recdescent; prepush { if ( top == stack_size ) { printf( "growing stack\n" ); stack_size = top * 2; stack = (int*)realloc( stack, sizeof(int)*stack_size ); } } postpop { if ( stack_size > (top * 4) ) { stack_size = top * 2; stack = (int*)realloc( stack, sizeof(int)*stack_size ); printf( "shrinking stack\n" ); } } action item_start { item = p; } action item_finish { printf( "item: " ); fwrite( item, 1, p-item, stdout ); printf( "\n" ); } action call_main { printf( "calling main\n" ); fcall main; } action return_main { if ( top == 0 ) { printf( "STRAY CLOSE\n" ); fbreak; } printf( "returning from main\n" ); fhold; fret; } id = [a-zA-Z_]+; number = [0-9]+; ws = [ \t\n]+; main := ( ws | ( number | id ) >item_start %item_finish | '{' @call_main '}' | '}' @return_main )**; }%% %% write data; void test( char *buf ) { int cs; int *stack; int top, stack_size; char *p, *pe, *eof, *item = 0; int len = strlen( buf ); %% write init; stack_size = 1; stack = (int*)malloc( sizeof(int) * stack_size ); p = buf; pe = buf + len; eof = pe; %% write exec; if ( cs == recdescent_error ) { /* Machine failed before finding a token. */ printf( "PARSE ERROR\n" ); } } int main() { test( "88 foo { 99 {{{{}}}}{ } }"); test( "76 } sadf"); return 0; } #ifdef _____OUTPUT_____ item: 88 item: foo calling main item: 99 calling main growing stack calling main growing stack calling main calling main growing stack returning from main returning from main returning from main returning from main shrinking stack calling main returning from main returning from main shrinking stack item: 76 STRAY CLOSE #endif ragel-6.8/test/langtrans_ruby.txl0000664000175000017500000002011212043335171014141 00000000000000include "testcase.txl" keys 'boolean 'new end keys define ruby_statements [repeat ruby_lang_stmt] end define define ruby_lang_stmt [al_ragel_stmt] | [ruby_expr_stmt] | [ruby_if_stmt] | [EX] 'do [IN] [NL] [ruby_statements] [EX] 'end [IN] [NL] end define define ruby_type_decl [al_type_decl] | 'boolean end define define ruby_expr_stmt [ruby_expr] '; [NL] end define define ruby_expr [ruby_term] [repeat ruby_expr_extend] end define define ruby_expr_extend [al_expr_op] [ruby_term] end define define ruby_term [al_term] | [stringlit] [union] | [id] [repeat ruby_dot_id] | [SPOFF] [id] [repeat ruby_dot_id] '( [SPON] [ruby_args] ') | [union] end define define ruby_dot_id '. [id] end define define ruby_args [list ruby_expr] end define define ruby_sign '- | '+ end define define ruby_if_stmt 'if [ruby_expr] [NL] [IN] [ruby_statements] [EX] [opt ruby_else] 'end [NL] end define define ruby_else 'else [NL] [IN] [ruby_statements] [EX] end define define ruby_lang [ruby_statements] '%% [NL] [ruby_statements] [ragel_def] end define define program [lang_indep] | [ruby_lang] end define redefine al_host_block '{ [NL] [IN] [al_statements] [EX] '} [NL] | '{ [NL] [IN] [ruby_statements] [EX] '} [NL] end define redefine cond_action_stmt 'action [id] '{ [al_expr] '} [NL] | 'action [id] '{ [ruby_expr] '} [NL] end redefine function initDecl1 VarDecl [al_variable_decl] deconstruct VarDecl 'bool Id [id] '; replace [repeat ruby_lang_stmt] by Id '= 'false '; end function function initDecl2 VarDecl [al_variable_decl] deconstruct VarDecl 'char Id [id] '; replace [repeat ruby_lang_stmt] by Id '= ''c' '; end function function initDecl3 VarDecl [al_variable_decl] deconstruct VarDecl 'int Id [id] '; replace [repeat ruby_lang_stmt] by Id '= '0 '; end function function initDecl4 VarDecl [al_variable_decl] deconstruct VarDecl 'ptr Id [id] '; replace [repeat ruby_lang_stmt] by Id '= '-1 '; end function function initDecl5 VarDecl [al_variable_decl] deconstruct VarDecl Type [al_type_decl] Id [id] Union [union] '; replace [repeat ruby_lang_stmt] by Id '= '[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0] '; end function function alStmtToRuby1 AlStmt [action_lang_stmt] deconstruct AlStmt VarDecl [al_variable_decl] deconstruct VarDecl Type [al_type_decl] Id [id] OptUnion [opt union] '; replace [repeat ruby_lang_stmt] by _ [initDecl1 VarDecl] [initDecl2 VarDecl] [initDecl3 VarDecl] [initDecl4 VarDecl] [initDecl5 VarDecl] end function rule alTermToRuby1 replace [al_term] 'first_token_char by 'data '[ts] end rule rule alTermToRuby2 replace [al_term] '< _ [al_type_decl] '> '( AlExpr [al_expr] ') by '( AlExpr ') end rule function alTermToRuby replace [al_term] AlTerm [al_term] by AlTerm [alTermToRuby1] [alTermToRuby2] end function function alExprExtendToRuby AlExprExtend [repeat al_expr_extend] deconstruct AlExprExtend Op [al_expr_op] Term [al_term] Rest [repeat al_expr_extend] construct RubyRest [repeat ruby_expr_extend] _ [alExprExtendToRuby Rest] replace [repeat ruby_expr_extend] by Op Term [alTermToRuby] RubyRest end function % Note: this doesn't go into the ( al_expr ) form of al_term. function alExprToRuby AlExpr [al_expr] deconstruct AlExpr ALTerm [al_term] AlExprExtend [repeat al_expr_extend] construct RubyExprExtend [repeat ruby_expr_extend] _ [alExprExtendToRuby AlExprExtend] construct Result [opt ruby_expr] ALTerm [alTermToRuby] RubyExprExtend replace [opt ruby_expr] by Result end function function alStmtToRuby2 AlStmt [action_lang_stmt] deconstruct AlStmt AlExpr [al_expr] '; construct OptRubyExpr [opt ruby_expr] _ [alExprToRuby AlExpr] deconstruct OptRubyExpr RubyExpr [ruby_expr] replace [repeat ruby_lang_stmt] by RubyExpr '; end function function liftBlock replace [repeat ruby_lang_stmt] 'do Block [repeat ruby_lang_stmt] 'end by Block end function function alOptElseRuby AlOptElse [opt al_else] deconstruct AlOptElse 'else AlSubStmt [action_lang_stmt] construct AlSubStmts [repeat action_lang_stmt] AlSubStmt construct RubySubStmts [repeat ruby_lang_stmt] _ [alToRuby AlSubStmts] deconstruct RubySubStmts RubySubStmt [ruby_lang_stmt] replace [opt ruby_else] by 'else RubySubStmts [liftBlock] end function function alStmtToRuby3 AlStmt [action_lang_stmt] deconstruct AlStmt 'if '( AlExpr [al_expr] ') AlSubStmt [action_lang_stmt] AlOptElse [opt al_else] construct OptRubyExpr [opt ruby_expr] _ [alExprToRuby AlExpr] deconstruct OptRubyExpr RubyExpr [ruby_expr] construct AlSubStmts [repeat action_lang_stmt] AlSubStmt construct RubySubStmts [repeat ruby_lang_stmt] _ [alToRuby AlSubStmts] construct OptRubyElse [opt ruby_else] _ [alOptElseRuby AlOptElse] replace [repeat ruby_lang_stmt] by 'if RubyExpr RubySubStmts [liftBlock] OptRubyElse 'end end function function alStmtToRuby4a AlStmt [action_lang_stmt] deconstruct AlStmt 'printi Id [id] '; replace [repeat ruby_lang_stmt] by 'print '( Id ') '; end function function alStmtToRuby4b AlStmt [action_lang_stmt] deconstruct AlStmt 'prints String [stringlit] '; replace [repeat ruby_lang_stmt] by 'print '( String ') '; end function function alStmtToRuby4c AlStmt [action_lang_stmt] deconstruct AlStmt 'printb Id [id] '; replace [repeat ruby_lang_stmt] by '_a = Id '[0..pos-1] '; 'print '( '_a '. 'pack '( '"c*" ') ') '; end function function alStmtToRuby4d AlStmt [action_lang_stmt] deconstruct AlStmt 'print_token '; replace [repeat ruby_lang_stmt] by '_m = 'data '[ts..te-1] '; 'print '( '_m '. 'pack '( '"c*" ') ') '; end function function alStmtToRuby5 AlStmt [action_lang_stmt] deconstruct AlStmt '{ AlSubStmts [repeat action_lang_stmt] '} construct RubySubStmts [repeat ruby_lang_stmt] _ [alToRuby AlSubStmts] replace [repeat ruby_lang_stmt] by 'do RubySubStmts 'end end function function alStmtToRuby6 AlStmt [action_lang_stmt] deconstruct AlStmt RagelStmt [al_ragel_stmt] replace [repeat ruby_lang_stmt] by RagelStmt end function rule fixCharLit replace $ [al_term] CharLit [charlit] construct BaseId [id] 'id construct Id [id] BaseId [unquote CharLit] construct EmptyString [stringlit] '"" construct Repl [stringlit] EmptyString [quote Id] by Repl '[0] end rule function alToRuby AlStmts [repeat action_lang_stmt] deconstruct AlStmts FirstStmt [action_lang_stmt] Rest [repeat action_lang_stmt] construct RubyFirst [repeat ruby_lang_stmt] _ [alStmtToRuby1 FirstStmt] [alStmtToRuby2 FirstStmt] [alStmtToRuby3 FirstStmt] [alStmtToRuby4a FirstStmt] [alStmtToRuby4b FirstStmt] [alStmtToRuby4c FirstStmt] [alStmtToRuby4d FirstStmt] [alStmtToRuby5 FirstStmt] [alStmtToRuby6 FirstStmt] [fixCharLit] construct RubyRest [repeat ruby_lang_stmt] _ [alToRuby Rest] replace [repeat ruby_lang_stmt] by RubyFirst [. RubyRest] end function rule actionTransRuby replace [al_host_block] '{ AlStmts [repeat action_lang_stmt] '} construct RubyStmts [repeat ruby_lang_stmt] _ [alToRuby AlStmts] by '{ RubyStmts '} end rule rule condTransRuby replace [cond_action_stmt] 'action Id [id] '{ AlExpr [al_expr] '} construct OptRubyExpr [opt ruby_expr] _ [alExprToRuby AlExpr] deconstruct OptRubyExpr RubyExpr [ruby_expr] by 'action Id '{ RubyExpr '} end rule rule lowercaseMachine replace $ [machine_stmt] 'machine Id [id] '; by 'machine Id [tolower] '; end rule function langTransRuby replace [program] Definitions [repeat action_lang_stmt] '%% Initializations [repeat action_lang_stmt] RagelDef [ragel_def] construct RubyDefinitions [repeat ruby_lang_stmt] _ [alToRuby Definitions] construct RubyInitializations [repeat ruby_lang_stmt] _ [alToRuby Initializations] construct NewRagelDef [ragel_def] RagelDef [actionTransRuby] [condTransRuby] [lowercaseMachine] import ArrayInits [ruby_statements] ArrayInitStmts [repeat ruby_lang_stmt] by RubyDefinitions '%% ArrayInitStmts [. RubyInitializations] NewRagelDef end function function main replace [program] P [program] export ArrayInits [ruby_statements] _ by P [langTransRuby] end function ragel-6.8/test/erract5.rl0000664000175000017500000000454412043335171012275 00000000000000/* * @LANG: obj-c */ /* * Test error actions. */ #include #include #include @interface ErrAct : Object { @public int cs; }; // Initialize the machine. Invokes any init statement blocks. Returns 0 // if the machine begins in a non-accepting state and 1 if the machine // begins in an accepting state. - (int) initFsm; // Execute the machine on a block of data. Returns -1 if after processing // the data, the machine is in the error state and can never accept, 0 if // the machine is in a non-accepting state and 1 if the machine is in an // accepting state. - (void) executeWithData:(const char *)data len:(int)len; // Indicate that there is no more data. Returns -1 if the machine finishes // in the error state and does not accept, 0 if the machine finishes // in any other non-accepting state and 1 if the machine finishes in an // accepting state. - (int) finish; @end @implementation ErrAct %%{ machine ErrAct; action expect_digit_plus_minus { printf(" DIGIT PLUS MINUS\n"); } action expect_digit { printf(" DIGIT\n"); } action expect_digit_decimal { printf(" DIGIT DECIMAL\n"); } float = ( ( [\-+] >!expect_digit_plus_minus %!expect_digit | "" ) ( [0-9] [0-9]* $!expect_digit_decimal ) ( '.' [0-9]+ $!expect_digit )? ); main := float '\n'; }%% %% write data; - (int) initFsm; { %% write init; return 1; } - (void) executeWithData:(const char *)_data len:(int)_len; { const char *p = _data; const char *pe = _data + _len; const char *eof = pe; %% write exec; } - (int) finish; { if ( cs == ErrAct_error ) return -1; else if ( cs >= ErrAct_first_final ) return 1; return 0; } @end #define BUFSIZE 1024 void test( char *buf ) { ErrAct *errAct = [[ErrAct alloc] init]; [errAct initFsm]; [errAct executeWithData:buf len:strlen(buf)]; if ( [errAct finish] > 0 ) printf("ACCEPT\n"); else printf("FAIL\n"); } int main() { test( "1\n" ); test( "+1\n" ); test( "-1\n" ); test( "1.1\n" ); test( "+1.1\n" ); test( "-1.1\n" ); test( "a\n" ); test( "-\n" ); test( "+\n" ); test( "-a\n" ); test( "+b\n" ); test( "1.\n" ); test( "1d\n" ); test( "1.d\n" ); test( "1.1d\n" ); return 0; } #ifdef _____OUTPUT_____ ACCEPT ACCEPT ACCEPT ACCEPT ACCEPT ACCEPT DIGIT PLUS MINUS FAIL DIGIT FAIL DIGIT FAIL DIGIT FAIL DIGIT FAIL DIGIT FAIL DIGIT DECIMAL FAIL DIGIT FAIL DIGIT FAIL #endif ragel-6.8/test/cppscan3.rl0000664000175000017500000001113612043335171012435 00000000000000/* * @LANG: c++ */ #include #include using namespace std; #define TK_Dlit 192 #define TK_Slit 193 #define TK_Float 194 #define TK_Id 195 #define TK_NameSep 197 #define TK_Arrow 211 #define TK_PlusPlus 212 #define TK_MinusMinus 213 #define TK_ArrowStar 214 #define TK_DotStar 215 #define TK_ShiftLeft 216 #define TK_ShiftRight 217 #define TK_IntegerDecimal 218 #define TK_IntegerOctal 219 #define TK_IntegerHex 220 #define TK_EqualsEquals 223 #define TK_NotEquals 224 #define TK_AndAnd 225 #define TK_OrOr 226 #define TK_MultAssign 227 #define TK_DivAssign 228 #define TK_PercentAssign 229 #define TK_PlusAssign 230 #define TK_MinusAssign 231 #define TK_AmpAssign 232 #define TK_CaretAssign 233 #define TK_BarAssign 234 #define TK_DotDotDot 240 #define TK_Whitespace 241 #define TK_Comment 242 #define BUFSIZE 4096 char buf[BUFSIZE]; struct Scanner { int cs, act; const char *ts, *te; void token( int tok ); void run(); void init( ); void execute( const char *data, int len ); int finish( ); }; %%{ machine Scanner; main := |* # Single and double literals. ( 'L'? "'" ( [^'\\\n] | /\\./ )* "'" ) => { token( TK_Slit );}; ( 'L'? '"' ( [^"\\\n] | /\\./ )* '"' ) => { token( TK_Dlit );}; # Identifiers ( [a-zA-Z_] [a-zA-Z0-9_]* ) =>{ token( TK_Id );}; # Floating literals. fract_const = digit* '.' digit+ | digit+ '.'; exponent = [eE] [+\-]? digit+; float_suffix = [flFL]; ( fract_const exponent? float_suffix? | digit+ exponent float_suffix? ) => { token( TK_Float );}; # Integer decimal. Leading part buffered by float. ( ( '0' | [1-9] [0-9]* ) [ulUL]{0,3} ) => { token( TK_IntegerDecimal );}; # Integer octal. Leading part buffered by float. ( '0' [0-9]+ [ulUL]{0,2} ) => { token( TK_IntegerOctal );}; # Integer hex. Leading 0 buffered by float. ( '0' ( 'x' [0-9a-fA-F]+ [ulUL]{0,2} ) ) => { token( TK_IntegerHex );}; # Only buffer the second item, first buffered by symbol. */ '::' => {token( TK_NameSep );}; '==' => {token( TK_EqualsEquals );}; '!=' => {token( TK_NotEquals );}; '&&' => {token( TK_AndAnd );}; '||' => {token( TK_OrOr );}; '*=' => {token( TK_MultAssign );}; '/=' => {token( TK_DivAssign );}; '%=' => {token( TK_PercentAssign );}; '+=' => {token( TK_PlusAssign );}; '-=' => {token( TK_MinusAssign );}; '&=' => {token( TK_AmpAssign );}; '^=' => {token( TK_CaretAssign );}; '|=' => {token( TK_BarAssign );}; '++' => {token( TK_PlusPlus );}; '--' => {token( TK_MinusMinus );}; '->' => {token( TK_Arrow );}; '->*' => {token( TK_ArrowStar );}; '.*' => {token( TK_DotStar );}; # Three char compounds, first item already buffered. */ '...' => { token( TK_DotDotDot );}; # Single char symbols. ( punct - [_"'] ) => { token( ts[0] );}; action comment { token( TK_Comment ); } # Comments and whitespace. '/*' ( any* $0 '*/' @1 ) => comment; '//' ( any* $0 '\n' @1 ) => comment; ( any - 33..126 )+ => { token( TK_Whitespace );}; *|; }%% %% write data; void Scanner::init( ) { %% write init; } /* Returns the count of bytes still in the buffer * (shifted to the biginning) */ void Scanner::execute( const char *data, int len ) { const char *p = data; const char *pe = data + len; const char *eof = pe; %% write exec; cout << "P: " << (p - data) << endl; } int Scanner::finish( ) { if ( cs == Scanner_error ) return -1; if ( cs >= Scanner_first_final ) return 1; return 0; } void Scanner::token( int tok ) { const char *data = ts; int len = te - ts; cout << "<" << tok << "> "; for ( int i = 0; i < len; i++ ) cout << data[i]; cout << '\n'; } void test( const char *buf ) { int len = strlen( buf ); std::ios::sync_with_stdio(false); Scanner scanner; scanner.init(); scanner.execute( buf, len ); if ( scanner.cs == Scanner_error ) { /* Machine failed before finding a token. */ cout << "PARSE ERROR" << endl; } /* FIXME: Last token may get lost. */ scanner.finish(); } int main() { test( "\"\\\"hi\" /*\n" "*/\n" "44 .44\n" "44. 44\n" "44 . 44\n" "44.44\n" "_hithere22" ); test( "'\\''\"\\n\\d'\\\"\"\n" "hi\n" "99\n" ".99\n" "99e-4\n" "->*\n" "||\n" "0x98\n" "0x\n" "//\n" "/* * */" ); test( "'\n" "'\n" ); } #ifdef _____OUTPUT_____ <192> "\"hi" <241> <242> /* */ <241> <218> 44 <241> <194> .44 <241> <194> 44. <241> <218> 44 <241> <218> 44 <241> <46> . <241> <218> 44 <241> <194> 44.44 <241> <195> _hithere22 P: 51 <193> '\'' <192> "\n\d'\"" <241> <195> hi <241> <218> 99 <241> <194> .99 <241> <194> 99e-4 <241> <214> ->* <241> <226> || <241> <220> 0x98 <241> <218> 0 <195> x <241> <242> // <242> /* * */ P: 55 P: 1 PARSE ERROR #endif ragel-6.8/test/high1.rl0000664000175000017500000000550612043335171011727 00000000000000/* * @LANG: c * @ALLOW_GENFLAGS: -T0 -T1 -G0 -G1 -G2 */ /** * Test a high character to make sure signedness * isn't messing us up. */ #include #include #include struct high { int cs; }; %%{ machine high; variable cs fsm->cs; # We Want the header portion. alphtype unsigned int; main := ( 0x20 .. 0xefffffff @1 @{printf("gothigh1\n");} | 0xf0000000 @1 @{printf("gothigh1\n");} | 0x200 .. 0xfe000000 @1 @{printf("gothigh2\n");} | any @0 @{printf("else\n");} )*; }%% %% write data; void high_init( struct high *fsm ) { %% write init; } void high_execute( struct high *fsm, const unsigned int *_data, int _len ) { const unsigned int *p = _data; const unsigned int *pe = _data+_len; %% write exec; } int high_finish( struct high *fsm ) { if ( fsm->cs == high_error ) return -1; if ( fsm->cs >= high_first_final ) return 1; return 0; } struct high high; #define BUFSIZE 1024 char cbuf[BUFSIZE]; unsigned int buf[BUFSIZE]; int buflen = 0; char numbuf[9]; int numlen = 0; struct tokenizer { int cs; }; %%{ machine tokenizer; variable cs fsm->cs; action bufdigit { if ( numlen < 8 ) numbuf[numlen++] = fc; } action writeDigit { /* Null terminate the buffer storing the number and reset. */ numbuf[numlen] = 0; numlen = 0; /* Store the number in the buf. If the buf is full then * flush and reset the buffer. */ buf[buflen++] = strtoul( numbuf, 0, 16 ); if ( buflen == BUFSIZE ) { high_execute( &high, buf, BUFSIZE ); buflen = 0; } } action finish { if ( buflen > 0 ) high_execute( &high, buf, buflen ); if ( high_finish( &high ) > 0 ) printf("ACCEPT\n"); else printf("FAIL\n"); } num = ( digit | 'a'..'f' )+ $bufdigit %writeDigit; main := ( num $1 %0 | space )* %/finish; }%% %% write data; void tokenizer_init( struct tokenizer *fsm ) { %% write init; } void tokenizer_execute( struct tokenizer *fsm, const char *_data, int _len ) { const char *p = _data; const char *pe = _data+_len; const char *eof = pe; %% write exec; } int tokenizer_finish( struct tokenizer *fsm ) { if ( fsm->cs == tokenizer_error ) return -1; if ( fsm->cs >= tokenizer_first_final ) return 1; return 0; } struct tokenizer tok; void test( char *cbuf ) { int len = strlen( cbuf ); high_init( &high ); tokenizer_init( &tok ); tokenizer_execute( &tok, cbuf, len ); if ( tokenizer_finish( &tok ) <= 0 ) printf("Tokenizer FAIL\n"); } char data[] = "10 20 30 40 50 200 300 400 \n" "d0000000 f0000000 fd000000 fe000000\n" "ff000000 ffffffffffffffffffffffffff\n" "ff\n"; int main() { test( data ); return 0; } #ifdef _____OUTPUT_____ else gothigh1 gothigh1 gothigh1 gothigh1 gothigh1 gothigh2 gothigh1 gothigh2 gothigh1 gothigh2 gothigh1 gothigh2 gothigh1 gothigh2 gothigh2 gothigh2 else else gothigh1 ACCEPT #endif ragel-6.8/test/java2.rl0000664000175000017500000000131612043335171011725 00000000000000/* * @LANG: java */ class java2 { %%{ machine java1; alphtype int; main := 1 2 3 4 ( 5 6 7 8 | 9 10 11 12 ) 1073741824; }%% %% write data; static void test( int data[] ) { int cs, p = 0, pe = data.length; int top; %% write init; %% write exec; if ( cs >= java1_first_final ) System.out.println( "ACCEPT" ); else System.out.println( "FAIL" ); } static final int t1[] = { 1, 2, 3, 4, 5, 6, 7, 8, 1073741824 }; static final int t2[] = { 1, 2, 3, 4, 9, 10, 11, 12, 1073741824 }; static final int t3[] = { 1, 2, 3, 4, 1073741824 }; public static void main( String args[] ) { test( t1 ); test( t2 ); test( t3 ); } } /* _____OUTPUT_____ ACCEPT ACCEPT FAIL */ ragel-6.8/test/strings1.rl0000664000175000017500000000543512043335171012502 00000000000000/* * @LANG: c */ #include #include struct strs { int cs; }; %%{ machine strs; variable cs fsm->cs; main := "__gmon_start__\n" | "cerr\n" | "__cp_push_exception\n" | "_DYNAMIC\n" | "__rtti_user\n" | "__rtti_si\n" | "_init\n" | "__throw\n" | "__deregister_frame_info\n" | "terminate__Fv\n" | "__builtin_vec_new\n" | "_fini\n" | "__builtin_vec_delete\n" | "_GLOBAL_OFFSET_TABLE_\n" | "__nw__FUiPv\n" | "__builtin_delete\n" | "__builtin_new\n" | "cout\n" | "__register_frame_info\n" | "__eh_alloc\n" | "strcpy\n" | "stdout\n" | "memmove\n" | "memcpy\n" | "malloc\n" | "isatty\n" | "strtoul\n" | "fprintf\n" | "stdin\n" | "ferror\n" | "strncpy\n" | "unlink\n" | "strcasecmp\n" | "realloc\n" | "_IO_getc\n" | "fread\n" | "memset\n" | "__assert_fail\n" | "strcmp\n" | "stderr\n" | "fwrite\n" | "exit\n" | "fopen\n" | "atoi\n" | "fileno\n" | "_IO_stdin_used\n" | "__libc_start_main\n" | "strlen\n" | "free\n" | "_edata\n" | "__bss_start\n" | "_end\n" | "QVhl\n" | "BPPh\n" | "PHRV\n" | "PHRj\n" | "PHRj\n" | "jphy\n" | "jqhy\n" | "PHRj\n" | "PHRj\n" | "LWVS\n" | "LWVS\n" | "bad_alloc\n" | "main\n" | "false\n" | "help\n" | "bad_alloc\n" | "bad_alloc\n" | "bad_alloc\n" | "ascii\n" | "extend\n" | "alnum\n" | "alpha\n" | "cntrl\n" | "digit\n" | "graph\n" | "lower\n" | "print\n" | "punct\n" | "space\n" | "upper\n" | "xdigit\n" | "false\n" | "bad_alloc\n" | "bad_alloc\n" | "bad_alloc\n" | "TransStruct\n" | "StateStruct\n" | "Struct\n" | "Init\n" | "bad_alloc\n" | "TransStruct\n" | "StateStruct\n" | "Struct\n" | "Init\n" | "Accept\n" | "Finish\n" | "bad_alloc\n" | "Struct\n" | "Init\n" | "Finish\n" | "Accept\n" | "bad_alloc\n" | "Struct\n" | "Init\n" | "bad_alloc\n" | "Struct\n" | "Init\n" | "Finish\n" | "Accept\n" | "bad_alloc\n" | "Struct\n" | "Init\n" | "Finish\n" | "Accept"; }%% %% write data; void strs_init( struct strs *fsm ) { %% write init; } void strs_execute( struct strs *fsm, const char *_data, int _len ) { const char *p = _data; const char *pe = _data+_len; %% write exec; } int strs_finish( struct strs *fsm ) { if ( fsm->cs == strs_error ) return -1; if ( fsm->cs >= strs_first_final ) return 1; return 0; } struct strs fsm; void test( char *buf ) { int len = strlen( buf ); strs_init( &fsm ); strs_execute( &fsm, buf, len ); if ( strs_finish( &fsm ) > 0 ) printf("ACCEPT\n"); else printf("FAIL\n"); } int main() { test( "stdin\n" ); test( "bad_alloc\n" ); test( "_GLOBAL_OFFSET_TABLE_\n" ); test( "not in\n" ); test( "isatty\n" "junk on end.\n" ); return 0; } #ifdef _____OUTPUT_____ ACCEPT ACCEPT ACCEPT FAIL FAIL #endif ragel-6.8/test/scan1.rl0000664000175000017500000000162512043335171011732 00000000000000/* * @LANG: indep */ ptr ts; ptr te; int act; int token; %% %%{ machine scanner; # Warning: changing the patterns or the input string will affect the # coverage of the scanner action types. main := |* 'a' => { prints "on last "; if ( p+1 == te ) prints "yes"; prints "\n"; }; 'b'+ => { prints "on next "; if ( p+1 == te ) prints "yes"; prints "\n"; }; 'c1' 'dxxx'? => { prints "on lag "; if ( p+1 == te ) prints "yes"; prints "\n"; }; 'd1' => { prints "lm switch1 "; if ( p+1 == te ) prints "yes"; prints "\n"; }; 'd2' => { prints "lm switch2 "; if ( p+1 == te ) prints "yes"; prints "\n"; }; [d0-9]+ '.'; '\n'; *|; }%% /* _____INPUT_____ "abbc1d1d2\n" _____INPUT_____ */ /* _____OUTPUT_____ on last yes on next yes on lag yes lm switch1 yes lm switch2 yes ACCEPT _____OUTPUT_____ */ ragel-6.8/test/langtrans_d.txl0000664000175000017500000001336212043335171013414 00000000000000include "testcase.txl" define d_statements [repeat d_lang_stmt] end define define d_lang_stmt [al_ragel_stmt] | [d_variable_decl] | [d_expr_stmt] | [d_if_stmt] | [EX] '{ [IN] [NL] [d_statements] [EX] '} [IN] [NL] end define define d_variable_decl [d_type_decl] [id] [opt union] '; [NL] end define define d_type_decl [al_type_decl] | 'char '* end define define d_expr_stmt [d_expr] '; [NL] end define define d_expr [d_term] [repeat d_expr_extend] end define define d_expr_extend [al_expr_op] [d_term] end define define d_term [al_term] | [id] '( [d_args] ') end define define d_args [list d_expr] end define define d_sign '- | '+ end define define d_if_stmt 'if '( [d_expr] ') [NL] [IN] [d_lang_stmt] [EX] [opt d_else] end define define d_else 'else [NL] [IN] [d_lang_stmt] [EX] end define define d_lang [d_statements] '%% [NL] [d_statements] [ragel_def] end define define program [lang_indep] | [d_lang] end define redefine al_host_block '{ [NL] [IN] [al_statements] [EX] '} [NL] | '{ [NL] [IN] [d_statements] [EX] '} [NL] end define rule ptrTypes replace [d_type_decl] 'ptr by 'char '* end rule function alStmtToD1 AlStmt [action_lang_stmt] deconstruct AlStmt VarDecl [al_variable_decl] deconstruct VarDecl Type [al_type_decl] Id [id] OptUnion [opt union] '; construct DType [d_type_decl] Type construct Result [d_variable_decl] DType [ptrTypes] Id OptUnion '; replace [repeat d_lang_stmt] by Result end function rule alTermToD1 replace [al_term] 'first_token_char by 'ts '[0] end rule rule alTermToD2 replace [al_term] '< _ [al_type_decl] '> '( AlExpr [al_expr] ') by '( AlExpr ') end rule function alTermToD replace [al_term] AlTerm [al_term] by AlTerm [alTermToD1] [alTermToD2] end function function alExprExtendToD AlExprExtend [repeat al_expr_extend] deconstruct AlExprExtend Op [al_expr_op] Term [al_term] Rest [repeat al_expr_extend] construct DRest [repeat d_expr_extend] _ [alExprExtendToD Rest] replace [repeat d_expr_extend] by Op Term [alTermToD] DRest end function function alExprToD AlExpr [al_expr] deconstruct AlExpr ALTerm [al_term] AlExprExtend [repeat al_expr_extend] construct DExprExtend [repeat d_expr_extend] _ [alExprExtendToD AlExprExtend] construct Result [opt d_expr] ALTerm [alTermToD] DExprExtend replace [opt d_expr] by Result end function function alStmtToD2 AlStmt [action_lang_stmt] deconstruct AlStmt AlExpr [al_expr] '; construct OptDExpr [opt d_expr] _ [alExprToD AlExpr] deconstruct OptDExpr DExpr [d_expr] replace [repeat d_lang_stmt] by DExpr '; end function function alOptElseD AlOptElse [opt al_else] deconstruct AlOptElse 'else AlSubStmt [action_lang_stmt] construct AlSubStmts [repeat action_lang_stmt] AlSubStmt construct DSubStmts [repeat d_lang_stmt] _ [alToD AlSubStmts] deconstruct DSubStmts DSubStmt [d_lang_stmt] replace [opt d_else] by 'else DSubStmt end function function alStmtToD3 AlStmt [action_lang_stmt] deconstruct AlStmt 'if '( AlExpr [al_expr] ') AlSubStmt [action_lang_stmt] AlOptElse [opt al_else] construct OptDExpr [opt d_expr] _ [alExprToD AlExpr] deconstruct OptDExpr DExpr [d_expr] construct AlSubStmts [repeat action_lang_stmt] AlSubStmt construct DSubStmts [repeat d_lang_stmt] _ [alToD AlSubStmts] deconstruct DSubStmts DSubStmt [d_lang_stmt] construct OptDElse [opt d_else] _ [alOptElseD AlOptElse] replace [repeat d_lang_stmt] by 'if '( DExpr ') DSubStmt OptDElse end function function alStmtToD4a AlStmt [action_lang_stmt] deconstruct AlStmt 'printi Id [id] '; replace [repeat d_lang_stmt] by 'writef '( '"%d" ', Id ') '; end function function alStmtToD4b AlStmt [action_lang_stmt] deconstruct AlStmt 'prints String [stringlit] '; replace [repeat d_lang_stmt] by 'writef '( '"%s" ', String ') '; end function function alStmtToD4c AlStmt [action_lang_stmt] deconstruct AlStmt 'printb Id [id] '; replace [repeat d_lang_stmt] by '_s '= Id '[0..pos] '; 'writef '( '"%s" ', '_s ') '; end function function alStmtToD4d AlStmt [action_lang_stmt] deconstruct AlStmt 'print_token '; replace [repeat d_lang_stmt] by '_s '= ts '[0..(te-ts)] '; 'writef '( '"%s" ', '_s ') '; end function function alStmtToD5 AlStmt [action_lang_stmt] deconstruct AlStmt '{ AlSubStmts [repeat action_lang_stmt] '} construct DSubStmts [repeat d_lang_stmt] _ [alToD AlSubStmts] replace [repeat d_lang_stmt] by '{ DSubStmts '} end function function alStmtToD6 AlStmt [action_lang_stmt] deconstruct AlStmt RagelStmt [al_ragel_stmt] replace [repeat d_lang_stmt] by RagelStmt end function function alToD AlStmts [repeat action_lang_stmt] deconstruct AlStmts FirstStmt [action_lang_stmt] Rest [repeat action_lang_stmt] construct DFirst [repeat d_lang_stmt] _ [alStmtToD1 FirstStmt] [alStmtToD2 FirstStmt] [alStmtToD3 FirstStmt] [alStmtToD4a FirstStmt] [alStmtToD4b FirstStmt] [alStmtToD4c FirstStmt] [alStmtToD4d FirstStmt] [alStmtToD5 FirstStmt] [alStmtToD6 FirstStmt] construct DRest [repeat d_lang_stmt] _ [alToD Rest] replace [repeat d_lang_stmt] by DFirst [. DRest] end function rule actionTransD replace [al_host_block] '{ AlStmts [repeat action_lang_stmt] '} construct DStmts [repeat d_lang_stmt] _ [alToD AlStmts] by '{ DStmts '} end rule function langTransD replace [program] Definitions [repeat action_lang_stmt] '%% Initializations [repeat action_lang_stmt] RagelDef [ragel_def] construct DDefinitions [repeat d_lang_stmt] _ [alToD Definitions] construct DInitializations [repeat d_lang_stmt] _ [alToD Initializations] by DDefinitions '%% DInitializations RagelDef [actionTransD] end function function main replace [program] P [program] by P [langTransD] end function ragel-6.8/test/Makefile.am0000664000175000017500000000417412106050031012411 00000000000000# # Copyright 2002-2009 Adrian Thurston # # This file is part of Ragel. # # Ragel is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # Ragel is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Ragel; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA TESTS = runtests EXTRA_DIST = \ atoi1.rl clang2.rl cond7.rl element3.rl erract8.rl forder3.rl java1.rl \ range.rl scan3.rl xml.rl atoi2.rl clang3.rl cppscan1.rl eofact.rl \ erract9.rl gotocallret1.rl java2.rl recdescent1.rl scan4.rl atoi3.rl \ clang4.rl cppscan2.rl erract1.rl export1.rl gotocallret2.rl keller1.rl \ recdescent2.rl stateact1.rl awkemu.rl cond1.rl cppscan3.rl erract2.rl \ export2.rl high1.rl lmgoto.rl recdescent3.rl statechart1.rl builtin.rl \ cond2.rl cppscan4.rl erract3.rl export3.rl high2.rl mailbox1.rl \ repetition.rl strings1.rl call1.rl cond3.rl cppscan5.rl erract4.rl \ export4.rl high3.rl mailbox2.rl rlscan.rl strings2.rl call2.rl cond4.rl \ cppscan6.rl erract5.rl fnext1.rl import1.rl mailbox3.rl ruby1.rl \ tokstart1.rl call3.rl cond5.rl element1.rl erract6.rl forder1.rl \ include1.rl minimize1.rl scan1.rl union.rl clang1.rl cond6.rl \ element2.rl erract7.rl forder2.rl include2.rl patact.rl scan2.rl \ xmlcommon.rl langtrans_c.sh langtrans_csharp.sh langtrans_d.sh \ langtrans_java.sh langtrans_ruby.sh checkeofact.txl \ langtrans_csharp.txl langtrans_c.txl langtrans_d.txl langtrans_java.txl \ langtrans_ruby.txl testcase.txl cppscan1.h eofact.h mailbox1.h strings2.h CLEANFILES = \ *.c *.cpp *.m *.d *.java *.bin *.class *.exp \ *.out *_c.rl *_d.rl *_java.rl *_ruby.rl *_csharp.rl *.cs \ *_go.rl *.go *.exe ragel-6.8/test/atoi1.rl0000664000175000017500000000126312062515525011744 00000000000000/* * @LANG: indep */ bool neg; int val; %% val = 0; neg = false; %%{ machine AtoI; action begin { neg = false; val = 0; } action see_neg { neg = true; } action add_digit { val = val * 10 + (fc - 48); } action finish { if ( neg ) { val = -1 * val; } } action print { printi val; prints "\n"; } atoi = ( ('-'@see_neg | '+')? (digit @add_digit)+ ) >begin %finish; main := atoi '\n' @print; }%% /* _____INPUT_____ "1\n" "12\n" "222222\n" "+2123\n" "213 3213\n" "-12321\n" "--123\n" "-99\n" " -3000\n" _____INPUT_____ */ /* _____OUTPUT_____ 1 ACCEPT 12 ACCEPT 222222 ACCEPT 2123 ACCEPT FAIL -12321 ACCEPT FAIL -99 ACCEPT FAIL _____OUTPUT_____ */ ragel-6.8/test/cond7.rl0000664000175000017500000000154612043335171011741 00000000000000/* * @LANG: indep */ int i; int c; %% %%{ machine foo; action testi {i > 0} action inc { i = i - 1; c = (fc); prints "item: "; printi c; prints "\n"; } count = [0-9] @{ i = (fc - '0'); prints "count: "; printi i; prints "\n"; }; sub = count # record the number of digits ( digit when testi @inc )* outwhen !testi; main := sub sub '\n'; }%% /* _____INPUT_____ "00\n" "019\n" "190\n" "1719\n" "1040000\n" "104000a\n" "104000\n" _____INPUT_____ */ /* _____OUTPUT_____ count: 0 count: 0 ACCEPT count: 0 count: 1 item: 57 ACCEPT count: 1 item: 57 count: 0 ACCEPT count: 1 item: 55 count: 1 item: 57 ACCEPT count: 1 item: 48 count: 4 item: 48 item: 48 item: 48 item: 48 ACCEPT count: 1 item: 48 count: 4 item: 48 item: 48 item: 48 FAIL count: 1 item: 48 count: 4 item: 48 item: 48 item: 48 FAIL _____OUTPUT_____ */ ragel-6.8/test/rlscan.rl0000664000175000017500000001056012106050031012172 00000000000000/* * Lexes Ragel input files. * * @LANG: c++ * * Test works with split code gen. */ #include #include #include #include using namespace std; void escapeXML( const char *data ) { while ( *data != 0 ) { switch ( *data ) { case '<': cout << "<"; break; case '>': cout << ">"; break; case '&': cout << "&"; break; default: cout << *data; break; } data += 1; } } void escapeXML( char c ) { switch ( c ) { case '<': cout << "<"; break; case '>': cout << ">"; break; case '&': cout << "&"; break; default: cout << c; break; } } void escapeXML( const char *data, int len ) { for ( const char *end = data + len; data != end; data++ ) { switch ( *data ) { case '<': cout << "<"; break; case '>': cout << ">"; break; case '&': cout << "&"; break; default: cout << *data; break; } } } inline void write( const char *data ) { cout << data; } inline void write( char c ) { cout << c; } inline void write( const char *data, int len ) { cout.write( data, len ); } %%{ machine RagelScan; word = [a-zA-Z_][a-zA-Z_0-9]*; integer = [0-9]+; hex = '0x' [0-9a-fA-F] [0-9a-fA-F]*; default = ^0; EOF = 0; # Handles comments in outside code and inline blocks. c_comment := ( default* :>> '*/' ) ${ escapeXML( fc ); } @{ fret; }; action emit { escapeXML( ts, te-ts ); } # # Inline action code # ilscan := |* "'" ( [^'\\] | /\\./ )* "'" => emit; '"' ( [^"\\] | /\\./ )* '"' => emit; '/*' { write( "/*" ); fcall c_comment; }; '//' [^\n]* '\n' => emit; '{' { write( '{' ); inline_depth += 1; }; '}' { write( '}' ); /* If dropping down to the last } then return * to ragel code. */ if ( --inline_depth == 0 ) { write( "\n" ); fgoto rlscan; } }; default => { escapeXML( *ts ); }; *|; # # Ragel Tokens # rlscan := |* '}%%' { if ( !single_line ) { write( "\n" ); fgoto main; } }; '\n' { if ( single_line ) { write( "\n" ); fgoto main; } }; # Word word { write( "" ); write( ts, te-ts ); write( "\n" ); }; # Decimal integer. integer { write( "" ); write( ts, te-ts ); write( "\n" ); }; # Hexidecimal integer. hex { write( "" ); write( ts, te-ts ); write( "\n" ); }; # Consume comments. '#' [^\n]* '\n'; # Single literal string. "'" ( [^'\\] | /\\./ )* "'" { write( "" ); escapeXML( ts, te-ts ); write( "\n" ); }; # Double literal string. '"' ( [^"\\] | /\\./ )* '"' { write( "" ); escapeXML( ts, te-ts ); write( "\n" ); }; # Or literal. '[' ( [^\]\\] | /\\./ )* ']' { write( "" ); escapeXML( ts, te-ts ); write( "\n" ); }; # Regex Literal. '/' ( [^/\\] | /\\./ ) * '/' { write( "" ); escapeXML( ts, te-ts ); write( "\n" ); }; # Open an inline block '{' { inline_depth = 1; write( "{" ); fgoto ilscan; }; punct { write( "" ); escapeXML( fc ); write( "\n" ); }; default; *|; # # Outside code. # main := |* "'" ( [^'\\] | /\\./ )* "'" => emit; '"' ( [^"\\] | /\\./ )* '"' => emit; '/*' { escapeXML( ts, te-ts ); fcall c_comment; }; '//' [^\n]* '\n' => emit; '%%{' { write( "
\n" ); single_line = false; fgoto rlscan; }; '%%' { write( "
\n" ); single_line = true; fgoto rlscan; }; default { escapeXML( *ts ); }; # EOF. EOF; *|; }%% %% write data nofinal; void test( const char *data ) { std::ios::sync_with_stdio(false); int cs, act; const char *ts, *te; int stack[1], top; bool single_line = false; int inline_depth = 0; %% write init; /* Read in a block. */ const char *p = data; const char *pe = data + strlen( data ); const char *eof = pe; %% write exec; if ( cs == RagelScan_error ) { /* Machine failed before finding a token. */ cerr << "PARSE ERROR" << endl; exit(1); } } #define BUFSIZE 2048 int main() { std::ios::sync_with_stdio(false); test("hi %%{ /'}%%'/ { /*{*/ {} } + '\\'' }%%there\n"); return 0; } #ifdef _____OUTPUT_____ hi
/'}%%'/ { /*{*/ {} } + '\''
there #endif ragel-6.8/test/mailbox1.rl0000664000175000017500000001215712043335171012443 00000000000000/* * @LANG: c++ * @CFLAGS: -I../aapl * * Test works with split code gen. */ /* * Parses unix mail boxes into headers and bodies. */ #include "mailbox1.h" %%{ machine MBox; # Buffer the header names. action bufHeadName { fsm->headName.append(fc); } # Buffer the header content. action bufHeadContent { fsm->headContent.append(fc); } # Terminate a header. If it is an interesting header then prints it. action finBufHeadContent { /* Terminate the buffers. */ fsm->headName.append(0); fsm->headContent.append(0); /* Print the header. Interesting headers. */ printf("%s:%s\n", fsm->headName.data, fsm->headContent.data); /* Clear for the next time we use them. */ fsm->headName.empty(); fsm->headContent.empty(); } action msgstart{ printf("NEW MESSAGE\n"); } # Prints a blank line after the end of the headers of each message. action blankLine { printf("\n"); } # Helpers we will use in matching the date section of the from line. day = /[A-Z][a-z][a-z]/; month = /[A-Z][a-z][a-z]/; year = /[0-9][0-9][0-9][0-9]/; time = /[0-9][0-9]:[0-9][0-9]/ . ( /:[0-9][0-9]/ | '' ); letterZone = /[A-Z][A-Z][A-Z]/; numZone = /[+\-][0-9][0-9][0-9][0-9]/; zone = letterZone | numZone; dayNum = /[0-9 ][0-9]/; # These are the different formats of the date minus an obscure # type that has a funny string 'remote from xxx' on the end. Taken # from c-client in the imap-2000 distribution. date = day . ' ' . month . ' ' . dayNum . ' ' . time . ' ' . ( year | year . ' ' . zone | zone . ' ' . year ); # Note the priority assignment on the end of the from line. While we # matching the body of a message we may enter into this machine. We will # not leave the body of the previous message until this entire from line is # matched. fromLine = 'From ' . /[^\n]/* . ' ' . date . '\n' @(new_msg,1) @msgstart; # The types of characters that can be used as a header name. hchar = print - [ :]; header = # The name of the header. hchar+ $bufHeadName . ':' # The content of the header. Look out for continuations. . ( (extend - '\n') $bufHeadContent | '\n'. [ \t] @bufHeadContent )* # Buffer must end with a newline that does not continue. . '\n' %finBufHeadContent; messageLine = ( extend - '\n' )* . '\n' @(new_msg, 0); # When we get to the last newline we are still matching messageLine # so on the last newline it will think we are still in the message. # We need this because we can't assume that every newline means # the end of the current message, whereas at the same time we requre # that there be a newline before the fromLine of the next message. message = ( fromLine . header* . '\n' @blankLine . messageLine* . '\n' ); # Its important that the priority in the fromLine gets bumped up # so that we are able to move to new messages. Otherwise we # will always stay in the message body of the first message. main := message*; }%% %% write data; void MBox::init( ) { MBox *fsm = this; %% write init; } void MBox::execute( const char *data, int len ) { MBox *fsm = this; const char *p = data; const char *pe = data + len; %%{ access fsm->; write exec; }%% } int MBox::finish( ) { if ( cs == MBox_error ) return -1; if ( cs >= MBox_first_final ) return 1; return 0; } MBox mbox; void test( const char *buf ) { int len = strlen( buf ); mbox.init(); mbox.execute( buf, len ); if ( mbox.finish() > 0 ) printf("ACCEPT\n"); else printf("FAIL\n"); } int main() { test( "From email address goes here Wed Nov 28 13:30:05 2001 -0500\n" "Header1: this is the header contents\n" " there is more on the second line\n" " and more on the third line.\n" "Header2: slkdj\n" "\n" "This is the message data\n" "\n" "From email Wed Nov 28 13:30:05 2001 -0500\n" "Header: \n" "\n" "mail message\n" "\n" ); test( "From user@host.dom Wed Nov 28 13:30:05 2001\n" "\n" "There are no headers. \n" "\n" "From email Wed Nov 28 13:30:05 EST 2000\n" "\n" "There are no headers.\n" "\n" ); test( "From user@host.dom Wed Nov 28 13:30:05 2001\n" "Header:alsdj\n" "\n" "Header:\n" "salkfj\n" "\n" "There are no headers. \n" "\n" ); test( "From user@host.dom Wed Nov 28 13:30:05 2001\n" "Header:alsdj\n" "\n" "Header:\n" "salkfj\n" "\n" "There are no headers. \n" "\n" ">From user@host.dom Wed Nov 28 13:30:05 2001\n" "\n" ); test( "From user@host.dom Wed Nov 28 13:30:05 2001\n" "Header:alsdj\n" "\n" "Header:\n" "salkfj\n" "\n" "There are no headers. \n" "\n" "From user@host.dom Wed Nov 28 13:30:05 2001\n" "\n" ); test( "From user@host.dom Wed Nov 28 13:30:05 2001\n" "Header:alsdj\n" "\n" "Header:\n" "salkfj\n" "\n" "There are no headers. \n" "\n" "From user@host.dom Wed Nov 28 13:30:05 2001\n" "\n" "\n" ); return 0; } #ifdef _____OUTPUT_____ NEW MESSAGE Header1: this is the header contents there is more on the second line and more on the third line. Header2: slkdj NEW MESSAGE Header: ACCEPT NEW MESSAGE NEW MESSAGE ACCEPT NEW MESSAGE Header:alsdj ACCEPT NEW MESSAGE Header:alsdj ACCEPT NEW MESSAGE Header:alsdj NEW MESSAGE FAIL NEW MESSAGE Header:alsdj NEW MESSAGE ACCEPT #endif ragel-6.8/test/repetition.rl0000664000175000017500000000431612043335171013107 00000000000000/* * @LANG: c++ */ /* Test repeptition operators. */ #include #include #include #include using namespace std; struct Rep { int cs; int init( ); int execute( const char *data, int len ); int finish( ); }; %%{ machine Rep; action begin { cout << "begin" << endl; } action in { cout << "in" << endl; } action end { cout << "end" << endl; } a = 'a' >begin @in %end; b = 'b' >begin @in %end; c = 'c' >begin @in %end; d = 'd' >begin @in %end; main := ( a {5} '\n' )* '-\n' ( b {,5} '\n' )* '-\n' ( c {5,} '\n' )* '-\n' ( d {2,5} '\n' )*; }%% %% write data; int Rep::init( ) { %% write init; return 1; } int Rep::execute( const char *_data, int _len ) { const char *p = _data; const char *pe = _data+_len; %% write exec; if ( cs == Rep_error ) return -1; if ( cs >= Rep_first_final ) return 1; return 0; } int Rep::finish( ) { if ( cs == Rep_error ) return -1; if ( cs >= Rep_first_final ) return 1; return 0; } void test( const char *buf ) { Rep rep; int len = strlen( buf ); rep.init(); rep.execute( buf, len ); if ( rep.finish() > 0 ) printf("ACCEPT\n"); else printf("FAIL\n"); } int main() { test( "aaaaa\n" "-\n" "\n" "b\n" "bb\n" "bbb\n" "bbbb\n" "bbbbb\n" "-\n" "ccccc\n" "ccccccc\n" "cccccccccc\n" "-\n" "dd\n" "ddd\n" "dddd\n" "ddddd\n" ); test( "a\n" "-\n" "b\n" "-\n" "c\n" "-\n" "d\n" ); return 0; } #ifdef _____OUTPUT_____ begin in end begin in end begin in end begin in end begin in end begin in end begin in end begin in end begin in end begin in end begin in end begin in end begin in end begin in end begin in end begin in end begin in end begin in end begin in end begin in end begin in end begin in end begin in end begin in end begin in end begin in end begin in end begin in end begin in end begin in end begin in end begin in end begin in end begin in end begin in end begin in end begin in end begin in end begin in end begin in end begin in end begin in end begin in end begin in end begin in end begin in end begin in end begin in end begin in end begin in end begin in end begin in end begin in end begin in end begin in end begin in end ACCEPT begin in FAIL #endif ragel-6.8/test/high3.rl0000664000175000017500000000362612043335171011732 00000000000000/* * @LANG: obj-c */ /** * Test a high character to make sure signedness * isn't messing us up. */ #include #include @interface Fsm : Object { @public int cs; }; // Initialize the machine. Invokes any init statement blocks. Returns 0 // if the machine begins in a non-accepting state and 1 if the machine // begins in an accepting state. - (int) initFsm; // Execute the machine on a block of data. Returns -1 if after processing // the data, the machine is in the error state and can never accept, 0 if // the machine is in a non-accepting state and 1 if the machine is in an // accepting state. - (void) executeWithData:(const unsigned char *)data len:(int)len; // Indicate that there is no more data. Returns -1 if the machine finishes // in the error state and does not accept, 0 if the machine finishes // in any other non-accepting state and 1 if the machine finishes in an // accepting state. - (int) finish; @end @implementation Fsm %%{ machine Fsm; alphtype unsigned char; # Indicate we got the high character. action gothigh { printf("yes\n"); } main := 0xe8 @gothigh '\n'; }%% %% write data; - (int) initFsm; { %% write init; return 1; } - (void) executeWithData:(const unsigned char *)_data len:(int)_len; { const unsigned char *p = _data; const unsigned char *pe = _data + _len; %% write exec; } - (int) finish; { if ( cs == Fsm_error ) return -1; else if ( cs >= Fsm_first_final ) return 1; return 0; } @end #define BUFSIZE 2048 Fsm *fsm; unsigned char buf[BUFSIZE]; void test( unsigned char *buf, int len ) { fsm = [[Fsm alloc] init]; [fsm initFsm]; [fsm executeWithData:buf len:len]; if ( [fsm finish] > 0 ) printf("ACCEPT\n"); else printf("FAIL\n"); } unsigned char data1[] = { 0xe8, 10 }; unsigned char data2[] = { 0xf8, 10 }; int main() { test( data1, 2 ); test( data2, 2 ); return 0; } #ifdef _____OUTPUT_____ yes ACCEPT FAIL #endif ragel-6.8/test/erract7.rl0000664000175000017500000000104512043335171012270 00000000000000/* * @LANG: c */ #include #include %%{ machine foo; action on_char { printf("char: %c\n", *p); } action on_err { printf("err: %c\n", *p); } action to_state { printf("to state: %c\n", *p); } main := 'heXXX' $on_char $err(on_err) $to(to_state); }%% %% write data; int main() { int cs; char *p = "hello", *pe = p + strlen(p); char *eof = pe; %%{ write init; write exec; }%% printf( "rest: %s\n", p ); return 0; } #ifdef _____OUTPUT_____ char: h to state: h char: e to state: e err: l rest: llo #endif ragel-6.8/test/erract3.rl0000664000175000017500000000252012043335171012263 00000000000000/* * @LANG: c */ #include #define IDENT_BUFLEN 256 struct erract { int cs; }; %%{ machine erract; variable cs fsm->cs; # The data that is to go into the fsm structure. action hello_fails { printf("hello fails\n");} newline = ( any | '\n' @{printf("newline\n");} )*; hello = 'hello\n'* $lerr hello_fails @eof hello_fails; main := newline | hello; }%% %% write data; void erract_init( struct erract *fsm ) { %% write init; } void erract_execute( struct erract *fsm, const char *_data, int _len ) { const char *p = _data; const char *pe = _data+_len; const char *eof = pe; %% write exec; } int erract_finish( struct erract *fsm ) { if ( fsm->cs == erract_error ) return -1; else if ( fsm->cs >= erract_first_final ) return 1; return 0; } #include #include struct erract fsm; void test( char *buf ) { int len = strlen(buf); erract_init( &fsm ); erract_execute( &fsm, buf, len ); if ( erract_finish( &fsm ) > 0 ) printf("ACCEPT\n"); else printf("FAIL\n"); } int main() { test( "hello\n" "hello\n" "hello\n" ); test( "hello\n" "hello\n" "hello there\n" ); test( "hello\n" "hello\n" "he" ); test( "" ); return 0; } #ifdef _____OUTPUT_____ newline newline newline ACCEPT newline newline hello fails newline ACCEPT newline newline hello fails ACCEPT ACCEPT #endif ragel-6.8/test/atoi2.rl0000664000175000017500000000171612043335171011744 00000000000000/* * @LANG: indep * This implementes an atoi machine using the statechart paradigm. */ bool neg; int val; %% val = 0; neg = false; %%{ machine StateChart; action begin { neg = false; val = 0; } action see_neg { neg = true; } action add_digit { val = val * 10 + (fc - 48); } action finish { if ( neg ) val = -1 * val; } atoi = ( start: ( '-' @see_neg ->om_num | '+' ->om_num | [0-9] @add_digit ->more_nums ), # One or more nums. om_num: ( [0-9] @add_digit ->more_nums ), # Zero ore more nums. more_nums: ( [0-9] @add_digit ->more_nums | '' -> final ) ) >begin %finish; action oneof { printi val; prints "\n"; } main := ( atoi '\n' @oneof )*; }%% /* _____INPUT_____ "1\n" "12\n" "222222\n" "+2123\n" "213 3213\n" "-12321\n" "--123\n" "-99\n" " -3000\n" _____INPUT_____ */ /* _____OUTPUT_____ 1 ACCEPT 12 ACCEPT 222222 ACCEPT 2123 ACCEPT FAIL -12321 ACCEPT FAIL -99 ACCEPT FAIL _____OUTPUT_____ */ ragel-6.8/test/langtrans_csharp.sh0000775000175000017500000000354412043335171014260 00000000000000#!/bin/bash # file=$1 [ -f $file ] || exit 1 root=${file%.rl} class=${root}_csharp # Make a temporary version of the test case using the Java language translations. sed -n '/\/\*/,/\*\//d;p' $file | txl -q stdin langtrans_csharp.txl - $class > $file.pr # Begin writing out the test case. cat << EOF /* * @LANG: csharp * @GENERATED: yes EOF grep '@ALLOW_GENFLAGS:' $file | sed 's/-G2//g' grep '@ALLOW_MINFLAGS:' $file cat << EOF */ using System; // Disables lots of warnings that appear in the test suite #pragma warning disable 0168, 0169, 0219, 0162, 0414 namespace Test { class $class { EOF # Write the data declarations sed -n '/^%%$/q;{s/^/\t/;p}' $file.pr # Write out the machine specification. sed -n '/^%%{$/,/^}%%/{s/^/\t/;p}' $file.pr # Write out the init and execute routines. cat << EOF int cs; %% write data; void init() { EOF sed -n '0,/^%%$/d; /^%%{$/q; {s/^/\t\t/;p}' $file.pr cat << EOF %% write init; } void exec( char[] data, int len ) { int p = 0; int pe = len; int eof = len; string _s; %% write exec; } void finish( ) { if ( cs >= ${class}_first_final ) Console.WriteLine( "ACCEPT" ); else Console.WriteLine( "FAIL" ); } EOF # Write out the test data. sed -n '0,/\/\* _____INPUT_____/d; /_____INPUT_____ \*\//q; p;' $file | awk ' BEGIN { print " static readonly string[] inp = {" } { print " " $0 "," } END { print " };" print "" print " static readonly int inplen = " NR ";" }' # Write out the main routine. cat << EOF public static void Main (string[] args) { $class machine = new $class(); for ( int i = 0; i < inplen; i++ ) { machine.init(); machine.exec( inp[i].ToCharArray(), inp[i].Length ); machine.finish(); } } } } EOF # Write out the expected output. sed -n '/\/\* _____OUTPUT_____/,/_____OUTPUT_____ \*\//p;' $file # Don't need this language-specific file anymore. rm $file.pr ragel-6.8/test/eofact.rl0000664000175000017500000000076512043335171012172 00000000000000/* * @LANG: indep * * Test works with split code gen. */ %% %%{ machine eofact; action a1 { prints "a1\n"; } action a2 { prints "a2\n"; } action a3 { prints "a3\n"; } action a4 { prints "a4\n"; } main := ( 'hello' @eof a1 %eof a2 '\n'? | 'there' @eof a3 %eof a4 ); }%% /* _____INPUT_____ "" "h" "hell" "hello" "hello\n" "t" "ther" "there" "friend" _____INPUT_____ */ /* _____OUTPUT_____ a1 a3 FAIL a1 FAIL a1 FAIL a2 ACCEPT ACCEPT a3 FAIL a3 FAIL a4 ACCEPT FAIL _____OUTPUT_____ */ ragel-6.8/test/cond1.rl0000664000175000017500000000170312043335171011726 00000000000000/* * @LANG: indep * @ALLOW_GENFLAGS: -T0 -T1 -G0 -G1 -G2 */ bool i; bool j; bool k; %% %%{ machine foo; action c1 {i} action c2 {j} action c3 {k} action one { prints " one\n";} action two { prints " two\n";} action three { prints " three\n";} action seti { if ( fc == 48 ) i = false; else i = true; } action setj { if ( fc == 48 ) j = false; else j = true; } action setk { if ( fc == 48 ) k = false; else k = true; } action break {fbreak;} one = 'a' 'b' when c1 'c' @one; two = 'a'* 'b' when c2 'c' @two; three = 'a'+ 'b' when c3 'c' @three; main := [01] @seti [01] @setj [01] @setk ( one | two | three ) '\n' @break; }%% /* _____INPUT_____ "000abc\n" "100abc\n" "010abc\n" "110abc\n" "001abc\n" "101abc\n" "011abc\n" "111abc\n" _____INPUT_____ */ /* _____OUTPUT_____ FAIL one ACCEPT two ACCEPT one two ACCEPT three ACCEPT one three ACCEPT two three ACCEPT one two three ACCEPT _____OUTPUT_____ */ ragel-6.8/test/clang3.rl0000664000175000017500000001564212043335171012100 00000000000000/* * @LANG: d * A mini C-like language scanner. */ module clang; import std.c.stdio; char[] string(char c) { char[] result = new char[2]; result[0] = c; result[1] = 0; return result[0 .. 1]; } class CLang { /* Parsing data. */ char[] identBuf; int curLine; this() { } /* State machine operation data. */ int cs; %%{ machine clang; # Function to buffer a character. action bufChar { identBuf ~= fc; } # Function to clear the buffer. action clearBuf { identBuf = null; } # Functions to dump tokens as they are matched. action ident { printf("ident(%i): %.*s\n", curLine, identBuf); } action literal { printf("literal(%i): %.*s\n", curLine, identBuf); } action float { printf("float(%i): %.*s\n", curLine, identBuf); } action int { printf("int(%i): %.*s\n", curLine, identBuf); } action hex { printf("hex(%i): 0x%.*s\n", curLine, identBuf); } action symbol { printf("symbol(%i): %.*s\n", curLine, identBuf); } # Alpha numberic characters or underscore. alnumu = alnum | '_'; # Alpha charactres or underscore. alphau = alpha | '_'; # Symbols. Upon entering clear the buffer. On all transitions # buffer a character. Upon leaving dump the symbol. symbol = ( punct - [_'"] ) >clearBuf $bufChar %symbol; # Identifier. Upon entering clear the buffer. On all transitions # buffer a character. Upon leaving, dump the identifier. ident = (alphau . alnumu*) >clearBuf $bufChar %ident; # Match single characters inside literal strings. Or match # an escape sequence. Buffers the charater matched. sliteralChar = ( extend - ['\\] ) @bufChar | ( '\\' . extend @bufChar ); dliteralChar = ( extend - ["\\] ) @bufChar | ( '\\' . extend @bufChar ); # Single quote and double quota literals. At the start clear # the buffer. Upon leaving dump the literal. sliteral = ('\'' @clearBuf . sliteralChar* . '\'' ) %literal; dliteral = ('"' @clearBuf . dliteralChar* . '"' ) %literal; literal = sliteral | dliteral; # Whitespace is standard ws, newlines and control codes. whitespace = any - 0x21..0x7e; # Describe both c style comments and c++ style comments. The # priority bump on tne terminator of the comments brings us # out of the extend* which matches everything. ccComment = '//' . extend* $0 . '\n' @1; cComment = '/*' . extend* $0 . '*/' @1; # Match an integer. We don't bother clearing the buf or filling it. # The float machine overlaps with int and it will do it. int = digit+ %int; # Match a float. Upon entering the machine clear the buf, buffer # characters on every trans and dump the float upon leaving. float = ( digit+ . '.' . digit+ ) >clearBuf $bufChar %float; # Match a hex. Upon entering the hex part, clear the buf, buffer characters # on every trans and dump the hex on leaving transitions. hex = '0x' . xdigit+ >clearBuf $bufChar %hex; # Or together all the lanuage elements. fin = ( ccComment | cComment | symbol | ident | literal | whitespace | int | float | hex ); # Star the language elements. It is critical in this type of application # that we decrease the priority of out transitions before doing so. This # is so that when we see 'aa' we stay in the fin machine to match an ident # of length two and not wrap around to the front to match two idents of # length one. clang_main = ( fin $1 %0 )*; # This machine matches everything, taking note of newlines. newline = ( any | '\n' @{ curLine++; } )*; # The final fsm is the lexer intersected with the newline machine which # will count lines for us. Since the newline machine accepts everything, # the strings accepted is goverened by the clang_main machine, onto which # the newline machine overlays line counting. main := clang_main & newline; }%% %% write data noprefix; // Initialize the machine. Invokes any init statement blocks. Returns 0 // if the machine begins in a non-accepting state and 1 if the machine // begins in an accepting state. void init( ) { curLine = 1; %% write init; } // Execute the machine on a block of data. Returns -1 if after processing // the data, the machine is in the error state and can never accept, 0 if // the machine is in a non-accepting state and 1 if the machine is in an // accepting state. void execute( char* _data, int _len ) { char *p = _data; char *pe = _data + _len; char *eof = pe; %% write exec; } // Indicate that there is no more data. Returns -1 if the machine finishes // in the error state and does not accept, 0 if the machine finishes // in any other non-accepting state and 1 if the machine finishes in an // accepting state. int finish( ) { if ( cs == error ) return -1; if ( cs >= first_final ) return 1; return 0; } } static const int BUFSIZE = 1024; void test( char buf[] ) { CLang scanner = new CLang(); scanner.init(); scanner.execute( buf.ptr, buf.length ); if ( scanner.finish() > 0 ) printf("ACCEPT\n"); else printf("FAIL\n"); return 0; } int main() { test( "999 0xaAFF99 99.99 /*\n" "*/ 'lksdj' //\n" "\"\n" "\n" "literal\n" "\n" "\n" "\"0x00aba foobardd.ddsf 0x0.9\n" ); test( "wordwithnum00asdf\n" "000wordfollowsnum,makes new symbol\n" "\n" "finishing early /* unfinished ...\n" ); test( "/*\n" " * Copyright\n" " */\n" "\n" "/* Aapl.\n" " */\n" " \n" "#define _AAPL_RESIZE_H\n" "\n" "#include \n" "\n" "#ifdef AAPL_NAMESPACE\n" "namespace Aapl {\n" "#endif\n" "#define LIN_DEFAULT_STEP 256\n" "#define EXPN_UP( existing, needed ) \\\n" " need > eng ? (ned<<1) : eing\n" " \n" "\n" "/*@}*/\n" "#undef EXPN_UP\n" "#ifdef AAPL_NAMESPACE\n" "#endif /* _AAPL_RESIZE_H */\n" ); return 0; } /+ _____OUTPUT_____ int(1): 999 hex(1): 0xaAFF99 float(1): 99.99 literal(2): lksdj literal(8): literal hex(8): 0x00aba ident(8): foobardd symbol(8): . ident(8): ddsf hex(8): 0x0 symbol(8): . int(8): 9 ACCEPT ident(1): wordwithnum00asdf int(2): 000 ident(2): wordfollowsnum symbol(2): , ident(2): makes ident(2): new ident(2): symbol ident(4): finishing ident(4): early FAIL symbol(8): # ident(8): define ident(8): _AAPL_RESIZE_H symbol(10): # ident(10): include symbol(10): < ident(10): assert symbol(10): . ident(10): h symbol(10): > symbol(12): # ident(12): ifdef ident(12): AAPL_NAMESPACE ident(13): namespace ident(13): Aapl symbol(13): { symbol(14): # ident(14): endif symbol(15): # ident(15): define ident(15): LIN_DEFAULT_STEP int(15): 256 symbol(16): # ident(16): define ident(16): EXPN_UP symbol(16): ( ident(16): existing symbol(16): , ident(16): needed symbol(16): ) symbol(16): \ ident(17): need symbol(17): > ident(17): eng symbol(17): ? symbol(17): ( ident(17): ned symbol(17): < symbol(17): < int(17): 1 symbol(17): ) symbol(17): : ident(17): eing symbol(21): # ident(21): undef ident(21): EXPN_UP symbol(22): # ident(22): ifdef ident(22): AAPL_NAMESPACE symbol(23): # ident(23): endif ACCEPT ++++++++++++++++/ ragel-6.8/test/checkeofact.txl0000664000175000017500000000270612043335171013357 00000000000000include "testcase.txl" define program [lang_indep] | 'yes | 'no end define rule findEof1 match [machine_expr_item] '>/ end rule rule findEof2 match [machine_expr_item] '/ end rule rule findEof7 match [repeat machine_expr_item] '> 'eof _ [repeat machine_expr_item] end rule rule findEof8 match [repeat machine_expr_item] '< 'eof _ [repeat machine_expr_item] end rule rule findEof9 match [repeat machine_expr_item] '$ 'eof _ [repeat machine_expr_item] end rule rule findEof10 match [repeat machine_expr_item] '% 'eof _ [repeat machine_expr_item] end rule rule findEof11 match [repeat machine_expr_item] '@ 'eof _ [repeat machine_expr_item] end rule rule findEof12 match [repeat machine_expr_item] '<> 'eof _ [repeat machine_expr_item] end rule rule findScanner match [machine_expr_item] '|* _ [repeat scanner_item] '*| end rule function findEof P [program] replace [program] _ [program] where P [findEof1] [findEof2] [findEof3] [findEof4] [findEof5] [findEof6] [findEof7] [findEof8] [findEof9] [findEof10] [findEof11] [findEof12] [findScanner] by 'yes end function function main replace [program] P [program] construct NewP [program] 'no by NewP [findEof P] end function ragel-6.8/test/cppscan1.h0000664000175000017500000000503312043335171012244 00000000000000#ifndef _CPPSCAN1_H #define _CPPSCAN1_H #include #include #include using namespace std; #define BUFSIZE 2048 #define TK_Dlit 192 #define TK_Slit 193 #define TK_Float 194 #define TK_Id 195 #define TK_NameSep 197 #define TK_Arrow 211 #define TK_PlusPlus 212 #define TK_MinusMinus 213 #define TK_ArrowStar 214 #define TK_DotStar 215 #define TK_ShiftLeft 216 #define TK_ShiftRight 217 #define TK_IntegerDecimal 218 #define TK_IntegerOctal 219 #define TK_IntegerHex 220 #define TK_EqualsEquals 223 #define TK_NotEquals 224 #define TK_AndAnd 225 #define TK_OrOr 226 #define TK_MultAssign 227 #define TK_DivAssign 228 #define TK_PercentAssign 229 #define TK_PlusAssign 230 #define TK_MinusAssign 231 #define TK_AmpAssign 232 #define TK_CaretAssign 233 #define TK_BarAssign 234 #define TK_DotDotDot 240 /* A growable buffer for collecting headers. */ struct Buffer { Buffer() : data(0), allocated(0), length(0) { } Buffer( const Buffer &other ) { data = (char*)malloc( other.allocated ); memcpy( data, other.data, other.length ); allocated = other.allocated; length = other.length; } ~Buffer() { empty(); } void append( char p ) { if ( ++length > allocated ) upAllocate( length*2 ); data[length-1] = p; } void append( char *str, int len ) { if ( (length += len) > allocated ) upAllocate( length*2 ); memcpy( data+length-len, str, len ); } void clear() { length = 0; } void upAllocate( int len ); void empty(); char *data; int allocated; int length; }; struct Scanner { Scanner( std::ostream &out ) : out(out) { } std::ostream &out; int line, col; int tokStart; int inlineDepth; int count; Buffer tokBuf; Buffer nonTokBuf; void pass(char c) { nonTokBuf.append(c); } void buf(char c) { tokBuf.append(c); } void token( int id ); int cs, stack, top; // Initialize the machine. Invokes any init statement blocks. Returns 0 // if the machine begins in a non-accepting state and 1 if the machine // begins in an accepting state. void init( ); // Execute the machine on a block of data. Returns -1 if after processing // the data, the machine is in the error state and can never accept, 0 if // the machine is in a non-accepting state and 1 if the machine is in an // accepting state. int execute( const char *data, int len ); // Indicate that there is no more data. Returns -1 if the machine finishes // in the error state and does not accept, 0 if the machine finishes // in any other non-accepting state and 1 if the machine finishes in an // accepting state. int finish( ); }; #endif ragel-6.8/test/element1.rl0000664000175000017500000000335512043335171012441 00000000000000/* * @LANG: c++ */ #include using namespace std; struct LangEl { int key; const char *name; }; struct Fsm { int cs; // Initialize the machine. Invokes any init statement blocks. Returns 0 // if the machine begins in a non-accepting state and 1 if the machine // begins in an accepting state. int init( ); // Execute the machine on a block of data. Returns -1 if after processing // the data, the machine is in the error state and can never accept, 0 if // the machine is in a non-accepting state and 1 if the machine is in an // accepting state. int execute( LangEl *data, int len ); // Indicate that there is no more data. Returns -1 if the machine finishes // in the error state and does not accept, 0 if the machine finishes // in any other non-accepting state and 1 if the machine finishes in an // accepting state. int finish( ); }; %%{ machine Fsm; alphtype int; getkey fpc->key; variable eof eof_marker; action a1 {} action a2 {} action a3 {} main := ( 1 2* 3 ) ${cout << fpc->name << endl;} %/{cout << "accept" << endl;}; }%% %% write data; int Fsm::init( ) { %% write init; return 0; } int Fsm::execute( LangEl *data, int len ) { LangEl *p = data; LangEl *pe = data + len; LangEl *eof_marker = pe; %% write exec; if ( cs == Fsm_error ) return -1; if ( cs >= Fsm_first_final ) return 1; return 0; } int Fsm::finish( ) { if ( cs == Fsm_error ) return -1; if ( cs >= Fsm_first_final ) return 1; return 0; } int main( ) { static Fsm fsm; static LangEl lel[] = { {1, "one"}, {2, "two-a"}, {2, "two-b"}, {2, "two-c"}, {3, "three"} }; fsm.init(); fsm.execute( lel, 5 ); fsm.finish(); return 0; } #ifdef _____OUTPUT_____ one two-a two-b two-c three accept #endif ragel-6.8/test/testcase.txl0000664000175000017500000000620512061772177012744 00000000000000comments '# end comments tokens union "\[[(\\\c)#\]]*\]" end tokens compounds '%% '%%{ '}%% '== ':= '-> '<> '>= '<= '=> '|* '*| '>! '! '>/ '/ end compounds keys 'int 'bool 'true 'false 'char 'ptr 'if 'else 'printi 'prints 'printb 'print_token 'fc 'fpc 'fbreak 'fgoto 'fcall 'fret 'fhold 'fexec 'machine 'alphtype 'action 'first_token_char end keys define lang_indep [al_statements] '%% [NL] [al_statements] [ragel_def] end define define ragel_def '%%{ [NL] [IN] [ragel_program] [EX] '}%% [NL] end define define ragel_program [repeat statement] end define define statement [machine_stmt] | [alphtype_stmt] | [action_stmt] | [cond_action_stmt] | [machine_def] | [machine_inst] end define define machine_stmt 'machine [id] '; [NL] end define define alphtype_stmt 'alphtype [repeat id] '; [NL] end define define action_stmt 'action [id] [al_host_block] end define define cond_action_stmt 'action [id] '{ [al_expr] '} [NL] end define define al_statements [repeat action_lang_stmt] end define define action_lang_stmt [al_ragel_stmt] | [al_variable_decl] | [al_expr_stmt] | [al_if_stmt] | [al_print_stmt] | '{ [al_statements] '} end define define al_print_stmt [print_cmd] [al_expr] '; [NL] | 'print_token '; [NL] end define define print_cmd 'printi | 'prints | 'printb end define define al_variable_decl [al_type_decl] [id] [opt union] '; [NL] end define define al_array_decl '[ [number] '] end define define al_type_decl 'int | 'bool | 'char | 'ptr end define define al_expr_stmt [al_expr] '; [NL] end define define al_expr [al_term] [repeat al_expr_extend] end define define al_expr_extend [al_expr_op] [al_term] end define define al_expr_op '= | '+ | '- | '* | '/ | '== | '<= | '>= | '< | '> end define define al_term [al_term_base] [opt union] end define define al_term_base [id] | [SPOFF] [id] '( [SPON] [al_expr] ') | [opt al_sign] [number] | [stringlit] | [charlit] | 'fc | 'true | 'false | '( [al_expr] ') | '< [SPOFF] [al_type_decl] '> '( [SPON] [al_expr] ') | 'first_token_char end define define al_sign '- | '+ end define define al_if_stmt 'if '( [al_expr] ') [NL] [IN] [action_lang_stmt] [EX] [opt al_else] end define define al_else 'else [NL] [IN] [action_lang_stmt] [EX] end define define al_ragel_stmt 'fbreak '; [NL] | 'fhold '; [NL] | 'fexec [repeat al_expr] '; [NL] | 'fnext [id] '; [NL] | 'fgoto [id] '; [NL] | 'fcall [id] '; [NL] | 'fnext '* [repeat al_expr] '; [NL] | 'fgoto '* [repeat al_expr] '; [NL] | 'fcall '* [repeat al_expr] '; [NL] | 'fret '; [NL] end define define machine_def [id] '= [machine_expr] '; [NL] end define define machine_inst [id] ':= [machine_expr] '; [NL] end define define machine_expr [repeat machine_expr_item] end define define scanner_item [repeat machine_expr_item] '; [NL] end define define machine_expr_item [action_embed] [al_host_block] | '|* [repeat scanner_item] '*| | [not ';] [not '*|] [token] end define define al_host_block '{ [NL] [IN] [al_statements] [EX] '} [NL] end define define action_embed '> | '$ | '@ | '% | '$! | '=> end define ragel-6.8/test/keller1.rl0000664000175000017500000004167612043335171012276 00000000000000/* * @LANG: c++ */ /* * Automatically generated by keller. Do not edit. * * Parts of this file are copied from Keller source covered by the GNU * GPL. As a special exception, you may use the parts of this file copied * from Keller source without restriction. The remainder is derived from * "tmp.gmr" and inherits the copyright status of that file. */ #line 1 "tmp.gmr" #include using std::cout; using std::endl; #line 16 "tmp.rl" enum token_type_e { tt_id, tt_equals, tt_semi, tt_pipe, tt_amp, tt_minus, tt_dot, tt_colon, tt_percent, tt_dollar, tt_plus, tt_number, tt_star, tt_question, tt_not, tt_andFSM, tt_orFSM, tt_open, tt_close }; struct LangEl { int line, lineEnd; int pos; int type; int state; LangEl *prev, *next; }; struct Token : public LangEl { const char *value; }; struct Lel_start : public LangEl { #line 32 "tmp.gmr" int si; #line 59 "tmp.rl" }; struct Lel_M : public LangEl { #line 36 "tmp.gmr" int mi; #line 67 "tmp.rl" }; #define l__error 19 #define l_tt_id 0 #define l_tt_equals 1 #define l_tt_semi 2 #define l_tt_pipe 3 #define l_tt_amp 4 #define l_tt_minus 5 #define l_tt_dot 6 #define l_tt_colon 7 #define l_tt_percent 8 #define l_tt_dollar 9 #define l_tt_plus 10 #define l_tt_number 11 #define l_tt_star 12 #define l_tt_question 13 #define l_tt_not 14 #define l_tt_andFSM 15 #define l_tt_orFSM 16 #define l_tt_open 17 #define l_tt_close 18 #define l_start 23 #define l_M 24 #define l_A 25 #define l_E 26 #define l_T 27 #define l_N 28 #define l_K 29 #define l_F 30 #define l__start 31 #define l__eof 20 struct LangEl; struct Parser { Parser(); void parseLangEl( LangEl *langEl ); int done( ); void push( LangEl *lel ) { lel->prev = stack; stack = lel; } LangEl *pop() { LangEl *ret = stack; stack = stack->prev; return ret; } int pop( int n ); void rem( LangEl *lel, int n ); LangEl *stack; int next; LangEl *redLel; LangEl *rhs[10]; int cs; // Initialize the machine. Invokes any init statement blocks. Returns 0 // if the machine begins in a non-accepting state and 1 if the machine // begins in an accepting state. int init( ); // Execute the machine on a block of data. Returns -1 if after processing // the data, the machine is in the error state and can never accept, 0 if // the machine is in a non-accepting state and 1 if the machine is in an // accepting state. int execute( LangEl *data, int len ); // Indicate that there is no more data. Returns -1 if the machine finishes // in the error state and does not accept, 0 if the machine finishes // in any other non-accepting state and 1 if the machine finishes in an // accepting state. int finish( ); }; %%{ machine Parser; getkey fpc->type; action shift { fpc->state = fcurs; push( fpc ); } action pop1 { fnext *pop(1); } action pop2 { fnext *pop(2); } action pop3 { fnext *pop(3); } action pop4 { fnext *pop(4); } action new_error { redLel = new LangEl(); redLel->type = 19; } action newstart { redLel = new Lel_start(); redLel->type = 23; } action newM { redLel = new Lel_M(); redLel->type = 24; } action newA { redLel = new LangEl(); redLel->type = 25; } action newE { redLel = new LangEl(); redLel->type = 26; } action newT { redLel = new LangEl(); redLel->type = 27; } action newN { redLel = new LangEl(); redLel->type = 28; } action newK { redLel = new LangEl(); redLel->type = 29; } action newF { redLel = new LangEl(); redLel->type = 30; } action new_eof { redLel = new LangEl(); redLel->type = 20; } action new_epsilon { redLel = new LangEl(); redLel->type = 21; } action new_null { redLel = new LangEl(); redLel->type = 22; } action rem1 { rem(fpc, 1); } action rem2 { rem(fpc, 2); } action rem3 { rem(fpc, 3); } action rem4 { rem(fpc, 4); } action r_start_0 { #line 41 "tmp.gmr" cout << "start = M;" << endl; static_cast(redLel)->si = static_cast(rhs[0])->mi; #line 214 "tmp.rl" } action r_M_0 { #line 44 "tmp.gmr" cout << "M = M A;" << endl; #line 221 "tmp.rl" } action r_M_1 { #line 45 "tmp.gmr" cout << "M = A;" << endl; #line 228 "tmp.rl" } action r_A_0 { #line 46 "tmp.gmr" cout << "A = tt_id tt_equals E tt_semi;" << endl; #line 235 "tmp.rl" } action r_E_0 { #line 47 "tmp.gmr" cout << "E = E tt_pipe T;" << endl; #line 242 "tmp.rl" } action r_E_1 { #line 48 "tmp.gmr" cout << "E = E tt_amp T;" << endl; #line 249 "tmp.rl" } action r_E_2 { #line 49 "tmp.gmr" cout << "E = E tt_minus T;" << endl; #line 256 "tmp.rl" } action r_E_3 { #line 50 "tmp.gmr" cout << "E = T;" << endl; #line 263 "tmp.rl" } action r_T_0 { #line 51 "tmp.gmr" cout << "T = T tt_dot N;" << endl; #line 270 "tmp.rl" } action r_T_1 { #line 52 "tmp.gmr" cout << "T = T N;" << endl; #line 277 "tmp.rl" } action r_T_2 { #line 53 "tmp.gmr" cout << "T = N;" << endl; #line 284 "tmp.rl" } action r_N_0 { #line 54 "tmp.gmr" cout << "N = N tt_colon tt_id;" << endl; #line 291 "tmp.rl" } action r_N_1 { #line 55 "tmp.gmr" cout << "N = N tt_percent tt_id;" << endl; #line 298 "tmp.rl" } action r_N_2 { #line 56 "tmp.gmr" cout << "N = N tt_dollar tt_id;" << endl; #line 305 "tmp.rl" } action r_N_3 { #line 57 "tmp.gmr" cout << "N = N tt_colon tt_plus tt_number;" << endl; #line 312 "tmp.rl" } action r_N_4 { #line 58 "tmp.gmr" cout << "N = N tt_colon tt_minus tt_number;" << endl; #line 319 "tmp.rl" } action r_N_5 { #line 59 "tmp.gmr" cout << "N = N tt_percent tt_plus tt_number;" << endl; #line 326 "tmp.rl" } action r_N_6 { #line 60 "tmp.gmr" cout << "N = N tt_percent tt_minus tt_number;" << endl; #line 333 "tmp.rl" } action r_N_7 { #line 61 "tmp.gmr" cout << "N = N tt_dollar tt_plus tt_number;" << endl; #line 340 "tmp.rl" } action r_N_8 { #line 62 "tmp.gmr" cout << "N = N tt_dollar tt_minus tt_number;" << endl; #line 347 "tmp.rl" } action r_N_9 { #line 63 "tmp.gmr" cout << "N = K;" << endl; #line 354 "tmp.rl" } action r_K_0 { #line 64 "tmp.gmr" cout << "K = F tt_star;" << endl; #line 361 "tmp.rl" } action r_K_1 { #line 65 "tmp.gmr" cout << "K = F tt_question;" << endl; #line 368 "tmp.rl" } action r_K_2 { #line 66 "tmp.gmr" cout << "K = F tt_plus;" << endl; #line 375 "tmp.rl" } action r_K_3 { #line 67 "tmp.gmr" cout << "K = F;" << endl; #line 382 "tmp.rl" } action r_K_4 { #line 68 "tmp.gmr" cout << "K = tt_not F tt_star;" << endl; #line 389 "tmp.rl" } action r_K_5 { #line 69 "tmp.gmr" cout << "K = tt_not F tt_question;" << endl; #line 396 "tmp.rl" } action r_K_6 { #line 70 "tmp.gmr" cout << "K = tt_not F tt_plus;" << endl; #line 403 "tmp.rl" } action r_K_7 { #line 71 "tmp.gmr" cout << "K = tt_not F;" << endl; #line 410 "tmp.rl" } action r_F_0 { #line 72 "tmp.gmr" cout << "F = tt_andFSM;" << endl; #line 417 "tmp.rl" } action r_F_1 { #line 73 "tmp.gmr" cout << "F = tt_orFSM;" << endl; #line 424 "tmp.rl" } action r_F_2 { #line 74 "tmp.gmr" cout << "F = tt_id;" << endl; #line 431 "tmp.rl" } action r_F_3 { #line 75 "tmp.gmr" cout << "F = tt_open E tt_close;" << endl; #line 438 "tmp.rl" } main := s0: start: ( 23 @shift -> s1 | 25 @shift -> s3 | 24 @shift -> s4 | 0 @shift -> s5 ), s1: ( 20 @shift -> s54 ), s2: ( (0|20) @pop2 @newM @r_M_0 @rem2 -> s54 ), s3: ( (0|20) @pop1 @newM @r_M_1 @rem1 -> s54 ), s4: ( 20 @pop1 @newstart @r_start_0 @rem1 -> s54 | 25 @shift -> s2 | 0 @shift -> s5 ), s5: ( 1 @shift -> s6 ), s6: ( 26 @shift -> s8 | 27 @shift -> s9 | 29 @shift -> s25 | 28 @shift -> s26 | 30 @shift -> s33 | 17 @shift -> s35 | 14 @shift -> s46 | 15 @shift -> s48 | 16 @shift -> s49 | 0 @shift -> s50 ), s7: ( (0|20) @pop4 @newA @r_A_0 @rem4 -> s54 ), s8: ( 2 @shift -> s7 | 3 @shift -> s37 | 4 @shift -> s38 | 5 @shift -> s39 ), s9: ( (2..5|18) @pop1 @newE @r_E_3 @rem1 -> s54 | 29 @shift -> s25 | 30 @shift -> s33 | 28 @shift -> s34 | 17 @shift -> s35 | 6 @shift -> s41 | 14 @shift -> s46 | 15 @shift -> s48 | 16 @shift -> s49 | 0 @shift -> s50 ), s10: ( (0|2..9|14..18) @pop3 @newN @r_N_0 @rem3 -> s54 ), s11: ( (0|2..9|14..18) @pop3 @newN @r_N_1 @rem3 -> s54 ), s12: ( (0|2..9|14..18) @pop3 @newN @r_N_2 @rem3 -> s54 ), s13: ( 11 @shift -> s14 ), s14: ( (0|2..9|14..18) @pop4 @newN @r_N_3 @rem4 -> s54 ), s15: ( 11 @shift -> s16 ), s16: ( (0|2..9|14..18) @pop4 @newN @r_N_4 @rem4 -> s54 ), s17: ( 11 @shift -> s18 ), s18: ( (0|2..9|14..18) @pop4 @newN @r_N_5 @rem4 -> s54 ), s19: ( 11 @shift -> s20 ), s20: ( (0|2..9|14..18) @pop4 @newN @r_N_6 @rem4 -> s54 ), s21: ( 11 @shift -> s22 ), s22: ( (0|2..9|14..18) @pop4 @newN @r_N_7 @rem4 -> s54 ), s23: ( 11 @shift -> s24 ), s24: ( (0|2..9|14..18) @pop4 @newN @r_N_8 @rem4 -> s54 ), s25: ( (0|2..9|14..18) @pop1 @newN @r_N_9 @rem1 -> s54 ), s26: ( (0|2..6|14..18) @pop1 @newT @r_T_2 @rem1 -> s54 | 7 @shift -> s27 | 8 @shift -> s28 | 9 @shift -> s29 ), s27: ( 0 @shift -> s10 | 10 @shift -> s13 | 5 @shift -> s15 ), s28: ( 0 @shift -> s11 | 10 @shift -> s17 | 5 @shift -> s19 ), s29: ( 0 @shift -> s12 | 10 @shift -> s21 | 5 @shift -> s23 ), s30: ( (0|2..9|14..18) @pop2 @newK @r_K_0 @rem2 -> s54 ), s31: ( (0|2..9|14..18) @pop2 @newK @r_K_1 @rem2 -> s54 ), s32: ( (0|2..9|14..18) @pop2 @newK @r_K_2 @rem2 -> s54 ), s33: ( (0|2..9|14..18) @pop1 @newK @r_K_3 @rem1 -> s54 | 12 @shift -> s30 | 13 @shift -> s31 | 10 @shift -> s32 ), s34: ( (0|2..6|14..18) @pop2 @newT @r_T_1 @rem2 -> s54 | 7 @shift -> s27 | 8 @shift -> s28 | 9 @shift -> s29 ), s35: ( 27 @shift -> s9 | 29 @shift -> s25 | 28 @shift -> s26 | 30 @shift -> s33 | 17 @shift -> s35 | 26 @shift -> s40 | 14 @shift -> s46 | 15 @shift -> s48 | 16 @shift -> s49 | 0 @shift -> s50 ), s36: ( (0|2..10|12..18) @pop3 @newF @r_F_3 @rem3 -> s54 ), s37: ( 29 @shift -> s25 | 28 @shift -> s26 | 30 @shift -> s33 | 17 @shift -> s35 | 14 @shift -> s46 | 15 @shift -> s48 | 16 @shift -> s49 | 0 @shift -> s50 | 27 @shift -> s53 ), s38: ( 29 @shift -> s25 | 28 @shift -> s26 | 30 @shift -> s33 | 17 @shift -> s35 | 14 @shift -> s46 | 15 @shift -> s48 | 16 @shift -> s49 | 0 @shift -> s50 | 27 @shift -> s52 ), s39: ( 29 @shift -> s25 | 28 @shift -> s26 | 30 @shift -> s33 | 17 @shift -> s35 | 27 @shift -> s42 | 14 @shift -> s46 | 15 @shift -> s48 | 16 @shift -> s49 | 0 @shift -> s50 ), s40: ( 18 @shift -> s36 | 3 @shift -> s37 | 4 @shift -> s38 | 5 @shift -> s39 ), s41: ( 29 @shift -> s25 | 30 @shift -> s33 | 17 @shift -> s35 | 14 @shift -> s46 | 15 @shift -> s48 | 16 @shift -> s49 | 0 @shift -> s50 | 28 @shift -> s51 ), s42: ( (2..5|18) @pop3 @newE @r_E_2 @rem3 -> s54 | 29 @shift -> s25 | 30 @shift -> s33 | 28 @shift -> s34 | 17 @shift -> s35 | 6 @shift -> s41 | 14 @shift -> s46 | 15 @shift -> s48 | 16 @shift -> s49 | 0 @shift -> s50 ), s43: ( (0|2..9|14..18) @pop3 @newK @r_K_4 @rem3 -> s54 ), s44: ( (0|2..9|14..18) @pop3 @newK @r_K_5 @rem3 -> s54 ), s45: ( (0|2..9|14..18) @pop3 @newK @r_K_6 @rem3 -> s54 ), s46: ( 17 @shift -> s35 | 30 @shift -> s47 | 15 @shift -> s48 | 16 @shift -> s49 | 0 @shift -> s50 ), s47: ( (0|2..9|14..18) @pop2 @newK @r_K_7 @rem2 -> s54 | 12 @shift -> s43 | 13 @shift -> s44 | 10 @shift -> s45 ), s48: ( (0|2..10|12..18) @pop1 @newF @r_F_0 @rem1 -> s54 ), s49: ( (0|2..10|12..18) @pop1 @newF @r_F_1 @rem1 -> s54 ), s50: ( (0|2..10|12..18) @pop1 @newF @r_F_2 @rem1 -> s54 ), s51: ( (0|2..6|14..18) @pop3 @newT @r_T_0 @rem3 -> s54 | 7 @shift -> s27 | 8 @shift -> s28 | 9 @shift -> s29 ), s52: ( (2..5|18) @pop3 @newE @r_E_1 @rem3 -> s54 | 29 @shift -> s25 | 30 @shift -> s33 | 28 @shift -> s34 | 17 @shift -> s35 | 6 @shift -> s41 | 14 @shift -> s46 | 15 @shift -> s48 | 16 @shift -> s49 | 0 @shift -> s50 ), s53: ( (2..5|18) @pop3 @newE @r_E_0 @rem3 -> s54 | 29 @shift -> s25 | 30 @shift -> s33 | 28 @shift -> s34 | 17 @shift -> s35 | 6 @shift -> s41 | 14 @shift -> s46 | 15 @shift -> s48 | 16 @shift -> s49 | 0 @shift -> s50 ), s54: ( '' -> final ) ; }%% %% write data; Parser::Parser( ) { } int Parser::init( ) { %% write init; return 0; } int Parser::execute( LangEl *_data, int _len ) { LangEl *p = _data; LangEl *pe = _data+_len; %% write exec; if ( cs == Parser_error ) return -1; if ( cs >= Parser_first_final ) return 1; return 0; } int Parser::finish( ) { if ( cs == Parser_error ) return -1; if ( cs >= Parser_first_final ) return 1; return 0; } void Parser::parseLangEl( LangEl *lel ) { redLel = 0; execute( lel, 1 ); while ( redLel != 0 ) { execute( redLel, 1 ); redLel = 0; execute( lel, 1 ); } } int Parser::pop( int n ) { for ( int i = n-1; i >= 0; i-- ) rhs[i] = pop(); return rhs[0]->state; } void Parser::rem( LangEl *lel, int n ) { for ( int i = n-1; i >= 0; i-- ) delete rhs[i]; } int Parser::done( ) { Token *eof = new Token; eof->type = l__eof; eof->line = 0; eof->pos = 0; parseLangEl( eof ); return finish(); } #line 77 "tmp.gmr" #include #define MAX_TOKS 10000 struct TokList { TokList() : numToks(0) { } void append( int type ); int parse(); Token *toks[MAX_TOKS]; int numToks; }; void TokList::append( int type ) { assert( numToks < MAX_TOKS ); toks[numToks] = new Token; toks[numToks]->type = type; numToks += 1; } int TokList::parse() { Parser parser; parser.init(); for ( int i = 0; i < numToks; i++ ) parser.parseLangEl( toks[i] ); return parser.done(); } void test0() { TokList tokList; tokList.append( tt_id ); tokList.append( tt_equals ); tokList.append( tt_id ); tokList.append( tt_star ); tokList.append( tt_minus ); tokList.append( tt_andFSM ); tokList.append( tt_dot ); tokList.append( tt_id ); tokList.append( tt_semi ); tokList.append( tt_id ); tokList.append( tt_equals ); tokList.append( tt_id ); tokList.append( tt_andFSM ); tokList.append( tt_id ); tokList.append( tt_semi ); cout << tokList.parse() << endl; } void test1() { TokList tokList; tokList.append( tt_id ); tokList.append( tt_equals ); tokList.append( tt_open ); tokList.append( tt_orFSM ); tokList.append( tt_minus ); tokList.append( tt_andFSM ); tokList.append( tt_close ); tokList.append( tt_star ); tokList.append( tt_semi ); cout << tokList.parse() << endl; } void test2() { TokList tokList; tokList.append( tt_id ); tokList.append( tt_equals ); tokList.append( tt_not ); tokList.append( tt_open ); tokList.append( tt_orFSM ); tokList.append( tt_minus ); tokList.append( tt_not ); tokList.append( tt_andFSM ); tokList.append( tt_close ); tokList.append( tt_star ); tokList.append( tt_semi ); cout << tokList.parse() << endl; } void test3() { TokList tokList; tokList.append( tt_id ); tokList.append( tt_equals ); tokList.append( tt_id ); tokList.append( tt_colon ); tokList.append( tt_minus ); tokList.append( tt_number ); tokList.append( tt_id ); tokList.append( tt_colon ); tokList.append( tt_id ); tokList.append( tt_id ); tokList.append( tt_dollar ); tokList.append( tt_plus ); tokList.append( tt_number ); tokList.append( tt_id ); tokList.append( tt_percent ); tokList.append( tt_minus ); tokList.append( tt_number ); tokList.append( tt_semi ); cout << tokList.parse() << endl; } void test4() { TokList tokList; tokList.append( tt_id ); tokList.append( tt_equals ); tokList.append( tt_id ); tokList.append( tt_pipe ); tokList.append( tt_id ); tokList.append( tt_amp ); tokList.append( tt_id ); tokList.append( tt_minus ); tokList.append( tt_id ); tokList.append( tt_semi ); cout << tokList.parse() << endl; } int main() { test0(); test1(); test2(); test3(); test4(); } #ifdef _____OUTPUT_____ F = tt_id; K = F tt_star; N = K; T = N; E = T; F = tt_andFSM; K = F; N = K; T = N; F = tt_id; K = F; N = K; T = T tt_dot N; E = E tt_minus T; A = tt_id tt_equals E tt_semi; M = A; F = tt_id; K = F; N = K; T = N; F = tt_andFSM; K = F; N = K; T = T N; F = tt_id; K = F; N = K; T = T N; E = T; A = tt_id tt_equals E tt_semi; M = M A; start = M; 1 F = tt_orFSM; K = F; N = K; T = N; E = T; F = tt_andFSM; K = F; N = K; T = N; E = E tt_minus T; F = tt_open E tt_close; K = F tt_star; N = K; T = N; E = T; A = tt_id tt_equals E tt_semi; M = A; start = M; 1 F = tt_orFSM; K = F; N = K; T = N; E = T; F = tt_andFSM; K = tt_not F; N = K; T = N; E = E tt_minus T; F = tt_open E tt_close; K = tt_not F tt_star; N = K; T = N; E = T; A = tt_id tt_equals E tt_semi; M = A; start = M; 1 F = tt_id; K = F; N = K; N = N tt_colon tt_minus tt_number; T = N; F = tt_id; K = F; N = K; N = N tt_colon tt_id; T = T N; F = tt_id; K = F; N = K; N = N tt_dollar tt_plus tt_number; T = T N; F = tt_id; K = F; N = K; N = N tt_percent tt_minus tt_number; T = T N; E = T; A = tt_id tt_equals E tt_semi; M = A; start = M; 1 F = tt_id; K = F; N = K; T = N; E = T; F = tt_id; K = F; N = K; T = N; E = E tt_pipe T; F = tt_id; K = F; N = K; T = N; E = E tt_amp T; F = tt_id; K = F; N = K; T = N; E = E tt_minus T; A = tt_id tt_equals E tt_semi; M = A; start = M; 1 #endif ragel-6.8/test/export2.rl0000664000175000017500000000151012043335171012321 00000000000000/* * @LANG: java */ class export2 { %%{ machine test; export c1 = 'c'; export c2 = 'z'; export c3 = 't'; commands := ( c1 . digit* '\n' @{ System.out.println( "c1" );} | c2 . alpha* '\n' @{ System.out.println( "c2" );}| c3 . '.'* '\n' @{ System.out.println( "c3" );} )*; other := any*; }%% %% write exports; %% write data; static void test( char data[] ) { int cs = test_en_commands, p = 0, pe = data.length; int top; %% write init nocs; %% write exec; if ( cs >= test_first_final ) System.out.println( "ACCEPT" ); else System.out.println( "FAIL" ); } public static void main( String args[] ) { char data[] = { test_ex_c1, '1', '2', '\n', test_ex_c2, 'a', 'b', '\n', test_ex_c3, '.', '.', '\n', }; test( data ); } } /* _____OUTPUT_____ c1 c2 c3 ACCEPT */ ragel-6.8/test/langtrans_c.txl0000664000175000017500000001442412043335171013413 00000000000000include "testcase.txl" define c_statements [repeat c_lang_stmt] end define define c_lang_stmt [al_ragel_stmt] | [c_variable_decl] | [c_expr_stmt] | [c_if_stmt] | [EX] '{ [IN] [NL] [c_statements] [EX] '} [IN] [NL] end define define c_variable_decl [c_type_decl] [id] [opt union] '; [NL] end define define c_type_decl [al_type_decl] | 'char '* end define define c_expr_stmt [c_expr] '; [NL] end define define c_expr [c_term] [repeat c_expr_extend] end define define c_expr_extend [al_expr_op] [c_term] end define define c_term [al_term] | [id] '( [c_args] ') end define define c_args [list c_expr] end define define c_sign '- | '+ end define define c_if_stmt 'if '( [c_expr] ') [NL] [IN] [c_lang_stmt] [EX] [opt c_else] end define define c_else 'else [NL] [IN] [c_lang_stmt] [EX] end define define c_lang [c_statements] '%% [NL] [c_statements] [ragel_def] end define define program [lang_indep] | [c_lang] end define redefine al_host_block '{ [NL] [IN] [al_statements] [EX] '} [NL] | '{ [NL] [IN] [c_statements] [EX] '} [NL] end define redefine cond_action_stmt 'action [id] '{ [al_expr] '} [NL] | 'action [id] '{ [c_expr] '} [NL] end redefine rule boolTypes replace [al_type_decl] 'bool by 'int end rule rule ptrTypes replace [c_type_decl] 'ptr by 'char '* end rule rule boolVals1 replace [al_term] 'true by '1 end rule rule boolVals2 replace [al_term] 'false by '0 end rule function alStmtToC1 AlStmt [action_lang_stmt] deconstruct AlStmt VarDecl [al_variable_decl] deconstruct VarDecl Type [al_type_decl] Id [id] OptUnion [opt union]'; construct CType [c_type_decl] Type construct Result [c_variable_decl] CType [boolTypes] [ptrTypes] Id OptUnion '; replace [repeat c_lang_stmt] by Result end function rule alTermToC1 replace [al_term] 'first_token_char by 'ts '[0] end rule rule alTermToC2 replace [al_term] '< _ [al_type_decl] '> '( AlExpr [al_expr] ') by '( AlExpr ') end rule function alTermToC replace [al_term] AlTerm [al_term] by AlTerm [alTermToC1] [alTermToC2] end function function alExprExtendToC AlExprExtend [repeat al_expr_extend] deconstruct AlExprExtend Op [al_expr_op] Term [al_term] Rest [repeat al_expr_extend] construct RestC [repeat c_expr_extend] _ [alExprExtendToC Rest] replace [repeat c_expr_extend] by Op Term [alTermToC] RestC end function function alExprToC AlExpr [al_expr] deconstruct AlExpr ALTerm [al_term] AlExprExtend [repeat al_expr_extend] construct CExprExtend [repeat c_expr_extend] _ [alExprExtendToC AlExprExtend] construct Result [opt c_expr] ALTerm [alTermToC] CExprExtend replace [opt c_expr] by Result [boolVals1] [boolVals2] end function function alStmtToC2 AlStmt [action_lang_stmt] deconstruct AlStmt AlExpr [al_expr] '; construct OptCExpr [opt c_expr] _ [alExprToC AlExpr] deconstruct OptCExpr CExpr [c_expr] replace [repeat c_lang_stmt] by CExpr '; end function function alOptElseC AlOptElse [opt al_else] deconstruct AlOptElse 'else AlSubStmt [action_lang_stmt] construct AlSubStmts [repeat action_lang_stmt] AlSubStmt construct CSubStmts [repeat c_lang_stmt] _ [alToC AlSubStmts] deconstruct CSubStmts CSubStmt [c_lang_stmt] replace [opt c_else] by 'else CSubStmt end function function alStmtToC3 AlStmt [action_lang_stmt] deconstruct AlStmt 'if '( AlExpr [al_expr] ') AlSubStmt [action_lang_stmt] AlOptElse [opt al_else] construct OptCExpr [opt c_expr] _ [alExprToC AlExpr] deconstruct OptCExpr CExpr [c_expr] construct AlSubStmts [repeat action_lang_stmt] AlSubStmt construct CSubStmts [repeat c_lang_stmt] _ [alToC AlSubStmts] deconstruct CSubStmts CSubStmt [c_lang_stmt] construct OptCElse [opt c_else] _ [alOptElseC AlOptElse] replace [repeat c_lang_stmt] by 'if '( CExpr ') CSubStmt OptCElse end function function alStmtToC4a AlStmt [action_lang_stmt] deconstruct AlStmt 'printi Id [id] '; replace [repeat c_lang_stmt] by 'printf '( '"%i" ', Id '); end function function alStmtToC4b AlStmt [action_lang_stmt] deconstruct AlStmt 'prints String [stringlit] '; replace [repeat c_lang_stmt] by 'fputs '( String , 'stdout '); end function function alStmtToC4c AlStmt [action_lang_stmt] deconstruct AlStmt 'printb Id [id] '; replace [repeat c_lang_stmt] by 'fwrite '( Id ', '1 ', 'pos ', 'stdout '); end function function alStmtToC4d AlStmt [action_lang_stmt] deconstruct AlStmt 'print_token '; replace [repeat c_lang_stmt] by 'fwrite '( 'ts ', '1 ', 'te '- 'ts ', 'stdout '); end function function alStmtToC5 AlStmt [action_lang_stmt] deconstruct AlStmt '{ AlSubStmts [repeat action_lang_stmt] '} construct CSubStmts [repeat c_lang_stmt] _ [alToC AlSubStmts] replace [repeat c_lang_stmt] by '{ CSubStmts '} end function function alStmtToC6 AlStmt [action_lang_stmt] deconstruct AlStmt RagelStmt [al_ragel_stmt] replace [repeat c_lang_stmt] by RagelStmt end function function alToC AlStmts [repeat action_lang_stmt] deconstruct AlStmts FirstStmt [action_lang_stmt] Rest [repeat action_lang_stmt] construct FirstC [repeat c_lang_stmt] _ [alStmtToC1 FirstStmt] [alStmtToC2 FirstStmt] [alStmtToC3 FirstStmt] [alStmtToC4a FirstStmt] [alStmtToC4b FirstStmt] [alStmtToC4c FirstStmt] [alStmtToC4d FirstStmt] [alStmtToC5 FirstStmt] [alStmtToC6 FirstStmt] construct RestC [repeat c_lang_stmt] _ [alToC Rest] replace [repeat c_lang_stmt] by FirstC [. RestC] end function rule actionTransC replace [al_host_block] '{ AlStmts [repeat action_lang_stmt] '} construct CStmts [repeat c_lang_stmt] _ [alToC AlStmts] by '{ CStmts '} end rule rule condTransC replace [cond_action_stmt] 'action Id [id] '{ AlExpr [al_expr] '} construct OptCExpr [opt c_expr] _ [alExprToC AlExpr] deconstruct OptCExpr CExpr [c_expr] by 'action Id '{ CExpr '} end rule function langTransC replace [program] Definitions [repeat action_lang_stmt] '%% Initializations [repeat action_lang_stmt] RagelDef [ragel_def] construct CDefinitions [repeat c_lang_stmt] _ [alToC Definitions] construct CInitializations [repeat c_lang_stmt] _ [alToC Initializations] by CDefinitions '%% CInitializations RagelDef [actionTransC] [condTransC] end function function main replace [program] P [program] by P [langTransC] end function ragel-6.8/test/awkemu.rl0000664000175000017500000000612312043335171012214 00000000000000/* * @LANG: c */ /* * Emulate the basic parser of the awk program. Breaks lines up into * words and prints the words. */ #include #include #define LINEBUF 2048 static char lineBuf[LINEBUF]; static char blineBuf[LINEBUF]; static int lineLen; static int blineLen; static int words; void finishLine(); struct awkemu { int cs; }; %%{ machine awkemu; variable cs fsm->cs; # Starts a line. Will initialize all the data necessary for capturing the line. action startline { lineLen = 0; blineLen = 0; words = 0; } # Will be executed on every character seen in a word. Captures the word # to the broken up line buffer. action wordchar { blineBuf[blineLen++] = fc; } # Terminate a word. Adds the null after the word and increments the word count # for the line. action termword { blineBuf[blineLen++] = 0; words += 1; } # Will be executed on every character seen in a line (not including # the newline itself. action linechar { lineBuf[lineLen++] = fc; } # This section of the machine deals with breaking up lines into fields. # Lines are separed by the whitespace and put in an array of words. # Words in a line. word = (extend - [ \t\n])+; # The whitespace separating words in a line. whitespace = [ \t]; # The components in a line to break up. Either a word or a single char of # whitespace. On the word capture characters. blineElements = word $wordchar %termword | whitespace; # Star the break line elements. Just be careful to decrement the leaving # priority as we don't want multiple character identifiers to be treated as # multiple single char identifiers. breakLine = ( blineElements $1 %0 )* . '\n'; # This machine lets us capture entire lines. We do it separate from the words # in a line. bufLine = (extend - '\n')* $linechar %{ finishLine(); } . '\n'; # A line can then consist of the machine that will break up the line into # words and a machine that will buffer the entire line. line = ( breakLine | bufLine ) > startline; # Any number of lines. main := line*; }%% void finishLine() { int i; char *pword = blineBuf; lineBuf[lineLen] = 0; printf("endline(%i): %s\n", words, lineBuf ); for ( i = 0; i < words; i++ ) { printf(" word: %s\n", pword ); pword += strlen(pword) + 1; } } %% write data; void awkemu_init( struct awkemu *fsm ) { %% write init; } void awkemu_execute( struct awkemu *fsm, const char *_data, int _len ) { const char *p = _data; const char *pe = _data+_len; %% write exec; } int awkemu_finish( struct awkemu *fsm ) { if ( fsm->cs == awkemu_error ) return -1; if ( fsm->cs >= awkemu_first_final ) return 1; return 0; } #include #define BUFSIZE 2048 struct awkemu fsm; char buf[BUFSIZE]; void test( char *buf ) { int len = strlen( buf ); awkemu_init( &fsm ); awkemu_execute( &fsm, buf, len ); if ( awkemu_finish( &fsm ) > 0 ) printf("ACCEPT\n"); else printf("FAIL\n"); } int main() { test( "" ); test( "one line with no newline" ); test( "one line\n" ); return 0; } #ifdef _____OUTPUT_____ ACCEPT FAIL endline(2): one line word: one word: line ACCEPT #endif ragel-6.8/test/recdescent2.rl0000664000175000017500000000375512043335171013134 00000000000000/* * @LANG: java */ class recdescent2 { %%{ machine recdescent; prepush { if ( top == stack_size ) { System.out.print( "growing stack\n" ); stack_size = top * 2; // Don't actually bother to resize here, but we do print messages. //stack = (int*)realloc( stack, sizeof(int)*stack_size ); } } postpop { if ( stack_size > (top * 4) ) { stack_size = top * 2; // Don't actually bother to resize here, but we do print messages. //stack = (int*)realloc( stack, sizeof(int)*stack_size ); System.out.print( "shrinking stack\n" ); } } action item_start { item = p; } action item_finish { String item_data = new String ( data, item, p-item ); System.out.print( "item: " ); System.out.print( item_data ); System.out.print( "\n" ); } action call_main { System.out.print( "calling main\n" ); fcall main; } action return_main { if ( top == 0 ) { System.out.print( "STRAY CLOSE\n" ); fbreak; } System.out.print( "returning from main\n" ); fhold; fret; } id = [a-zA-Z_]+; number = [0-9]+; ws = [ \t\n]+; main := ( ws | ( number | id ) >item_start %item_finish | '{' @call_main '}' | '}' @return_main )**; }%% %% write data; static void test( char data[] ) { int cs, p = 0, pe = data.length, eof = data.length, item = 0; int stack[] = new int[1024]; int stack_size = 1; int top; %% write init; %% write exec; if ( cs == recdescent_error ) System.out.println( "SCANNER ERROR" ); } public static void main( String args[] ) { test( "88 foo { 99 {{{{}}}}{ } }".toCharArray() ); test( "76 } sadf".toCharArray() ); } } /* _____OUTPUT_____ item: 88 item: foo calling main item: 99 calling main growing stack calling main growing stack calling main calling main growing stack returning from main returning from main returning from main returning from main shrinking stack calling main returning from main returning from main shrinking stack item: 76 STRAY CLOSE */ ragel-6.8/test/cond5.rl0000664000175000017500000000245512043335171011737 00000000000000/* * @LANG: c++ */ #include #include using std::cout; using std::endl; %%{ machine foo; write data noerror; }%% void test( const char *str ) { int cs = foo_start; int c = 0; const char *p = str; const char *pe = str + strlen( str ); char last = '0'; cout << "run:"; %%{ action d1 { cout << " d1"; } action see_five { cout << " see_five"; } see_five = ([0-9] when{c++ < 5} @d1)* '\n' @see_five; action in_sequence { cout << " in_sequence"; } action d2 { last = *p; cout << " d2"; } in_sequence = ( [0-9] when { *p == last+1 } @d2 )* '\n' @in_sequence; main := ( see_five | in_sequence ) ${cout << " |";}; write exec; }%% if ( cs < foo_first_final ) cout << " failure"; cout << endl; } int main() { test( "123456789012\n" ); // fails both test( "123456789\n" ); // fails five test( "1234\n" ); // fails five test( "13245\n" ); // fails sequence test( "12345\n" ); // succeeds in both return 0; } #ifdef _____OUTPUT_____ run: d1 d2 | d1 d2 | d1 d2 | d1 d2 | d1 d2 | d2 | d2 | d2 | d2 | failure run: d1 d2 | d1 d2 | d1 d2 | d1 d2 | d1 d2 | d2 | d2 | d2 | d2 | in_sequence | run: d1 d2 | d1 d2 | d1 d2 | d1 d2 | see_five in_sequence | run: d1 d2 | d1 | d1 | d1 | d1 | see_five | run: d1 d2 | d1 d2 | d1 d2 | d1 d2 | d1 d2 | see_five in_sequence | #endif ragel-6.8/test/cond3.rl0000664000175000017500000000162112043335171011727 00000000000000/* * @LANG: c++ */ #include #include using std::cout; using std::endl; %%{ machine foo; action hit_5 {c == 5} action done { cout << " done" << endl; } action inc {c++;} # The any* includes '\n' when hit_5 is true, so use guarded concatenation. main := (any @inc)* :> '\n' when hit_5 @done; }%% %% write data noerror; void test( const char *str ) { int cs = foo_start; int c = 0; const char *p = str; const char *pe = str + strlen( str ); cout << "run:" << endl; %% write exec; if ( cs >= foo_first_final ) cout << " success" << endl; else cout << " failure" << endl; cout << endl; } int main() { test( "12345\n" ); // success test( "\n2345\n" ); // success, first newline ignored test( "1234\n" ); // failure, didn't get 5 chars before newline. return 0; } #ifdef _____OUTPUT_____ run: done success run: done success run: failure #endif ragel-6.8/test/cond2.rl0000664000175000017500000000202212043335171011722 00000000000000/* * @LANG: c++ */ #include #include using std::cout; using std::endl; %%{ machine foo; action c1 {i} action c2 {j} action one { cout << " one" << endl;} action two { cout << " two" << endl;} main := ( [a-z] | ('\n' when c1 @one) )* ('\n' when c2 @two); }%% %% write data noerror; void test( int i, int j, const char *str ) { int cs = foo_start; const char *p = str; const char *pe = str + strlen( str ); cout << "run:" << endl; %% write exec; if ( cs >= foo_first_final ) cout << " success" << endl; else cout << " failure" << endl; cout << endl; } int main() { test( 0, 0, "hi\n\n" ); test( 1, 0, "hi\n\n" ); test( 0, 1, "hi\n" ); test( 0, 1, "hi\n\n" ); test( 1, 1, "hi\n" ); test( 1, 1, "hi\n\n" ); test( 1, 1, "hi\n\nx" ); return 0; } #ifdef _____OUTPUT_____ run: failure run: one one failure run: two success run: two failure run: one two success run: one two one two success run: one two one two failure #endif ragel-6.8/test/scan3.rl0000664000175000017500000000066312043335171011735 00000000000000/* * @LANG: indep */ ptr ts; ptr te; int act; int token; %% %%{ machine scanner; # Warning: changing the patterns or the input string will affect the # coverage of the scanner action types. main := |* 'a' => { prints "pat1\n"; }; 'b' => { prints "pat2\n"; }; [ab] any* => { prints "pat3\n"; }; *|; }%% /* _____INPUT_____ "ab89" _____INPUT_____ */ /* _____OUTPUT_____ pat3 ACCEPT _____OUTPUT_____ */ ragel-6.8/test/scan2.rl0000664000175000017500000000067612043335171011740 00000000000000/* * @LANG: indep */ ptr ts; ptr te; int act; int token; %% %%{ machine scanner; # Warning: changing the patterns or the input string will affect the # coverage of the scanner action types. main := |* 'a' => { prints "pat1\n"; }; [ab]+ . 'c' => { prints "pat2\n"; }; any => { prints "any\n"; }; *|; }%% /* _____INPUT_____ "a" _____INPUT_____ */ /* _____OUTPUT_____ pat1 ACCEPT _____OUTPUT_____ */ ragel-6.8/test/mailbox2.rl0000664000175000017500000000630512106050031012427 00000000000000/* * @LANG: c++ * @CFLAGS: -I../aapl */ #include #include using std::cin; using std::cout; using std::cerr; using std::endl; %%{ machine mailbox; action prn_char { cout << *p; } action prn_space { cout << ' '; } action prn_word { cout.write(ws, p-ws); cout << ' '; } action prn_addr1 { cout << "| "; cout.write(ws+1, p-ws-2); } action prn_addr2 { cout << "| "; cout.write(ws, p-ws); } action prn_tab { cout << '\t'; } action prn_nl { cout << '\n'; } action prn_separator { cout << "------\n"; } action prn_from { cout << "FROM\n"; } action prn_to { cout << "TO\n"; } action prn_subj { cout << "SUBJECT\n"; } action start_word { ws = p; } action start_headers { preserve = p; } action end_headers {preserve = 0;} day = upper lower{2}; month = upper lower{2}; year = digit{4}; time = digit{2} ':' digit{2} ( ':' digit{2} )?; letterZone = upper{3}; numZone = [+\-] digit{4}; zone = letterZone | numZone; dayNum = ( digit | ' ' ) digit; date = day ' ' month ' ' dayNum ' ' time ' ' ( year | year ' ' zone | zone ' ' year ); fromLine = 'From ' [^\n]* ' ' date '\n' @start_headers; headerChar = print - [ :]; headersToPrint = 'From' | 'To' | 'Subject'; headersToConsume = headerChar+ - headersToPrint; consumeHeader = headersToConsume ':' ( [^\n] | ( '\n' [ \t] ) )* '\n'; addrWS = ( [ \t]+ | '\n' [ \t]+ ); addrComment = '(' [^)]* ')'; addrWord = [^"'@,<>() \t\n]+; addrAddr1 = '<' [^>]* '>'; addrAddr2 = addrWord '@' addrWord; addrString = '"' [^"]* '"' | "'" [^']* "'"; addrItem = ( addrAddr1 %prn_addr1 | addrAddr2 %prn_addr2 | addrWord %prn_word | addrString %prn_word ) >start_word; address = ( addrWS | addrComment | addrItem )** >prn_tab; addrHeader = ( 'From' %prn_from | 'To' %prn_to ) ':' address ( ',' @prn_nl address )* '\n' %prn_nl; subjectHeader = 'Subject:' @prn_subj @prn_tab ' '* <: ( [^\n] @prn_char | ( '\n' [ \t]+ ) %prn_space )** '\n' %prn_nl; header = consumeHeader | addrHeader | subjectHeader; messageLine = ( [^\n]* '\n' - fromLine ); main := ( fromLine %prn_separator header* '\n' @end_headers messageLine* )*; }%% %% write data; #define BUFSIZE 8192 void test( const char *buf ) { int cs, len = strlen( buf ); const char *preserve = 0, *ws = 0; %% write init; const char *p = buf; const char *pe = p + len; %% write exec; if ( cs == mailbox_error ) cerr << "ERROR" << endl; if ( cs < mailbox_first_final ) cerr << "DID NOT FINISH IN A FINAL STATE" << endl; } int main() { test( "From user@host.com Wed Nov 28 13:30:05 2001\n" "From: \"Adrian D. Thurston\" \n" "Subject: the squirrel has landed\n" "\n" "Message goes here. \n" "From (trick from line).\n" "From: not really a header\n" "\n" "From user2@host2.com Wed Nov 28 13:30:05 2001\n" "To: Edgar Allen Poe (da man)\n" "Subject: (no subject) \n" "\n" "Message goes here. \n" "\n" ); return 0; } #ifdef _____OUTPUT_____ ------ FROM "Adrian D. Thurston" | thurston@complang.org SUBJECT the squirrel has landed ------ TO Edgar Allen Poe | ep@net.com SUBJECT (no subject) #endif ragel-6.8/test/range.rl0000664000175000017500000000166712043335171012027 00000000000000/* * @LANG: c */ #include #include struct range { int cs; }; %%{ machine range; variable cs fsm->cs; main := ( 'a' .. 'c' | 'c' .. 'e' | 'm' .. 'n' | 'a' .. 'z' ) '\n'; }%% %% write data; void range_init( struct range *fsm ) { %% write init; } void range_execute( struct range *fsm, const char *_data, int _len ) { const char *p = _data; const char *pe = _data+_len; %% write exec; } int range_finish( struct range *fsm ) { if ( fsm->cs == range_error ) return -1; if ( fsm->cs >= range_first_final ) return 1; return 0; } struct range fsm; void test( char *buf ) { int len = strlen( buf ); range_init( &fsm ); range_execute( &fsm, buf, len ); if ( range_finish( &fsm ) > 0 ) printf("ACCEPT\n"); else printf("FAIL\n"); } int main() { test( "a\n" ); test( "z\n" ); test( "g\n" ); test( "no\n" ); test( "1\n" ); return 0; } #ifdef _____OUTPUT_____ ACCEPT ACCEPT ACCEPT FAIL FAIL #endif ragel-6.8/test/langtrans_java.sh0000775000175000017500000000327412043335171013721 00000000000000#!/bin/bash # file=$1 [ -f $file ] || exit 1 root=${file%.rl} class=${root}_java # Make a temporary version of the test case using the Java language translations. sed -n '/\/\*/,/\*\//d;p' $file | txl -q stdin langtrans_java.txl - $class > $file.pr # Begin writing out the test case. cat << EOF /* * @LANG: java * @GENERATED: yes EOF grep '@ALLOW_GENFLAGS:' $file grep '@ALLOW_MINFLAGS:' $file cat << EOF */ class $class { EOF # Write the data declarations sed -n '/^%%$/q;{s/^/\t/;p}' $file.pr # Write out the machine specification. sed -n '/^%%{$/,/^}%%/{s/^/\t/;p}' $file.pr # Write out the init and execute routines. cat << EOF int cs; %% write data; void init() { EOF sed -n '0,/^%%$/d; /^%%{$/q; {s/^/\t\t/;p}' $file.pr cat << EOF %% write init; } void exec( char data[], int len ) { int p = 0; int pe = len; int eof = len; String _s; %% write exec; } void finish( ) { if ( cs >= ${class}_first_final ) System.out.println( "ACCEPT" ); else System.out.println( "FAIL" ); } EOF # Write out the test data. sed -n '0,/\/\* _____INPUT_____/d; /_____INPUT_____ \*\//q; p;' $file | awk ' BEGIN { print " static final String inp[] = {" } { print " " $0 "," } END { print " };" print "" print " static final int inplen = " NR ";" }' # Write out the main routine. cat << EOF public static void main (String[] args) { $class machine = new $class(); for ( int i = 0; i < inplen; i++ ) { machine.init(); machine.exec( inp[i].toCharArray(), inp[i].length() ); machine.finish(); } } } EOF # Write out the expected output. sed -n '/\/\* _____OUTPUT_____/,/_____OUTPUT_____ \*\//p;' $file # Don't need this language-specific file anymore. rm $file.pr ragel-6.8/test/element3.rl0000664000175000017500000000475612043335171012451 00000000000000/* * @LANG: obj-c */ #include #include struct LangEl { int key; char *name; }; @interface Fsm : Object { @public int cs; }; // Initialize the machine. Invokes any init statement blocks. Returns 0 // if the machine begins in a non-accepting state and 1 if the machine // begins in an accepting state. - (int) initFsm; // Execute the machine on a block of data. Returns -1 if after processing // the data, the machine is in the error state and can never accept, 0 if // the machine is in a non-accepting state and 1 if the machine is in an // accepting state. - (int) executeWithData:( struct LangEl *)data len:(int)len; // Indicate that there is no more data. Returns -1 if the machine finishes // in the error state and does not accept, 0 if the machine finishes // in any other non-accepting state and 1 if the machine finishes in an // accepting state. - (int) finish; @end; @implementation Fsm %%{ machine Fsm; alphtype int; getkey fpc->key; action a1 {} action a2 {} action a3 {} main := ( 1 2* 3 ) ${printf("%s\n", fpc->name);} %/{printf("accept\n");}; }%% %% write data; - (int) initFsm; { %% write init; return 0; } - (int) executeWithData:( struct LangEl *)_data len:(int)_len; { struct LangEl *p = _data; struct LangEl *pe = _data + _len; struct LangEl *eof = pe; %% write exec; if ( self->cs == Fsm_error ) return -1; return ( self->cs >= Fsm_first_final ) ? 1 : 0; } - (int) finish; { if ( self->cs == Fsm_error ) return -1; return ( self->cs >= Fsm_first_final ) ? 1 : 0; } @end int main() { static Fsm *fsm; static struct LangEl lel[] = { {1, "one"}, {2, "two-a"}, {2, "two-b"}, {2, "two-c"}, {3, "three"} }; fsm = [[Fsm alloc] init]; [fsm initFsm]; [fsm executeWithData:lel len:5]; [fsm finish]; return 0; } @interface Fsm2 : Object { // The current state may be read and written to from outside of the // machine. From within action code, curs is -1 and writing to it has no // effect. @public int cs; @protected } // Execute the machine on a block of data. Returns -1 if after processing // the data, the machine is in the error state and can never accept, 0 if // the machine is in a non-accepting state and 1 if the machine is in an // accepting state. - (int) executeWithElements:(int) elements length:(unsigned)length; @end @implementation Fsm2 - (int) executeWithElements:(int)elements length:(unsigned)length; { return 0; } @end #ifdef _____OUTPUT_____ one two-a two-b two-c three accept #endif ragel-6.8/test/scan4.rl0000664000175000017500000000063712043335171011737 00000000000000/* * @LANG: indep */ ptr ts; ptr te; int act; int token; %% %%{ machine scanner; # Warning: changing the patterns or the input string will affect the # coverage of the scanner action types. main := |* 'a' => { prints "pat1\n"; }; [ab]+ . 'c' => { prints "pat2\n"; }; any; *|; }%% /* _____INPUT_____ "ba a" _____INPUT_____ */ /* _____OUTPUT_____ pat1 pat1 ACCEPT _____OUTPUT_____ */ ragel-6.8/test/gotocallret1.rl0000664000175000017500000000444312043335171013326 00000000000000/* * @LANG: indep */ /* * Demonstrate the use of goto, call and return. This machine expects either a * lower case char or a digit as a command then a space followed by the command * arg. If the command is a char, then the arg must be an a string of chars. * If the command is a digit, then the arg must be a string of digits. This * choice is determined by action code, rather than though transition * desitinations. */ char comm; int top; int stack[32]; %% %%{ machine GotoCallRet; # A reference to a state in an unused action caused a segfault in 5.8. */ action unusedAction { fentry(garble_line); } action err_garbling_line { prints "error: garbling line\n"; } action goto_main { fgoto main; } action recovery_failed { prints "error: failed to recover\n"; } # Error machine, consumes to end of # line, then starts the main line over. garble_line := ( (any-'\n')*'\n') >err_garbling_line @goto_main $/recovery_failed; action hold_and_return {fhold; fret;} # Look for a string of alphas or of digits, # on anything else, hold the character and return. alp_comm := alpha+ $!hold_and_return; dig_comm := digit+ $!hold_and_return; # Choose which to machine to call into based on the command. action comm_arg { if ( comm >= 'a' ) fcall alp_comm; else fcall dig_comm; } # Specifies command string. Note that the arg is left out. command = ( [a-z0-9] @{comm = fc;} ' ' @comm_arg '\n' ) @{prints "correct command\n";}; # Any number of commands. If there is an # error anywhere, garble the line. main := command* $!{fhold;fgoto garble_line;}; }%% /* _____INPUT_____ "lkajsdf\n" "2134\n" "(\n" "\n" "*234234()0909 092 -234aslkf09`1 11\n" "1\n" "909\n" "1 a\n" "11 1\n" "a 1\n" "aa a\n" "1 1\n" "1 123456\n" "a a\n" "a abcdef\n" "h" "a aa1" _____INPUT_____ */ /* _____OUTPUT_____ error: garbling line ACCEPT error: garbling line ACCEPT error: garbling line ACCEPT error: garbling line ACCEPT error: garbling line ACCEPT error: garbling line ACCEPT error: garbling line ACCEPT error: garbling line ACCEPT error: garbling line ACCEPT error: garbling line ACCEPT error: garbling line ACCEPT correct command ACCEPT correct command ACCEPT correct command ACCEPT correct command ACCEPT error: failed to recover FAIL error: garbling line error: failed to recover FAIL _____OUTPUT_____ */ ragel-6.8/test/call1.rl0000664000175000017500000000261612043335171011722 00000000000000/* * @LANG: c */ #include #include int num = 0; struct test { int cs, top, stack[32]; }; %%{ machine test; access fsm->; action check_num { if ( num & 1 ) fcall *fentry(odd); else fcall even; } # Test call and return functionality. even := 'even' any @{fhold; fret;}; odd := 'odd' any @{fhold; fret;}; num = [0-9]+ ${ num = num * 10 + (fc - '0'); }; even_odd = num ' ' @check_num "\n"; # Test calls in out actions. fail := !(any*); out_acts = 'OA ok\n' | 'OA error1\n' | 'OA error2\n'; main := even_odd | out_acts; }%% %% write data; void test_init( struct test *fsm ) { num = 0; %% write init; } void test_execute( struct test *fsm, const char *data, int len ) { const char *p = data; const char *pe = data+len; %% write exec; } int test_finish( struct test *fsm ) { if ( fsm->cs == test_error ) return -1; if ( fsm->cs >= test_first_final ) return 1; return 0; } #define BUFSIZE 1024 void test( char *buf ) { struct test test; test_init( &test ); test_execute( &test, buf, strlen(buf) ); if ( test_finish( &test ) > 0 ) printf( "ACCEPT\n" ); else printf( "FAIL\n" ); } int main() { test( "78 even\n" ); test( "89 odd\n" ); test( "1 even\n" ); test( "0 odd\n" ); test( "OA ok\n" ); test( "OA error1\n" ); test( "OA error2\n" ); return 0; } #ifdef _____OUTPUT_____ ACCEPT ACCEPT FAIL FAIL ACCEPT ACCEPT ACCEPT #endif ragel-6.8/test/erract8.rl0000664000175000017500000000127412043335171012275 00000000000000/* * @LANG: java */ class erract8 { %%{ machine erract8; action on_char { System.out.println("char: " + data[p]); } action on_err { System.out.println("err: " + data[p]); } action to_state { System.out.println("to state: " + data[p]); } main := 'heXXX' $on_char $err(on_err) $to(to_state); }%% %% write data; static void test( char data[] ) { int cs, p = 0, pe = data.length; int eof = pe; int top; %% write init; %% write exec; System.out.println("rest: " + data[p] + data[p+1] + data[p+2]); } public static void main( String args[] ) { test( "hello".toCharArray() ); } } /* _____OUTPUT_____ char: h to state: h char: e to state: e err: l rest: llo */ ragel-6.8/test/strings2.h0000664000175000017500000000011312043335171012301 00000000000000#ifndef _STRINGS1_H #define _STRINGS1_H struct strs { int cs; }; #endif ragel-6.8/test/recdescent3.rl0000664000175000017500000000337212043335171013130 00000000000000# # @LANG: ruby # %%{ machine recdescent3; prepush { if top == stack_size print( "growing stack\n" ); stack_size = top * 2; # Don't actually bother to resize here, but we do print messages. # stack = (int*)realloc( stack, sizeof(int)*stack_size ); end } postpop { if stack_size > (top * 4) print( "shrinking stack\n" ); stack_size = top * 2; # Don't actually bother to resize here, but we do print messages. # stack = (int*)realloc( stack, sizeof(int)*stack_size ); end } action item_start { item = p; } action item_finish { print( "item: " ); print( data[item..p-1] ); print( "\n" ); } action call_main { print( "calling main\n" ); fcall main; } action return_main { if top == 0 print( "STRAY CLOSE\n" ); fbreak; end print( "returning from main\n" ); fhold; fret; } id = [a-zA-Z_]+; number = [0-9]+; ws = [ \t\n]+; main := ( ws | ( number | id ) >item_start %item_finish | '{' @call_main '}' | '}' @return_main )**; }%% %% write data; def run_machine( data ) item = 0; p = 0; pe = data.length; eof = pe; cs = 0; stack = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]; stack_size = 1; top = 0; %% write init; %% write exec; if cs == recdescent3_error puts "SCANNER_ERROR" end end inp = [ "88 foo { 99 {{{{}}}}{ } }", "76 } sadf" ] inp.each { |str| run_machine(str) } =begin _____OUTPUT_____ item: 88 item: foo calling main item: 99 calling main growing stack calling main growing stack calling main calling main growing stack returning from main returning from main returning from main returning from main shrinking stack calling main returning from main returning from main shrinking stack item: 76 STRAY CLOSE =end _____OUTPUT_____ ragel-6.8/test/mailbox3.rl0000664000175000017500000001216712106050031012433 00000000000000/* * @LANG: c++ * @CFLAGS: -I../aapl */ #include #include using std::cin; using std::cout; using std::cerr; using std::endl; %%{ machine mailbox; action prn_char { cout << *p; } action prn_space { cout << ' '; } action prn_word { cout.write(ws, p-ws); cout << ' '; } action prn_addr1 { cout << "| "; cout.write(ws+1, p-ws-2); } action prn_addr2 { cout << "| "; cout.write(ws, p-ws); } action prn_tab { cout << '\t'; } action prn_nl { cout << '\n'; } action prn_separator { cout << "------\n"; } action prn_from { cout << "FROM\n"; } action prn_to { cout << "TO\n"; } action prn_subj { cout << "SUBJECT\n"; } action start_word { ws = p; } action start_headers { preserve = p; } action end_headers {preserve = 0;} day = upper lower{2}; month = upper lower{2}; year = digit{4}; time = digit{2} ':' digit{2} ( ':' digit{2} )?; letterZone = upper{3}; numZone = [+\-] digit{4}; zone = letterZone | numZone; dayNum = ( digit | ' ' ) digit; date = day ' ' month ' ' dayNum ' ' time ' ' ( year | year ' ' zone | zone ' ' year ); fromLine = 'From ' [^\n]* ' ' date '\n' @start_headers; headerChar = print - [ :]; headersToPrint = 'From' | 'To' | 'Subject'; headersToConsume = headerChar+ - headersToPrint; action init_hlen {hlen = 0;} action hlen {hlen++ < 50} consumeHeaderBody = ':' @init_hlen ( [^\n] | ( '\n' [ \t] ) )* when hlen '\n'; consumeHeader = headersToConsume consumeHeaderBody; addrWS = ( [ \t]+ | '\n' [ \t]+ ); addrComment = '(' [^)]* ')'; addrWord = [^"'@,<>() \t\n]+; addrAddr1 = '<' [^>]* '>'; addrAddr2 = addrWord '@' addrWord; addrString = '"' [^"]* '"' | "'" [^']* "'"; addrItem = ( addrAddr1 %prn_addr1 | addrAddr2 %prn_addr2 | addrWord %prn_word | addrString %prn_word ) >start_word; address = ( addrWS | addrComment | addrItem )** >prn_tab; addrHeader = ( 'From' %prn_from | 'To' %prn_to ) ':' @init_hlen ( address ( ',' @prn_nl address )* ) when hlen '\n' %prn_nl; subjectHeader = 'Subject:' @prn_subj @prn_tab @init_hlen ( ' '* <: ( [^\n] @prn_char | ( '\n' [ \t]+ ) %prn_space )** ) when hlen '\n' %prn_nl; header = consumeHeader | addrHeader | subjectHeader; messageLine = ( [^\n]* when hlen '\n' @init_hlen ) - fromLine; main := ( fromLine %prn_separator header* '\n' @end_headers @init_hlen messageLine* )*; }%% %% write data; #define BUFSIZE 8192 void test( const char *buf ) { int cs, len = strlen( buf ); const char *preserve = 0, *ws = 0; int hlen = 0; %% write init; const char *p = buf; const char *pe = p + len; %% write exec; if ( cs < mailbox_first_final ) { cout << endl << endl; cout << "DID NOT FINISH IN A FINAL STATE" << endl; } } int main() { test( "From user@host.com Wed Nov 28 13:30:05 2001\n" "From: \"Adrian D. Thurston\" \n" "Subject: the squirrel has landed\n" "\n" "Message goes here. \n" "From (trick from line).\n" "From: not really a header\n" "\n" "From user2@host2.com Wed Nov 28 13:30:05 2001\n" "To: \"(kill 1)\" Edgar Allen Poe (da man)\n" "Subject: (no subject) this is a really long subject which should fail the length constraint \n" "Other: 0123456789\n" "\n" "Message goes here. \n" "\n" ); test( "From user@host.com Wed Nov 28 13:30:05 2001\n" "To: \"(kill 2)\" some guy \n" "From: \"Adrian D. Thurston this name is far too long\" \n" "Subject: the squirrel has landed\n" "\n" "From user2@host2.com Wed Nov 28 13:30:05 2001\n" "To: Edgar Allen Poe (da man)\n" "Subject: (no subject) \n" "\n" ); test( "From user@host.com Wed Nov 28 13:30:05 2001\n" "To: \"(kill 3)\" some guy \n" "From: \"Adrian D. Thurston This name is fore sure absolutely too long\" \n" "Subject: the squirrel has landed\n" "\n" ); test( "From user@host.com Wed Nov 28 13:30:05 2001\n" "From: \"Adrian D. Thurston \" \n" "Subject: (kill 4) the squirrel has landed\n" "Other: This is another header field, not interpreted, that is too long\n" "\n" ); test( "From user@host.com Wed Nov 28 13:30:05 2001\n" "From: \"Adrian D. Thurston \" \n" "Subject: (kill 5)the squirrel has landed\n" "\n" "This message line is okay.\n" "But this message line is far too long and will cause an error.\n" ); return 0; } #ifdef _____OUTPUT_____ ------ FROM "Adrian D. Thurston" | thurston@complang.org SUBJECT the squirrel has landed ------ TO "(kill 1)" Edgar Allen Poe | ep@net.com SUBJECT (no subject) this is a really long subject whic DID NOT FINISH IN A FINAL STATE ------ TO "(kill 2)" some guy | sg@net.com FROM "Adrian D. Thurston this name is far too long" DID NOT FINISH IN A FINAL STATE ------ TO "(kill 3)" some guy | sg@net.com FROM DID NOT FINISH IN A FINAL STATE ------ FROM "Adrian D. Thurston " | t@cs.ca SUBJECT (kill 4) the squirrel has landed DID NOT FINISH IN A FINAL STATE ------ FROM "Adrian D. Thurston " | t@cs.ca SUBJECT (kill 5)the squirrel has landed DID NOT FINISH IN A FINAL STATE #endif ragel-6.8/test/erract1.rl0000664000175000017500000000460412043335171012266 00000000000000/* * @LANG: c++ */ /* * Test error actions. */ #include #include #include using namespace std; struct ErrAct { int cs; // Initialize the machine. Invokes any init statement blocks. Returns 0 // if the machine begins in a non-accepting state and 1 if the machine // begins in an accepting state. int init( ); // Execute the machine on a block of data. Returns -1 if after processing // the data, the machine is in the error state and can never accept, 0 if // the machine is in a non-accepting state and 1 if the machine is in an // accepting state. int execute( const char *data, int len ); // Indicate that there is no more data. Returns -1 if the machine finishes // in the error state and does not accept, 0 if the machine finishes // in any other non-accepting state and 1 if the machine finishes in an // accepting state. int finish( ); }; %%{ machine ErrAct; action expect_digit_plus_minus { printf(" DIGIT PLUS MINUS\n"); } action expect_digit { printf(" DIGIT\n"); } action expect_digit_decimal { printf(" DIGIT DECIMAL\n"); } float = ( ( [\-+] >err expect_digit_plus_minus %err expect_digit | "" ) ( [0-9] [0-9]* $err expect_digit_decimal ) ( '.' [0-9]+ $err expect_digit )? ); main := float '\n'; }%% %% write data; int ErrAct::init( ) { %% write init; return 0; } int ErrAct::execute( const char *_data, int _len ) { const char *p = _data; const char *pe = _data+_len; const char *eof = pe; %% write exec; if ( cs == ErrAct_error ) return -1; if ( cs >= ErrAct_first_final ) return 1; return 0; } int ErrAct::finish( ) { if ( cs == ErrAct_error ) return -1; if ( cs >= ErrAct_first_final ) return 1; return 0; } #define BUFSIZE 1024 void test( const char *buf ) { ErrAct errAct; errAct.init(); errAct.execute( buf, strlen(buf) ); if ( errAct.finish() > 0 ) cout << "ACCEPT" << endl; else cout << "FAIL" << endl; } int main() { test( "1\n" ); test( "+1\n" ); test( "-1\n" ); test( "1.1\n" ); test( "+1.1\n" ); test( "-1.1\n" ); test( "a\n" ); test( "-\n" ); test( "+\n" ); test( "-a\n" ); test( "+b\n" ); test( "1.\n" ); test( "1d\n" ); test( "1.d\n" ); test( "1.1d\n" ); return 0; } #ifdef _____OUTPUT_____ ACCEPT ACCEPT ACCEPT ACCEPT ACCEPT ACCEPT DIGIT PLUS MINUS FAIL DIGIT FAIL DIGIT FAIL DIGIT FAIL DIGIT FAIL DIGIT FAIL DIGIT DECIMAL FAIL DIGIT FAIL DIGIT FAIL #endif ragel-6.8/test/import1.rl0000664000175000017500000000143212043335171012314 00000000000000/* * @LANG: c */ #include char *foo = "foo"; char b = 98; char a = 97; char r = 114; #define SP 32 #define NL '\n' %%{ machine tmp; import "import1.rl"; foobar = foo @{printf("foo\n"); } | b a r @{printf("bar\n");}; main := ( foobar SP foobar NL )*; }%% %% write data; int cs; void exec_str( char *p, int len ) { char *pe = p + len; %% write exec; } void exec_c( char c ) { exec_str( &c, 1 ); } int main() { %% write init; exec_str( foo, 3 ); exec_c( SP ); exec_c( b ); exec_c( a ); exec_c( r ); exec_c( NL ); exec_c( b ); exec_c( a ); exec_c( r ); exec_c( SP ); exec_str( foo, 3 ); exec_c( NL ); if ( cs < tmp_first_final ) printf("FAIL\n"); else printf("ACCEPT\n"); return 0; } #ifdef _____OUTPUT_____ foo bar bar foo ACCEPT #endif ragel-6.8/test/langtrans_csharp.txl0000664000175000017500000001744312043335171014455 00000000000000include "testcase.txl" keys 'bool 'new end keys define csharp_statements [repeat csharp_lang_stmt] end define define csharp_lang_stmt [al_ragel_stmt] | [csharp_variable_decl] | [csharp_expr_stmt] | [csharp_if_stmt] | [EX] '{ [IN] [NL] [csharp_statements] [EX] '} [IN] [NL] end define define csharp_variable_decl [csharp_type_decl] [opt union] [id] '; [NL] end define define csharp_type_decl [al_type_decl] | 'bool | 'String end define define csharp_expr_stmt [csharp_expr] '; [NL] end define define csharp_expr [csharp_term] [repeat csharp_expr_extend] end define define csharp_expr_extend [al_expr_op] [csharp_term] end define define csharp_term [al_term] | [id] [repeat csharp_dot_id] | [id] [repeat csharp_dot_id] '( [csharp_args] ') | 'new [csharp_type_decl] [union] | 'new [csharp_type_decl] '( [csharp_args] ') end define define csharp_dot_id '. [id] end define define csharp_args [list csharp_expr] end define define csharp_sign '- | '+ end define define csharp_if_stmt 'if '( [csharp_expr] ') [NL] [IN] [csharp_lang_stmt] [EX] [opt csharp_else] end define define csharp_else 'else [NL] [IN] [csharp_lang_stmt] [EX] end define define csharp_lang [csharp_statements] '%% [NL] [csharp_statements] [ragel_def] end define define program [lang_indep] | [csharp_lang] end define redefine al_host_block '{ [NL] [IN] [al_statements] [EX] '} [NL] | '{ [NL] [IN] [csharp_statements] [EX] '} [NL] end define redefine cond_action_stmt 'action [id] '{ [al_expr] '} [NL] | 'action [id] '{ [csharp_expr] '} [NL] end redefine function clearUnion Type [csharp_type_decl] Id [id] replace [opt union] Union [union] import ArrayInits [csharp_statements] Stmts [repeat csharp_lang_stmt] export ArrayInits Id '= 'new Type Union '; Stmts by '[] end function rule ptrTypes replace [al_type_decl] 'ptr by 'int end rule function alStmtToCSharp1 AlStmt [action_lang_stmt] deconstruct AlStmt VarDecl [al_variable_decl] deconstruct VarDecl Type [al_type_decl] Id [id] OptUnion [opt union] '; construct CSharpType [csharp_type_decl] Type construct Result [csharp_variable_decl] CSharpType [ptrTypes] OptUnion [clearUnion CSharpType Id] Id '; replace [repeat csharp_lang_stmt] by Result end function rule alTermToCSharp1 replace [al_term] 'first_token_char by 'data '[ts] end rule rule alTermToCSharp2 replace [al_term] '< _ [al_type_decl] '> '( AlExpr [al_expr] ') by '( AlExpr ') end rule function alTermToCSharp replace [al_term] AlTerm [al_term] by AlTerm [alTermToCSharp1] [alTermToCSharp2] end function function alExprExtendToCSharp AlExprExtend [repeat al_expr_extend] deconstruct AlExprExtend Op [al_expr_op] Term [al_term] Rest [repeat al_expr_extend] construct CSharpRest [repeat csharp_expr_extend] _ [alExprExtendToCSharp Rest] replace [repeat csharp_expr_extend] by Op Term [alTermToCSharp] CSharpRest end function function alExprToCSharp AlExpr [al_expr] deconstruct AlExpr ALTerm [al_term] AlExprExtend [repeat al_expr_extend] construct CSharpExprExtend [repeat csharp_expr_extend] _ [alExprExtendToCSharp AlExprExtend] construct Result [opt csharp_expr] ALTerm [alTermToCSharp] CSharpExprExtend replace [opt csharp_expr] by Result end function function alStmtToCSharp2 AlStmt [action_lang_stmt] deconstruct AlStmt AlExpr [al_expr] '; construct OptCSharpExpr [opt csharp_expr] _ [alExprToCSharp AlExpr] deconstruct OptCSharpExpr CSharpExpr [csharp_expr] replace [repeat csharp_lang_stmt] by CSharpExpr '; end function function alOptElseCSharp AlOptElse [opt al_else] deconstruct AlOptElse 'else AlSubStmt [action_lang_stmt] construct AlSubStmts [repeat action_lang_stmt] AlSubStmt construct CSharpSubStmts [repeat csharp_lang_stmt] _ [alToCSharp AlSubStmts] deconstruct CSharpSubStmts CSharpSubStmt [csharp_lang_stmt] replace [opt csharp_else] by 'else CSharpSubStmt end function function alStmtToCSharp3 AlStmt [action_lang_stmt] deconstruct AlStmt 'if '( AlExpr [al_expr] ') AlSubStmt [action_lang_stmt] AlOptElse [opt al_else] construct OptCSharpExpr [opt csharp_expr] _ [alExprToCSharp AlExpr] deconstruct OptCSharpExpr CSharpExpr [csharp_expr] construct AlSubStmts [repeat action_lang_stmt] AlSubStmt construct CSharpSubStmts [repeat csharp_lang_stmt] _ [alToCSharp AlSubStmts] deconstruct CSharpSubStmts CSharpSubStmt [csharp_lang_stmt] construct OptCSharpElse [opt csharp_else] _ [alOptElseCSharp AlOptElse] replace [repeat csharp_lang_stmt] by 'if '( CSharpExpr ') CSharpSubStmt OptCSharpElse end function function alStmtToCSharp4a AlStmt [action_lang_stmt] deconstruct AlStmt 'printi Id [id] '; replace [repeat csharp_lang_stmt] by 'Console '. 'Write '( Id '); end function function alStmtToCSharp4b AlStmt [action_lang_stmt] deconstruct AlStmt 'prints String [stringlit] '; replace [repeat csharp_lang_stmt] by 'Console '. 'Write '( String '); end function function alStmtToCSharp4c AlStmt [action_lang_stmt] deconstruct AlStmt 'printb Id [id] '; replace [repeat csharp_lang_stmt] by '_s '= 'new 'String '( Id ', '0 ', 'pos ') '; 'Console '. 'Write '( '_s '); end function function alStmtToCSharp4d AlStmt [action_lang_stmt] deconstruct AlStmt 'print_token '; replace [repeat csharp_lang_stmt] by '_s '= 'new 'String '( 'data ', 'ts ', 'te '- 'ts ') '; 'Console '. 'Write '( '_s '); end function function alStmtToCSharp5 AlStmt [action_lang_stmt] deconstruct AlStmt '{ AlSubStmts [repeat action_lang_stmt] '} construct CSharpSubStmts [repeat csharp_lang_stmt] _ [alToCSharp AlSubStmts] replace [repeat csharp_lang_stmt] by '{ CSharpSubStmts '} end function function alStmtToCSharp6 AlStmt [action_lang_stmt] deconstruct AlStmt RagelStmt [al_ragel_stmt] replace [repeat csharp_lang_stmt] by RagelStmt end function function alToCSharp AlStmts [repeat action_lang_stmt] deconstruct AlStmts FirstStmt [action_lang_stmt] Rest [repeat action_lang_stmt] construct CSharpFirst [repeat csharp_lang_stmt] _ [alStmtToCSharp1 FirstStmt] [alStmtToCSharp2 FirstStmt] [alStmtToCSharp3 FirstStmt] [alStmtToCSharp4a FirstStmt] [alStmtToCSharp4b FirstStmt] [alStmtToCSharp4c FirstStmt] [alStmtToCSharp4d FirstStmt] [alStmtToCSharp5 FirstStmt] [alStmtToCSharp6 FirstStmt] construct CSharpRest [repeat csharp_lang_stmt] _ [alToCSharp Rest] replace [repeat csharp_lang_stmt] by CSharpFirst [. CSharpRest] end function rule actionTransCSharp replace [al_host_block] '{ AlStmts [repeat action_lang_stmt] '} construct CSharpStmts [repeat csharp_lang_stmt] _ [alToCSharp AlStmts] by '{ CSharpStmts '} end rule rule condTransCSharp replace [cond_action_stmt] 'action Id [id] '{ AlExpr [al_expr] '} construct OptCSharpExpr [opt csharp_expr] _ [alExprToCSharp AlExpr] deconstruct OptCSharpExpr CSharpExpr [csharp_expr] by 'action Id '{ CSharpExpr '} end rule rule machineName replace $ [machine_stmt] 'machine _ [id] '; import TXLargs [repeat stringlit] Arg1 [stringlit] _ [repeat stringlit] construct ClassName [id] _ [unquote Arg1] by 'machine ClassName '; end rule function langTransCSharp replace [program] Definitions [repeat action_lang_stmt] '%% Initializations [repeat action_lang_stmt] RagelDef [ragel_def] construct CSharpDefinitions [repeat csharp_lang_stmt] _ [alToCSharp Definitions] construct CSharpInitializations [repeat csharp_lang_stmt] _ [alToCSharp Initializations] construct NewRagelDef [ragel_def] RagelDef [actionTransCSharp] [condTransCSharp] [machineName] import ArrayInits [csharp_statements] ArrayInitStmts [repeat csharp_lang_stmt] by CSharpDefinitions '%% ArrayInitStmts [. CSharpInitializations] NewRagelDef end function function main replace [program] P [program] export ArrayInits [csharp_statements] _ by P [langTransCSharp] end function ragel-6.8/test/element2.rl0000664000175000017500000000176012043335171012440 00000000000000/* * @LANG: c */ #include struct LangEl { int key; char *name; }; struct fsm { int cs; }; %%{ machine fsm; alphtype int; getkey fpc->key; variable cs fsm->cs; action a1 {} action a2 {} action a3 {} main := ( 1 2* 3 ) ${printf("%s\n", fpc->name);} %/{printf("accept\n");}; }%% %% write data; void fsm_init( struct fsm *fsm ) { %% write init; } void fsm_execute( struct fsm *fsm, struct LangEl *_data, int _len ) { struct LangEl *p = _data; struct LangEl *pe = _data+_len; struct LangEl *eof = pe; %% write exec; } int fsm_finish( struct fsm *fsm ) { if ( fsm->cs == fsm_error ) return -1; if ( fsm->cs >= fsm_first_final ) return 1; return 0; } int main() { static struct fsm fsm; static struct LangEl lel[] = { {1, "one"}, {2, "two-a"}, {2, "two-b"}, {2, "two-c"}, {3, "three"} }; fsm_init( &fsm ); fsm_execute( &fsm, lel, 5 ); fsm_finish( &fsm ); return 0; } #ifdef _____OUTPUT_____ one two-a two-b two-c three accept #endif ragel-6.8/test/erract4.rl0000664000175000017500000000416412043335171012272 00000000000000/* * @LANG: obj-c */ #include #include #define IDENT_BUFLEN 256 @interface ErrAct : Object { @public int cs; }; // Initialize the machine. Invokes any init statement blocks. Returns 0 // if the machine begins in a non-accepting state and 1 if the machine // begins in an accepting state. - (int) initFsm; // Execute the machine on a block of data. Returns -1 if after processing // the data, the machine is in the error state and can never accept, 0 if // the machine is in a non-accepting state and 1 if the machine is in an // accepting state. - (void) executeWithData:(const char *)data len:(int)len; // Indicate that there is no more data. Returns -1 if the machine finishes // in the error state and does not accept, 0 if the machine finishes // in any other non-accepting state and 1 if the machine finishes in an // accepting state. - (int) finish; @end @implementation ErrAct %%{ machine ErrAct; # The data that is to go into the fsm structure. action hello_fails { printf("hello fails\n");} newline = ( any | '\n' @{printf("newline\n");} )*; hello = 'hello\n'* $^hello_fails @/hello_fails; main := newline | hello; }%% %% write data; - (int) initFsm; { %% write init; return 1; } - (void) executeWithData:(const char *)_data len:(int)_len; { const char *p = _data; const char *pe = _data + _len; const char *eof = pe; %% write exec; } - (int) finish; { if ( cs == ErrAct_error ) return -1; else if ( cs >= ErrAct_first_final ) return 1; return 0; } @end #include #include #define BUFSIZE 2048 ErrAct *fsm; char buf[BUFSIZE]; void test( char *buf ) { int len = strlen(buf); fsm = [[ErrAct alloc] init]; [fsm initFsm]; [fsm executeWithData:buf len:len]; if ( [fsm finish] > 0 ) printf("ACCEPT\n"); else printf("FAIL\n"); } int main() { test( "hello\n" "hello\n" "hello\n" ); test( "hello\n" "hello\n" "hello there\n" ); test( "hello\n" "hello\n" "he" ); test( "" ); return 0; } #ifdef _____OUTPUT_____ newline newline newline ACCEPT newline newline hello fails newline ACCEPT newline newline hello fails ACCEPT ACCEPT #endif ragel-6.8/test/atoi3.rl0000664000175000017500000000163012043335171011740 00000000000000# # @LANG: ruby # %%{ machine atoi3; action begin { neg = false; val = 0; } action see_neg { neg = true; } action add_digit { val = val * 10 + (fc - "0"[0]); } action finish { val = -1 * val if neg } action print { puts val; } atoi = (('-' @ see_neg | '+') ? (digit @ add_digit) +) > begin % finish; main := atoi '\n' @ print; }%% %% write data; def run_machine( data ) p = 0; pe = data.length cs = 0 val = 0; neg = false; %% write init; %% write exec; if cs >= atoi3_first_final puts "ACCEPT" else puts "FAIL" end end inp = [ "1\n", "12\n", "222222\n", "+2123\n", "213 3213\n", "-12321\n", "--123\n", "-99\n", " -3000\n", ] inp.each { |str| run_machine(str) } =begin _____OUTPUT_____ 1 ACCEPT 12 ACCEPT 222222 ACCEPT 2123 ACCEPT FAIL -12321 ACCEPT FAIL -99 ACCEPT FAIL =end _____OUTPUT_____ ragel-6.8/test/export3.rl0000664000175000017500000000123012043335171012321 00000000000000# # @LANG: ruby # %%{ machine test; export c1 = 'c'; export c2 = 'z'; export c3 = 't'; commands := ( c1 . digit* '\n' @{ puts "c1"; } | c2 . alpha* '\n' @{ puts "c2"; }| c3 . '.'* '\n' @{ puts "c3"; } )*; other := any*; }%% %% write exports; %% write data; def run_machine( data ) p = 0; pe = data.length cs = test_en_commands val = 0; neg = false; %% write init nocs; %% write exec; if cs >= test_first_final puts "ACCEPT" else puts "FAIL" end end inp = [ test_ex_c1, ?1, ?2, ?\n, test_ex_c2, ?a, ?b, ?\n, test_ex_c3, ?., ?., ?\n ] run_machine( inp ); =begin _____OUTPUT_____ c1 c2 c3 ACCEPT =end _____OUTPUT_____ ragel-6.8/test/include2.rl0000664000175000017500000000113412043335171012425 00000000000000/* * @LANG: c */ #include #include %%{ machine include_test_4; action NonRef3 {printf(" nr3");} a3 = 'a'@{printf(" a3");}; b3 = 'b'@{printf(" b3");}; }%% %%{ machine include_test_1; include "include1.rl"; include include_test_2 "include1.rl"; include include_test_4; main := a1 b1 @NonRef1 a2 b2 @NonRef2 a3 b3 @NonRef3 0 @{fbreak;}; }%% %% write data; void test( char *p ) { int cs; %% write init; %% write exec noend; printf("\n"); } int main() { test( "ababab" ); return 0; } #ifdef _____OUTPUT_____ a1 b1 nr1 a2 b2 nr2 a3 b3 nr3 #endif ragel-6.8/test/forder2.rl0000664000175000017500000000333112043335171012264 00000000000000/* * @LANG: c */ #include #include /* * After the fact start and ending transitions. Behaves like constructors of * and destructors in c++. */ struct forder { int cs; }; %%{ machine forder; variable cs fsm->cs; inner = 'inner' >{printf("enter inner\n");} ${printf("inside inner\n");} %{printf("leave inner\n");} ; outter = inner >{printf("enter outter\n");} ${printf("inside outter\n");} %{printf("leave outter\n");} ; main := outter . '\n'; }%% %% write data; void forder_init( struct forder *fsm ) { %% write init; } void forder_execute( struct forder *fsm, const char *_data, int _len ) { const char *p = _data; const char *pe = _data+_len; %% write exec; } int forder_finish( struct forder *fsm ) { if ( fsm->cs == forder_error ) return -1; if ( fsm->cs >= forder_first_final ) return 1; return 0; } struct forder fsm; void test( char *buf ) { int len = strlen( buf ); forder_init( &fsm ); forder_execute( &fsm, buf, len ); if ( forder_finish( &fsm ) > 0 ) printf("ACCEPT\n"); else printf("FAIL\n"); } int main() { test( "inner\n"); test( "inner\n" "foobar\n" ); test( "" ); test( "\n" ); test( "inn\n" ); return 0; } #ifdef _____OUTPUT_____ enter outter enter inner inside inner inside outter inside inner inside outter inside inner inside outter inside inner inside outter inside inner inside outter leave inner leave outter ACCEPT enter outter enter inner inside inner inside outter inside inner inside outter inside inner inside outter inside inner inside outter inside inner inside outter leave inner leave outter FAIL FAIL FAIL enter outter enter inner inside inner inside outter inside inner inside outter inside inner inside outter FAIL #endif ragel-6.8/test/clang1.rl0000664000175000017500000001371012043335171012070 00000000000000/* * @LANG: c * A mini C-like language scanner. */ #include #include #define IDENT_BUFLEN 256 %%{ machine clang; # Function to buffer a character. action bufChar { if ( identLen < IDENT_BUFLEN ) { identBuf[identLen] = fc; identLen += 1; } } # Function to clear the buffer. action clearBuf { identLen = 0; } # Functions to dump tokens as they are matched. action ident { identBuf[identLen] = 0; printf("ident(%i): %s\n", curLine, identBuf); } action literal { identBuf[identLen] = 0; printf("literal(%i): %s\n", curLine, identBuf); } action float { identBuf[identLen] = 0; printf("float(%i): %s\n", curLine, identBuf); } action int { identBuf[identLen] = 0; printf("int(%i): %s\n", curLine, identBuf); } action hex { identBuf[identLen] = 0; printf("hex(%i): 0x%s\n", curLine, identBuf); } action symbol { identBuf[identLen] = 0; printf("symbol(%i): %s\n", curLine, identBuf); } # Alpha numberic characters or underscore. alnumu = alnum | '_'; # Alpha charactres or underscore. alphau = alpha | '_'; # Symbols. Upon entering clear the buffer. On all transitions # buffer a character. Upon leaving dump the symbol. symbol = ( punct - [_'"] ) >clearBuf $bufChar %symbol; # Identifier. Upon entering clear the buffer. On all transitions # buffer a character. Upon leaving, dump the identifier. ident = (alphau . alnumu*) >clearBuf $bufChar %ident; # Match single characters inside literal strings. Or match # an escape sequence. Buffers the charater matched. sliteralChar = ( extend - ['\\] ) @bufChar | ( '\\' . extend @bufChar ); dliteralChar = ( extend - ["\\] ) @bufChar | ( '\\' . extend @bufChar ); # Single quote and double quota literals. At the start clear # the buffer. Upon leaving dump the literal. sliteral = ('\'' @clearBuf . sliteralChar* . '\'' ) %literal; dliteral = ('"' @clearBuf . dliteralChar* . '"' ) %literal; literal = sliteral | dliteral; # Whitespace is standard ws, newlines and control codes. whitespace = any - 0x21..0x7e; # Describe both c style comments and c++ style comments. The # priority bump on tne terminator of the comments brings us # out of the extend* which matches everything. ccComment = '//' . extend* $0 . '\n' @1; cComment = '/*' . extend* $0 . '*/' @1; # Match an integer. We don't bother clearing the buf or filling it. # The float machine overlaps with int and it will do it. int = digit+ %int; # Match a float. Upon entering the machine clear the buf, buffer # characters on every trans and dump the float upon leaving. float = ( digit+ . '.' . digit+ ) >clearBuf $bufChar %float; # Match a hex. Upon entering the hex part, clear the buf, buffer characters # on every trans and dump the hex on leaving transitions. hex = '0x' . xdigit+ >clearBuf $bufChar %hex; # Or together all the lanuage elements. fin = ( ccComment | cComment | symbol | ident | literal | whitespace | int | float | hex ); # Star the language elements. It is critical in this type of application # that we decrease the priority of out transitions before doing so. This # is so that when we see 'aa' we stay in the fin machine to match an ident # of length two and not wrap around to the front to match two idents of # length one. clang_main = ( fin $1 %0 )*; # This machine matches everything, taking note of newlines. newline = ( any | '\n' @{ curLine += 1; } )*; # The final fsm is the lexer intersected with the newline machine which # will count lines for us. Since the newline machine accepts everything, # the strings accepted is goverened by the clang_main machine, onto which # the newline machine overlays line counting. main := clang_main & newline; }%% #include %% write data noerror; char data[] = "/*\n" " * Copyright\n" " */\n" "\n" "/* Aapl.\n" " */\n" " \n" "#define _AAPL_RESIZE_H\n" "\n" "#include \n" "\n" "#ifdef AAPL_NAMESPACE\n" "namespace Aapl {\n" "#endif\n" "#define LIN_DEFAULT_STEP 256\n" "#define EXPN_UP( existing, needed ) \\\n" " need > eng ? (ned<<1) : eing\n" " \n" "\n" "/*@}*/\n" "#undef EXPN_UP\n" "#ifdef AAPL_NAMESPACE\n" "#endif /* _AAPL_RESIZE_H */\n"; void test( char *buf ) { int len = strlen( buf ); char *p = buf, *pe = buf + len; char *eof = pe; char identBuf[IDENT_BUFLEN+1]; int identLen; int curLine; int cs; identLen = 0; curLine = 1; %% write init; %% write exec; if ( cs >= clang_first_final ) printf("ACCEPT\n"); else printf("FAIL\n"); } int main() { test( "999 0xaAFF99 99.99 /*\n" "*/ 'lksdj' //\n" "\"\n" "\n" "literal\n" "\n" "\n" "\"0x00aba foobardd.ddsf 0x0.9\n" ); test( "wordwithnum00asdf\n" "000wordfollowsnum,makes new symbol\n" "\n" "finishing early /* unfinished ...\n" ); test( data ); return 0; } #ifdef _____OUTPUT_____ int(1): 999 hex(1): 0xaAFF99 float(1): 99.99 literal(2): lksdj literal(8): literal hex(8): 0x00aba ident(8): foobardd symbol(8): . ident(8): ddsf hex(8): 0x0 symbol(8): . int(8): 9 ACCEPT ident(1): wordwithnum00asdf int(2): 000 ident(2): wordfollowsnum symbol(2): , ident(2): makes ident(2): new ident(2): symbol ident(4): finishing ident(4): early FAIL symbol(8): # ident(8): define ident(8): _AAPL_RESIZE_H symbol(10): # ident(10): include symbol(10): < ident(10): assert symbol(10): . ident(10): h symbol(10): > symbol(12): # ident(12): ifdef ident(12): AAPL_NAMESPACE ident(13): namespace ident(13): Aapl symbol(13): { symbol(14): # ident(14): endif symbol(15): # ident(15): define ident(15): LIN_DEFAULT_STEP int(15): 256 symbol(16): # ident(16): define ident(16): EXPN_UP symbol(16): ( ident(16): existing symbol(16): , ident(16): needed symbol(16): ) symbol(16): \ ident(17): need symbol(17): > ident(17): eng symbol(17): ? symbol(17): ( ident(17): ned symbol(17): < symbol(17): < int(17): 1 symbol(17): ) symbol(17): : ident(17): eing symbol(21): # ident(21): undef ident(21): EXPN_UP symbol(22): # ident(22): ifdef ident(22): AAPL_NAMESPACE symbol(23): # ident(23): endif ACCEPT #endif ragel-6.8/test/xmlcommon.rl0000664000175000017500000001277412043335171012745 00000000000000/* * This file is included by xml.rl * * @IGNORE: yes */ %%{ # # Common XML grammar rules based on the XML 1.0 BNF from: # http://www.jelks.nu/XML/xmlebnf.html # machine CommonXml; S = (0x20 | 0x9 | 0xD | 0xA)+; # WAS PubidChar = 0x20 | 0xD | 0xA | [a-zA-Z0-9] | [-'()+,./:=?;!*#@$_%]; PubidChar = 0x20 | 0xD | 0xA | [a-zA-Z0-9] | [\-'()+,./:=?;!*#@$_%]; PubidLiteral = '"' PubidChar* '"' | "'" (PubidChar - "'")* "'"; Name = (Letter | '_' | ':') (NameChar)*; Comment = ''; # Used strong subtraction operator, and replaced * with +. Ragel complained since using # * results in a machine that accepts 0 length strings, and later it's only used in an # optional construct anyway. # CharData_Old = [^<&]* - ([^<&]* ']]>' [^<&]*); CharData = [^<&]+ -- ']]>'; SystemLiteral = ('"' [^"]* '"') | ("'" [^']* "'"); Eq = S? '=' S?; VersionNum = ([a-zA-Z0-9_.:] | '-')+; # WAS S 'version' Eq (' VersionNum ' | " VersionNum ") - fixed quotes VersionInfo = S 'version' Eq ("'" VersionNum "'" | '"' VersionNum '"'); ExternalID = 'SYSTEM' S SystemLiteral | 'PUBLIC' S PubidLiteral S SystemLiteral; PublicID = 'PUBLIC' S PubidLiteral; NotationDecl = ''; EncName = [A-Za-z] ([A-Za-z0-9._] | '-')*; EncodingDecl = S 'encoding' Eq ('"' EncName '"' | "'" EncName "'" ); # UNUSED TextDecl = ''; NDataDecl = S 'NDATA' S Name; PEReference = '%' Name ';'; EntityRef = '&' Name ';'; CharRef = '&#' [0-9]+ ';' | '&0x' [0-9a-fA-F]+ ';'; Reference = EntityRef | CharRef; EntityValue = '"' ([^%&"] | PEReference | Reference)* '"' | "'" ([^%&'] | PEReference | Reference)* "'"; PEDef = EntityValue | ExternalID; EntityDef = EntityValue | (ExternalID NDataDecl?); PEDecl = ''; GEDecl = ''; EntityDecl = GEDecl | PEDecl; Mixed = '(' S? '#PCDATA' (S? '|' S? Name)* S? ')*' | '(' S? '#PCDATA' S? ')'; # WAS cp = (Name | choice | seq) ('?' | '*' | '+')?; # WAS seq = '(' S? cp ( S? ',' S? cp )* S? ')'; # WAS choice = '(' S? cp ( S? '|' S? cp )* S? ')'; # WAS children = (choice | seq) ('?' | '*' | '+')?; # TODO put validation for this in and make it clearer alt = '?' | '*' | '+'; children = '(' S? ( ( Name alt? ) | '(' | ( ')' alt? ) | [,|] | S ) ')' alt?; contentspec = 'EMPTY' | 'ANY' | Mixed | children; elementdecl = ''; AttValue = '"' ([^<&"] | Reference)* '"' | "'" ([^<&'] | Reference)* "'"; Attribute = Name Eq AttValue; Nmtoken = (NameChar)+; # UNUSED Nmtokens = Nmtoken (S Nmtoken)*; Enumeration = '(' S? Nmtoken (S? '|' S? Nmtoken)* S? ')'; NotationType = 'NOTATION' S '(' S? Name (S? '|' S? Name)* S? ')'; EnumeratedType = NotationType | Enumeration; TokenizedType = 'ID' | 'IDREF' | 'IDREFS' | 'ENTITY' | 'ENTITIES' | 'NMTOKEN' | 'NMTOKENS'; StringType = 'CDATA'; AttType = StringType | TokenizedType | EnumeratedType; DefaultDecl = '#REQUIRED' | '#IMPLIED' | (('#FIXED' S)? AttValue); AttDef = S Name S AttType S DefaultDecl; AttlistDecl = ''; EmptyElemTag = '<' Name (S Attribute)* S? '/>'; ETag = ''; PITarget_Old = Name - (('X' | 'x') ('M' | 'm') ('L' | 'l')); PITarget = Name -- "xml"i; PI = '' Char*)))? '?>'; markupdecl = elementdecl | AttlistDecl | EntityDecl | NotationDecl | PI | Comment; doctypedecl = ''; # TODO extSubsetDecl = ( markupdecl | conditionalSect | PEReference | S )*; # UNUSED extSubsetDecl = ( markupdecl | PEReference | S )*; # UNUSED extSubset = TextDecl? extSubsetDecl; # UNUSED Ignore = Char* - (Char* ('') Char*); # TODO: ignoreSectContents = Ignore ('' Ignore)*; # UNUSED ignoreSectContents = Ignore ('' Ignore)*; # UNUSED ignoreSect = ''; # UNUSED includeSect = ''; # UNUSED conditionalSect = includeSect | ignoreSect; STag = '<' Name (S Attribute)* S? '>'; CDStart = ''; # WAS CData = (Char* - (Char* ']]>' Char*)); CData = (Char* -- CDEnd); CDSect = CDStart CData CDEnd; # UNUSED Subcode = ([a-z] | [A-Z])+; # UNUSED UserCode = ('x' | 'X') '-' ([a-z] | [A-Z])+; # UNUSED IanaCode = ('i' | 'I') '-' ([a-z] | [A-Z])+; # UNUSED ISO639Code = ([a-z] | [A-Z]) ([a-z] | [A-Z]); # UNUSED Langcode = ISO639Code | IanaCode | UserCode; # UNUSED LanguageID = Langcode ('-' Subcode)*; SDDecl = S 'standalone' Eq (("'" ('yes' | 'no') "'") | ('"' ('yes' | 'no') '"')); # UNUSED extPE = TextDecl? extSubsetDecl; Misc = Comment | PI | S; XMLDecl = ''; prolog = XMLDecl? Misc* (doctypedecl Misc*)?; # UNUSED Names = Name (S Name)*; # Added fcall - TODO check logic is correct # UNUSED extParsedEnt = TextDecl? @{fcall content;}; # TODO tag stack validation # WAS element = EmptyElemTag | STag content ETag # WAS content = (element | CharData | Reference | CDSect | PI | Comment)*; content = (EmptyElemTag | STag | ETag | CharData | Reference | CDSect | PI | Comment)*; # WAS document = prolog element Misc*; document = prolog ( EmptyElemTag | ( STag content ETag ) ) Misc*; main := document; }%% ragel-6.8/test/runtests.in0000775000175000017500000002037612106310017012604 00000000000000#!/bin/bash # # Copyright 2006-2009 Adrian Thurston # # This file is part of Ragel. # # Ragel is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # Ragel is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Ragel; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA while getopts "gcnmleT:F:G:P:CDJRAZ" opt; do case $opt in T|F|G|P) genflags="$genflags -$opt$OPTARG" options="$options -$opt$OPTARG" ;; n|m|l|e) minflags="$minflags -$opt" options="$options -$opt" ;; c) compile_only="true" options="$options -$opt" ;; g) allow_generated="true" ;; C|D|J|R|A|Z) langflags="$langflags -$opt" ;; esac done [ -z "$minflags" ] && minflags="-n -m -l -e" [ -z "$genflags" ] && genflags="-T0 -T1 -F0 -F1 -G0 -G1 -G2" [ -z "$langflags" ] && langflags="-C -D -J -R -A -Z" shift $((OPTIND - 1)); [ -z "$*" ] && set -- *.rl config=../src/config.h ragel=../ragel/ragel cxx_compiler="@CXX@" c_compiler="@CC@" objc_compiler="@GOBJC@" d_compiler="@GDC@" java_compiler="@JAVAC@" txl_engine="@TXL@" ruby_engine="@RUBY@" csharp_compiler="@GMCS@" go_compiler="@GOBIN@" function test_error { exit 1; } # split_objs="" # if test $split_iters != "$gen_opt"; then # n=0; # while test $n -lt $split_iters; do # part_root=${root}_`awk 'BEGIN { # width = 0; # high = '$split_iters' - 1; # while ( high > 0 ) { # width = width + 1; # high = int(high / 10); # } # suffFormat = "%" width "." width "d\n"; # printf( suffFormat, '$n' ); # exit 0; # }'` # part_src=${part_root}.c # part_bin=${part_root}.o # echo "$compiler -c $cflags -o $part_bin $part_src" # if ! $compiler -c $cflags -o $part_bin $part_src; then # test_error; # fi # split_objs="$split_objs $part_bin" # n=$((n+1)) # done # fi function run_test() { echo "$ragel $lang_opt $min_opt $gen_opt -o $code_src $test_case" if ! $ragel $lang_opt $min_opt $gen_opt -o $code_src $test_case; then test_error; fi out_args="" [ $lang != java ] && out_args="-o ${binary}"; [ $lang == csharp ] && out_args="-out:${binary}"; # Ruby doesn't need to be compiled. if [ $lang != ruby ]; then echo "$compiler ${cflags} ${out_args} ${code_src}" if ! $compiler ${cflags} ${out_args} ${code_src}; then test_error; fi fi if [ "$compile_only" != "true" ]; then echo -n "running $root ... "; exec_cmd=./$binary [ $lang = java ] && exec_cmd="java ${root}" [ $lang = ruby ] && exec_cmd="ruby ${code_src}" [ $lang = csharp ] && [ "$csharp_compiler" = gmcs ] && exec_cmd="mono ${exec_cmd}" $exec_cmd 2>&1 > $output; if diff --strip-trailing-cr $expected_out $output > /dev/null; then echo "passed"; else echo "FAILED"; test_error; fi; fi } for test_case; do root=${test_case%.rl}; if ! [ -f "$test_case" ]; then echo "runtests: not a file: $test_case"; >&2 exit 1; fi # Check if we should ignore the test case ignore=`sed '/@IGNORE:/s/^.*: *//p;d' $test_case` if [ "$ignore" = yes ]; then continue; fi # If the generated flag is given make sure that the test case is generated. is_generated=`sed '/@GENERATED:/s/^.*: *//p;d' $test_case` if [ "$is_generated" = yes ] && [ "$allow_generated" != true ]; then continue; fi expected_out=$root.exp; sed '1,/_____OUTPUT_____/d;$d' $test_case > $expected_out lang=`sed '/@LANG:/s/^.*: *//p;d' $test_case` if [ -z "$lang" ]; then echo "$test_case: language unset"; >&2 exit 1; fi case $lang in c++) lang_opt=-C; code_suffix=cpp; compiler=$cxx_compiler; cflags="-pedantic -ansi -Wall -O3" ;; d) lang_opt=-D; code_suffix=d; compiler=$d_compiler; cflags="-Wall -O3" ;; c) lang_opt=-C; code_suffix=c; compiler=$c_compiler; cflags="-pedantic -ansi -Wall -O3" ;; obj-c) lang_opt=-C; code_suffix=m; compiler=$objc_compiler cflags="-Wall -O3 -fno-strict-aliasing -lobjc" ;; java) lang_opt=-J; code_suffix=java; compiler=$java_compiler cflags="" ;; ruby) lang_opt=-R; code_suffix=rb; compiler=$ruby_engine cflags="" ;; csharp) lang_opt="-A"; code_suffix=cs; compiler=$csharp_compiler cflags="" ;; go) lang_opt="-Z" code_suffix=go compiler=$go_compiler cflags="" ;; indep) lang_opt=""; # If we have no txl engine then skip this test. [ -z "$txl_engine" ] && continue for lang in c d java ruby csharp go; do case $lang in c) lf="-C";; d) lf="-D";; java) lf="-J";; ruby) lf="-R";; csharp) lf="-A";; go) lf="-Z";; esac echo "$langflags" | grep -e $lf >/dev/null || continue targ=${root}_$lang.rl echo "./langtrans_$lang.sh $test_case > $targ" if ! ./langtrans_$lang.sh $test_case > $targ; then test_error fi echo "./runtests -g $options $targ" if ! ./runtests -g $options $targ; then test_error fi done continue; ;; *) echo "$test_case: unknown language type $lang" >&2 exit 1; ;; esac # Make sure that we are interested in the host language. echo "$langflags" | grep -e $lang_opt >/dev/null || continue code_src=$root.$code_suffix; binary=$root.bin; output=$root.out; # If we have no compiler for the source program then skip it. [ -z "$compiler" ] && continue additional_cflags=`sed '/@CFLAGS:/s/^.*: *//p;d' $test_case` [ -n "$additional_cflags" ] && cflags="$cflags $additional_cflags" allow_minflags=`sed '/@ALLOW_MINFLAGS:/s/^.*: *//p;d' $test_case` [ -z "$allow_minflags" ] && allow_minflags="-n -m -l -e" case $lang in c|c++|d) # Using genflags, get the allowed gen flags from the test case. If the # test case doesn't specify assume that all gen flags are allowed. allow_genflags=`sed '/@ALLOW_GENFLAGS:/s/^.*: *//p;d' $test_case` [ -z "$allow_genflags" ] && allow_genflags="-T0 -T1 -F0 -F1 -G0 -G1 -G2" for min_opt in $minflags; do echo "$allow_minflags" | grep -e $min_opt >/dev/null || continue for gen_opt in $genflags; do echo "$allow_genflags" | grep -e $gen_opt >/dev/null || continue run_test done done ;; java) # Not interested in gen opt. gen_opt="" for min_opt in $minflags; do echo "$allow_minflags" | grep -e $min_opt >/dev/null || continue run_test done ;; ruby) # Using genflags, get the allowed gen flags from the test case. If the # test case doesn't specify assume that all gen flags are allowed. allow_genflags=`sed '/@ALLOW_GENFLAGS:/s/^.*: *//p;d' $test_case` [ -z "$allow_genflags" ] && allow_genflags="-T0 -T1 -F0 -F1" for min_opt in $minflags; do echo "$allow_minflags" | grep -e $min_opt >/dev/null || continue for gen_opt in $genflags; do echo "$allow_genflags" | grep -e $gen_opt >/dev/null || continue run_test done done ;; csharp) # Using genflags, get the allowed gen flags from the test case. If the # test case doesn't specify assume that all gen flags are allowed. allow_genflags=`sed '/@ALLOW_GENFLAGS:/s/^.*: *//p;d' $test_case` [ -z "$allow_genflags" ] && allow_genflags="-T0 -T1 -F0 -F1 -G0 -G1" for min_opt in $minflags; do echo "$allow_minflags" | grep -e $min_opt >/dev/null || continue for gen_opt in $genflags; do echo "$allow_genflags" | grep -e $gen_opt >/dev/null || continue run_test done done ;; go) # Using genflags, get the allowed gen flags from the test case. If the # test case doesn't specify assume that all gen flags are allowed. allow_genflags=`sed '/@ALLOW_GENFLAGS:/s/^.*: *//p;d' $test_case` [ -z "$allow_genflags" ] && allow_genflags="-T0 -T1 -F0 -F1 -G0 -G1 -G2" for min_opt in $minflags; do echo "$allow_minflags" | grep -e $min_opt >/dev/null || continue for gen_opt in $genflags; do echo "$allow_genflags" | grep -e $gen_opt >/dev/null || continue run_test done done ;; esac done ragel-6.8/test/call3.rl0000664000175000017500000000427712043335171011731 00000000000000/* * @LANG: obj-c */ #include #include #include int num = 0; @interface CallTest : Object { @public /* State machine operation data. */ int cs, top, stack[32]; }; // Initialize the machine. Invokes any init statement blocks. Returns 0 // if the machine begins in a non-accepting state and 1 if the machine // begins in an accepting state. - (void) initFsm; // Execute the machine on a block of data. Returns -1 if after processing // the data, the machine is in the error state and can never accept, 0 if // the machine is in a non-accepting state and 1 if the machine is in an // accepting state. - (void) executeWithData:(const char *)data len:(int)len; // Indicate that there is no more data. Returns -1 if the machine finishes // in the error state and does not accept, 0 if the machine finishes // in any other non-accepting state and 1 if the machine finishes in an // accepting state. - (int) finish; @end @implementation CallTest %%{ machine CallTest; action check_num { if ( num & 1 ) fcall odd; else fcall even; } # Test call and return functionality. even := 'even' any @{fhold; fret;}; odd := 'odd' any @{fhold; fret;}; num = [0-9]+ ${ num = num * 10 + (fc - '0'); }; even_odd = num ' ' @check_num "\n"; # Test calls in out actions. fail := !(any*); out_acts = 'OA ok\n' | 'OA error1\n' | 'OA error2\n'; main := even_odd | out_acts; }%% %% write data; - (void) initFsm; { num = 0; %% write init; } - (void) executeWithData:(const char *)data len:(int)len; { const char *p = data; const char *pe = data + len; %% write exec; } - (int) finish; { if ( cs == CallTest_error ) return -1; return ( cs >= CallTest_first_final ) ? 1 : 0; } @end #define BUFSIZE 1024 void test( char *buf ) { CallTest *test = [[CallTest alloc] init]; [test initFsm]; [test executeWithData:buf len:strlen(buf)]; if ( [test finish] > 0 ) printf( "ACCEPT\n" ); else printf( "FAIL\n" ); } int main() { test( "78 even\n" ); test( "89 odd\n" ); test( "1 even\n" ); test( "0 odd\n" ); test( "OA ok\n" ); test( "OA error1\n" ); test( "OA error2\n" ); return 0; } #ifdef _____OUTPUT_____ ACCEPT ACCEPT FAIL FAIL ACCEPT ACCEPT ACCEPT #endif ragel-6.8/test/include1.rl0000664000175000017500000000055312043335171012430 00000000000000/* * @LANG: c * @IGNORE: yes * * Provides definitions for include tests. */ %%{ machine include_test_1; action A {printf(" a1");} action B {printf(" b1");} action NonRef1 {printf(" nr1");} a1 = 'a' @A; b1 = 'b' @B; }%% %%{ machine include_test_2; action NonRef2 {printf(" nr2");} a2 = 'a' @{printf(" a2");}; b2 = 'b' @{printf(" b2");}; }%% ragel-6.8/test/minimize1.rl0000664000175000017500000000171712043335171012631 00000000000000/* * @LANG: c */ #include #include struct min { int cs; }; %%{ machine min; variable cs fsm->cs; action a_or_b { printf("a or b\n"); } main := ( ( 'a' . [ab]* @a_or_b ) | ( 'b' . [ab]* @a_or_b ) ) . '\n'; }%% %% write data; void min_init( struct min *fsm ) { %% write init; } void min_execute( struct min *fsm, const char *_data, int _len ) { const char *p = _data; const char *pe = _data+_len; %% write exec; } int min_finish( struct min *fsm ) { if ( fsm->cs == min_error ) return -1; if ( fsm->cs >= min_first_final ) return 1; return 0; } struct min fsm; void test( char *buf ) { int len = strlen( buf ); min_init( &fsm ); min_execute( &fsm, buf, len ); if ( min_finish( &fsm ) > 0 ) printf("ACCEPT\n"); else printf("FAIL\n"); } int main() { test( "aaaaaa\n" ); test( "a\n" ); test( "abc\n" ); return 0; } #ifdef _____OUTPUT_____ a or b a or b a or b a or b a or b ACCEPT ACCEPT a or b FAIL #endif ragel-6.8/test/clang2.rl0000664000175000017500000001502412043335171012071 00000000000000/* * @LANG: obj-c * A mini C-like language scanner. */ #include #include #include #define IDENT_BUFLEN 256 @interface Clang : Object { @public /* State machine operation data. */ int cs; /* Parsing data. */ char identBuf[IDENT_BUFLEN+1]; int identLen; int curLine; }; - (void) initFsm; - (void) executeWithData:(const char *)data len:(int)len; - (int) finish; @end %%{ machine Clang; # Function to buffer a character. action bufChar { if ( identLen < IDENT_BUFLEN ) { identBuf[identLen] = fc; identLen += 1; } } # Function to clear the buffer. action clearBuf { identLen = 0; } # Functions to dump tokens as they are matched. action ident { identBuf[identLen] = 0; printf("ident(%i): %s\n", curLine, identBuf); } action literal { identBuf[identLen] = 0; printf("literal(%i): %s\n", curLine, identBuf); } action float { identBuf[identLen] = 0; printf("float(%i): %s\n", curLine, identBuf); } action int { identBuf[identLen] = 0; printf("int(%i): %s\n", curLine, identBuf); } action hex { identBuf[identLen] = 0; printf("hex(%i): 0x%s\n", curLine, identBuf); } action symbol { identBuf[identLen] = 0; printf("symbol(%i): %s\n", curLine, identBuf); } # Alpha numberic characters or underscore. alnumu = alnum | '_'; # Alpha charactres or underscore. alphau = alpha | '_'; # Symbols. Upon entering clear the buffer. On all transitions # buffer a character. Upon leaving dump the symbol. symbol = ( punct - [_'"] ) >clearBuf $bufChar %symbol; # Identifier. Upon entering clear the buffer. On all transitions # buffer a character. Upon leaving, dump the identifier. ident = (alphau . alnumu*) >clearBuf $bufChar %ident; # Match single characters inside literal strings. Or match # an escape sequence. Buffers the charater matched. sliteralChar = ( extend - ['\\] ) @bufChar | ( '\\' . extend @bufChar ); dliteralChar = ( extend - ["\\] ) @bufChar | ( '\\' . extend @bufChar ); # Single quote and double quota literals. At the start clear # the buffer. Upon leaving dump the literal. sliteral = ('\'' @clearBuf . sliteralChar* . '\'' ) %literal; dliteral = ('"' @clearBuf . dliteralChar* . '"' ) %literal; literal = sliteral | dliteral; # Whitespace is standard ws, newlines and control codes. whitespace = any - 0x21..0x7e; # Describe both c style comments and c++ style comments. The # priority bump on tne terminator of the comments brings us # out of the extend* which matches everything. ccComment = '//' . extend* $0 . '\n' @1; cComment = '/*' . extend* $0 . '*/' @1; # Match an integer. We don't bother clearing the buf or filling it. # The float machine overlaps with int and it will do it. int = digit+ %int; # Match a float. Upon entering the machine clear the buf, buffer # characters on every trans and dump the float upon leaving. float = ( digit+ . '.' . digit+ ) >clearBuf $bufChar %float; # Match a hex. Upon entering the hex part, clear the buf, buffer characters # on every trans and dump the hex on leaving transitions. hex = '0x' . xdigit+ >clearBuf $bufChar %hex; # Or together all the lanuage elements. fin = ( ccComment | cComment | symbol | ident | literal | whitespace | int | float | hex ); # Star the language elements. It is critical in this type of application # that we decrease the priority of out transitions before doing so. This # is so that when we see 'aa' we stay in the fin machine to match an ident # of length two and not wrap around to the front to match two idents of # length one. clang_main = ( fin $1 %0 )*; # This machine matches everything, taking note of newlines. newline = ( any | '\n' @{ curLine += 1; } )*; # The final fsm is the lexer intersected with the newline machine which # will count lines for us. Since the newline machine accepts everything, # the strings accepted is goverened by the clang_main machine, onto which # the newline machine overlays line counting. main := clang_main & newline; }%% @implementation Clang %% write data; - (void) initFsm; { identLen = 0; curLine = 1; %% write init; } - (void) executeWithData:(const char *)data len:(int)len; { const char *p = data; const char *pe = data + len; const char *eof = pe; %% write exec; } - (int) finish; { if ( cs == Clang_error ) return -1; if ( cs >= Clang_first_final ) return 1; return 0; } @end #define BUFSIZE 2048 Clang *fsm; char buf[BUFSIZE]; void test( char *buf ) { int len = strlen(buf); fsm = [[Clang alloc] init]; [fsm initFsm]; [fsm executeWithData:buf len:len]; if ( [fsm finish] > 0 ) printf("ACCEPT\n"); else printf("FAIL\n"); } int main() { test( "999 0xaAFF99 99.99 /*\n" "*/ 'lksdj' //\n" "\"\n" "\n" "literal\n" "\n" "\n" "\"0x00aba foobardd.ddsf 0x0.9\n" ); test( "wordwithnum00asdf\n" "000wordfollowsnum,makes new symbol\n" "\n" "finishing early /* unfinished ...\n" ); test( "/*\n" " * Copyright\n" " */\n" "\n" "/* Aapl.\n" " */\n" " \n" "#define _AAPL_RESIZE_H\n" "\n" "#include \n" "\n" "#ifdef AAPL_NAMESPACE\n" "namespace Aapl {\n" "#endif\n" "#define LIN_DEFAULT_STEP 256\n" "#define EXPN_UP( existing, needed ) \\\n" " need > eng ? (ned<<1) : eing\n" " \n" "\n" "/*@}*/\n" "#undef EXPN_UP\n" "#ifdef AAPL_NAMESPACE\n" "#endif /* _AAPL_RESIZE_H */\n" ); return 0; } #ifdef _____OUTPUT_____ int(1): 999 hex(1): 0xaAFF99 float(1): 99.99 literal(2): lksdj literal(8): literal hex(8): 0x00aba ident(8): foobardd symbol(8): . ident(8): ddsf hex(8): 0x0 symbol(8): . int(8): 9 ACCEPT ident(1): wordwithnum00asdf int(2): 000 ident(2): wordfollowsnum symbol(2): , ident(2): makes ident(2): new ident(2): symbol ident(4): finishing ident(4): early FAIL symbol(8): # ident(8): define ident(8): _AAPL_RESIZE_H symbol(10): # ident(10): include symbol(10): < ident(10): assert symbol(10): . ident(10): h symbol(10): > symbol(12): # ident(12): ifdef ident(12): AAPL_NAMESPACE ident(13): namespace ident(13): Aapl symbol(13): { symbol(14): # ident(14): endif symbol(15): # ident(15): define ident(15): LIN_DEFAULT_STEP int(15): 256 symbol(16): # ident(16): define ident(16): EXPN_UP symbol(16): ( ident(16): existing symbol(16): , ident(16): needed symbol(16): ) symbol(16): \ ident(17): need symbol(17): > ident(17): eng symbol(17): ? symbol(17): ( ident(17): ned symbol(17): < symbol(17): < int(17): 1 symbol(17): ) symbol(17): : ident(17): eing symbol(21): # ident(21): undef ident(21): EXPN_UP symbol(22): # ident(22): ifdef ident(22): AAPL_NAMESPACE symbol(23): # ident(23): endif ACCEPT #endif ragel-6.8/test/forder1.rl0000664000175000017500000000223012043335171012260 00000000000000/* * @LANG: c */ #include #include struct forder { int cs; }; %%{ machine forder; variable cs fsm->cs; second = 'b' >{printf("enter b1\n");} >{printf("enter b2\n");} ; first = 'a' %{printf("leave a\n");} @{printf("finish a\n");} ; main := first . second . '\n'; }%% %% write data; void forder_init( struct forder *fsm ) { %% write init; } void forder_execute( struct forder *fsm, const char *_data, int _len ) { const char *p = _data; const char *pe = _data+_len; %% write exec; } int forder_finish( struct forder *fsm ) { if ( fsm->cs == forder_error ) return -1; if ( fsm->cs >= forder_first_final ) return 1; return 0; } struct forder fsm; void test( char *buf ) { int len = strlen(buf); forder_init( &fsm ); forder_execute( &fsm, buf, len ); if ( forder_finish( &fsm ) > 0 ) printf("ACCEPT\n"); else printf("FAIL\n"); } int main() { test( "ab\n"); test( "abx\n"); test( "" ); test( "ab\n" "fail after newline\n" ); return 0; } #ifdef _____OUTPUT_____ finish a leave a enter b1 enter b2 ACCEPT finish a leave a enter b1 enter b2 FAIL FAIL finish a leave a enter b1 enter b2 FAIL #endif ragel-6.8/test/cppscan4.rl0000664000175000017500000001773312043335171012447 00000000000000/* * @LANG: d */ module cppscan; import std.c.stdio; import std.string; const int BUFSIZE = 2048; const int TK_Dlit = 192; const int TK_Slit = 193; const int TK_Float = 194; const int TK_Id = 195; const int TK_NameSep = 197; const int TK_Arrow = 211; const int TK_PlusPlus = 212; const int TK_MinusMinus = 213; const int TK_ArrowStar = 214; const int TK_DotStar = 215; const int TK_ShiftLeft = 216; const int TK_ShiftRight = 217; const int TK_IntegerDecimal = 218; const int TK_IntegerOctal = 219; const int TK_IntegerHex = 220; const int TK_EqualsEquals = 223; const int TK_NotEquals = 224; const int TK_AndAnd = 225; const int TK_OrOr = 226; const int TK_MultAssign = 227; const int TK_DivAssign = 228; const int TK_PercentAssign = 229; const int TK_PlusAssign = 230; const int TK_MinusAssign = 231; const int TK_AmpAssign = 232; const int TK_CaretAssign = 233; const int TK_BarAssign = 234; const int TK_DotDotDot = 240; class Scanner { int line, col; int tokStart; int inlineDepth; int count; char[] tokBuf; char[] nonTokBuf; void pass(char c) { nonTokBuf ~= c; } void buf(char c) { tokBuf ~= c; } void token( int id ) { /* Leader. */ if ( nonTokBuf.length > 0 ) { printf("%.*s", nonTokBuf); nonTokBuf = ""; } /* Token data. */ printf("<%d>%.*s", id, tokBuf); tokBuf = ""; } int cs, stack, top; %%{ machine Scanner; action pass { pass(fc); } action buf { buf(fc); } action emit_slit { token( TK_Slit ); } action emit_dlit { token( TK_Dlit ); } action emit_id { token( TK_Id ); } action emit_integer_decimal { token( TK_IntegerDecimal ); } action emit_integer_octal { token( TK_IntegerOctal ); } action emit_integer_hex { token( TK_IntegerHex ); } action emit_float { token( TK_Float ); } action emit_symbol { token( tokBuf[0] ); } action tokst { tokStart = col; } # Single and double literals. slit = ( 'L'? ( "'" ( [^'\\\n] | /\\./ )* "'" ) $buf ) >tokst %emit_slit; dlit = ( 'L'? ( '"' ( [^"\\\n] | /\\./ )* '"' ) $buf ) >tokst %emit_dlit; # Identifiers id = ( [a-zA-Z_] [a-zA-Z0-9_]* ) >tokst $buf %emit_id; # Floating literals. fract_const = digit* '.' digit+ | digit+ '.'; exponent = [eE] [+\-]? digit+; float_suffix = [flFL]; float = ( fract_const exponent? float_suffix? | digit+ exponent float_suffix? ) >tokst $buf %emit_float; # Integer decimal. Leading part buffered by float. integer_decimal = ( ( '0' | [1-9] [0-9]* ) [ulUL]{0,3} $buf ) %emit_integer_decimal; # Integer octal. Leading part buffered by float. integer_octal = ( '0' [0-9]+ [ulUL]{0,2} $buf ) %emit_integer_octal; # Integer hex. Leading 0 buffered by float. integer_hex = ( '0' ( 'x' [0-9a-fA-F]+ [ulUL]{0,2} ) $buf ) %emit_integer_hex; # Only buffer the second item, first buffered by symbol. */ namesep = '::' @buf %{token( TK_NameSep );}; deqs = '==' @buf %{token( TK_EqualsEquals );}; neqs = '!=' @buf %{token( TK_NotEquals );}; and_and = '&&' @buf %{token( TK_AndAnd );}; or_or = '||' @buf %{token( TK_OrOr );}; mult_assign = '*=' @buf %{token( TK_MultAssign );}; percent_assign = '%=' @buf %{token( TK_PercentAssign );}; plus_assign = '+=' @buf %{token( TK_PlusAssign );}; minus_assign = '-=' @buf %{token( TK_MinusAssign );}; amp_assign = '&=' @buf %{token( TK_AmpAssign );}; caret_assign = '^=' @buf %{token( TK_CaretAssign );}; bar_assign = '|=' @buf %{token( TK_BarAssign );}; plus_plus = '++' @buf %{token( TK_PlusPlus );}; minus_minus = '--' @buf %{token( TK_MinusMinus );}; arrow = '->' @buf %{token( TK_Arrow );}; arrow_star = '->*' @buf %{token( TK_ArrowStar );}; dot_star = '.*' @buf %{token( TK_DotStar );}; # Buffer both items. * div_assign = '/=' @{buf('/');buf(fc);} %{token( TK_DivAssign );}; # Double dot is sent as two dots. dot_dot = '..' %{token('.'); buf('.'); token('.');}; # Three char compounds, first item already buffered. */ dot_dot_dot = '...' %{buf('.'); buf('.'); token( TK_DotDotDot );}; # All compunds compound = namesep | deqs | neqs | and_and | or_or | mult_assign | div_assign | percent_assign | plus_assign | minus_assign | amp_assign | caret_assign | bar_assign | plus_plus | minus_minus | arrow | arrow_star | dot_star | dot_dot | dot_dot_dot; # Single char symbols. symbol = ( punct - [./_"'] ) >tokst $buf %emit_symbol | # Do not immediately buffer slash, may be start of comment. '/' >tokst %{ buf('/'); token( '/' ); } | # Dot covered by float. '.' %emit_symbol; # Comments and whitespace. commc = '/*' @{pass('/'); pass('*');} ( any* $0 '*/' @1 ) $pass; commcc = '//' @{pass('/'); pass('/');} ( any* $0 '\n' @1 ) $pass; whitespace = ( any - ( 0 | 33..126 ) )+ $pass; action onEOFChar { /* On EOF char, write out the non token buffer. */ printf("%.*s", nonTokBuf); nonTokBuf = ""; } # Using 0 as eof. If seeingAs a result all null characters get ignored. EOF = 0 @onEOFChar; # All outside code tokens. tokens = ( id | slit | dlit | float | integer_decimal | integer_octal | integer_hex | compound | symbol ); nontok = ( commc | commcc | whitespace | EOF ); position = ( '\n' @{ line += 1; col = 1; } | [^\n] @{ col += 1; } )*; main := ( ( tokens | nontok )** ) & position; }%% %% write data noprefix; void init( ) { /* A count of the number of characters in * a token. Used for % sequences. */ count = 0; line = 1; col = 1; %% write init; return 1; } int execute( char* _data, int _len ) { char *p = _data; char *pe = _data + _len; char *eof = null; %% write exec; if ( cs == error ) return -1; if ( cs >= first_final ) return 1; return 0; } // Indicate that there is no more data. Returns -1 if the machine finishes // in the error state and does not accept, 0 if the machine finishes // in any other non-accepting state and 1 if the machine finishes in an // accepting state. int finish( ) { if ( cs == error ) return -1; if ( cs >= first_final ) return 1; return 0; } }; void test(char[] buf) { Scanner scanner = new Scanner(); scanner.init(); scanner.execute( buf.ptr, buf.length ); /* The last token is ignored (because there is no next token). Send * trailing null to force the last token into whitespace. */ char eof_char = 0; if ( scanner.execute( &eof_char, 1 ) <= 0 ) { fprintf(stderr, "cppscan: scan failed\n"); } } int main() { test( "/*\n" " * Copyright \n" " */\n" "\n" "RedTransAp *RedFsmAp::reduceTrans( TransAp *trans )\n" "{\n" " RedAction *action = 0;\n" " if ( trans->actionTable.length() > 0 ) {\n" " if ( actionMap.insert( trans->actionTable, &action ) )\n" " action->id = nextActionId++;\n" " }\n" " \n" " RedStateAp *targ = (RedStateAp*)trans->toState;\n" " if ( action == 0 ) {\n" " delete trans;\n" " return 0;\n" " }\n" "\n" " trans->~TransAp();\n" " inDict = new(trans) RedTransAp( targ, action, nextTransId++ );\n" " transSet.insert( inDict );\n" "}\n" ); test( "->*\n" ".*\n" "/*\"*/\n" "\"/*\"\n" "L'\"'\n" "L\"'\"\n" ); return 0; } /+ _____OUTPUT_____ /* * Copyright */ <195>RedTransAp <42>*<195>RedFsmAp<197>::<195>reduceTrans<40>( <195>TransAp <42>*<195>trans <41>) <123>{ <195>RedAction <42>*<195>action <61>= <218>0<59>; <195>if <40>( <195>trans<211>-><195>actionTable<46>.<195>length<40>(<41>) <62>> <218>0 <41>) <123>{ <195>if <40>( <195>actionMap<46>.<195>insert<40>( <195>trans<211>-><195>actionTable<44>, <38>&<195>action <41>) <41>) <195>action<211>-><195>id <61>= <195>nextActionId<212>++<59>; <125>} <195>RedStateAp <42>*<195>targ <61>= <40>(<195>RedStateAp<42>*<41>)<195>trans<211>-><195>toState<59>; <195>if <40>( <195>action <223>== <218>0 <41>) <123>{ <195>delete <195>trans<59>; <195>return <218>0<59>; <125>} <195>trans<211>-><126>~<195>TransAp<40>(<41>)<59>; <195>inDict <61>= <195>new<40>(<195>trans<41>) <195>RedTransAp<40>( <195>targ<44>, <195>action<44>, <195>nextTransId<212>++ <41>)<59>; <195>transSet<46>.<195>insert<40>( <195>inDict <41>)<59>; <125>} <214>->* <215>.* /*"*/ <192>"/*" <193>L'"' <192>L"'" +++++++++++++++++/ ragel-6.8/test/clang4.rl0000664000175000017500000001073012063362072012074 00000000000000/* * @LANG: indep * @NEEDS_EOF: yes */ char array[32]; int pos; int line; %% pos = 0; line = 1; %%{ machine clang; # Function to buffer a character. action bufChar { array[pos] = fc; pos = pos + 1; } # Function to clear the buffer. action clearBuf { pos = 0; } # Functions to dump tokens as they are matched. action ident { prints "ident("; printi line; prints ","; printi pos; prints "): "; printb array; prints "\n"; } action literal { prints "literal("; printi line; prints ","; printi pos; prints "): "; printb array; prints "\n"; } action float { prints "float("; printi line; prints ","; printi pos; prints "): "; printb array; prints "\n"; } action integer { prints "int("; printi line; prints ","; printi pos; prints "): "; printb array; prints "\n"; } action hex { prints "hex("; printi line; prints ","; printi pos; prints "): "; printb array; prints "\n"; } action symbol { prints "symbol("; printi line; prints ","; printi pos; prints "): "; printb array; prints "\n"; } # Alpha numberic characters or underscore. alnumu = alnum | '_'; # Alpha charactres or underscore. alphau = alpha | '_'; # Symbols. Upon entering clear the buffer. On all transitions # buffer a character. Upon leaving dump the symbol. symbol = ( punct - [_'"] ) >clearBuf $bufChar %symbol; # Identifier. Upon entering clear the buffer. On all transitions # buffer a character. Upon leaving, dump the identifier. ident = (alphau . alnumu*) >clearBuf $bufChar %ident; # Match single characters inside literal strings. Or match # an escape sequence. Buffers the charater matched. sliteralChar = ( extend - ['\\] ) @bufChar | ( '\\' . extend @bufChar ); dliteralChar = ( extend - ["\\] ) @bufChar | ( '\\' . extend @bufChar ); # Single quote and double quota literals. At the start clear # the buffer. Upon leaving dump the literal. sliteral = ('\'' @clearBuf . sliteralChar* . '\'' ) %literal; dliteral = ('"' @clearBuf . dliteralChar* . '"' ) %literal; literal = sliteral | dliteral; # Whitespace is standard ws, newlines and control codes. whitespace = any - 33 .. 126; # Describe both c style comments and c++ style comments. The # priority bump on tne terminator of the comments brings us # out of the extend* which matches everything. ccComment = '//' . extend* $0 . '\n' @1; cComment = '/!' . extend* $0 . '!/' @1; # Match an integer. We don't bother clearing the buf or filling it. # The float machine overlaps with int and it will do it. integer = digit+ %integer; # Match a float. Upon entering the machine clear the buf, buffer # characters on every trans and dump the float upon leaving. float = ( digit+ . '.' . digit+ ) >clearBuf $bufChar %float; # Match a hex. Upon entering the hex part, clear the buf, buffer characters # on every trans and dump the hex on leaving transitions. hex = '0x' . xdigit+ >clearBuf $bufChar %hex; # Or together all the lanuage elements. fin = ( ccComment | cComment | symbol | ident | literal | whitespace | integer | float | hex ); # Star the language elements. It is critical in this type of application # that we decrease the priority of out transitions before doing so. This # is so that when we see 'aa' we stay in the fin machine to match an ident # of length two and not wrap around to the front to match two idents of # length one. clang_main = ( fin $1 %0 )*; # This machine matches everything, taking note of newlines. newline = ( any | '\n' @{ line = line + 1; } )*; # The final fsm is the lexer intersected with the newline machine which # will count lines for us. Since the newline machine accepts everything, # the strings accepted is goverened by the clang_main machine, onto which # the newline machine overlays line counting. main := clang_main & newline; }%% /* _____INPUT_____ "999 0xaAFF99 99.99 /!\n!/ 'lksdj' //\n\"\n\nliteral\n\n\n\"0x00aba foobardd.ddsf 0x0.9\n" "wordwithnum00asdf\n000wordfollowsnum,makes new symbol\n\nfinishing early /! unfinished ...\n" _____INPUT_____ */ /* _____OUTPUT_____ int(1,3): 999 hex(1,6): aAFF99 float(1,5): 99.99 literal(2,5): lksdj literal(8,12): literal hex(8,5): 00aba ident(8,8): foobardd symbol(8,1): . ident(8,4): ddsf hex(8,1): 0 symbol(8,1): . int(8,1): 9 ACCEPT ident(1,17): wordwithnum00asdf int(2,3): 000 ident(2,14): wordfollowsnum symbol(2,1): , ident(2,5): makes ident(2,3): new ident(2,6): symbol ident(4,9): finishing ident(4,5): early FAIL _____OUTPUT_____ */ ragel-6.8/test/cppscan6.rl0000664000175000017500000001145112043335171012440 00000000000000/* * @LANG: indep * * const char *data = ts; * int len = te - ts; * cout << "<" << tok << "> "; * for ( int i = 0; i < len; i++ ) * cout << data[i]; * cout << '\n'; */ ptr ts; ptr te; int act; int token; %% %%{ machine scanner; action comment { token = 242; prints "<"; printi token; prints "> "; print_token; prints "\n"; } main := |* # Single and double literals. ( 'L'? "'" ( [^'\\\n] | '\\' any )* "'" ) => { token = 193; prints "<"; printi token; prints "> "; print_token; prints "\n"; }; ( 'L'? '"' ( [^"\\\n] | '\\' any )* '"' ) => { token = 192; prints "<"; printi token; prints "> "; print_token; prints "\n"; }; # Identifiers ( [a-zA-Z_] [a-zA-Z0-9_]* ) =>{ token = 195; prints "<"; printi token; prints "> "; print_token; prints "\n"; }; # Floating literals. fract_const = digit* '.' digit+ | digit+ '.'; exponent = [eE] [+\-]? digit+; float_suffix = [flFL]; ( fract_const exponent? float_suffix? | digit+ exponent float_suffix? ) => { token = 194; prints "<"; printi token; prints "> "; print_token; prints "\n"; }; # Integer decimal. Leading part buffered by float. ( ( '0' | [1-9] [0-9]* ) [ulUL]? ) => { token = 218; prints "<"; printi token; prints "> "; print_token; prints "\n"; }; # Integer octal. Leading part buffered by float. ( '0' [0-9]+ [ulUL]? ) => { token = 219; prints "<"; printi token; prints "> "; print_token; prints "\n"; }; # Integer hex. Leading 0 buffered by float. ( '0' ( 'x' [0-9a-fA-F]+ [ulUL]? ) ) => { token = 220; prints "<"; printi token; prints "> "; print_token; prints "\n"; }; # Only buffer the second item, first buffered by symbol. '::' => { token = 197; prints "<"; printi token; prints "> "; print_token; prints "\n"; }; '==' => { token = 223; prints "<"; printi token; prints "> "; print_token; prints "\n"; }; '!=' => { token = 224; prints "<"; printi token; prints "> "; print_token; prints "\n"; }; '&&' => { token = 225; prints "<"; printi token; prints "> "; print_token; prints "\n"; }; '||' => { token = 226; prints "<"; printi token; prints "> "; print_token; prints "\n"; }; '*=' => { token = 227; prints "<"; printi token; prints "> "; print_token; prints "\n"; }; '/=' => { token = 228; prints "<"; printi token; prints "> "; print_token; prints "\n"; }; '%=' => { token = 229; prints "<"; printi token; prints "> "; print_token; prints "\n"; }; '+=' => { token = 230; prints "<"; printi token; prints "> "; print_token; prints "\n"; }; '-=' => { token = 231; prints "<"; printi token; prints "> "; print_token; prints "\n"; }; '&=' => { token = 232; prints "<"; printi token; prints "> "; print_token; prints "\n"; }; '^=' => { token = 233; prints "<"; printi token; prints "> "; print_token; prints "\n"; }; '|=' => { token = 234; prints "<"; printi token; prints "> "; print_token; prints "\n"; }; '++' => { token = 212; prints "<"; printi token; prints "> "; print_token; prints "\n"; }; '--' => { token = 213; prints "<"; printi token; prints "> "; print_token; prints "\n"; }; '->' => { token = 211; prints "<"; printi token; prints "> "; print_token; prints "\n"; }; '->*' => { token = 214; prints "<"; printi token; prints "> "; print_token; prints "\n"; }; '.*' => { token = 215; prints "<"; printi token; prints "> "; print_token; prints "\n"; }; # Three char compounds, first item already buffered. '...' => { token = 240; prints "<"; printi token; prints "> "; print_token; prints "\n"; }; # Single char symbols. ( punct - [_"'] ) => { token = (first_token_char); prints "<"; printi token; prints "> "; print_token; prints "\n"; }; # Comments and whitespace. '/!' ( any* $0 '!/' @1 ) => comment; '//' ( any* $0 '\n' @1 ) => comment; ( any - 33..126 )+ => { token = 241; prints "<"; printi token; prints "> "; print_token; prints "\n"; }; *|; }%% /* _____INPUT_____ "\"\\\"hi\" /!\n!/\n44 .44\n44. 44\n44 . 44\n44.44\n_hithere22" "'\\''\"\\n\\d'\\\"\"\nhi\n99\n.99\n99e-4\n->*\n||\n0x98\n0x\n//\n/! * !/" "'\n'\n" _____INPUT_____ */ /* _____OUTPUT_____ <192> "\"hi" <241> <242> /! !/ <241> <218> 44 <241> <194> .44 <241> <194> 44. <241> <218> 44 <241> <218> 44 <241> <46> . <241> <218> 44 <241> <194> 44.44 <241> <195> _hithere22 ACCEPT <193> '\'' <192> "\n\d'\"" <241> <195> hi <241> <218> 99 <241> <194> .99 <241> <194> 99e-4 <241> <214> ->* <241> <226> || <241> <220> 0x98 <241> <218> 0 <195> x <241> <242> // <242> /! * !/ ACCEPT FAIL _____OUTPUT_____ */ ragel-6.8/test/langtrans_c.sh0000775000175000017500000000352412062240603013214 00000000000000#!/bin/bash # file=$1 [ -f $file ] || exit 1 # Get the machine name. machine=`sed -n 's/^[\t ]*machine[\t ]*\([a-zA-Z_0-9]*\)[\t ]*;[\t ]*$/\1/p' $file` # Make a temporary version of the test case using the C language translations. sed -n '/\/\*/,/\*\//d;p' $file | txl -q stdin langtrans_c.txl > $file.pr needs_eof=`sed '/@NEEDS_EOF/s/^.*$/yes/p;d' $file` if [ "$needs_eof" != 'yes' ]; then needs_eof=`sed -n '/\/\*/,/\*\//d;p' $file | txl -q stdin checkeofact.txl` fi # Begin writing out the test case. cat << EOF /* * @LANG: c * @GENERATED: yes EOF grep '@ALLOW_GENFLAGS:' $file grep '@ALLOW_MINFLAGS:' $file cat << EOF */ #include #include EOF # Write the data declarations sed -n '/^%%$/q;p' $file.pr # Write out the machine specification. sed -n '/^%%{$/,/^}%%/p' $file.pr # Write out the init and execute routines. cat << EOF int cs; %% write data; void init() { EOF sed -n '0,/^%%$/d; /^%%{$/q; {s/^/\t/;p}' $file.pr cat << EOF %% write init; } void exec( char *data, int len ) { char *p = data; char *pe = data + len; EOF [ "$needs_eof" = "yes" ] && echo "char *eof = pe;" cat << EOF %% write exec; } void finish( ) { if ( cs >= ${machine}_first_final ) printf( "ACCEPT\\n" ); else printf( "FAIL\\n" ); } EOF # Write out the test data. sed -n '0,/\/\* _____INPUT_____/d; /_____INPUT_____ \*\//q; p;' $file | awk ' BEGIN { print "char *inp[] = {" } { print " " $0 "," } END { print "};" print "" print "int inplen = " NR ";" }' # Write out the main routine. cat << EOF int main( ) { int i; for ( i = 0; i < inplen; i++ ) { init(); exec( inp[i], strlen(inp[i]) ); finish(); } return 0; } #ifdef _____OUTPUT_____ EOF # Write out the expected output. sed -n '0,/\/\* _____OUTPUT_____/d; /_____OUTPUT_____ \*\//q; p;' $file echo "#endif" # Don't need this language-specific file anymore. rm $file.pr ragel-6.8/test/call2.rl0000664000175000017500000000407712043335171011726 00000000000000/* * @LANG: c++ */ #include #include int num = 0; struct CallTest { int cs, top, stack[32]; // Initialize the machine. Invokes any init statement blocks. Returns 0 // if the machine begins in a non-accepting state and 1 if the machine // begins in an accepting state. void init( ); // Execute the machine on a block of data. Returns -1 if after processing // the data, the machine is in the error state and can never accept, 0 if // the machine is in a non-accepting state and 1 if the machine is in an // accepting state. void execute( const char *data, int len ); // Indicate that there is no more data. Returns -1 if the machine finishes // in the error state and does not accept, 0 if the machine finishes // in any other non-accepting state and 1 if the machine finishes in an // accepting state. int finish( ); }; %%{ machine CallTest; action check_num { if ( num & 1 ) fcall *fentry(odd); else fcall even; } # Test call and return functionality. even := 'even' any @{fhold; fret;}; odd := 'odd' any @{fhold; fret;}; num = [0-9]+ ${ num = num * 10 + (fc - '0'); }; even_odd = num ' ' @check_num "\n"; # Test calls in out actions. fail := !(any*); out_acts = 'OA ok\n' | 'OA error1\n' | 'OA error2\n'; main := even_odd | out_acts; }%% %% write data; void CallTest::init( ) { num = 0; %% write init; } void CallTest::execute( const char *data, int len ) { const char *p = data; const char *pe = data+len; %% write exec; } int CallTest::finish( ) { if ( this->cs == CallTest_error ) return -1; if ( this->cs >= CallTest_first_final ) return 1; return 0; } #define BUFSIZE 1024 void test( const char *buf ) { CallTest test; test.init(); test.execute( buf, strlen(buf) ); if ( test.finish() > 0 ) printf( "ACCEPT\n" ); else printf( "FAIL\n" ); } int main() { test( "78 even\n" ); test( "89 odd\n" ); test( "1 even\n" ); test( "0 odd\n" ); test( "OA ok\n" ); test( "OA error1\n" ); test( "OA error2\n" ); return 0; } #ifdef _____OUTPUT_____ ACCEPT ACCEPT FAIL FAIL ACCEPT ACCEPT ACCEPT #endif ragel-6.8/test/union.rl0000664000175000017500000000666712106050031012055 00000000000000/* * @LANG: c++ * Show off concurrent abilities. */ #include #include #include #include using namespace std; #define BUFSIZE 2048 struct Concurrent { int cur_char; int start_word; int start_comment; int start_literal; int cs; // Initialize the machine. Invokes any init statement blocks. Returns 0 // if the machine begins in a non-accepting state and 1 if the machine // begins in an accepting state. void init( ); // Execute the machine on a block of data. Returns -1 if after processing // the data, the machine is in the error state and can never accept, 0 if // the machine is in a non-accepting state and 1 if the machine is in an // accepting state. void execute( const char *data, int len ); // Indicate that there is no more data. Returns -1 if the machine finishes // in the error state and does not accept, 0 if the machine finishes // in any other non-accepting state and 1 if the machine finishes in an // accepting state. int finish( ); }; %%{ machine Concurrent; action next_char { cur_char += 1; } action start_word { start_word = cur_char; } action end_word { cout << "word: " << start_word << " " << cur_char-1 << endl; } action start_comment { start_comment = cur_char; } action end_comment { cout << "comment: " << start_comment << " " << cur_char-1 << endl; } action start_literal { start_literal = cur_char; } action end_literal { cout << "literal: " << start_literal << " " << cur_char-1 << endl; } # Count characters. chars = ( any @next_char )*; # Words are non-whitespace. word = ( any-space )+ >start_word %end_word; words = ( ( word | space ) $1 %0 )*; # Finds C style comments. comment = ( '/*' any* $0 '*/'@1 ) >start_comment %end_comment; comments = ( ( comment | any ) $1 %0 )*; # Finds single quoted strings. literalChar = ( any - ['\\] ) | ( '\\' . any ); literal = ('\'' literalChar* '\'' ) >start_literal %end_literal; literals = ( ( literal | (any-'\'') ) $1 %0 )*; main := chars | words | comments | literals; }%% %% write data; void Concurrent::init( ) { cur_char = 0; %% write init; } void Concurrent::execute( const char *data, int len ) { const char *p = data; const char *pe = data + len; const char *eof = pe; %% write exec; } int Concurrent::finish( ) { if ( cs == Concurrent_error ) return -1; if ( cs >= Concurrent_first_final ) return 1; return 0; } void test( const char *buf ) { Concurrent concurrent; concurrent.init(); concurrent.execute( buf, strlen(buf) ); if ( concurrent.finish() > 0 ) cout << "ACCEPT" << endl; else cout << "FAIL" << endl; } int main() { test( "/* in a comment,\n" " * ' and now in a literal string\n" " */ \n" " \n" "the comment has now ended but the literal string lives on\n" "\n" "' comment closed\n" ); test( "/* * ' \\' */ \\' '\n" ); test( "/**/'\\''/*/*/\n" ); return 0; } #ifdef _____OUTPUT_____ word: 1 2 word: 4 5 word: 7 7 word: 9 16 word: 19 19 word: 21 21 word: 23 25 word: 27 29 word: 31 32 word: 34 34 word: 36 42 word: 44 49 word: 52 53 comment: 1 53 word: 58 60 word: 62 68 word: 70 72 word: 74 76 word: 78 82 word: 84 86 word: 88 90 word: 92 98 word: 100 105 word: 107 111 word: 113 114 word: 117 117 literal: 21 117 word: 119 125 word: 127 132 ACCEPT word: 1 2 word: 4 4 word: 6 6 word: 8 9 word: 11 12 comment: 1 12 word: 14 15 word: 17 17 literal: 6 17 ACCEPT comment: 1 4 literal: 5 8 word: 1 13 comment: 9 13 ACCEPT #endif ragel-6.8/test/cppscan1.rl0000664000175000017500000001650212043335171012435 00000000000000/* * @LANG: c++ * * Test works with split code gen. */ #include "cppscan1.h" %%{ machine Scanner; access fsm->; action pass { fsm->pass(fc); } action buf { fsm->buf(fc); } action emit_slit { fsm->token( TK_Slit ); } action emit_dlit { fsm->token( TK_Dlit ); } action emit_id { fsm->token( TK_Id ); } action emit_integer_decimal { fsm->token( TK_IntegerDecimal ); } action emit_integer_octal { fsm->token( TK_IntegerOctal ); } action emit_integer_hex { fsm->token( TK_IntegerHex ); } action emit_float { fsm->token( TK_Float ); } action emit_symbol { fsm->token( fsm->tokBuf.data[0] ); } action tokst { fsm->tokStart = fsm->col; } # Single and double literals. slit = ( 'L'? ( "'" ( [^'\\\n] | /\\./ )* "'" ) $buf ) >tokst %emit_slit; dlit = ( 'L'? ( '"' ( [^"\\\n] | /\\./ )* '"' ) $buf ) >tokst %emit_dlit; # Identifiers id = ( [a-zA-Z_] [a-zA-Z0-9_]* ) >tokst $buf %emit_id; # Floating literals. fract_const = digit* '.' digit+ | digit+ '.'; exponent = [eE] [+\-]? digit+; float_suffix = [flFL]; float = ( fract_const exponent? float_suffix? | digit+ exponent float_suffix? ) >tokst $buf %emit_float; # Integer decimal. Leading part buffered by float. integer_decimal = ( ( '0' | [1-9] [0-9]* ) [ulUL]{0,3} $buf ) %emit_integer_decimal; # Integer octal. Leading part buffered by float. integer_octal = ( '0' [0-9]+ [ulUL]{0,2} $buf ) %emit_integer_octal; # Integer hex. Leading 0 buffered by float. integer_hex = ( '0' ( 'x' [0-9a-fA-F]+ [ulUL]{0,2} ) $buf ) %emit_integer_hex; # Only buffer the second item, first buffered by symbol. */ namesep = '::' @buf %{fsm->token( TK_NameSep );}; deqs = '==' @buf %{fsm->token( TK_EqualsEquals );}; neqs = '!=' @buf %{fsm->token( TK_NotEquals );}; and_and = '&&' @buf %{fsm->token( TK_AndAnd );}; or_or = '||' @buf %{fsm->token( TK_OrOr );}; mult_assign = '*=' @buf %{fsm->token( TK_MultAssign );}; percent_assign = '%=' @buf %{fsm->token( TK_PercentAssign );}; plus_assign = '+=' @buf %{fsm->token( TK_PlusAssign );}; minus_assign = '-=' @buf %{fsm->token( TK_MinusAssign );}; amp_assign = '&=' @buf %{fsm->token( TK_AmpAssign );}; caret_assign = '^=' @buf %{fsm->token( TK_CaretAssign );}; bar_assign = '|=' @buf %{fsm->token( TK_BarAssign );}; plus_plus = '++' @buf %{fsm->token( TK_PlusPlus );}; minus_minus = '--' @buf %{fsm->token( TK_MinusMinus );}; arrow = '->' @buf %{fsm->token( TK_Arrow );}; arrow_star = '->*' @buf %{fsm->token( TK_ArrowStar );}; dot_star = '.*' @buf %{fsm->token( TK_DotStar );}; # Buffer both items. * div_assign = '/=' @{fsm->buf('/');fsm->buf(fc);} %{fsm->token( TK_DivAssign );}; # Double dot is sent as two dots. dot_dot = '..' %{fsm->token('.'); fsm->buf('.'); fsm->token('.');}; # Three char compounds, first item already buffered. */ dot_dot_dot = '...' %{fsm->buf('.'); fsm->buf('.'); fsm->token( TK_DotDotDot );}; # All compunds compound = namesep | deqs | neqs | and_and | or_or | mult_assign | div_assign | percent_assign | plus_assign | minus_assign | amp_assign | caret_assign | bar_assign | plus_plus | minus_minus | arrow | arrow_star | dot_star | dot_dot | dot_dot_dot; # Single char symbols. symbol = ( punct - [./_"'] ) >tokst $buf %emit_symbol | # Do not immediately buffer slash, may be start of comment. '/' >tokst %{ fsm->buf('/'); fsm->token( '/' ); } | # Dot covered by float. '.' %emit_symbol; # Comments and whitespace. commc = '/*' @{fsm->pass('/'); fsm->pass('*');} ( any* $0 '*/' @1 ) $pass; commcc = '//' @{fsm->pass('/'); fsm->pass('/');} ( any* $0 '\n' @1 ) $pass; whitespace = ( any - ( 0 | 33..126 ) )+ $pass; action onEOFChar { /* On EOF char, write out the non token buffer. */ fsm->nonTokBuf.append(0); cout << fsm->nonTokBuf.data; fsm->nonTokBuf.clear(); } # Using 0 as eof. If seeingAs a result all null characters get ignored. EOF = 0 @onEOFChar; # All outside code tokens. tokens = ( id | slit | dlit | float | integer_decimal | integer_octal | integer_hex | compound | symbol ); nontok = ( commc | commcc | whitespace | EOF ); position = ( '\n' @{ fsm->line += 1; fsm->col = 1; } | [^\n] @{ fsm->col += 1; } )*; main := ( ( tokens | nontok )** ) & position; }%% %% write data; void Scanner::init( ) { Scanner *fsm = this; /* A count of the number of characters in * a token. Used for % sequences. */ count = 0; line = 1; col = 1; %% write init; } int Scanner::execute( const char *data, int len ) { Scanner *fsm = this; const char *p = data; const char *pe = data + len; const char *eof = pe; %% write exec; if ( cs == Scanner_error ) return -1; if ( cs >= Scanner_first_final ) return 1; return 0; } int Scanner::finish( ) { if ( cs == Scanner_error ) return -1; if ( cs >= Scanner_first_final ) return 1; return 0; } void Scanner::token( int id ) { /* Leader. */ if ( nonTokBuf.length > 0 ) { nonTokBuf.append(0); cout << nonTokBuf.data; nonTokBuf.clear(); } /* Token data. */ tokBuf.append(0); cout << '<' << id << '>' << tokBuf.data; tokBuf.clear(); } void Buffer::empty() { if ( data != 0 ) { free( data ); data = 0; length = 0; allocated = 0; } } void Buffer::upAllocate( int len ) { if ( data == 0 ) data = (char*) malloc( len ); else data = (char*) realloc( data, len ); allocated = len; } void test( const char *buf ) { Scanner scanner(cout); scanner.init(); scanner.execute( buf, strlen(buf) ); /* The last token is ignored (because there is no next token). Send * trailing null to force the last token into whitespace. */ char eof = 0; if ( scanner.execute( &eof, 1 ) <= 0 ) { cerr << "cppscan: scan failed" << endl; return; } cout.flush(); } int main() { test( "/*\n" " * Copyright \n" " */\n" "\n" "/* Construct an fsmmachine from a graph. */\n" "RedFsmAp::RedFsmAp( FsmAp *graph, bool complete )\n" ":\n" " graph(graph),\n" "{\n" " assert( sizeof(RedTransAp) <= sizeof(TransAp) );\n" "\n" " reduceMachine();\n" "}\n" "\n" "{\n" " /* Get the transition that we want to extend. */\n" " RedTransAp *extendTrans = list[pos].value;\n" "\n" " /* Look ahead in the transition list. */\n" " for ( int next = pos + 1; next < list.length(); pos++, next++ ) {\n" " if ( ! keyOps->eq( list[pos].highKey, nextKey ) )\n" " break;\n" " }\n" " return false;\n" "}\n" "\n" ); test( "->*\n" ".*\n" "/*\"*/\n" "\"/*\"\n" "L'\"'\n" "L\"'\"\n" ); return 0; } #ifdef _____OUTPUT_____ /* * Copyright */ /* Construct an fsmmachine from a graph. */ <195>RedFsmAp<197>::<195>RedFsmAp<40>( <195>FsmAp <42>*<195>graph<44>, <195>bool <195>complete <41>) <58>: <195>graph<40>(<195>graph<41>)<44>, <123>{ <195>assert<40>( <195>sizeof<40>(<195>RedTransAp<41>) <60><<61>= <195>sizeof<40>(<195>TransAp<41>) <41>)<59>; <195>reduceMachine<40>(<41>)<59>; <125>} <123>{ /* Get the transition that we want to extend. */ <195>RedTransAp <42>*<195>extendTrans <61>= <195>list<91>[<195>pos<93>]<46>.<195>value<59>; /* Look ahead in the transition list. */ <195>for <40>( <195>int <195>next <61>= <195>pos <43>+ <218>1<59>; <195>next <60>< <195>list<46>.<195>length<40>(<41>)<59>; <195>pos<212>++<44>, <195>next<212>++ <41>) <123>{ <195>if <40>( <33>! <195>keyOps<211>-><195>eq<40>( <195>list<91>[<195>pos<93>]<46>.<195>highKey<44>, <195>nextKey <41>) <41>) <195>break<59>; <125>} <195>return <195>false<59>; <125>} <214>->* <215>.* /*"*/ <192>"/*" <193>L'"' <192>L"'" #endif ragel-6.8/test/erract9.rl0000664000175000017500000000117312043335171012274 00000000000000# # @LANG: ruby # # Test the host language scanning for ruby. # %%{ machine erract9; action on_char { print("char: ", data[p..p], "\n"); } action on_err { print("err: ", data[p..p], "\n"); } action to_state { print("to state: " , data[p..p], "\n"); } main := 'heXXX' $on_char $err(on_err) $to(to_state); }%% %% write data; def run_machine( data ) p = 0; pe = data.length cs = 0 %% write init; %% write exec; print("rest: " , data[p..p+2], "\n") end inp = [ "hello\n", ] inp.each { |str| run_machine(str) } =begin _____OUTPUT_____ char: h to state: h char: e to state: e err: l rest: llo =end _____OUTPUT_____ ragel-6.8/test/tokstart1.rl0000664000175000017500000001135012043335171012655 00000000000000/* * @LANG: c++ */ #include #include using namespace std; extern char buf[]; struct Scanner { int cs, act; char *ts, *te; // Initialize the machine. Invokes any init statement blocks. Returns 0 // if the machine begins in a non-accepting state and 1 if the machine // begins in an accepting state. void init( ); // Execute the machine on a block of data. Returns -1 if after processing // the data, the machine is in the error state and can never accept, 0 if // the machine is in a non-accepting state and 1 if the machine is in an // accepting state. int execute( char *data, int len ); // Indicate that there is no more data. Returns -1 if the machine finishes // in the error state and does not accept, 0 if the machine finishes // in any other non-accepting state and 1 if the machine finishes in an // accepting state. int finish( ); }; %%{ machine Scanner; action to_act { cout << "to: fc = "; if ( fc == '\'' ) cout << (int)fc; else cout << fc; cout << " ts = " << ( ts == 0 ? -1 : ts-buf ) << endl; } action from_act { cout << "from: fc = "; if ( fc == '\'' ) cout << (int)fc; else cout << fc; cout << " ts = " << ( ts == 0 ? -1 : ts-buf ) << endl; } c_comm := ( any* $0 '*/' @1 @{ fgoto main; } ) $~to_act $*from_act; cxx_comm := ( any* $0 '\n' @1 @{ fgoto main; } ) $~to_act $*from_act; main := |* # Single and double literals. ( 'L'? "'" ( [^'\\\n] | /\\./ )* "'" ) $~ to_act $* from_act; ( 'L'? '"' ( [^"\\\n] | /\\./ )* '"' ) $~ to_act $* from_act; # Identifiers ( [a-zA-Z_] [a-zA-Z0-9_]* ) $~ to_act $* from_act; # Floating literals. fract_const = digit* '.' digit+ | digit+ '.'; exponent = [eE] [+\-]? digit+; float_suffix = [flFL]; ( fract_const exponent? float_suffix? | digit+ exponent float_suffix? ) $~ to_act $* from_act; # Integer decimal. Leading part buffered by float. ( ( '0' | [1-9] [0-9]* ) [ulUL]{0,3} ) $~ to_act $* from_act; # Integer octal. Leading part buffered by float. ( '0' [0-9]+ [ulUL]{0,2} ) $~ to_act $* from_act; # Integer hex. Leading 0 buffered by float. ( '0x' [0-9a-fA-F]+ [ulUL]{0,2} ) $~ to_act $* from_act; # Three char compounds, first item already buffered. */ ( '...' ) $~ to_act $* from_act; # Single char symbols. ( punct - [_"'] ) $~ to_act $* from_act; # Comments and whitespace. ( '/*' ) $~ to_act $* from_act { fgoto c_comm; }; ( '//' ) $~ to_act $* from_act { fgoto cxx_comm; }; ( any - 33..126 )+ $~ to_act $* from_act; *|; }%% %% write data; void Scanner::init( ) { %% write init; } int Scanner::execute( char *data, int len ) { char *p = data; char *pe = data + len; char *eof = pe; %% write exec; return 0; } int Scanner::finish( ) { if ( cs == Scanner_error ) return -1; if ( cs >= Scanner_first_final ) return 1; return 0; } void test( ) { int len = strlen( buf ); Scanner scanner; scanner.init(); scanner.execute( buf, len ); if ( scanner.cs == Scanner_error ) { /* Machine failed before finding a token. */ cout << "PARSE ERROR" << endl; } scanner.finish(); } char buf[4096]; int main() { strcpy( buf, "a b 0.98 /*\n" "9 */'\\''//hi\n" "there\n" ); test(); return 0; } #ifdef _____OUTPUT_____ from: fc = a ts = 0 to: fc = a ts = 0 from: fc = ts = 0 to: fc = a ts = -1 from: fc = ts = 1 to: fc = ts = 1 from: fc = b ts = 1 to: fc = ts = -1 from: fc = b ts = 2 to: fc = b ts = 2 from: fc = ts = 2 to: fc = b ts = -1 from: fc = ts = 3 to: fc = ts = 3 from: fc = 0 ts = 3 to: fc = ts = -1 from: fc = 0 ts = 4 to: fc = 0 ts = 4 from: fc = . ts = 4 to: fc = . ts = 4 from: fc = 9 ts = 4 to: fc = 9 ts = 4 from: fc = 8 ts = 4 to: fc = 8 ts = 4 from: fc = ts = 4 to: fc = 8 ts = -1 from: fc = ts = 8 to: fc = ts = 8 from: fc = / ts = 8 to: fc = ts = -1 from: fc = / ts = 9 to: fc = / ts = 9 from: fc = * ts = 9 to: fc = * ts = -1 from: fc = ts = -1 to: fc = ts = -1 from: fc = 9 ts = -1 to: fc = 9 ts = -1 from: fc = ts = -1 to: fc = ts = -1 from: fc = * ts = -1 to: fc = * ts = -1 from: fc = / ts = -1 to: fc = / ts = -1 from: fc = 39 ts = 16 to: fc = 39 ts = 16 from: fc = \ ts = 16 to: fc = \ ts = 16 from: fc = 39 ts = 16 to: fc = 39 ts = 16 from: fc = 39 ts = 16 to: fc = 39 ts = -1 from: fc = / ts = 20 to: fc = / ts = 20 from: fc = / ts = 20 to: fc = / ts = -1 from: fc = h ts = -1 to: fc = h ts = -1 from: fc = i ts = -1 to: fc = i ts = -1 from: fc = ts = -1 to: fc = ts = -1 from: fc = t ts = 25 to: fc = t ts = 25 from: fc = h ts = 25 to: fc = h ts = 25 from: fc = e ts = 25 to: fc = e ts = 25 from: fc = r ts = 25 to: fc = r ts = 25 from: fc = e ts = 25 to: fc = e ts = 25 from: fc = ts = 25 to: fc = e ts = -1 from: fc = ts = 30 to: fc = ts = 30 to: fc = ts = -1 #endif ragel-6.8/test/erract6.rl0000664000175000017500000000207312043335171012271 00000000000000/* * @LANG: c */ /* * Test of a transition going to the error state. */ #include #define BUFSIZE 2048 struct errintrans { int cs; }; %%{ machine errintrans; variable cs fsm->cs; char = any - (digit | '\n'); line = char* "\n"; main := line+; }%% %% write data; void errintrans_init( struct errintrans *fsm ) { %% write init; } void errintrans_execute( struct errintrans *fsm, const char *_data, int _len ) { const char *p = _data; const char *pe = _data+_len; %% write exec; } int errintrans_finish( struct errintrans *fsm ) { if ( fsm->cs == errintrans_error ) return -1; if ( fsm->cs >= errintrans_first_final ) return 1; return 0; } struct errintrans fsm; #include void test( char *buf ) { int len = strlen( buf ); errintrans_init( &fsm ); errintrans_execute( &fsm, buf, len ); if ( errintrans_finish( &fsm ) > 0 ) printf("ACCEPT\n"); else printf("FAIL\n"); } int main() { test( "good, does not have numbers\n" ); test( "bad, has numbers 666\n" ); return 0; } #ifdef _____OUTPUT_____ ACCEPT FAIL #endif ragel-6.8/test/langtrans_java.txl0000664000175000017500000001710712043335171014113 00000000000000include "testcase.txl" keys 'boolean 'new end keys define java_statements [repeat java_lang_stmt] end define define java_lang_stmt [al_ragel_stmt] | [java_variable_decl] | [java_expr_stmt] | [java_if_stmt] | [EX] '{ [IN] [NL] [java_statements] [EX] '} [IN] [NL] end define define java_variable_decl [java_type_decl] [id] [opt union] '; [NL] end define define java_type_decl [al_type_decl] | 'boolean | 'String end define define java_expr_stmt [java_expr] '; [NL] end define define java_expr [java_term] [repeat java_expr_extend] end define define java_expr_extend [al_expr_op] [java_term] end define define java_term [al_term] | [id] [repeat java_dot_id] | [id] [repeat java_dot_id] '( [java_args] ') | 'new [java_type_decl] [union] | 'new [java_type_decl] '( [java_args] ') end define define java_dot_id '. [id] end define define java_args [list java_expr] end define define java_sign '- | '+ end define define java_if_stmt 'if '( [java_expr] ') [NL] [IN] [java_lang_stmt] [EX] [opt java_else] end define define java_else 'else [NL] [IN] [java_lang_stmt] [EX] end define define java_lang [java_statements] '%% [NL] [java_statements] [ragel_def] end define define program [lang_indep] | [java_lang] end define redefine al_host_block '{ [NL] [IN] [al_statements] [EX] '} [NL] | '{ [NL] [IN] [java_statements] [EX] '} [NL] end define redefine cond_action_stmt 'action [id] '{ [al_expr] '} [NL] | 'action [id] '{ [java_expr] '} [NL] end redefine function clearUnion Type [java_type_decl] Id [id] replace [opt union] Union [union] import ArrayInits [java_statements] Stmts [repeat java_lang_stmt] export ArrayInits Id '= 'new Type Union '; Stmts by '[] end function rule boolTypes replace [java_type_decl] 'bool by 'boolean end rule rule ptrTypes replace [al_type_decl] 'ptr by 'int end rule function alStmtToJava1 AlStmt [action_lang_stmt] deconstruct AlStmt VarDecl [al_variable_decl] deconstruct VarDecl Type [al_type_decl] Id [id] OptUnion [opt union] '; construct JavaType [java_type_decl] Type construct Result [java_variable_decl] JavaType [boolTypes] [ptrTypes] Id OptUnion [clearUnion JavaType Id] '; replace [repeat java_lang_stmt] by Result end function rule alTermToJava1 replace [al_term] 'first_token_char by 'data '[ts] end rule rule alTermToJava2 replace [al_term] '< _ [al_type_decl] '> '( AlExpr [al_expr] ') by '( AlExpr ') end rule function alTermToJava replace [al_term] AlTerm [al_term] by AlTerm [alTermToJava1] [alTermToJava2] end function function alExprExtendToJava AlExprExtend [repeat al_expr_extend] deconstruct AlExprExtend Op [al_expr_op] Term [al_term] Rest [repeat al_expr_extend] construct JavaRest [repeat java_expr_extend] _ [alExprExtendToJava Rest] replace [repeat java_expr_extend] by Op Term [alTermToJava] JavaRest end function function alExprToJava AlExpr [al_expr] deconstruct AlExpr ALTerm [al_term] AlExprExtend [repeat al_expr_extend] construct JavaExprExtend [repeat java_expr_extend] _ [alExprExtendToJava AlExprExtend] construct Result [opt java_expr] ALTerm [alTermToJava] JavaExprExtend replace [opt java_expr] by Result end function function alStmtToJava2 AlStmt [action_lang_stmt] deconstruct AlStmt AlExpr [al_expr] '; construct OptJavaExpr [opt java_expr] _ [alExprToJava AlExpr] deconstruct OptJavaExpr JavaExpr [java_expr] replace [repeat java_lang_stmt] by JavaExpr '; end function function alOptElseJava AlOptElse [opt al_else] deconstruct AlOptElse 'else AlSubStmt [action_lang_stmt] construct AlSubStmts [repeat action_lang_stmt] AlSubStmt construct JavaSubStmts [repeat java_lang_stmt] _ [alToJava AlSubStmts] deconstruct JavaSubStmts JavaSubStmt [java_lang_stmt] replace [opt java_else] by 'else JavaSubStmt end function function alStmtToJava3 AlStmt [action_lang_stmt] deconstruct AlStmt 'if '( AlExpr [al_expr] ') AlSubStmt [action_lang_stmt] AlOptElse [opt al_else] construct OptJavaExpr [opt java_expr] _ [alExprToJava AlExpr] deconstruct OptJavaExpr JavaExpr [java_expr] construct AlSubStmts [repeat action_lang_stmt] AlSubStmt construct JavaSubStmts [repeat java_lang_stmt] _ [alToJava AlSubStmts] deconstruct JavaSubStmts JavaSubStmt [java_lang_stmt] construct OptJavaElse [opt java_else] _ [alOptElseJava AlOptElse] replace [repeat java_lang_stmt] by 'if '( JavaExpr ') JavaSubStmt OptJavaElse end function function alStmtToJava4a AlStmt [action_lang_stmt] deconstruct AlStmt 'printi Id [id] '; replace [repeat java_lang_stmt] by 'System '. 'out '. 'print '( Id '); end function function alStmtToJava4b AlStmt [action_lang_stmt] deconstruct AlStmt 'prints String [stringlit] '; replace [repeat java_lang_stmt] by 'System '. 'out '. 'print '( String '); end function function alStmtToJava4c AlStmt [action_lang_stmt] deconstruct AlStmt 'printb Id [id] '; replace [repeat java_lang_stmt] by '_s '= 'new 'String '( Id ', '0 ', 'pos ') '; 'System '. 'out '. 'print '( '_s '); end function function alStmtToJava4d AlStmt [action_lang_stmt] deconstruct AlStmt 'print_token '; replace [repeat java_lang_stmt] by '_s '= 'new 'String '( 'data ', 'ts ', 'te '- 'ts ') '; 'System '. 'out '. 'print '( '_s '); end function function alStmtToJava5 AlStmt [action_lang_stmt] deconstruct AlStmt '{ AlSubStmts [repeat action_lang_stmt] '} construct JavaSubStmts [repeat java_lang_stmt] _ [alToJava AlSubStmts] replace [repeat java_lang_stmt] by '{ JavaSubStmts '} end function function alStmtToJava6 AlStmt [action_lang_stmt] deconstruct AlStmt RagelStmt [al_ragel_stmt] replace [repeat java_lang_stmt] by RagelStmt end function function alToJava AlStmts [repeat action_lang_stmt] deconstruct AlStmts FirstStmt [action_lang_stmt] Rest [repeat action_lang_stmt] construct JavaFirst [repeat java_lang_stmt] _ [alStmtToJava1 FirstStmt] [alStmtToJava2 FirstStmt] [alStmtToJava3 FirstStmt] [alStmtToJava4a FirstStmt] [alStmtToJava4b FirstStmt] [alStmtToJava4c FirstStmt] [alStmtToJava4d FirstStmt] [alStmtToJava5 FirstStmt] [alStmtToJava6 FirstStmt] construct JavaRest [repeat java_lang_stmt] _ [alToJava Rest] replace [repeat java_lang_stmt] by JavaFirst [. JavaRest] end function rule actionTransJava replace [al_host_block] '{ AlStmts [repeat action_lang_stmt] '} construct JavaStmts [repeat java_lang_stmt] _ [alToJava AlStmts] by '{ JavaStmts '} end rule rule condTransJava replace [cond_action_stmt] 'action Id [id] '{ AlExpr [al_expr] '} construct OptJavaExpr [opt java_expr] _ [alExprToJava AlExpr] deconstruct OptJavaExpr JavaExpr [java_expr] by 'action Id '{ JavaExpr '} end rule rule machineName replace $ [machine_stmt] 'machine _ [id] '; import TXLargs [repeat stringlit] Arg1 [stringlit] _ [repeat stringlit] construct ClassName [id] _ [unquote Arg1] by 'machine ClassName '; end rule function langTransJava replace [program] Definitions [repeat action_lang_stmt] '%% Initializations [repeat action_lang_stmt] RagelDef [ragel_def] construct JavaDefinitions [repeat java_lang_stmt] _ [alToJava Definitions] construct JavaInitializations [repeat java_lang_stmt] _ [alToJava Initializations] construct NewRagelDef [ragel_def] RagelDef [actionTransJava] [condTransJava] [machineName] import ArrayInits [java_statements] ArrayInitStmts [repeat java_lang_stmt] by JavaDefinitions '%% ArrayInitStmts [. JavaInitializations] NewRagelDef end function function main replace [program] P [program] export ArrayInits [java_statements] _ by P [langTransJava] end function ragel-6.8/test/cppscan2.rl0000664000175000017500000001710612043335171012437 00000000000000/* * @LANG: c++ */ #include #include using namespace std; #define TK_Dlit 192 #define TK_Slit 193 #define TK_Float 194 #define TK_Id 195 #define TK_NameSep 197 #define TK_Arrow 211 #define TK_PlusPlus 212 #define TK_MinusMinus 213 #define TK_ArrowStar 214 #define TK_DotStar 215 #define TK_ShiftLeft 216 #define TK_ShiftRight 217 #define TK_IntegerDecimal 218 #define TK_IntegerOctal 219 #define TK_IntegerHex 220 #define TK_EqualsEquals 223 #define TK_NotEquals 224 #define TK_AndAnd 225 #define TK_OrOr 226 #define TK_MultAssign 227 #define TK_DivAssign 228 #define TK_PercentAssign 229 #define TK_PlusAssign 230 #define TK_MinusAssign 231 #define TK_AmpAssign 232 #define TK_CaretAssign 233 #define TK_BarAssign 234 #define TK_DotDotDot 240 #define TK_Whitespace 241 #define TK_Comment 242 #define BUFSIZE 4096 int tok; char buf[BUFSIZE]; const char *ts, *te; void token( const char *data, int len ); bool discard = false; struct Scanner { int cs; // Initialize the machine. Invokes any init statement blocks. Returns 0 // if the machine begins in a non-accepting state and 1 if the machine // begins in an accepting state. int init( ); // Execute the machine on a block of data. Returns -1 if after processing // the data, the machine is in the error state and can never accept, 0 if // the machine is in a non-accepting state and 1 if the machine is in an // accepting state. int execute( const char *data, int len ); // Indicate that there is no more data. Returns -1 if the machine finishes // in the error state and does not accept, 0 if the machine finishes // in any other non-accepting state and 1 if the machine finishes in an // accepting state. int finish( ); }; %%{ machine Scanner; # Single and double literals. slit = ( 'L'? "'" ( [^'\\\n] | /\\./ )* "'" ) @{tok = TK_Slit;}; dlit = ( 'L'? '"' ( [^"\\\n] | /\\./ )* '"' ) @{tok = TK_Dlit;}; # Identifiers id = ( [a-zA-Z_] [a-zA-Z0-9_]* ) @{tok = TK_Id;}; # Floating literals. fract_const = digit* '.' digit+ | digit+ '.'; exponent = [eE] [+\-]? digit+; float_suffix = [flFL]; float = ( fract_const exponent? float_suffix? | digit+ exponent float_suffix? ) @{tok = TK_Float;}; # Integer decimal. Leading part buffered by float. integer_decimal = ( ( '0' | [1-9] [0-9]* ) [ulUL]{0,3} ) @{tok = TK_IntegerDecimal;}; # Integer octal. Leading part buffered by float. integer_octal = ( '0' [0-9]+ [ulUL]{0,2} ) @{tok = TK_IntegerOctal;}; # Integer hex. Leading 0 buffered by float. integer_hex = ( '0' ( 'x' [0-9a-fA-F]+ [ulUL]{0,2} ) ) @{tok = TK_IntegerHex;}; # Only buffer the second item, first buffered by symbol. */ namesep = '::' @{tok = TK_NameSep;}; deqs = '==' @{tok = TK_EqualsEquals;}; neqs = '!=' @{tok = TK_NotEquals;}; and_and = '&&' @{tok = TK_AndAnd;}; or_or = '||' @{tok = TK_OrOr;}; mult_assign = '*=' @{tok = TK_MultAssign;}; div_assign = '/=' @{tok = TK_DivAssign;}; percent_assign = '%=' @{tok = TK_PercentAssign;}; plus_assign = '+=' @{tok = TK_PlusAssign;}; minus_assign = '-=' @{tok = TK_MinusAssign;}; amp_assign = '&=' @{tok = TK_AmpAssign;}; caret_assign = '^=' @{tok = TK_CaretAssign;}; bar_assign = '|=' @{tok = TK_BarAssign;}; plus_plus = '++' @{tok = TK_PlusPlus;}; minus_minus = '--' @{tok = TK_MinusMinus;}; arrow = '->' @{tok = TK_Arrow;}; arrow_star = '->*' @{tok = TK_ArrowStar;}; dot_star = '.*' @{tok = TK_DotStar;}; # Three char compounds, first item already buffered. */ dot_dot_dot = '...' @{tok = TK_DotDotDot;}; # All compunds compound = namesep | deqs | neqs | and_and | or_or | mult_assign | div_assign | percent_assign | plus_assign | minus_assign | amp_assign | caret_assign | bar_assign | plus_plus | minus_minus | arrow | arrow_star | dot_star | dot_dot_dot; # Single char symbols. symbol = ( punct - [_"'] ) @{tok = fc;}; action discard { discard = true; } # Comments and whitespace. commc = '/*' @discard ( any* $0 '*/' @1 ) @{tok = TK_Comment;}; commcc = '//' @discard ( any* $0 '\n' @1 ) @{tok = TK_Comment;}; whitespace = ( any - 33..126 )+ >discard @{tok = TK_Whitespace;}; # All outside code tokens. tokens = ( id | slit | dlit | float | integer_decimal | integer_octal | integer_hex | compound | symbol | commc | commcc | whitespace ); action onError { if ( tok != 0 ) { const char *rst_data; if ( tok == TK_Comment || tok == TK_Whitespace ) { /* Reset comment status, don't send. */ discard = false; /* Restart right at the error point if consuming whitespace or * a comment. Consume may have spanned multiple buffers. */ rst_data = fpc; } else { /* Send the token. */ token( ts, te - ts + 1 ); /* Restart right after the token. */ rst_data = te+1; } ts = 0; fexec rst_data; fgoto main; } } main := tokens >{ts=fpc;} @{te=fpc;} $!onError; }%% %% write data; int Scanner::init( ) { tok = 0; ts = 0; te = 0; %% write init; return 1; } int Scanner::execute( const char *data, int len ) { const char *p = data; const char *pe = data + len; const char *eof = pe; %% write exec; if ( cs == Scanner_error ) return -1; if ( cs >= Scanner_first_final ) return 1; return 0; } int Scanner::finish( ) { if ( cs == Scanner_error ) return -1; if ( cs >= Scanner_first_final ) return 1; return 0; } void token( const char *data, int len ) { cout << "<" << tok << "> "; for ( int i = 0; i < len; i++ ) cout << data[i]; cout << '\n'; } void test( const char * data ) { Scanner scanner; scanner.init(); scanner.execute( data, strlen(data) ); scanner.finish(); if ( tok != 0 && tok != TK_Comment && tok != TK_Whitespace ) token( ts, te - ts + 1 ); } int main() { test( "/*\n" " * Copyright \n" " */\n" "\n" "\n" "/* Move ranges to the singles list. */\n" "void RedFsmAp::move( RedStateAp *state )\n" "{\n" " RedTranst &range = state->outRange;\n" " for ( int rpos = 0; rpos < range.length(); ) {\n" " if ( can( range, rpos ) ) {\n" " while ( range[rpos].value != range[rpos+1].value ) {\n" " single.append( range[rpos+1] );\n" " }\n" " \n" " range[rpos].highKey = range[rpos+1].highKey;\n" " }\n" " else if ( keyOps->span( range[rpos].lowKey, range[rpos].highKey ) == 1 ) {\n" " single.append( range[rpos] );\n" " }\n" " }\n" "}\n" "\n" ); test( "->*\n" ".*\n" "/*\"*/\n" "\"/*\"\n" "L'\"'\n" "L\"'\"\n" "...\n" ); } #ifdef _____OUTPUT_____ <195> void <195> RedFsmAp <197> :: <195> move <40> ( <195> RedStateAp <42> * <195> state <41> ) <123> { <195> RedTranst <38> & <195> range <61> = <195> state <211> -> <195> outRange <59> ; <195> for <40> ( <195> int <195> rpos <61> = <218> 0 <59> ; <195> rpos <60> < <195> range <46> . <195> length <40> ( <41> ) <59> ; <41> ) <123> { <195> if <40> ( <195> can <40> ( <195> range <44> , <195> rpos <41> ) <41> ) <123> { <195> while <40> ( <195> range <91> [ <195> rpos <93> ] <46> . <195> value <224> != <195> range <91> [ <195> rpos <43> + <218> 1 <93> ] <46> . <195> value <41> ) <123> { <195> single <46> . <195> append <40> ( <195> range <91> [ <195> rpos <43> + <218> 1 <93> ] <41> ) <59> ; <125> } <195> range <91> [ <195> rpos <93> ] <46> . <195> highKey <61> = <195> range <91> [ <195> rpos <43> + <218> 1 <93> ] <46> . <195> highKey <59> ; <125> } <195> else <195> if <40> ( <195> keyOps <211> -> <195> span <40> ( <195> range <91> [ <195> rpos <93> ] <46> . <195> lowKey <44> , <195> range <91> [ <195> rpos <93> ] <46> . <195> highKey <41> ) <223> == <218> 1 <41> ) <123> { <195> single <46> . <195> append <40> ( <195> range <91> [ <195> rpos <93> ] <41> ) <59> ; <125> } <125> } <125> } <214> ->* <215> .* <192> "/*" <193> L'"' <192> L"'" <240> ... #endif ragel-6.8/test/fnext1.rl0000664000175000017500000000200512054170763012131 00000000000000/* * @LANG: c * * Tests fnext in combination with fbreak. */ #include #include char comm; int top; int stack [32]; %%{ machine fnext; action break {fbreak;} main := 'h' @{ /*h*/ fnext e; fbreak; }; e := 'e' @{ /*e*/ fnext l; } @{ fbreak; }; l := 'll' @{ /*ll*/ fnext o; } ${ fbreak; }; o := |* 'o' { /*o*/ fnext nl; fbreak; }; *|; nl := '\n' @{ /*nl*/ fbreak; printf("ACCEPT\n"); }; }%% int cs; char *ts, *te; int act; %% write data; void init() { %% write init; } void exec( char *data, int len ) { char *p = data; char *pe = data + len; while ( cs != fnext_error && p < pe ) { printf( "%c\n", *p ); %% write exec; } } void finish( ) { if ( cs >= fnext_first_final ) printf( "ACCEPT\n" ); else printf( "FAIL\n" ); } char *inp[] = { "hello\n" }; int inplen = 1; int main( ) { int i; for ( i = 0; i < inplen; i++ ) { init(); exec( inp[i], strlen(inp[i]) ); finish(); } return 0; } #ifdef _____OUTPUT_____ h e l l o ACCEPT #endif ragel-6.8/test/gotocallret2.rl0000664000175000017500000000350612043335171013326 00000000000000/* * @LANG: indep */ char comm; int top; int stack[32]; ptr ts; ptr te; int act; int val; %% %%{ machine GotoCallRet; sp = ' '; handle := any @{ prints "handle "; fhold; if ( val == 1 ) fnext *fentry(one); if ( val == 2 ) fnext *fentry(two); if ( val == 3 ) fnext main; }; one := |* '{' => { prints "{ "; fcall *fentry(one); }; "[" => { prints "[ "; fcall *fentry(two); }; "}" sp* => { prints "} "; fret; }; [a-z]+ => { prints "word "; val = 1; fgoto *fentry(handle); }; ' ' => { prints "space "; }; *|; two := |* '{' => { prints "{ "; fcall *fentry(one); }; "[" => { prints "[ "; fcall *fentry(two); }; ']' sp* => { prints "] "; fret; }; [a-z]+ => { prints "word "; val = 2; fgoto *fentry(handle); }; ' ' => { prints "space "; }; *|; main := |* '{' => { prints "{ "; fcall one; }; "[" => { prints "[ "; fcall two; }; [a-z]+ => { prints "word "; val = 3; fgoto handle; }; [a-z] ' foil' => { prints "this is the foil";}; ' ' => { prints "space "; }; '\n'; *|; }%% /* _____INPUT_____ "{a{b[c d]d}c}\n" "[a{b[c d]d}c}\n" "[a[b]c]d{ef{g{h}i}j}l\n" "{{[]}}\n" "a b c\n" "{a b c}\n" "[a b c]\n" "{]\n" "{{}\n" "[[[[[[]]]]]]\n" "[[[[[[]]}]]]\n" _____INPUT_____ */ /* _____OUTPUT_____ { word handle { word handle [ word handle space word handle ] word handle } word handle } ACCEPT [ word handle { word handle [ word handle space word handle ] word handle } word handle FAIL [ word handle [ word handle ] word handle ] word handle { word handle { word handle { word handle } word handle } word handle } word handle ACCEPT { { [ ] } } ACCEPT word handle space word handle space word handle ACCEPT { word handle space word handle space word handle } ACCEPT [ word handle space word handle space word handle ] ACCEPT { FAIL { { } FAIL [ [ [ [ [ [ ] ] ] ] ] ] ACCEPT [ [ [ [ [ [ ] ] FAIL _____OUTPUT_____ */ ragel-6.8/test/Makefile.in0000664000175000017500000003402012106313353012424 00000000000000# Makefile.in generated by automake 1.11.3 from Makefile.am. # @configure_input@ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, # 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software # Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ # # Copyright 2002-2009 Adrian Thurston # # This file is part of Ragel. # # Ragel is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # Ragel is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Ragel; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA VPATH = @srcdir@ pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : subdir = test DIST_COMMON = README $(srcdir)/Makefile.am $(srcdir)/Makefile.in \ $(srcdir)/runtests.in ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/configure.in am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/ragel/config.h CONFIG_CLEAN_FILES = runtests CONFIG_CLEAN_VPATH_FILES = SOURCES = DIST_SOURCES = am__tty_colors = \ red=; grn=; lgn=; blu=; std= DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EXEEXT = @EXEEXT@ FIG2DEV = @FIG2DEV@ GDC = @GDC@ GMCS = @GMCS@ GOBIN = @GOBIN@ GOBJC = @GOBJC@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ JAVAC = @JAVAC@ KELBT = @KELBT@ LDFLAGS = @LDFLAGS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LTLIBOBJS = @LTLIBOBJS@ MAKEINFO = @MAKEINFO@ MKDIR_P = @MKDIR_P@ OBJEXT = @OBJEXT@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PDFLATEX = @PDFLATEX@ PUBDATE = @PUBDATE@ RAGEL = @RAGEL@ RANLIB = @RANLIB@ RUBY = @RUBY@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ TXL = @TXL@ VERSION = @VERSION@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build_alias = @build_alias@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host_alias = @host_alias@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ TESTS = runtests EXTRA_DIST = \ atoi1.rl clang2.rl cond7.rl element3.rl erract8.rl forder3.rl java1.rl \ range.rl scan3.rl xml.rl atoi2.rl clang3.rl cppscan1.rl eofact.rl \ erract9.rl gotocallret1.rl java2.rl recdescent1.rl scan4.rl atoi3.rl \ clang4.rl cppscan2.rl erract1.rl export1.rl gotocallret2.rl keller1.rl \ recdescent2.rl stateact1.rl awkemu.rl cond1.rl cppscan3.rl erract2.rl \ export2.rl high1.rl lmgoto.rl recdescent3.rl statechart1.rl builtin.rl \ cond2.rl cppscan4.rl erract3.rl export3.rl high2.rl mailbox1.rl \ repetition.rl strings1.rl call1.rl cond3.rl cppscan5.rl erract4.rl \ export4.rl high3.rl mailbox2.rl rlscan.rl strings2.rl call2.rl cond4.rl \ cppscan6.rl erract5.rl fnext1.rl import1.rl mailbox3.rl ruby1.rl \ tokstart1.rl call3.rl cond5.rl element1.rl erract6.rl forder1.rl \ include1.rl minimize1.rl scan1.rl union.rl clang1.rl cond6.rl \ element2.rl erract7.rl forder2.rl include2.rl patact.rl scan2.rl \ xmlcommon.rl langtrans_c.sh langtrans_csharp.sh langtrans_d.sh \ langtrans_java.sh langtrans_ruby.sh checkeofact.txl \ langtrans_csharp.txl langtrans_c.txl langtrans_d.txl langtrans_java.txl \ langtrans_ruby.txl testcase.txl cppscan1.h eofact.h mailbox1.h strings2.h CLEANFILES = \ *.c *.cpp *.m *.d *.java *.bin *.class *.exp \ *.out *_c.rl *_d.rl *_java.rl *_ruby.rl *_csharp.rl *.cs \ *_go.rl *.go *.exe all: all-am .SUFFIXES: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign test/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign test/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): runtests: $(top_builddir)/config.status $(srcdir)/runtests.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ tags: TAGS TAGS: ctags: CTAGS CTAGS: check-TESTS: $(TESTS) @failed=0; all=0; xfail=0; xpass=0; skip=0; \ srcdir=$(srcdir); export srcdir; \ list=' $(TESTS) '; \ $(am__tty_colors); \ if test -n "$$list"; then \ for tst in $$list; do \ if test -f ./$$tst; then dir=./; \ elif test -f $$tst; then dir=; \ else dir="$(srcdir)/"; fi; \ if $(TESTS_ENVIRONMENT) $${dir}$$tst; then \ all=`expr $$all + 1`; \ case " $(XFAIL_TESTS) " in \ *[\ \ ]$$tst[\ \ ]*) \ xpass=`expr $$xpass + 1`; \ failed=`expr $$failed + 1`; \ col=$$red; res=XPASS; \ ;; \ *) \ col=$$grn; res=PASS; \ ;; \ esac; \ elif test $$? -ne 77; then \ all=`expr $$all + 1`; \ case " $(XFAIL_TESTS) " in \ *[\ \ ]$$tst[\ \ ]*) \ xfail=`expr $$xfail + 1`; \ col=$$lgn; res=XFAIL; \ ;; \ *) \ failed=`expr $$failed + 1`; \ col=$$red; res=FAIL; \ ;; \ esac; \ else \ skip=`expr $$skip + 1`; \ col=$$blu; res=SKIP; \ fi; \ echo "$${col}$$res$${std}: $$tst"; \ done; \ if test "$$all" -eq 1; then \ tests="test"; \ All=""; \ else \ tests="tests"; \ All="All "; \ fi; \ if test "$$failed" -eq 0; then \ if test "$$xfail" -eq 0; then \ banner="$$All$$all $$tests passed"; \ else \ if test "$$xfail" -eq 1; then failures=failure; else failures=failures; fi; \ banner="$$All$$all $$tests behaved as expected ($$xfail expected $$failures)"; \ fi; \ else \ if test "$$xpass" -eq 0; then \ banner="$$failed of $$all $$tests failed"; \ else \ if test "$$xpass" -eq 1; then passes=pass; else passes=passes; fi; \ banner="$$failed of $$all $$tests did not behave as expected ($$xpass unexpected $$passes)"; \ fi; \ fi; \ dashes="$$banner"; \ skipped=""; \ if test "$$skip" -ne 0; then \ if test "$$skip" -eq 1; then \ skipped="($$skip test was not run)"; \ else \ skipped="($$skip tests were not run)"; \ fi; \ test `echo "$$skipped" | wc -c` -le `echo "$$banner" | wc -c` || \ dashes="$$skipped"; \ fi; \ report=""; \ if test "$$failed" -ne 0 && test -n "$(PACKAGE_BUGREPORT)"; then \ report="Please report to $(PACKAGE_BUGREPORT)"; \ test `echo "$$report" | wc -c` -le `echo "$$banner" | wc -c` || \ dashes="$$report"; \ fi; \ dashes=`echo "$$dashes" | sed s/./=/g`; \ if test "$$failed" -eq 0; then \ col="$$grn"; \ else \ col="$$red"; \ fi; \ echo "$${col}$$dashes$${std}"; \ echo "$${col}$$banner$${std}"; \ test -z "$$skipped" || echo "$${col}$$skipped$${std}"; \ test -z "$$report" || echo "$${col}$$report$${std}"; \ echo "$${col}$$dashes$${std}"; \ test "$$failed" -eq 0; \ else :; fi distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am $(MAKE) $(AM_MAKEFLAGS) check-TESTS check: check-am all-am: Makefile installdirs: install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic mostlyclean-am distclean: distclean-am -rm -f Makefile distclean-am: clean-am distclean-generic dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-generic pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: .MAKE: check-am install-am install-strip .PHONY: all all-am check check-TESTS check-am clean clean-generic \ distclean distclean-generic distdir dvi dvi-am html html-am \ info info-am install install-am install-data install-data-am \ install-dvi install-dvi-am install-exec install-exec-am \ install-html install-html-am install-info install-info-am \ install-man install-pdf install-pdf-am install-ps \ install-ps-am install-strip installcheck installcheck-am \ installdirs maintainer-clean maintainer-clean-generic \ mostlyclean mostlyclean-generic pdf pdf-am ps ps-am uninstall \ uninstall-am # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: ragel-6.8/test/export1.rl0000664000175000017500000000144212043335171012324 00000000000000/* * @LANG: c */ #include #include %%{ machine test; export c1 = 'c'; export c2 = 'z'; export c3 = 't'; commands := ( c1 . digit* '\n' @{ printf( "c1\n" );} | c2 . alpha* '\n' @{ printf( "c2\n" );}| c3 . '.'* '\n' @{ printf( "c3\n" );} )*; some_other := any*; }%% %% write exports; %% write data; int test( const char *data, int len ) { int cs = test_en_commands; const char *p = data, *pe = data + len; %% write init nocs; %% write exec; if ( cs >= test_first_final ) printf("ACCEPT\n"); else printf("ERROR\n"); return 0; } char data[] = { test_ex_c1, '1', '2', '\n', test_ex_c2, 'a', 'b', '\n', test_ex_c3, '.', '.', '\n', 0 }; int main() { test( data, strlen( data ) ); return 0; } #ifdef _____OUTPUT_____ c1 c2 c3 ACCEPT #endif ragel-6.8/test/high2.rl0000664000175000017500000000347612043335171011734 00000000000000/* * @LANG: c++ */ /** * Test a high character to make sure signedness * isn't messing us up. */ #include #include struct Fsm { int cs; // Initialize the machine. Invokes any init statement blocks. Returns 0 // if the machine begins in a non-accepting state and 1 if the machine // begins in an accepting state. int init( ); // Execute the machine on a block of data. Returns -1 if after processing // the data, the machine is in the error state and can never accept, 0 if // the machine is in a non-accepting state and 1 if the machine is in an // accepting state. int execute( const unsigned char *data, int len ); // Indicate that there is no more data. Returns -1 if the machine finishes // in the error state and does not accept, 0 if the machine finishes // in any other non-accepting state and 1 if the machine finishes in an // accepting state. int finish( ); }; %%{ machine Fsm; alphtype unsigned char; # Indicate we got the high character. action gothigh { printf("yes\n"); } main := 0xe8 @gothigh '\n'; }%% %% write data; int Fsm::init( ) { %% write init; return 0; } int Fsm::execute( const unsigned char *_data, int _len ) { const unsigned char *p = _data; const unsigned char *pe = _data+_len; %% write exec; if ( cs == Fsm_error ) return -1; if ( cs >= Fsm_first_final ) return 1; return 0; } int Fsm::finish() { if ( cs == Fsm_error ) return -1; if ( cs >= Fsm_first_final ) return 1; return 0; } Fsm fsm; void test( unsigned char *buf, int len ) { fsm.init(); fsm.execute( buf, len ); if ( fsm.finish() > 0 ) printf("ACCEPT\n"); else printf("FAIL\n"); } unsigned char data1[] = { 0xe8, 10 }; unsigned char data2[] = { 0xf8, 10 }; int main() { test( data1, 2 ); test( data2, 2 ); return 0; } #ifdef _____OUTPUT_____ yes ACCEPT FAIL #endif ragel-6.8/test/cppscan5.rl0000664000175000017500000001154112043335171012437 00000000000000/* * @LANG: d */ /* * Test in and out state actions. */ import std.c.stdio; import std.string; static const int TK_Dlit = 192; static const int TK_Slit = 193; static const int TK_Float = 194; static const int TK_Id = 195; static const int TK_NameSep = 197; static const int TK_Arrow = 211; static const int TK_PlusPlus = 212; static const int TK_MinusMinus = 213; static const int TK_ArrowStar = 214; static const int TK_DotStar = 215; static const int TK_ShiftLeft = 216; static const int TK_ShiftRight = 217; static const int TK_IntegerDecimal = 218; static const int TK_IntegerOctal = 219; static const int TK_IntegerHex = 220; static const int TK_EqualsEquals = 223; static const int TK_NotEquals = 224; static const int TK_AndAnd = 225; static const int TK_OrOr = 226; static const int TK_MultAssign = 227; static const int TK_DivAssign = 228; static const int TK_PercentAssign = 229; static const int TK_PlusAssign = 230; static const int TK_MinusAssign = 231; static const int TK_AmpAssign = 232; static const int TK_CaretAssign = 233; static const int TK_BarAssign = 234; static const int TK_DotDotDot = 240; static const int TK_Whitespace = 241; static const int TK_Comment = 242; class Scanner { int cs, act; char *ts, te; void token( int tok ) { char *data = ts; int len = te - ts; printf( "<%i> ", tok ); for ( int i = 0; i < len; i++ ) printf( "%c", data[i] ); printf( "\n" ); } %%{ machine Scanner; main := |* # Single and double literals. ( 'L'? "'" ( [^'\\\n] | /\\./ )* "'" ) => { token( TK_Slit );}; ( 'L'? '"' ( [^"\\\n] | /\\./ )* '"' ) => { token( TK_Dlit );}; # Identifiers ( [a-zA-Z_] [a-zA-Z0-9_]* ) =>{ token( TK_Id );}; # Floating literals. fract_const = digit* '.' digit+ | digit+ '.'; exponent = [eE] [+\-]? digit+; float_suffix = [flFL]; ( fract_const exponent? float_suffix? | digit+ exponent float_suffix? ) => { token( TK_Float );}; # Integer decimal. Leading part buffered by float. ( ( '0' | [1-9] [0-9]* ) [ulUL]{0,3} ) => { token( TK_IntegerDecimal );}; # Integer octal. Leading part buffered by float. ( '0' [0-9]+ [ulUL]{0,2} ) => { token( TK_IntegerOctal );}; # Integer hex. Leading 0 buffered by float. ( '0' ( 'x' [0-9a-fA-F]+ [ulUL]{0,2} ) ) => { token( TK_IntegerHex );}; # Only buffer the second item, first buffered by symbol. */ '::' => {token( TK_NameSep );}; '==' => {token( TK_EqualsEquals );}; '!=' => {token( TK_NotEquals );}; '&&' => {token( TK_AndAnd );}; '||' => {token( TK_OrOr );}; '*=' => {token( TK_MultAssign );}; '/=' => {token( TK_DivAssign );}; '%=' => {token( TK_PercentAssign );}; '+=' => {token( TK_PlusAssign );}; '-=' => {token( TK_MinusAssign );}; '&=' => {token( TK_AmpAssign );}; '^=' => {token( TK_CaretAssign );}; '|=' => {token( TK_BarAssign );}; '++' => {token( TK_PlusPlus );}; '--' => {token( TK_MinusMinus );}; '->' => {token( TK_Arrow );}; '->*' => {token( TK_ArrowStar );}; '.*' => {token( TK_DotStar );}; # Three char compounds, first item already buffered. */ '...' => { token( TK_DotDotDot );}; # Single char symbols. ( punct - [_"'] ) => { token( ts[0] );}; action comment { token( TK_Comment ); } # Comments and whitespace. '/*' ( any* $0 '*/' @1 ) => comment; '//' ( any* $0 '\n' @1 ) => comment; ( any - 33..126 )+ => { token( TK_Whitespace );}; *|; }%% %% write data noprefix; void init( ) { %% write init; } void execute( char* data, int len ) { char *p = data; char *pe = data + len; char *eof = pe; %% write exec; } // Indicate that there is no more data. Returns -1 if the machine finishes // in the error state and does not accept, 0 if the machine finishes // in any other non-accepting state and 1 if the machine finishes in an // accepting state. int finish( ) { if ( cs == error ) return -1; if ( cs >= first_final ) return 1; return 0; } }; static const int BUFSIZE = 12; void test( char buf[] ) { Scanner scanner = new Scanner(); scanner.init(); scanner.execute( buf.ptr, buf.length ); if ( scanner.cs == Scanner.error ) { /* Machine failed before finding a token. */ printf("PARSE ERROR\n"); } scanner.finish(); return 0; } int main() { test( "\"\\\"hi\" /*\n" "*/\n" "44 .44\n" "44. 44\n" "44 . 44\n" "44.44\n" "_hithere22" ); test( "'\\''\"\\n\\d'\\\"\"\n" "hi\n" "99\n" ".99\n" "99e-4\n" "->*\n" "||\n" "0x98\n" "0x\n" "//\n" "/* * */" ); test( "'\n" "'\n" ); return 0; } /+ _____OUTPUT_____ <192> "\"hi" <241> <242> /* */ <241> <218> 44 <241> <194> .44 <241> <194> 44. <241> <218> 44 <241> <218> 44 <241> <46> . <241> <218> 44 <241> <194> 44.44 <241> <195> _hithere22 <193> '\'' <192> "\n\d'\"" <241> <195> hi <241> <218> 99 <241> <194> .99 <241> <194> 99e-4 <241> <214> ->* <241> <226> || <241> <220> 0x98 <241> <218> 0 <195> x <241> <242> // <242> /* * */ PARSE ERROR +++++++++++++++++++/ ragel-6.8/test/erract2.rl0000664000175000017500000000215312043335171012264 00000000000000/* * @LANG: indep * * Test error actions. */ %% %%{ machine ErrAct; action err_start { prints "err_start\n"; } action err_all { prints "err_all\n"; } action err_middle { prints "err_middle\n"; } action err_out { prints "err_out\n"; } action eof_start { prints "eof_start\n"; } action eof_all { prints "eof_all\n"; } action eof_middle { prints "eof_middle\n"; } action eof_out { prints "eof_out\n"; } main := ( 'hello' >err err_start $err err_all <>err err_middle %err err_out >eof eof_start $eof eof_all <>eof eof_middle %eof eof_out ) '\n'; }%% /* _____INPUT_____ "" "h" "x" "he" "hx" "hel" "hex" "hell" "helx" "hello" "hellx" "hello\n" "hellox" _____INPUT_____ */ /* _____OUTPUT_____ err_start eof_start err_all eof_all FAIL err_all err_middle eof_all eof_middle FAIL err_start err_all FAIL err_all err_middle eof_all eof_middle FAIL err_all err_middle FAIL err_all err_middle eof_all eof_middle FAIL err_all err_middle FAIL err_all err_middle eof_all eof_middle FAIL err_all err_middle FAIL err_all err_out eof_all eof_out FAIL err_all err_middle FAIL ACCEPT err_all err_out FAIL _____OUTPUT_____ */ ragel-6.8/test/xml.rl0000664000175000017500000001540712043335171011530 00000000000000/* * XML parser based on the XML 1.0 BNF from: * http://www.jelks.nu/XML/xmlebnf.html * * @LANG: c++ * @ALLOW_MINFLAGS: -l -e * @ALLOW_GENFLAGS: -T0 -T1 */ #include #include #include using namespace std; #define BUFSIZE 2048 struct XML { int cur_char; int start_word; int start_comment; int start_literal; int cs, top, stack[1024]; int init( ); int execute( const unsigned short *data, int len ); int finish( ); }; %%{ machine XML; alphtype unsigned short; action next_char { cur_char += 1; } action start_word { start_word = cur_char; } action end_word { cout << "word: " << start_word << " " << cur_char-1 << endl; } Extender = 0x00B7 | 0x02D0 | 0x02D1 | 0x0387 | 0x0640 | 0x0E46 | 0x0EC6 | 0x3005 | (0x3031..0x3035) | (0x309D..0x309E) | (0x30FC..0x30FE); Digit = (0x0030..0x0039) | (0x0660..0x0669) | (0x06F0..0x06F9) | (0x0966..0x096F) | (0x09E6..0x09EF) | (0x0A66..0x0A6F) | (0x0AE6..0x0AEF) | (0x0B66..0x0B6F) | (0x0BE7..0x0BEF) | (0x0C66..0x0C6F) | (0x0CE6..0x0CEF) | (0x0D66..0x0D6F) | (0x0E50..0x0E59) | (0x0ED0..0x0ED9) | (0x0F20..0x0F29); CombiningChar = (0x0300..0x0345) | (0x0360..0x0361) | (0x0483..0x0486) | (0x0591..0x05A1) | (0x05A3..0x05B9) | (0x05BB..0x05BD) | 0x05BF | (0x05C1..0x05C2) | 0x05C4 | (0x064B..0x0652) | 0x0670 | (0x06D6..0x06DC) | (0x06DD..0x06DF) | (0x06E0..0x06E4) | (0x06E7..0x06E8) | (0x06EA..0x06ED) | (0x0901..0x0903) | 0x093C | (0x093E..0x094C) | 0x094D | (0x0951..0x0954) | (0x0962..0x0963) | (0x0981..0x0983) | 0x09BC | 0x09BE | 0x09BF | (0x09C0..0x09C4) | (0x09C7..0x09C8) | (0x09CB..0x09CD) | 0x09D7 | (0x09E2..0x09E3) | 0x0A02 | 0x0A3C | 0x0A3E | 0x0A3F | (0x0A40..0x0A42) | (0x0A47..0x0A48) | (0x0A4B..0x0A4D) | (0x0A70..0x0A71) | (0x0A81..0x0A83) | 0x0ABC | (0x0ABE..0x0AC5) | (0x0AC7..0x0AC9) | (0x0ACB..0x0ACD) | (0x0B01..0x0B03) | 0x0B3C | (0x0B3E..0x0B43) | (0x0B47..0x0B48) | (0x0B4B..0x0B4D) | (0x0B56..0x0B57) | (0x0B82..0x0B83) | (0x0BBE..0x0BC2) | (0x0BC6..0x0BC8) | (0x0BCA..0x0BCD) | 0x0BD7 | (0x0C01..0x0C03) | (0x0C3E..0x0C44) | (0x0C46..0x0C48) | (0x0C4A..0x0C4D) | (0x0C55..0x0C56) | (0x0C82..0x0C83) | (0x0CBE..0x0CC4) | (0x0CC6..0x0CC8) | (0x0CCA..0x0CCD) | (0x0CD5..0x0CD6) | (0x0D02..0x0D03) | (0x0D3E..0x0D43) | (0x0D46..0x0D48) | (0x0D4A..0x0D4D) | 0x0D57 | 0x0E31 | (0x0E34..0x0E3A) | (0x0E47..0x0E4E) | 0x0EB1 | (0x0EB4..0x0EB9) | (0x0EBB..0x0EBC) | (0x0EC8..0x0ECD) | (0x0F18..0x0F19) | 0x0F35 | 0x0F37 | 0x0F39 | 0x0F3E | 0x0F3F | (0x0F71..0x0F84) | (0x0F86..0x0F8B) | (0x0F90..0x0F95) | 0x0F97 | (0x0F99..0x0FAD) | (0x0FB1..0x0FB7) | 0x0FB9 | (0x20D0..0x20DC) | 0x20E1 | (0x302A..0x302F) | 0x3099 | 0x309A; Ideographic = (0x4E00..0x9FA5) | 0x3007 | (0x3021..0x3029); BaseChar = (0x0041..0x005A) | (0x0061..0x007A) | (0x00C0..0x00D6) | (0x00D8..0x00F6) | (0x00F8..0x00FF) | (0x0100..0x0131) | (0x0134..0x013E) | (0x0141..0x0148) | (0x014A..0x017E) | (0x0180..0x01C3) | (0x01CD..0x01F0) | (0x01F4..0x01F5) | (0x01FA..0x0217) | (0x0250..0x02A8) | (0x02BB..0x02C1) | 0x0386 | (0x0388..0x038A) | 0x038C | (0x038E..0x03A1) | (0x03A3..0x03CE) | (0x03D0..0x03D6) | 0x03DA | 0x03DC | 0x03DE | 0x03E0 | (0x03E2..0x03F3) | (0x0401..0x040C) | (0x040E..0x044F) | (0x0451..0x045C) | (0x045E..0x0481) | (0x0490..0x04C4) | (0x04C7..0x04C8) | (0x04CB..0x04CC) | (0x04D0..0x04EB) | (0x04EE..0x04F5) | (0x04F8..0x04F9) | (0x0531..0x0556) | 0x0559 | (0x0561..0x0586) | (0x05D0..0x05EA) | (0x05F0..0x05F2) | (0x0621..0x063A) | (0x0641..0x064A) | (0x0671..0x06B7) | (0x06BA..0x06BE) | (0x06C0..0x06CE) | (0x06D0..0x06D3) | 0x06D5 | (0x06E5..0x06E6) | (0x0905..0x0939) | 0x093D | (0x0958..0x0961) | (0x0985..0x098C) | (0x098F..0x0990) | (0x0993..0x09A8) | (0x09AA..0x09B0) | 0x09B2 | (0x09B6..0x09B9) | (0x09DC..0x09DD) | (0x09DF..0x09E1) | (0x09F0..0x09F1) | (0x0A05..0x0A0A) | (0x0A0F..0x0A10) | (0x0A13..0x0A28) | (0x0A2A..0x0A30) | (0x0A32..0x0A33) | (0x0A35..0x0A36) | (0x0A38..0x0A39) | (0x0A59..0x0A5C) | 0x0A5E | (0x0A72..0x0A74) | (0x0A85..0x0A8B) | 0x0A8D | (0x0A8F..0x0A91) | (0x0A93..0x0AA8) | (0x0AAA..0x0AB0) | (0x0AB2..0x0AB3) | (0x0AB5..0x0AB9) | 0x0ABD | 0x0AE0 | (0x0B05..0x0B0C) | (0x0B0F..0x0B10) | (0x0B13..0x0B28) | (0x0B2A..0x0B30) | (0x0B32..0x0B33) | (0x0B36..0x0B39) | 0x0B3D | (0x0B5C..0x0B5D) | (0x0B5F..0x0B61) | (0x0B85..0x0B8A) | (0x0B8E..0x0B90) | (0x0B92..0x0B95) | (0x0B99..0x0B9A) | 0x0B9C | (0x0B9E..0x0B9F) | (0x0BA3..0x0BA4) | (0x0BA8..0x0BAA) | (0x0BAE..0x0BB5) | (0x0BB7..0x0BB9) | (0x0C05..0x0C0C) | (0x0C0E..0x0C10) | (0x0C12..0x0C28) | (0x0C2A..0x0C33) | (0x0C35..0x0C39) | (0x0C60..0x0C61) | (0x0C85..0x0C8C) | (0x0C8E..0x0C90) | (0x0C92..0x0CA8) | (0x0CAA..0x0CB3) | (0x0CB5..0x0CB9) | 0x0CDE | (0x0CE0..0x0CE1) | (0x0D05..0x0D0C) | (0x0D0E..0x0D10) | (0x0D12..0x0D28) | (0x0D2A..0x0D39) | (0x0D60..0x0D61) | (0x0E01..0x0E2E) | 0x0E30 | (0x0E32..0x0E33) | (0x0E40..0x0E45) | (0x0E81..0x0E82) | 0x0E84 | (0x0E87..0x0E88) | 0x0E8A | 0x0E8D | (0x0E94..0x0E97) | (0x0E99..0x0E9F) | (0x0EA1..0x0EA3) | 0x0EA5 | 0x0EA7 | (0x0EAA..0x0EAB) | (0x0EAD..0x0EAE) | 0x0EB0 | (0x0EB2..0x0EB3) | 0x0EBD | (0x0EC0..0x0EC4) | (0x0F40..0x0F47) | (0x0F49..0x0F69) | (0x10A0..0x10C5) | (0x10D0..0x10F6) | 0x1100 | (0x1102..0x1103) | (0x1105..0x1107) | 0x1109 | (0x110B..0x110C) | (0x110E..0x1112) | 0x113C | 0x113E | 0x1140 | 0x114C | 0x114E | 0x1150 | (0x1154..0x1155) | 0x1159 | (0x115F..0x1161) | 0x1163 | 0x1165 | 0x1167 | 0x1169 | (0x116D..0x116E) | (0x1172..0x1173) | 0x1175 | 0x119E | 0x11A8 | 0x11AB | (0x11AE..0x11AF) | (0x11B7..0x11B8) | 0x11BA | (0x11BC..0x11C2) | 0x11EB | 0x11F0 | 0x11F9 | (0x1E00..0x1E9B) | (0x1EA0..0x1EF9) | (0x1F00..0x1F15) | (0x1F18..0x1F1D) | (0x1F20..0x1F45) | (0x1F48..0x1F4D) | (0x1F50..0x1F57) | 0x1F59 | 0x1F5B | 0x1F5D | (0x1F5F..0x1F7D) | (0x1F80..0x1FB4) | (0x1FB6..0x1FBC) | 0x1FBE | (0x1FC2..0x1FC4) | (0x1FC6..0x1FCC) | (0x1FD0..0x1FD3) | (0x1FD6..0x1FDB) | (0x1FE0..0x1FEC) | (0x1FF2..0x1FF4) | (0x1FF6..0x1FFC) | 0x2126 | (0x212A..0x212B) | 0x212E | (0x2180..0x2182) | (0x3041..0x3094) | (0x30A1..0x30FA) | (0x3105..0x312C) | (0xAC00..0xD7A3); # Full Unicode 3.1 requires: Char = 0x9 | 0xA | 0xD | (0x20..0xD7FF) | (0xE000..0xFFFD) | (0x10000..0x10FFFF); Char = 0x9 | 0xA | 0xD | (0x20..0xD7FF) | (0xE000..0xFFFD); Letter = BaseChar | Ideographic; NameChar = Letter | Digit | '.' | '-' | '_' | ':' | CombiningChar | Extender; include CommonXml "xmlcommon.rl"; }%% %% write data; int XML::init( ) { %% write init; cur_char = 0; return 1; } int XML::execute( const unsigned short *data, int len ) { const unsigned short *p = data; const unsigned short *pe = data + len; %% write exec; if ( cs == XML_error ) return -1; if ( cs >= XML_first_final ) return 1; return 0; } int XML::finish( ) { if ( cs == XML_error ) return -1; if ( cs >= XML_first_final ) return 1; return 0; } int main() { return 0; } /* _____OUTPUT_____ _____OUTPUT_____ */ ragel-6.8/test/eofact.h0000664000175000017500000000011112043335171011765 00000000000000#ifndef _EOFACT_H #define _EOFACT_H struct eofact { int cs; }; #endif ragel-6.8/test/langtrans_ruby.sh0000775000175000017500000000317412043335171013760 00000000000000#!/bin/bash # file=$1 [ -f $file ] || exit 1 # Get the machine name. machine=`sed -n 's/^[\t ]*machine[\t ]*\([a-zA-Z_0-9]*\)[\t ]*;[\t ]*$/\1/p' \ $file | tr '[A-Z]' '[a-z]'` # Make a temporary version of the test case using the Ruby language translations. sed -n '/\/\*/,/\*\//d;p' $file | txl -q stdin langtrans_ruby.txl > $file.pr # Begin writing out the test case. cat << EOF # # @LANG: ruby # @GENERATED: yes EOF grep '@ALLOW_GENFLAGS:' $file | sed 's/^ *\*/#/' | sed 's/-G.//g' grep '@ALLOW_MINFLAGS:' $file | sed 's/^ *\*/#/' cat << EOF # EOF # Write out the machine specification. sed -n '/^%%{$/,/^}%%/{s/^/\t/;p}' $file.pr # Write out the init and execute routines. cat << EOF %% write data; def run_machine( data ) p = 0 pe = data.length eof = data.length cs = 0; EOF # Write the data declarations sed -n '/^%%$/q;{s/^/\t/;p}' $file.pr # Write the data initializations sed -n '0,/^%%$/d; /^%%{$/q; {s/^/\t\t/;p}' $file.pr cat << EOF %% write init; %% write exec; if cs >= ${machine}_first_final puts "ACCEPT" else puts "FAIL" end end EOF # Write out the test data. sed -n '0,/\/\* _____INPUT_____/d; /_____INPUT_____ \*\//q; p;' $file | awk ' BEGIN { print " inp = [" } { print " " $0 "," } END { print " ]" print "" print " inplen = " NR ";" }' # Write out the main routine. cat << EOF inp.each { |str| run_machine(str.unpack("c*")) } EOF # Write out the expected output. echo "=begin _____OUTPUT_____" sed -n '/\/\* _____OUTPUT_____/,/_____OUTPUT_____ \*\//{/_____OUTPUT_____/d;p;};' $file echo "=end _____OUTPUT_____" # Don't need this language-specific file anymore. rm $file.pr ragel-6.8/test/stateact1.rl0000664000175000017500000000111212062506216012606 00000000000000/* * @LANG: indep * * Test in and out state actions. */ %% %%{ machine state_act; action a1 { prints "a1\n"; } action a2 { prints "a2\n"; } action b1 { prints "b1\n"; } action b2 { prints "b2\n"; } action c1 { prints "c1\n"; } action c2 { prints "c2\n"; } action next_again {fnext again;} hi = 'hi'; line = again: hi >to b1 >from b2 '\n' >to c1 >from c2 @next_again; main := line* >to a1 >from a2; }%% /* _____INPUT_____ "hi\nhi\n" _____INPUT_____ */ /* _____OUTPUT_____ a2 b2 c1 c2 b1 b2 c1 c2 b1 FAIL _____OUTPUT_____ */ ragel-6.8/test/strings2.rl0000664000175000017500000011434612043335171012505 00000000000000/* * @LANG: c * @ALLOW_GENFLAGS: -T0 -T1 -F0 -F1 * @ALLOW_MINFLAGS: -n -m -l * * Test works with split code gen. */ #include #include #include "strings2.h" %%{ machine strs; variable cs fsm->cs; main := "/lib/ld-linux.so.2\n" | "libstdc++-libc6.2-2.so.3\n" | "cerr\n" | "__cp_push_exception\n" | "_DYNAMIC\n" | "endl__FR7ostream\n" | "__ls__7ostreamc\n" | "_._9exception\n" | "__vt_9bad_alloc\n" | "__rtti_user\n" | "__ls__7ostreamPFR7ostream_R7ostream\n" | "__rtti_si\n" | "_init\n" | "bad__C3ios\n" | "__throw\n" | "__ls__7ostreamPCc\n" | "__deregister_frame_info\n" | "terminate__Fv\n" | "__ls__7ostreamb\n" | "__ls__7ostreami\n" | "__8ofstreamiPCcii\n" | "__builtin_vec_new\n" | "_fini\n" | "__9exception\n" | "__builtin_vec_delete\n" | "_GLOBAL_OFFSET_TABLE_\n" | "__vt_9exception\n" | "__nw__FUiPv\n" | "_._9bad_alloc\n" | "__builtin_delete\n" | "__builtin_new\n" | "cout\n" | "__register_frame_info\n" | "__eh_alloc\n" | "__gmon_start__\n" | "libm.so.6\n" | "libc.so.6\n" | "strcpy\n" | "stdout\n" | "memmove\n" | "memcpy\n" | "malloc\n" | "strtoul\n" | "fprintf\n" | "stdin\n" | "ferror\n" | "strncpy\n" | "strcasecmp\n" | "realloc\n" | "_IO_getc\n" | "fread\n" | "memset\n" | "clearerr\n" | "__assert_fail\n" | "strcmp\n" | "stderr\n" | "fwrite\n" | "__errno_location\n" | "exit\n" | "fopen\n" | "atoi\n" | "_IO_stdin_used\n" | "__libc_start_main\n" | "strlen\n" | "free\n" | "_edata\n" | "__bss_start\n" | "_end\n" | "GLIBC_2.1\n" | "GLIBC_2.0\n" | "PTRh\n" | "QVhL\n" | " Write output to .\n" | " -s Print stats on the compiled fsm.\n" | " -f Dump the final fsm.\n" | "fsm minimization:\n" | " -n No minimization (default).\n" | " -m Find the minimal fsm accepting the language.\n" | "generated code language:\n" | " -c Generate c code (default).\n" | " -C Generate c++ code.\n" | "generated code style:\n" | " -T0 Generate a table driven fsm (default).\n" | " -T1 Generate a faster table driven fsm.\n" | " -S0 Generate a switch driven fsm.\n" | " -G0 Generate a goto driven fsm.\n" | " -G1 Generate a faster goto driven fsm.\n" | " -G2 Generate a really fast goto driven fsm.\n" | "char * FileNameFromStem(char *, char *)\n" | "main.cpp\n" | "len > 0\n" | "main\n" | "ragel: main graph not defined\n" | "graph states: \n" | "graph transitions: \n" | "machine states: \n" | "machine functions: \n" | "function array: \n" | "T:S:G:Cco:senmabjkfhH?-:\n" | "ragel: zero length output file name given\n" | "ragel: output file already given\n" | "ragel: invalid param specified (try -h for a list of options)\n" | "help\n" | "ragel: zero length input file name given\n" | "ragel: input file already given\n" | "ragel: warning: -e given but minimization is not enabled\n" | "ragel: no input file (try -h for a list of options)\n" | " for reading\n" | "ragel: could not open \n" | " for writing\n" | "ragel: error opening \n" | " * Parts of this file are copied from Ragel source covered by the GNU\n" | " * GPL. As a special exception, you may use the parts of this file copied\n" | " * from Ragel source without restriction. The remainder is derived from\n" | "bad_alloc\n" | "%s:%i: unterminated literal\n" | "%s:%i: unterminated comment\n" | "%s:%i: bad character in literal\n" | "fatal flex scanner internal error--no action found\n" | "fatal flex scanner internal error--end of buffer missed\n" | "fatal error - scanner input buffer overflow\n" | "input in flex scanner failed\n" | "out of dynamic memory in yy_create_buffer()\n" | "out of dynamic memory in yy_scan_buffer()\n" | "out of dynamic memory in yy_scan_bytes()\n" | "bad buffer in yy_scan_bytes()\n" | "bad_alloc\n" | "%s:%i: warning: range gives null fsm\n" | "%s:%i: warning: literal used in range is not of length 1, using 0x%x\n" | "%s:%i: warning: overflow in byte constant\n" | "parse error\n" | "parser stack overflow\n" | "%s:%i: %s\n" | "bad_alloc\n" | "extend\n" | "ascii\n" | "alpha\n" | "digit\n" | "alnum\n" | "lower\n" | "upper\n" | "cntrl\n" | "graph\n" | "print\n" | "punct\n" | "space\n" | "xdigit\n" | "struct Fsm * FactorWithAugNode::Walk()\n" | "parsetree.cpp\n" | "false\n" | "bad_alloc\n" | "xx []()\n" | " df \n" | "StartState: \n" | "Final States:\n" | "void FsmGraph::AttachStates(State *, State *, Trans *, FsmKeyType, int)\n" | "rlfsm/fsmattach.cpp\n" | "trans->toState == __null\n" | "trans->fromState == __null\n" | "void FsmGraph::DetachStates(State *, State *, Trans *, FsmKeyType, int)\n" | "trans->toState == to\n" | "trans->fromState == from\n" | "inTel != __null\n" | "void Vector,ResizeExpn>::setAs(const Vector,ResizeExpn> &)\n" | "aapl/vectcommon.h\n" | "&v != this\n" | "void FsmGraph::ChangeRangeLowerKey(Trans *, int, int)\n" | "inRangeEl != __null\n" | "void FsmGraph::IsolateStartState()\n" | "rlfsm/fsmgraph.cpp\n" | "md.stateDict.nodeCount == 0\n" | "md.stfil.listLength == 0\n" | "struct State * FsmGraph::DetachState(State *)\n" | "fromTel != __null\n" | "struct Trans * FsmGraph::AttachStates(State *, State *, FsmKeyType, int, int)\n" | "outTel != __null\n" | "outTel1 != __null\n" | "from->defOutTrans == __null\n" | "void FsmGraph::VerifyOutFuncs()\n" | "state->outTransFuncTable.tableLength == 0\n" | "!state->isOutPriorSet\n" | "state->outPriority == 0\n" | "void FsmGraph::VerifyIntegrity()\n" | "rlfsm/fsmbase.cpp\n" | "outIt.trans->fromState == state\n" | "inIt.trans->toState == state\n" | "static int FsmTrans >::ComparePartPtr(FsmTrans > *, FsmTrans > *)\n" | "rlfsm/fsmstate.cpp\n" | "false\n" | "void FsmGraph::InTransMove(State *, State *)\n" | "dest != src\n" | "static bool FsmTrans >::ShouldMarkPtr(MarkIndex &, FsmTrans > *, FsmTrans > *)\n" | "bad_alloc\n" | "10FsmCodeGen\n" | "bad_alloc\n" | " case \n" | "break;}\n" | "unsigned char\n" | "unsigned short\n" | "unsigned int\n" | "{0, \n" | "/* Forward dec state for the transition structure. */\n" | "struct \n" | "StateStruct;\n" | "/* A single transition. */\n" | "struct \n" | "TransStruct\n" | " struct \n" | "StateStruct *toState;\n" | " int *funcs;\n" | "typedef struct \n" | "TransStruct \n" | "Trans;\n" | "/* A single state. */\n" | "struct \n" | "StateStruct\n" | " int lowIndex;\n" | " int highIndex;\n" | " void *transIndex;\n" | " unsigned int dflIndex;\n" | " int *outFuncs;\n" | " int isFinState;\n" | "typedef struct \n" | "StateStruct \n" | "State;\n" | "/* Only non-static data: current state. */\n" | "struct \n" | "Struct\n" | "State *curState;\n" | " int accept;\n" | "typedef struct \n" | "Struct \n" | "/* Init the fsm. */\n" | "void \n" | "Init( \n" | " *fsm );\n" | "/* Execute some chunk of data. */\n" | "void \n" | "Execute( \n" | " *fsm, char *data, int dlen );\n" | "/* Indicate to the fsm tha there is no more data. */\n" | "void \n" | "Finish( \n" | " *fsm );\n" | "/* Did the machine accept? */\n" | "int \n" | "Accept( \n" | " *fsm );\n" | "#define f \n" | "#define s \n" | "#define i \n" | "#define t \n" | "/* The array of functions. */\n" | "#if \n" | "static int \n" | "_f[] = {\n" | "#endif\n" | "/* The array of indicies into the transition array. */\n" | "#if \n" | "static \n" | "_i[] = {\n" | "#endif\n" | "/* The aray of states. */\n" | "static \n" | "State \n" | "_s[] = {\n" | "/* The array of transitions. */\n" | "static \n" | "Trans \n" | "_t[] = {\n" | "/* The start state. */\n" | "static \n" | "State *\n" | "_startState = s+\n" | "#undef f\n" | "#undef s\n" | "#undef i\n" | "#undef t\n" | "* Execute functions pointed to by funcs until the null function is found. \n" | "inline static void \n" | "ExecFuncs( \n" | " *fsm, int *funcs, char *p )\n" | " int len = *funcs++;\n" | " while ( len-- > 0 ) {\n" | " switch ( *funcs++ ) {\n" | " * Init the fsm to a runnable state.\n" | "void \n" | " *fsm )\n" | " fsm->curState = \n" | "_startState;\n" | " fsm->accept = 0;\n" | " * Did the fsm accept? \n" | "int \n" | " *fsm )\n" | " return fsm->accept;\n" | " * Execute the fsm on some chunk of data. \n" | "void \n" | " *fsm, char *data, int dlen )\n" | " char *p = data;\n" | " int len = dlen;\n" | "State *cs = fsm->curState;\n" | " for ( ; len > 0; p++, len-- ) {\n" | " int c = (unsigned char) *p;\n" | "Trans *trans;\n" | " if ( cs == 0 )\n" | " goto finished;\n" | " /* If the character is within the index bounds then get the\n" | " * transition for it. If it is out of the transition bounds\n" | " * we will use the default transition. */\n" | " if ( cs->lowIndex <= c && c < cs->highIndex ) {\n" | " /* Use the index to look into the transition array. */\n" | " trans = \n" | "_t + \n" | " ((\n" | "*)cs->transIndex)[c - cs->lowIndex];\n" | " else {\n" | " /* Use the default index as the char is out of range. */\n" | " trans = \n" | "_t + cs->dflIndex;\n" | " /* If there are functions for this transition then execute them. */\n" | " if ( trans->funcs != 0 )\n" | "ExecFuncs( fsm, trans->funcs, p );\n" | " /* Move to the new state. */\n" | " cs = trans->toState;\n" | "finished:\n" | " fsm->curState = cs;\n" | " * Indicate to the fsm that the input is done. Does cleanup tasks.\n" | "void \n" | " *fsm )\n" | "State *cs = fsm->curState;\n" | " if ( cs != 0 && cs->isFinState ) {\n" | " /* If finishing in a final state then execute the\n" | " * out functions for it. (if any). */\n" | " if ( cs->outFuncs != 0 )\n" | "ExecFuncs( fsm, cs->outFuncs, 0 );\n" | " fsm->accept = 1;\n" | " else {\n" | " /* If we are not in a final state then this\n" | " * is an error. Move to the error state. */\n" | " fsm->curState = 0;\n" | "class \n" | "public:\n" | " /* Forward dec state for the transition structure. */\n" | " struct State;\n" | " /* A single transition. */\n" | " struct Trans\n" | " State *toState;\n" | " int *funcs;\n" | " /* A single state. */\n" | " struct State\n" | " int lowIndex;\n" | " int highIndex;\n" | " void *transIndex;\n" | " unsigned int dflIndex;\n" | " int *outFuncs;\n" | " int isFinState;\n" | " /* Constructor. */\n" | " void Init( );\n" | " /* Execute some chunk of data. */\n" | " void Execute( char *data, int dlen );\n" | " /* Indicate to the fsm tha there is no more data. */\n" | " void Finish( );\n" | " /* Did the machine accept? */\n" | " int Accept( );\n" | " State *curState;\n" | " int accept;\n" | " inline void ExecFuncs( int *funcs, char *p );\n" | "/* The array of functions. */\n" | "#if \n" | "::State \n" | "/* The array of trainsitions. */\n" | "static \n" | "::Trans \n" | "/* The start state. */\n" | "static \n" | "::State *\n" | " * Execute functions pointed to by funcs until the null function is found. \n" | "inline void \n" | "::ExecFuncs( int *funcs, char *p )\n" | " int len = *funcs++;\n" | " while ( len-- > 0 ) {\n" | " switch ( *funcs++ ) {\n" | " * Constructor\n" | " Init();\n" | "Init\n" | "void \n" | "::Init( )\n" | " curState = \n" | "_startState;\n" | " accept = 0;\n" | "::Accept( )\n" | " return accept;\n" | "::Execute( char *data, int dlen )\n" | " char *p = data;\n" | " int len = dlen;\n" | " State *cs = curState;\n" | " for ( ; len > 0; p++, len-- ) {\n" | " int c = (unsigned char)*p;\n" | " Trans *trans;\n" | " if ( cs == 0 )\n" | " goto finished;\n" | " /* If the character is within the index bounds then get the\n" | " * transition for it. If it is out of the transition bounds\n" | " * we will use the default transition. */\n" | " if ( cs->lowIndex <= c && c < cs->highIndex ) {\n" | " /* Use the index to look into the transition array. */\n" | " trans = \n" | "_t + cs->dflIndex;\n" | " /* If there are functions for this transition then execute them. */\n" | " if ( trans->funcs != 0 )\n" | " ExecFuncs( trans->funcs, p );\n" | " /* Move to the new state. */\n" | " cs = trans->toState;\n" | "finished:\n" | " curState = cs;\n" | "::Finish( )\n" | " State *cs = curState;\n" | " if ( cs != 0 && cs->isFinState ) {\n" | " /* If finishing in a final state then execute the\n" | " * out functions for it. (if any). */\n" | " if ( cs->outFuncs != 0 )\n" | " ExecFuncs( cs->outFuncs, 0 );\n" | " accept = 1;\n" | " else {\n" | " /* If we are not in a final state then this\n" | " * is an error. Move to the error state. */\n" | " curState = 0;\n" | "10TabCodeGen\n" | "11CTabCodeGen\n" | "12CCTabCodeGen\n" | "10FsmCodeGen\n" | "bad_alloc\n" | " case \n" | " break;\n" | "/* Forward dec state for the transition structure. */\n" | "struct \n" | "StateStruct;\n" | "/* A single transition. */\n" | "struct \n" | "TransStruct\n" | " struct \n" | "StateStruct *toState;\n" | " int funcs;\n" | "typedef struct \n" | "TransStruct \n" | "Trans;\n" | "/* A single state. */\n" | "struct \n" | "StateStruct\n" | " int lowIndex;\n" | " int highIndex;\n" | " void *transIndex;\n" | " int dflIndex;\n" | " int outFuncs;\n" | " int isFinState;\n" | "typedef struct \n" | "StateStruct \n" | "State;\n" | "/* Only non-static data: current state. */\n" | "struct \n" | "Struct\n" | "State *curState;\n" | " int accept;\n" | "typedef struct \n" | "Struct \n" | "/* Init the fsm. */\n" | "void \n" | "Init( \n" | " *fsm );\n" | "/* Execute some chunk of data. */\n" | "void \n" | "Execute( \n" | " *fsm, char *data, int dlen );\n" | "/* Indicate to the fsm tha there is no more data. */\n" | "void \n" | "Finish( \n" | " *fsm );\n" | "/* Did the machine accept? */\n" | "int \n" | "Accept( \n" | " *fsm );\n" | "#define s \n" | "#define i \n" | "#define t \n" | "/* The array of indicies into the transition array. */\n" | "#if \n" | "static \n" | "_i[] = {\n" | "#endif\n" | "/* The aray of states. */\n" | "static \n" | "State \n" | "_s[] = {\n" | "/* The array of trainsitions. */\n" | "static \n" | "Trans \n" | "_t[] = {\n" | "/* The start state. */\n" | "static \n" | "State *\n" | "_startState = s+\n" | "#undef f\n" | "#undef s\n" | "#undef i\n" | "#undef t\n" | "/***************************************************************************\n" | " * Execute functions pointed to by funcs until the null function is found. \n" | "inline static void \n" | "ExecFuncs( \n" | " *fsm, int funcs, char *p )\n" | " switch ( funcs ) {\n" | "/****************************************\n" | "Init\n" | "void \n" | " *fsm )\n" | " fsm->curState = \n" | "_startState;\n" | " fsm->accept = 0;\n" | "/****************************************\n" | "Accept\n" | " * Did the fsm accept? \n" | "int \n" | " *fsm )\n" | " return fsm->accept;\n" | "/**********************************************************************\n" | " * Execute the fsm on some chunk of data. \n" | "void \n" | " *fsm, char *data, int dlen )\n" | " char *p = data;\n" | " int len = dlen;\n" | "State *cs = fsm->curState;\n" | " for ( ; len > 0; p++, len-- ) {\n" | " int c = (unsigned char)*p;\n" | "Trans *trans;\n" | " if ( cs == 0 )\n" | " goto finished;\n" | " /* If the character is within the index bounds then get the\n" | " * transition for it. If it is out of the transition bounds\n" | " * we will use the default transition. */\n" | " if ( cs->lowIndex <= c && c < cs->highIndex ) {\n" | " /* Use the index to look into the transition array. */\n" | " trans = \n" | "_t + \n" | " ((\n" | "*)cs->transIndex)[c - cs->lowIndex];\n" | " else {\n" | " /* Use the default index as the char is out of range. */\n" | " trans = \n" | "_t + cs->dflIndex;\n" | " /* If there are functions for this transition then execute them. */\n" | " if ( trans->funcs >= 0 )\n" | "ExecFuncs( fsm, trans->funcs, p );\n" | " /* Move to the new state. */\n" | " cs = trans->toState;\n" | "finished:\n" | " fsm->curState = cs;\n" | "/**********************************************************************\n" | "Finish\n" | " * Indicate to the fsm that the input is done. Does cleanup tasks.\n" | "void \n" | " *fsm )\n" | "State *cs = fsm->curState;\n" | " if ( cs != 0 && cs->isFinState ) {\n" | " /* If finishing in a final state then execute the\n" | " * out functions for it. (if any). */\n" | " if ( cs->outFuncs != 0 )\n" | "ExecFuncs( fsm, cs->outFuncs, 0 );\n" | " fsm->accept = 1;\n" | " else {\n" | " /* If we are not in a final state then this\n" | " * is an error. Move to the error state. */\n" | " fsm->curState = 0;\n" | "class \n" | "public:\n" | " /* Function and index type. */\n" | " typedef int Func;\n" | " /* Forward dec state for the transition structure. */\n" | " struct State;\n" | " /* A single transition. */\n" | " struct Trans\n" | " State *toState;\n" | " int funcs;\n" | " /* A single state. */\n" | " struct State\n" | " int lowIndex;\n" | " int highIndex;\n" | " void *transIndex;\n" | " int dflIndex;\n" | " int outFuncs;\n" | " int isFinState;\n" | " /* Constructor. */\n" | " void Init( );\n" | " /* Execute some chunk of data. */\n" | " void Execute( char *data, int dlen );\n" | " /* Indicate to the fsm tha there is no more data. */\n" | " void Finish( );\n" | " /* Did the machine accept? */\n" | " int Accept( );\n" | " State *curState;\n" | " int accept;\n" | " inline void ExecFuncs( int funcs, char *p );\n" | "::State \n" | "::Trans \n" | "::State *\n" | "/***************************************************************************\n" | " * Execute functions pointed to by funcs until the null function is found. \n" | "inline void \n" | "::ExecFuncs( int funcs, char *p )\n" | " switch ( funcs ) {\n" | "/****************************************\n" | " * Constructor\n" | " Init();\n" | "/****************************************\n" | "::Init( )\n" | " curState = \n" | "_startState;\n" | " accept = 0;\n" | "/****************************************\n" | " * Did the fsm accept? \n" | "int \n" | "::Accept( )\n" | " return accept;\n" | "/**********************************************************************\n" | " * Execute the fsm on some chunk of data. \n" | "void \n" | "::Execute( char *data, int dlen )\n" | " char *p = data;\n" | " int len = dlen;\n" | " State *cs = curState;\n" | " for ( ; len > 0; p++, len-- ) {\n" | " int c = (unsigned char)*p;\n" | " Trans *trans;\n" | " if ( cs == 0 )\n" | " goto finished;\n" | " /* If the character is within the index bounds then get the\n" | " * transition for it. If it is out of the transition bounds\n" | " * we will use the default transition. */\n" | " if ( cs->lowIndex <= c && c < cs->highIndex ) {\n" | " /* Use the index to look into the transition array. */\n" | " trans = \n" | "_t + cs->dflIndex;\n" | " /* If there are functions for this transition then execute them. */\n" | " if ( trans->funcs != 0 )\n" | " ExecFuncs( trans->funcs, p );\n" | " /* Move to the new state. */\n" | " cs = trans->toState;\n" | "finished:\n" | " curState = cs;\n" | "/**********************************************************************\n" | " * Indicate to the fsm that the input is done. Does cleanup tasks.\n" | "void \n" | "::Finish( )\n" | " State *cs = curState;\n" | " if ( cs != 0 && cs->isFinState ) {\n" | " /* If finishing in a final state then execute the\n" | " * out functions for it. (if any). */\n" | " if ( cs->outFuncs != 0 )\n" | " ExecFuncs( cs->outFuncs, 0 );\n" | " accept = 1;\n" | " else {\n" | " /* If we are not in a final state then this\n" | " * is an error. Move to the error state. */\n" | " curState = 0;\n" | "11FTabCodeGen\n" | "12CFTabCodeGen\n" | "13CCFTabCodeGen\n" | "bad_alloc\n" | "cs = -1; \n" | "cs = \n" | "break;\n" | " switch( cs ) {\n" | " case \n" | " switch ( c ) {\n" | "case \n" | "default: \n" | " }\n" | " break;\n" | " switch( cs ) {\n" | "accept = 1; \n" | "/* Only non-static data: current state. */\n" | "struct \n" | "Struct\n" | " int curState;\n" | " int accept;\n" | "typedef struct \n" | "Struct \n" | "/* Init the fsm. */\n" | "void \n" | "Init( \n" | " *fsm );\n" | "/* Execute some chunk of data. */\n" | "void \n" | "Execute( \n" | " *fsm, char *data, int dlen );\n" | "/* Indicate to the fsm tha there is no more data. */\n" | "void \n" | "Finish( \n" | " *fsm );\n" | "/* Did the machine accept? */\n" | "int \n" | "Accept( \n" | " *fsm );\n" | "/* The start state. */\n" | "static int \n" | "_startState = \n" | "/****************************************\n" | "Init\n" | "void \n" | " *fsm )\n" | " fsm->curState = \n" | "_startState;\n" | " fsm->accept = 0;\n" | "/**********************************************************************\n" | " * Execute the fsm on some chunk of data. \n" | "void \n" | " *fsm, char *data, int dlen )\n" | " char *p = data;\n" | " int len = dlen;\n" | " int cs = fsm->curState;\n" | " for ( ; len > 0; p++, len-- ) {\n" | " unsigned char c = (unsigned char)*p;\n" | " fsm->curState = cs;\n" | "/**********************************************************************\n" | "Finish\n" | " * Indicate to the fsm that the input is done. Does cleanup tasks.\n" | "void \n" | " *fsm )\n" | " int cs = fsm->curState;\n" | " int accept = 0;\n" | " fsm->accept = accept;\n" | "/*******************************************************\n" | "Accept\n" | " * Did the machine accept?\n" | "int \n" | " *fsm )\n" | " return fsm->accept;\n" | "/* Only non-static data: current state. */\n" | "class \n" | "public:\n" | " /* Init the fsm. */\n" | " void Init( );\n" | " /* Execute some chunk of data. */\n" | " void Execute( char *data, int dlen );\n" | " /* Indicate to the fsm tha there is no more data. */\n" | " void Finish( );\n" | " /* Did the machine accept? */\n" | " int Accept( );\n" | " int curState;\n" | " int accept;\n" | " /* The start state. */\n" | " static int startState;\n" | "/* The start state. */\n" | "int \n" | "::startState = \n" | " Init();\n" | "/****************************************\n" | "::Init\n" | "void \n" | "::Init( )\n" | " curState = startState;\n" | " accept = 0;\n" | "::Execute( char *data, int dlen )\n" | " char *p = data;\n" | " int len = dlen;\n" | " int cs = curState;\n" | " for ( ; len > 0; p++, len-- ) {\n" | " unsigned char c = (unsigned char)*p;\n" | " curState = cs;\n" | "/**********************************************************************\n" | "::Finish\n" | " * Indicate to the fsm that the input is done. Does cleanup tasks.\n" | "void \n" | "::Finish( )\n" | " int cs = curState;\n" | " int accept = 0;\n" | " this->accept = accept;\n" | "/*******************************************************\n" | "::Accept\n" | " * Did the machine accept?\n" | "int \n" | "::Accept( )\n" | " return accept;\n" | "10SelCodeGen\n" | "11CSelCodeGen\n" | "12CCSelCodeGen\n" | "10FsmCodeGen\n" | "bad_alloc\n" | "goto tr\n" | "goto st\n" | "goto err;\n" | " case \n" | "break;}\n" | ": goto st\n" | " case \n" | " default: return;\n" | " goto st\n" | " if ( --len == 0 )\n" | " goto out\n" | " switch( (alph) *++p ) {\n" | "case \n" | " default: \n" | " return;\n" | "curState = \n" | " switch( cs ) {\n" | "accept = 1; \n" | "break;\n" | "err:\n" | "curState = -1;\n" | ", p );\n" | "ExecFuncs( fsm, f+\n" | "fsm->\n" | "/* Only non-static data: current state. */\n" | "struct \n" | "Struct\n" | " int curState;\n" | " int accept;\n" | "typedef struct \n" | "Struct \n" | "/* Init the fsm. */\n" | "void \n" | "Init( \n" | " *fsm );\n" | "/* Execute some chunk of data. */\n" | "void \n" | "Execute( \n" | " *fsm, char *data, int dlen );\n" | "/* Indicate to the fsm tha there is no more data. */\n" | "void \n" | "Finish( \n" | " *fsm );\n" | "/* Did the machine accept? */\n" | "int \n" | "Accept( \n" | " *fsm );\n" | "/* The start state. */\n" | "static int \n" | "_startState = \n" | "#define f \n" | "#define alph unsigned char\n" | "/* The array of functions. */\n" | "#if \n" | "static int \n" | "_f[] = {\n" | "#endif\n" | "/****************************************\n" | "Init\n" | "void \n" | " *fsm )\n" | " fsm->curState = \n" | "_startState;\n" | " fsm->accept = 0;\n" | "/***************************************************************************\n" | " * Function exection. We do not inline this as in tab\n" | " * code gen because if we did, we might as well just expand \n" | " * the function as in the faster goto code generator.\n" | "static void \n" | "ExecFuncs( \n" | " *fsm, int *funcs, char *p )\n" | " int len = *funcs++;\n" | " while ( len-- > 0 ) {\n" | " switch ( *funcs++ ) {\n" | "/**********************************************************************\n" | " * Execute the fsm on some chunk of data. \n" | "void \n" | " *fsm, char *data, int dlen )\n" | " /* Prime these to one back to simulate entering the \n" | " * machine on a transition. */ \n" | " register char *p = data - 1;\n" | " register int len = dlen + 1;\n" | " /* Switch statment to enter the machine. */\n" | " switch ( \n" | "curState ) {\n" | "/**********************************************************************\n" | " * Indicate to the fsm that the input is done. Does cleanup tasks.\n" | "void \n" | " *fsm )\n" | " int cs = fsm->curState;\n" | " int accept = 0;\n" | " fsm->accept = accept;\n" | "/*******************************************************\n" | " * Did the machine accept?\n" | "int \n" | " *fsm )\n" | " return fsm->accept;\n" | "#undef f\n" | "#undef alph\n" | " ExecFuncs( f+\n" | "/* Only non-static data: current state. */\n" | "class \n" | "public:\n" | " /* Init the fsm. */\n" | " void Init( );\n" | " /* Execute some chunk of data. */\n" | " void Execute( char *data, int dlen );\n" | " /* Indicate to the fsm tha there is no more data. */\n" | " void Finish( );\n" | " /* Did the machine accept? */\n" | " int Accept( );\n" | " int curState;\n" | " int accept;\n" | " /* The start state. */\n" | " static int startState;\n" | " /* Function exection. We do not inline this as in tab code gen\n" | " * because if we did, we might as well just expand the function \n" | " * as in the faster goto code generator. */\n" | " void ExecFuncs( int *funcs, char * );\n" | "/* The start state. */\n" | "int \n" | "::startState = \n" | "/* some defines to lessen the code size. */\n" | "#define f \n" | "#endif\n" | "/****************************************\n" | " * Make sure the fsm is initted.\n" | " Init();\n" | "/****************************************\n" | " * Initialize the fsm.\n" | "void \n" | "::Init( )\n" | " curState = startState;\n" | " accept = 0;\n" | "/***************************************************************************\n" | " * Execute functions pointed to by funcs until the null function is found. \n" | "void \n" | "::ExecFuncs( int *funcs, char *p )\n" | " int len = *funcs++;\n" | " while ( len-- > 0 ) {\n" | " switch ( *funcs++ ) {\n" | "/**********************************************************************\n" | " * Execute the fsm on some chunk of data. \n" | "void \n" | "::Execute( char *data, int dlen )\n" | " /* Prime these to one back to simulate entering the \n" | " * machine on a transition. */ \n" | " register char *p = data - 1;\n" | " register int len = dlen + 1;\n" | " /* Switch statment to enter the machine. */\n" | " switch ( curState ) {\n" | "/**********************************************************************\n" | "::Finish\n" | " * Indicate to the fsm that the input is done. Does cleanup tasks.\n" | "void \n" | "::Finish( )\n" | " int cs = curState;\n" | " int accept = 0;\n" | " this->accept = accept;\n" | "/*******************************************************\n" | "::Accept\n" | " * Did the machine accept?\n" | "int \n" | "::Accept( )\n" | " return accept;\n" | "#undef f\n" | "#undef alph\n" | "11GotoCodeGen\n" | "12CGotoCodeGen\n" | "13CCGotoCodeGen\n" | "10FsmCodeGen\n" | "bad_alloc\n" | " case \n" | " break;\n" | ", p );\n" | "ExecFuncs( fsm, \n" | "fsm->\n" | "/* Only non-static data: current state. */\n" | "struct \n" | "Struct\n" | " int curState;\n" | " int accept;\n" | "typedef struct \n" | "Struct \n" | "/* Init the fsm. */\n" | "void \n" | "Init( \n" | " *fsm );\n" | "/* Execute some chunk of data. */\n" | "void \n" | "Execute( \n" | " *fsm, char *data, int dlen );\n" | "/* Indicate to the fsm tha there is no more data. */\n" | "void \n" | "Finish( \n" | " *fsm );\n" | "/* Did the machine accept? */\n" | "int \n" | "Accept( \n" | " *fsm );\n" | "/* The start state. */\n" | "static int \n" | "_startState = \n" | "/****************************************\n" | "Init\n" | "void \n" | " *fsm )\n" | " fsm->curState = \n" | "_startState;\n" | " fsm->accept = 0;\n" | "/***************************************************************************\n" | " * Function exection. We do not inline this as in tab\n" | " * code gen because if we did, we might as well just expand \n" | " * the function as in the faster goto code generator.\n" | "static void \n" | "ExecFuncs( \n" | " *fsm, int func, char *p )\n" | " switch ( func ) {\n" | "#define alph unsigned char\n" | "/**********************************************************************\n" | " * Execute the fsm on some chunk of data. \n" | "void \n" | " *fsm, char *data, int dlen )\n" | " /* Prime these to one back to simulate entering the \n" | " * machine on a transition. */ \n" | " register char *p = data-1;\n" | " register int len = dlen+1;\n" | " /* Switch statment to enter the machine. */\n" | " switch ( \n" | "curState ) {\n" | "/**********************************************************************\n" | "Finish\n" | " * Indicate to the fsm that the input is done. Does cleanup tasks.\n" | "void \n" | " *fsm )\n" | " int cs = fsm->curState;\n" | " int accept = 0;\n" | " fsm->accept = accept;\n" | "/*******************************************************\n" | "Accept\n" | " * Did the machine accept?\n" | "int \n" | " *fsm )\n" | " return fsm->accept;\n" | "#undef alph\n" | " ExecFuncs( \n" | "/* Only non-static data: current state. */\n" | "class \n" | "public:\n" | " /* Init the fsm. */\n" | " void Init( );\n" | " /* Execute some chunk of data. */\n" | " void Execute( char *data, int dlen );\n" | " /* Indicate to the fsm tha there is no more data. */\n" | " void Finish( );\n" | " /* Did the machine accept? */\n" | " int Accept( );\n" | " int curState;\n" | " int accept;\n" | " /* The start state. */\n" | " static int startState;\n" | " /* Function exection. We do not inline this as in tab code gen\n" | " * because if we did, we might as well just expand the function \n" | " * as in the faster goto code generator. */\n" | " void ExecFuncs( int func, char *p );\n" | "/* The start state. */\n" | "int \n" | "::startState = \n" | " Init();\n" | "/****************************************\n" | "::Init\n" | "void \n" | "::Init( )\n" | " curState = startState;\n" | " accept = 0;\n" | "/***************************************************************************\n" | " * Execute functions pointed to by funcs until the null function is found. \n" | "void \n" | "::ExecFuncs( int func, char *p )\n" | " switch ( func ) {\n" | "::Execute( char *data, int dlen )\n" | " /* Prime these to one back to simulate entering the \n" | " * machine on a transition. */ \n" | " register char *p = data-1;\n" | " register int len = dlen+1;\n" | " /* Switch statment to enter the machine. */\n" | " switch ( curState ) {\n" | "::Finish\n" | " * Indicate to the fsm that the input is done. Does cleanup tasks.\n" | "void \n" | "::Finish( )\n" | " int cs = curState;\n" | " int accept = 0;\n" | " this->accept = accept;\n" | "/*******************************************************\n" | "::Accept\n" | " * Did the machine accept?\n" | "int \n" | "::Accept( )\n" | " return accept;\n" | "#undef alph\n" | "12FGotoCodeGen\n" | "13CFGotoCodeGen\n" | "14CCFGotoCodeGen\n" | "11GotoCodeGen\n" | "10FsmCodeGen\n" | "bad_alloc\n" | "fsm->\n" | "/* Only non-static data: current state. */\n" | "struct \n" | "Struct\n" | " int curState;\n" | " int accept;\n" | "typedef struct \n" | "Struct \n" | "/* Init the fsm. */\n" | "void \n" | "Init( \n" | " *fsm );\n" | "/* Execute some chunk of data. */\n" | "void \n" | "Execute( \n" | " *fsm, char *data, int dlen );\n" | "/* Indicate to the fsm tha there is no more data. */\n" | "void \n" | "Finish( \n" | " *fsm );\n" | "/* Did the machine accept? */\n" | "int \n" | "Accept( \n" | " *fsm );\n" | "/* The start state. */\n" | "static int \n" | "_startState = \n" | "/****************************************\n" | "Init\n" | "void \n" | " *fsm )\n" | " fsm->curState = \n" | "_startState;\n" | " fsm->accept = 0;\n" | "#define alph unsigned char\n" | "/**********************************************************************\n" | " * Execute the fsm on some chunk of data. \n" | "void \n" | " *fsm, char *data, int dlen )\n" | " /* Prime these to one back to simulate entering the \n" | " * machine on a transition. */ \n" | " register char *p = data-1;\n" | " register int len = dlen+1;\n" | " /* Switch statment to enter the machine. */\n" | " switch ( \n" | "curState ) {\n" | "/**********************************************************************\n" | "Finish\n" | " * Indicate to the fsm that the input is done. Does cleanup tasks.\n" | "void \n" | " *fsm )\n" | " int cs = fsm->curState;\n" | " int accept = 0;\n" | " fsm->accept = accept;\n" | "/*******************************************************\n" | "Accept\n" | " * Did the machine accept?\n" | "int \n" | " *fsm )\n" | " return fsm->accept;\n" | "#undef alph\n" | "/* Only non-static data: current state. */\n" | "class \n" | "public:\n" | " /* Init the fsm. */\n" | " void Init( );\n" | " /* Execute some chunk of data. */\n" | " void Execute( char *data, int dlen );\n" | " /* Indicate to the fsm tha there is no more data. */\n" | " void Finish( );\n" | " /* Did the machine accept? */\n" | " int Accept( );\n" | " int curState;\n" | " int accept;\n" | " /* The start state. */\n" | " static int startState;\n" | "/* The start state. */\n" | "int \n" | "::startState = \n" | " Init();\n" | "/****************************************\n" | "::Init\n" | "void \n" | "::Init( )\n" | " curState = startState;\n" | " accept = 0;\n" | "#define alph unsigned char\n" | "/**********************************************************************\n" | " * Execute the fsm on some chunk of data. \n" | "void \n" | "::Execute( char *data, int dlen )\n" | " /* Prime these to one back to simulate entering the \n" | " * machine on a transition. */ \n" | " register char *p = data-1;\n" | " register int len = dlen+1;\n" | " /* Switch statment to enter the machine. */\n" | " switch ( curState ) {\n" | "::Finish\n" | " * Indicate to the fsm that the input is done. Does cleanup tasks.\n" | "void \n" | "::Finish( )\n" | " int cs = curState;\n" | " int accept = 0;\n" | " this->accept = accept;\n" | "/*******************************************************\n" | "::Accept\n" | " * Did the machine accept?\n" | "int \n" | "::Accept( )\n" | " return accept;\n" | "#undef alph\n" | "13IpGotoCodeGen\n" | "14CIpGotoCodeGen\n" | "15CCIpGotoCodeGen\n" | "11GotoCodeGen\n" | "10FsmCodeGen\n"; }%% %% write data; struct strs the_fsm; void test( char *buf ) { struct strs *fsm = &the_fsm; char *p = buf; char *pe = buf + strlen( buf ); %% write init; %% write exec; if ( fsm->cs >= strs_first_final ) printf("ACCEPT\n"); else printf("FAIL\n"); } int main() { test( "stdin\n" ); test( "bad_alloc\n" ); test( "_GLOBAL_OFFSET_TABLE_\n" ); test( "not in\n" ); test( "isatty\n" "junk on end.\n" ); return 0; } #ifdef _____OUTPUT_____ ACCEPT ACCEPT ACCEPT FAIL FAIL #endif ragel-6.8/test/builtin.rl0000664000175000017500000002147212043335171012375 00000000000000/* * @LANG: c */ #include void alph(const char *type) { printf("%s\n", type); } struct builtin { int cs; }; %%{ machine builtin; alphtype unsigned int; variable cs fsm->cs; main := ( any @{alph("any");} | ascii @{alph("ascii");} | extend @{alph("extend");} | alpha @{alph("alpha");} | digit @{alph("digit");} | alnum @{alph("alnum");} | lower @{alph("lower");} | upper @{alph("upper");} | cntrl @{alph("cntrl");} | graph @{alph("graph");} | print @{alph("print");} | punct @{alph("punct");} | space @{alph("space");} | xdigit @{alph("xdigit");} )*; }%% %% write data; void builtin_init( struct builtin *fsm ) { %% write init; } void builtin_execute( struct builtin *fsm, const unsigned int *data, int len ) { const unsigned int *p = data; const unsigned int *pe = data+len; %% write exec; } int builtin_finish( struct builtin *fsm ) { if ( fsm->cs == builtin_error ) return -1; else if ( fsm->cs >= builtin_first_final ) return 1; return 0; } #include #define BUFSIZE 2048 struct builtin fsm; char buf[BUFSIZE]; unsigned int i; int test( const unsigned int *data, int len ) { builtin_init( &fsm ); builtin_execute( &fsm, data, len ); if ( builtin_finish( &fsm ) > 0 ) printf("ACCEPT\n"); else printf("FAIL\n"); return 0; } #define DLEN 258 unsigned int data[DLEN] = { -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256 }; int main() { test( data, DLEN ); return 0; } #ifdef _____OUTPUT_____ any any ascii extend cntrl any ascii extend cntrl any ascii extend cntrl any ascii extend cntrl any ascii extend cntrl any ascii extend cntrl any ascii extend cntrl any ascii extend cntrl any ascii extend cntrl any ascii extend cntrl space any ascii extend cntrl space any ascii extend cntrl space any ascii extend cntrl space any ascii extend cntrl space any ascii extend cntrl any ascii extend cntrl any ascii extend cntrl any ascii extend cntrl any ascii extend cntrl any ascii extend cntrl any ascii extend cntrl any ascii extend cntrl any ascii extend cntrl any ascii extend cntrl any ascii extend cntrl any ascii extend cntrl any ascii extend cntrl any ascii extend cntrl any ascii extend cntrl any ascii extend cntrl any ascii extend cntrl any ascii extend cntrl any ascii extend print space any ascii extend graph print punct any ascii extend graph print punct any ascii extend graph print punct any ascii extend graph print punct any ascii extend graph print punct any ascii extend graph print punct any ascii extend graph print punct any ascii extend graph print punct any ascii extend graph print punct any ascii extend graph print punct any ascii extend graph print punct any ascii extend graph print punct any ascii extend graph print punct any ascii extend graph print punct any ascii extend graph print punct any ascii extend digit alnum graph print xdigit any ascii extend digit alnum graph print xdigit any ascii extend digit alnum graph print xdigit any ascii extend digit alnum graph print xdigit any ascii extend digit alnum graph print xdigit any ascii extend digit alnum graph print xdigit any ascii extend digit alnum graph print xdigit any ascii extend digit alnum graph print xdigit any ascii extend digit alnum graph print xdigit any ascii extend digit alnum graph print xdigit any ascii extend graph print punct any ascii extend graph print punct any ascii extend graph print punct any ascii extend graph print punct any ascii extend graph print punct any ascii extend graph print punct any ascii extend graph print punct any ascii extend alpha alnum upper graph print xdigit any ascii extend alpha alnum upper graph print xdigit any ascii extend alpha alnum upper graph print xdigit any ascii extend alpha alnum upper graph print xdigit any ascii extend alpha alnum upper graph print xdigit any ascii extend alpha alnum upper graph print xdigit any ascii extend alpha alnum upper graph print any ascii extend alpha alnum upper graph print any ascii extend alpha alnum upper graph print any ascii extend alpha alnum upper graph print any ascii extend alpha alnum upper graph print any ascii extend alpha alnum upper graph print any ascii extend alpha alnum upper graph print any ascii extend alpha alnum upper graph print any ascii extend alpha alnum upper graph print any ascii extend alpha alnum upper graph print any ascii extend alpha alnum upper graph print any ascii extend alpha alnum upper graph print any ascii extend alpha alnum upper graph print any ascii extend alpha alnum upper graph print any ascii extend alpha alnum upper graph print any ascii extend alpha alnum upper graph print any ascii extend alpha alnum upper graph print any ascii extend alpha alnum upper graph print any ascii extend alpha alnum upper graph print any ascii extend alpha alnum upper graph print any ascii extend graph print punct any ascii extend graph print punct any ascii extend graph print punct any ascii extend graph print punct any ascii extend graph print punct any ascii extend graph print punct any ascii extend alpha alnum lower graph print xdigit any ascii extend alpha alnum lower graph print xdigit any ascii extend alpha alnum lower graph print xdigit any ascii extend alpha alnum lower graph print xdigit any ascii extend alpha alnum lower graph print xdigit any ascii extend alpha alnum lower graph print xdigit any ascii extend alpha alnum lower graph print any ascii extend alpha alnum lower graph print any ascii extend alpha alnum lower graph print any ascii extend alpha alnum lower graph print any ascii extend alpha alnum lower graph print any ascii extend alpha alnum lower graph print any ascii extend alpha alnum lower graph print any ascii extend alpha alnum lower graph print any ascii extend alpha alnum lower graph print any ascii extend alpha alnum lower graph print any ascii extend alpha alnum lower graph print any ascii extend alpha alnum lower graph print any ascii extend alpha alnum lower graph print any ascii extend alpha alnum lower graph print any ascii extend alpha alnum lower graph print any ascii extend alpha alnum lower graph print any ascii extend alpha alnum lower graph print any ascii extend alpha alnum lower graph print any ascii extend alpha alnum lower graph print any ascii extend alpha alnum lower graph print any ascii extend graph print punct any ascii extend graph print punct any ascii extend graph print punct any ascii extend graph print punct any ascii extend cntrl any extend any extend any extend any extend any extend any extend any extend any extend any extend any extend any extend any extend any extend any extend any extend any extend any extend any extend any extend any extend any extend any extend any extend any extend any extend any extend any extend any extend any extend any extend any extend any extend any extend any extend any extend any extend any extend any extend any extend any extend any extend any extend any extend any extend any extend any extend any extend any extend any extend any extend any extend any extend any extend any extend any extend any extend any extend any extend any extend any extend any extend any extend any extend any extend any extend any extend any extend any extend any extend any extend any extend any extend any extend any extend any extend any extend any extend any extend any extend any extend any extend any extend any extend any extend any extend any extend any extend any extend any extend any extend any extend any extend any extend any extend any extend any extend any extend any extend any extend any extend any extend any extend any extend any extend any extend any extend any extend any extend any extend any extend any extend any extend any extend any extend any extend any extend any extend any extend any extend any extend any extend any extend any extend any extend any extend any extend any extend any extend any ACCEPT #endif ragel-6.8/test/cond4.rl0000664000175000017500000000147012043335171011732 00000000000000/* * @LANG: c++ */ #include #include using std::cout; using std::endl; %%{ machine foo; action c1 {(cout << "c1 ", true)} action c2 {(cout << "c2 ", true)} action c3 {(cout << "c3 ", true)} action c4 {(cout << "c4 ", true)} main := ( 10 .. 60 when c1 | 20 .. 40 when c2 | 30 .. 50 when c3 | 32 .. 38 when c4 | 0 .. 70 )* ${cout << "char: " << (int)*p << endl;}; }%% %% write data noerror nofinal; void test( char *str ) { int len = strlen( str ); int cs = foo_start; char *p = str, *pe = str+len; %% write exec; } char data[] = { 5, 15, 25, 31, 35, 39, 45, 55, 65, 0 }; int main() { test( data ); return 0; } #ifdef _____OUTPUT_____ char: 5 c1 char: 15 c1 c2 char: 25 c1 c2 c3 char: 31 c1 c2 c3 c4 char: 35 c1 c2 c3 char: 39 c1 c3 char: 45 c1 char: 55 char: 65 #endif ragel-6.8/test/forder3.rl0000664000175000017500000000275012043335171012271 00000000000000/* * @LANG: c */ #include #include struct forder { int cs; }; %%{ machine forder; variable cs fsm->cs; m1 = ( "" %{printf("enter m1 aa\n");} | 'aa'* >{printf("enter m1 aa\n");} %{printf("leave m1 aa\n");} ) 'b' @{printf("through m1 b\n");} . 'b'* . 'a'*; m2 = 'bbb'* 'aa'*; main := ( m1 %{printf("accept m1\n");} | "" %{printf("enter m2\n");} | m2 >{printf("enter m2\n");} %{printf("accept m2\n");} ) . '\n'; }%% %% write data; void forder_init( struct forder *fsm ) { %% write init; } void forder_execute( struct forder *fsm, const char *_data, int _len ) { const char *p = _data; const char *pe = _data+_len; %% write exec; } int forder_finish( struct forder *fsm ) { if ( fsm->cs == forder_error ) return -1; if ( fsm->cs >= forder_first_final ) return 1; return 0; } struct forder fsm; void test( char *buf ) { int len = strlen( buf ); forder_init( &fsm ); forder_execute( &fsm, buf, len ); if ( forder_finish( &fsm ) > 0 ) printf("ACCEPT\n"); else printf("FAIL\n"); } int main() { test( "aaaaaabbbaa\n" ); test( "\n" ); test( "bbbbbbaaaaaaa\n" ); test( "bbbbbbaaaaaa\n" ); test( "aaaaa\n" ); return 0; } #ifdef _____OUTPUT_____ enter m1 aa enter m2 leave m1 aa through m1 b accept m1 ACCEPT enter m2 enter m2 accept m2 ACCEPT enter m1 aa enter m1 aa leave m1 aa through m1 b enter m2 accept m1 ACCEPT enter m1 aa enter m1 aa leave m1 aa through m1 b enter m2 accept m1 accept m2 ACCEPT enter m1 aa enter m2 FAIL #endif ragel-6.8/test/langtrans_d.sh0000775000175000017500000000333312043335171013217 00000000000000#!/bin/bash # file=$1 [ -f $file ] || exit 1 # Get the amchine name. machine=`sed -n 's/^[\t ]*machine[\t ]*\([a-zA-Z_0-9]*\)[\t ]*;[\t ]*$/\1/p' $file` # Make a temporary version of the test case the D language translations. sed -n '/\/\*/,/\*\//d;p' $file | txl -q stdin langtrans_d.txl > $file.pr # Begin writing out the test case. cat << EOF /* * @LANG: d * @GENERATED: yes EOF grep '@ALLOW_GENFLAGS:' $file grep '@ALLOW_MINFLAGS:' $file cat << EOF */ import std.stdio; import std.string; class $machine { EOF # Write the data declarations sed -n '/^%%$/q;{s/^/\t/;p}' $file.pr # Write out the machine specification. sed -n '/^%%{$/,/^}%%/{s/^/\t/;p}' $file.pr # Write out the init and execute routines. cat << EOF int cs; %% write data; void init() { EOF sed -n '0,/^%%$/d; /^%%{$/q; {s/^/\t\t/;p}' $file.pr cat << EOF %% write init; } void exec( char data[] ) { char *p = data.ptr; char *pe = data.ptr + data.length; char *eof = pe; char _s[]; %% write exec; } void finish( ) { if ( cs >= ${machine}_first_final ) writefln( "ACCEPT" ); else writefln( "FAIL" ); } EOF # Write out the test data. sed -n '0,/\/\* _____INPUT_____/d; /_____INPUT_____ \*\//q; p;' $file | awk ' BEGIN { print " char[][] inp = [" } { print " " $0 "," } END { print " ];" print "" print " int inplen = " NR ";" }' # Write out the main routine. cat << EOF } int main( ) { $machine m = new $machine(); int i; for ( i = 0; i < m.inplen; i++ ) { m.init(); m.exec( m.inp[i] ); m.finish(); } return 0; } /* _____OUTPUT_____ EOF # Write out the expected output. sed -n '0,/\/\* _____OUTPUT_____/d; /_____OUTPUT_____ \*\//q; p;' $file echo "*/" # Don't need this language-specific file anymore. rm $file.pr ragel-6.8/test/lmgoto.rl0000664000175000017500000001000012043335171012211 00000000000000/* * @LANG: c++ */ #include #include using namespace std; #define TK_Dlit 192 #define TK_Slit 193 #define TK_Float 194 #define TK_Id 195 #define TK_NameSep 197 #define TK_Arrow 211 #define TK_PlusPlus 212 #define TK_MinusMinus 213 #define TK_ArrowStar 214 #define TK_DotStar 215 #define TK_ShiftLeft 216 #define TK_ShiftRight 217 #define TK_IntegerDecimal 218 #define TK_IntegerOctal 219 #define TK_IntegerHex 220 #define TK_EqualsEquals 223 #define TK_NotEquals 224 #define TK_AndAnd 225 #define TK_OrOr 226 #define TK_MultAssign 227 #define TK_DivAssign 228 #define TK_PercentAssign 229 #define TK_PlusAssign 230 #define TK_MinusAssign 231 #define TK_AmpAssign 232 #define TK_CaretAssign 233 #define TK_BarAssign 234 #define TK_DotDotDot 240 #define TK_Whitespace 241 #define TK_Comment 242 struct Scanner { int cs, act; const char *ts, *te; bool isCxx; void token( int tok ); void run( const char *buf ); }; %%{ machine Scanner; # Process all comments, relies on isCxx being set. comment := |* '*/' { if ( ! isCxx ) fgoto main; else { cout << "comm char: " << ts[0] << endl; cout << "comm char: " << ts[1] << endl; } }; '\n' { if ( isCxx ) fgoto main; else cout << "comm char: " << ts[0] << endl; }; any { cout << "comm char: " << ts[0] << endl; }; *|; main := |* # Single and double literals. ( 'L'? "'" ( [^'\\\n] | /\\./ )* "'" ) { token( TK_Slit );}; ( 'L'? '"' ( [^"\\\n] | /\\./ )* '"' ) { token( TK_Dlit );}; # Identifiers ( [a-zA-Z_] [a-zA-Z0-9_]* ) { token( TK_Id ); }; # Floating literals. fract_const = digit* '.' digit+ | digit+ '.'; exponent = [eE] [+\-]? digit+; float_suffix = [flFL]; ( fract_const exponent? float_suffix? | digit+ exponent float_suffix? ) { token( TK_Float );}; # Integer decimal. Leading part buffered by float. ( ( '0' | [1-9] [0-9]* ) [ulUL]{0,3} ) { token( TK_IntegerDecimal );}; # Integer octal. Leading part buffered by float. ( '0' [0-9]+ [ulUL]{0,2} ) { token( TK_IntegerOctal );}; # Integer hex. Leading 0 buffered by float. ( '0' ( 'x' [0-9a-fA-F]+ [ulUL]{0,2} ) ) { token( TK_IntegerHex );}; # Only buffer the second item, first buffered by symbol. */ '::' {token( TK_NameSep );}; '==' {token( TK_EqualsEquals );}; '!=' {token( TK_NotEquals );}; '&&' {token( TK_AndAnd );}; '||' {token( TK_OrOr );}; '*=' {token( TK_MultAssign );}; '/=' {token( TK_DivAssign );}; '%=' {token( TK_PercentAssign );}; '+=' {token( TK_PlusAssign );}; '-=' {token( TK_MinusAssign );}; '&=' {token( TK_AmpAssign );}; '^=' {token( TK_CaretAssign );}; '|=' {token( TK_BarAssign );}; '++' {token( TK_PlusPlus );}; '--' {token( TK_MinusMinus );}; '->' {token( TK_Arrow );}; '->*' {token( TK_ArrowStar );}; '.*' {token( TK_DotStar );}; # Three char compounds, first item already buffered. */ '...' { token( TK_DotDotDot );}; # Single char symbols. ( punct - [_"'] ) { token( ts[0] );}; # Comments and whitespace. Handle these outside of the machine so that se # don't end up buffering the comments. '/*' { isCxx = false; fgoto comment; }; '//' { isCxx = true; fgoto comment; }; ( any - 33..126 )+ { token( TK_Whitespace );}; *|; }%% %% write data nofinal; void Scanner::token( int tok ) { const char *data = ts; int len = te - ts; cout << "<" << tok << "> "; if ( data != 0 ) { for ( int i = 0; i < len; i++ ) cout << data[i]; } cout << '\n'; } void Scanner::run( const char *buf ) { int len = strlen( buf ); %% write init; const char *p = buf; const char *pe = buf + len; const char *eof = pe; %% write exec; if ( cs == Scanner_error ) { /* Machine failed before finding a token. */ cout << "PARSE ERROR" << endl; } } int main() { Scanner scanner; scanner.run( "//hello*/\n" "/*hi there*/ hello 0x88" ); return 0; } #ifdef _____OUTPUT_____ comm char: h comm char: e comm char: l comm char: l comm char: o comm char: * comm char: / comm char: h comm char: i comm char: comm char: t comm char: h comm char: e comm char: r comm char: e <241> <195> hello <241> <220> 0x88 #endif ragel-6.8/test/mailbox1.h0000664000175000017500000000164112043335171012251 00000000000000#ifndef _MAILBOX1_H #define _MAILBOX1_H #include #include #include "vector.h" struct MBox { int cs; Vector headName; Vector headContent; // Initialize the machine. Invokes any init statement blocks. Returns 0 // if the machine begins in a non-accepting state and 1 if the machine // begins in an accepting state. void init( ); // Execute the machine on a block of data. Returns -1 if after processing // the data, the machine is in the error state and can never accept, 0 if // the machine is in a non-accepting state and 1 if the machine is in an // accepting state. void execute( const char *data, int len ); // Indicate that there is no more data. Returns -1 if the machine finishes // in the error state and does not accept, 0 if the machine finishes // in any other non-accepting state and 1 if the machine finishes in an // accepting state. int finish( ); }; #endif ragel-6.8/test/java1.rl0000664000175000017500000000132212043335171011721 00000000000000/* * @LANG: java */ class java1 { %%{ machine java1; one := 'one\n'; two := 'two\n'; four := 'four\n'; main := ( 'hello' | 'there' | 'friend' ) '\n' @{int s = fentry(one); fgoto *s; char c = fc;} ( 'one' | 'two' | 'four' ) '\n'; }%% %% write data; static void test( char data[] ) { int cs, p = 0, pe = data.length; int top; %% write init; %% write exec; if ( cs >= java1_first_final ) System.out.println( "ACCEPT" ); else System.out.println( "FAIL" ); } public static void main( String args[] ) { test( "hello\none\n".toCharArray() ); test( "there\ntwo\n".toCharArray() ); test( "friend\nfour\n".toCharArray() ); } } /* _____OUTPUT_____ ACCEPT FAIL FAIL */ ragel-6.8/test/patact.rl0000664000175000017500000000311612043335171012176 00000000000000/* * @LANG: indep */ char comm; int top; int stack[32]; ptr ts; ptr te; int act; int val; %% %%{ machine patact; other := |* [a-z]+ => { prints "word\n"; }; [0-9]+ => { prints "num\n"; }; [\n ] => { prints "space\n"; }; *|; exec_test := |* [a-z]+ => { prints "word (w/lbh)\n"; fexec te-1; fgoto other; }; [a-z]+ ' foil' => { prints "word (c/lbh)\n"; }; [\n ] => { prints "space\n"; }; '22' => { prints "num (w/switch)\n"; }; [0-9]+ => { prints "num (w/switch)\n"; fexec te-1; fgoto other;}; [0-9]+ ' foil' => {prints "num (c/switch)\n"; }; '!';# => { prints "immdiate\n"; fgoto exec_test; }; *|; semi := |* ';' => { prints "in semi\n"; fgoto main; }; *|; main := |* [a-z]+ => { prints "word (w/lbh)\n"; fhold; fgoto other; }; [a-z]+ ' foil' => { prints "word (c/lbh)\n"; }; [\n ] => { prints "space\n"; }; '22' => { prints "num (w/switch)\n"; }; [0-9]+ => { prints "num (w/switch)\n"; fhold; fgoto other;}; [0-9]+ ' foil' => {prints "num (c/switch)\n"; }; ';' => { prints "going to semi\n"; fhold; fgoto semi;}; '!' => { prints "immdiate\n"; fgoto exec_test; }; *|; }%% /* _____INPUT_____ "abcd foix\n" "abcd\nanother\n" "123 foix\n" "!abcd foix\n" "!abcd\nanother\n" "!123 foix\n" ";" _____INPUT_____ */ /* _____OUTPUT_____ word (w/lbh) word space word space ACCEPT word (w/lbh) word space word space ACCEPT num (w/switch) num space word space ACCEPT immdiate word (w/lbh) word space word space ACCEPT immdiate word (w/lbh) word space word space ACCEPT immdiate num (w/switch) num space word space ACCEPT going to semi in semi ACCEPT _____OUTPUT_____ */ ragel-6.8/test/export4.rl0000664000175000017500000000142212043335171012325 00000000000000/* * @LANG: d */ import std.c.stdio; import std.string; %%{ machine test; export c1 = 'c'; export c2 = 'z'; export c3 = 't'; commands := ( c1 . digit* '\n' @{ printf( "c1\n" );} | c2 . alpha* '\n' @{ printf( "c2\n" );}| c3 . '.'* '\n' @{ printf( "c3\n" );} )*; some_other := any*; }%% %% write exports; %% write data; int test( char data[] ) { int cs = test_en_commands; char *p = data.ptr, pe = data.ptr + data.length; %% write init nocs; %% write exec; if ( cs >= test_first_final ) printf("ACCEPT\n"); else printf("ERROR\n"); return 0; } char data[] = [ test_ex_c1, '1', '2', '\n', test_ex_c2, 'a', 'b', '\n', test_ex_c3, '.', '.', '\n' ]; int main() { test( data ); return 0; } /+ _____OUTPUT_____ c1 c2 c3 ACCEPT ++++++++++++++++++/ ragel-6.8/test/cond6.rl0000664000175000017500000000153512043335171011736 00000000000000/* * @LANG: c++ */ /* Balanced parenthesis with conditions. */ #include #include using std::cout; using std::endl; %%{ machine cond; write data noerror; }%% void test( const char *str ) { int cs = cond_start, n = 0; const char *p = str; const char *pe = str + strlen( str ); %%{ comment = '(' @{n=0;} ( '('@{n++;} | ')'@{n--;} | [^()] )* :> ')' when{!n}; main := ' '* comment ' '* '\n' @{cout << "success";}; write exec; }%% if ( cs < cond_first_final ) cout << "failure"; cout << endl; } int main() { test( "( ( )\n" ); test( "()()\n" ); test( "(((\n" ); test( "((()\n" ); test( "((())\n" ); test( "()\n" ); test( "((()))\n" ); test( "(()())\n" ); test( "((())()(((()))))\n" ); return 0; } #ifdef _____OUTPUT_____ failure failure failure failure failure success success success success #endif ragel-6.8/test/ruby1.rl0000664000175000017500000000105012043335171011757 00000000000000# # @LANG: ruby # # Test the host language scanning for ruby. # # %%{ a = 1 b = /%%\{\}/; %%{ machine ruby1; main := lower+ digit+ '\n' @{ # } c = 1 d = /\}/ puts "NL" }; }%% # %%{ e = 1 f = /%%\{\}/; %% write data; # %%{ g = 1 h = /%%\{\}/; def run_machine( data ) p = 0; pe = data.length cs = 0 %% write init; %% write exec; if cs >= ruby1_first_final puts "ACCEPT" else puts "FAIL" end end inp = [ "abc1231\n", ] inp.each { |str| run_machine(str) } =begin _____OUTPUT_____ NL ACCEPT =end _____OUTPUT_____ ragel-6.8/test/README0000664000175000017500000000075712043335171011253 00000000000000 The test suite now depends on TXL. Since the trend in Ragel is towards independence of the host-language, tests are now being written in a fictional mini-language designed for the purpose of testing ragel. The host language test-cases are then generated using a TXL transformation. This allows one test case to be run against all host languages in addition to all code generation styles. TXL is not open source, but a free download is available from the homepage. http://www.txl.ca/ -Adrian ragel-6.8/ragel/0000775000175000017500000000000012106315064010554 500000000000000ragel-6.8/ragel/fsmmin.cpp0000664000175000017500000005536112106050031012471 00000000000000/* * Copyright 2002 Adrian Thurston */ /* This file is part of Ragel. * * Ragel is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Ragel is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Ragel; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "fsmgraph.h" #include "mergesort.h" int FsmAp::partitionRound( StateAp **statePtrs, MinPartition *parts, int numParts ) { /* Need a mergesort object and a single partition compare. */ MergeSort mergeSort; PartitionCompare partCompare; /* For each partition. */ for ( int p = 0; p < numParts; p++ ) { /* Fill the pointer array with the states in the partition. */ StateList::Iter state = parts[p].list; for ( int s = 0; state.lte(); state++, s++ ) statePtrs[s] = state; /* Sort the states using the partitioning compare. */ int numStates = parts[p].list.length(); mergeSort.sort( statePtrs, numStates ); /* Assign the states into partitions based on the results of the sort. */ int destPart = p, firstNewPart = numParts; for ( int s = 1; s < numStates; s++ ) { /* If this state differs from the last then move to the next partition. */ if ( partCompare.compare( statePtrs[s-1], statePtrs[s] ) < 0 ) { /* The new partition is the next avail spot. */ destPart = numParts; numParts += 1; } /* If the state is not staying in the first partition, then * transfer it to its destination partition. */ if ( destPart != p ) { StateAp *state = parts[p].list.detach( statePtrs[s] ); parts[destPart].list.append( state ); } } /* Fix the partition pointer for all the states that got moved to a new * partition. This must be done after the states are transfered so the * result of the sort is not altered. */ for ( int newPart = firstNewPart; newPart < numParts; newPart++ ) { StateList::Iter state = parts[newPart].list; for ( ; state.lte(); state++ ) state->alg.partition = &parts[newPart]; } } return numParts; } /** * \brief Minimize by partitioning version 1. * * Repeatedly tries to split partitions until all partitions are unsplittable. * Produces the most minimal FSM possible. */ void FsmAp::minimizePartition1() { /* Need one mergesort object and partition compares. */ MergeSort mergeSort; InitPartitionCompare initPartCompare; /* Nothing to do if there are no states. */ if ( stateList.length() == 0 ) return; /* * First thing is to partition the states by final state status and * transition functions. This gives us an initial partitioning to work * with. */ /* Make a array of pointers to states. */ int numStates = stateList.length(); StateAp** statePtrs = new StateAp*[numStates]; /* Fill up an array of pointers to the states for easy sorting. */ StateList::Iter state = stateList; for ( int s = 0; state.lte(); state++, s++ ) statePtrs[s] = state; /* Sort the states using the array of states. */ mergeSort.sort( statePtrs, numStates ); /* An array of lists of states is used to partition the states. */ MinPartition *parts = new MinPartition[numStates]; /* Assign the states into partitions. */ int destPart = 0; for ( int s = 0; s < numStates; s++ ) { /* If this state differs from the last then move to the next partition. */ if ( s > 0 && initPartCompare.compare( statePtrs[s-1], statePtrs[s] ) < 0 ) { /* Move to the next partition. */ destPart += 1; } /* Put the state into its partition. */ statePtrs[s]->alg.partition = &parts[destPart]; parts[destPart].list.append( statePtrs[s] ); } /* We just moved all the states from the main list into partitions without * taking them off the main list. So clean up the main list now. */ stateList.abandon(); /* Split partitions. */ int numParts = destPart + 1; while ( true ) { /* Test all partitions for splitting. */ int newNum = partitionRound( statePtrs, parts, numParts ); /* When no partitions can be split, stop. */ if ( newNum == numParts ) break; numParts = newNum; } /* Fuse states in the same partition. The states will end up back on the * main list. */ fusePartitions( parts, numParts ); /* Cleanup. */ delete[] statePtrs; delete[] parts; } /* Split partitions that need splittting, decide which partitions might need * to be split as a result, continue until there are no more that might need * to be split. */ int FsmAp::splitCandidates( StateAp **statePtrs, MinPartition *parts, int numParts ) { /* Need a mergesort and a partition compare. */ MergeSort mergeSort; PartitionCompare partCompare; /* The lists of unsplitable (partList) and splitable partitions. * Only partitions in the splitable list are check for needing splitting. */ PartitionList partList, splittable; /* Initially, all partitions are born from a split (the initial * partitioning) and can cause other partitions to be split. So any * partition with a state with a transition out to another partition is a * candidate for splitting. This will make every partition except possibly * partitions of final states split candidates. */ for ( int p = 0; p < numParts; p++ ) { /* Assume not active. */ parts[p].active = false; /* Look for a trans out of any state in the partition. */ for ( StateList::Iter state = parts[p].list; state.lte(); state++ ) { /* If there is at least one transition out to another state then * the partition becomes splittable. */ if ( state->outList.length() > 0 ) { parts[p].active = true; break; } } /* If it was found active then it goes on the splittable list. */ if ( parts[p].active ) splittable.append( &parts[p] ); else partList.append( &parts[p] ); } /* While there are partitions that are splittable, pull one off and try * to split it. If it splits, determine which partitions may now be split * as a result of the newly split partition. */ while ( splittable.length() > 0 ) { MinPartition *partition = splittable.detachFirst(); /* Fill the pointer array with the states in the partition. */ StateList::Iter state = partition->list; for ( int s = 0; state.lte(); state++, s++ ) statePtrs[s] = state; /* Sort the states using the partitioning compare. */ int numStates = partition->list.length(); mergeSort.sort( statePtrs, numStates ); /* Assign the states into partitions based on the results of the sort. */ MinPartition *destPart = partition; int firstNewPart = numParts; for ( int s = 1; s < numStates; s++ ) { /* If this state differs from the last then move to the next partition. */ if ( partCompare.compare( statePtrs[s-1], statePtrs[s] ) < 0 ) { /* The new partition is the next avail spot. */ destPart = &parts[numParts]; numParts += 1; } /* If the state is not staying in the first partition, then * transfer it to its destination partition. */ if ( destPart != partition ) { StateAp *state = partition->list.detach( statePtrs[s] ); destPart->list.append( state ); } } /* Fix the partition pointer for all the states that got moved to a new * partition. This must be done after the states are transfered so the * result of the sort is not altered. */ int newPart; for ( newPart = firstNewPart; newPart < numParts; newPart++ ) { StateList::Iter state = parts[newPart].list; for ( ; state.lte(); state++ ) state->alg.partition = &parts[newPart]; } /* Put the partition we just split and any new partitions that came out * of the split onto the inactive list. */ partition->active = false; partList.append( partition ); for ( newPart = firstNewPart; newPart < numParts; newPart++ ) { parts[newPart].active = false; partList.append( &parts[newPart] ); } if ( destPart == partition ) continue; /* Now determine which partitions are splittable as a result of * splitting partition by walking the in lists of the states in * partitions that got split. Partition is the faked first item in the * loop. */ MinPartition *causalPart = partition; newPart = firstNewPart - 1; while ( newPart < numParts ) { /* Loop all states in the causal partition. */ StateList::Iter state = causalPart->list; for ( ; state.lte(); state++ ) { /* Walk all transition into the state and put the partition * that the from state is in onto the splittable list. */ for ( TransInList::Iter trans = state->inList; trans.lte(); trans++ ) { MinPartition *fromPart = trans->fromState->alg.partition; if ( ! fromPart->active ) { fromPart->active = true; partList.detach( fromPart ); splittable.append( fromPart ); } } } newPart += 1; causalPart = &parts[newPart]; } } return numParts; } /** * \brief Minimize by partitioning version 2 (best alg). * * Repeatedly tries to split partitions that may splittable until there are no * more partitions that might possibly need splitting. Runs faster than * version 1. Produces the most minimal fsm possible. */ void FsmAp::minimizePartition2() { /* Need a mergesort and an initial partition compare. */ MergeSort mergeSort; InitPartitionCompare initPartCompare; /* Nothing to do if there are no states. */ if ( stateList.length() == 0 ) return; /* * First thing is to partition the states by final state status and * transition functions. This gives us an initial partitioning to work * with. */ /* Make a array of pointers to states. */ int numStates = stateList.length(); StateAp** statePtrs = new StateAp*[numStates]; /* Fill up an array of pointers to the states for easy sorting. */ StateList::Iter state = stateList; for ( int s = 0; state.lte(); state++, s++ ) statePtrs[s] = state; /* Sort the states using the array of states. */ mergeSort.sort( statePtrs, numStates ); /* An array of lists of states is used to partition the states. */ MinPartition *parts = new MinPartition[numStates]; /* Assign the states into partitions. */ int destPart = 0; for ( int s = 0; s < numStates; s++ ) { /* If this state differs from the last then move to the next partition. */ if ( s > 0 && initPartCompare.compare( statePtrs[s-1], statePtrs[s] ) < 0 ) { /* Move to the next partition. */ destPart += 1; } /* Put the state into its partition. */ statePtrs[s]->alg.partition = &parts[destPart]; parts[destPart].list.append( statePtrs[s] ); } /* We just moved all the states from the main list into partitions without * taking them off the main list. So clean up the main list now. */ stateList.abandon(); /* Split partitions. */ int numParts = splitCandidates( statePtrs, parts, destPart+1 ); /* Fuse states in the same partition. The states will end up back on the * main list. */ fusePartitions( parts, numParts ); /* Cleanup. */ delete[] statePtrs; delete[] parts; } void FsmAp::initialMarkRound( MarkIndex &markIndex ) { /* P and q for walking pairs. */ StateAp *p = stateList.head, *q; /* Need an initial partition compare. */ InitPartitionCompare initPartCompare; /* Walk all unordered pairs of (p, q) where p != q. * The second depth of the walk stops before reaching p. This * gives us all unordered pairs of states (p, q) where p != q. */ while ( p != 0 ) { q = stateList.head; while ( q != p ) { /* If the states differ on final state status, out transitions or * any transition data then they should be separated on the initial * round. */ if ( initPartCompare.compare( p, q ) != 0 ) markIndex.markPair( p->alg.stateNum, q->alg.stateNum ); q = q->next; } p = p->next; } } bool FsmAp::markRound( MarkIndex &markIndex ) { /* P an q for walking pairs. Take note if any pair gets marked. */ StateAp *p = stateList.head, *q; bool pairWasMarked = false; /* Need a mark comparison. */ MarkCompare markCompare; /* Walk all unordered pairs of (p, q) where p != q. * The second depth of the walk stops before reaching p. This * gives us all unordered pairs of states (p, q) where p != q. */ while ( p != 0 ) { q = stateList.head; while ( q != p ) { /* Should we mark the pair? */ if ( !markIndex.isPairMarked( p->alg.stateNum, q->alg.stateNum ) ) { if ( markCompare.shouldMark( markIndex, p, q ) ) { markIndex.markPair( p->alg.stateNum, q->alg.stateNum ); pairWasMarked = true; } } q = q->next; } p = p->next; } return pairWasMarked; } /** * \brief Minimize by pair marking. * * Decides if each pair of states is distinct or not. Uses O(n^2) memory and * should only be used on small graphs. Produces the most minmimal FSM * possible. */ void FsmAp::minimizeStable() { /* Set the state numbers. */ setStateNumbers( 0 ); /* This keeps track of which pairs have been marked. */ MarkIndex markIndex( stateList.length() ); /* Mark pairs where final stateness, out trans, or trans data differ. */ initialMarkRound( markIndex ); /* While the last round of marking succeeded in marking a state * continue to do another round. */ int modified = markRound( markIndex ); while (modified) modified = markRound( markIndex ); /* Merge pairs that are unmarked. */ fuseUnmarkedPairs( markIndex ); } bool FsmAp::minimizeRound() { /* Nothing to do if there are no states. */ if ( stateList.length() == 0 ) return false; /* Need a mergesort on approx compare and an approx compare. */ MergeSort mergeSort; ApproxCompare approxCompare; /* Fill up an array of pointers to the states. */ StateAp **statePtrs = new StateAp*[stateList.length()]; StateList::Iter state = stateList; for ( int s = 0; state.lte(); state++, s++ ) statePtrs[s] = state; bool modified = false; /* Sort The list. */ mergeSort.sort( statePtrs, stateList.length() ); /* Walk the list looking for duplicates next to each other, * merge in any duplicates. */ StateAp **pLast = statePtrs; StateAp **pState = statePtrs + 1; for ( int i = 1; i < stateList.length(); i++, pState++ ) { if ( approxCompare.compare( *pLast, *pState ) == 0 ) { /* Last and pState are the same, so fuse together. Move forward * with pState but not with pLast. If any more are identical, we * must */ fuseEquivStates( *pLast, *pState ); modified = true; } else { /* Last and this are different, do not set to merge them. Move * pLast to the current (it may be way behind from merging many * states) and pState forward one to consider the next pair. */ pLast = pState; } } delete[] statePtrs; return modified; } /** * \brief Minmimize by an approximation. * * Repeatedly tries to find states with transitions out to the same set of * states on the same set of keys until no more identical states can be found. * Does not produce the most minimial FSM possible. */ void FsmAp::minimizeApproximate() { /* While the last minimization round succeeded in compacting states, * continue to try to compact states. */ while ( true ) { bool modified = minimizeRound(); if ( ! modified ) break; } } /* Remove states that have no path to them from the start state. Recursively * traverses the graph marking states that have paths into them. Then removes * all states that did not get marked. */ void FsmAp::removeUnreachableStates() { /* Misfit accounting should be off and there should be no states on the * misfit list. */ assert( !misfitAccounting && misfitList.length() == 0 ); /* Mark all the states that can be reached * through the existing set of entry points. */ markReachableFromHere( startState ); for ( EntryMap::Iter en = entryPoints; en.lte(); en++ ) markReachableFromHere( en->value ); /* Delete all states that are not marked * and unmark the ones that are marked. */ StateAp *state = stateList.head; while ( state ) { StateAp *next = state->next; if ( state->stateBits & STB_ISMARKED ) state->stateBits &= ~ STB_ISMARKED; else { detachState( state ); stateList.detach( state ); delete state; } state = next; } } bool FsmAp::outListCovers( StateAp *state ) { /* Must be at least one range to cover. */ if ( state->outList.length() == 0 ) return false; /* The first must start at the lower bound. */ TransList::Iter trans = state->outList.first(); if ( keyOps->minKey < trans->lowKey ) return false; /* Loop starts at second el. */ trans.increment(); /* Loop checks lower against prev upper. */ for ( ; trans.lte(); trans++ ) { /* Lower end of the trans must be one greater than the * previous' high end. */ Key lowKey = trans->lowKey; lowKey.decrement(); if ( trans->prev->highKey < lowKey ) return false; } /* Require that the last range extends to the upper bound. */ trans = state->outList.last(); if ( trans->highKey < keyOps->maxKey ) return false; return true; } /* Remove states that that do not lead to a final states. Works recursivly traversing * the graph in reverse (starting from all final states) and marking seen states. Then * removes states that did not get marked. */ void FsmAp::removeDeadEndStates() { /* Misfit accounting should be off and there should be no states on the * misfit list. */ assert( !misfitAccounting && misfitList.length() == 0 ); /* Mark all states that have paths to the final states. */ StateAp **st = finStateSet.data; int nst = finStateSet.length(); for ( int i = 0; i < nst; i++, st++ ) markReachableFromHereReverse( *st ); /* Start state gets honorary marking. If the machine accepts nothing we * still want the start state to hang around. This must be done after the * recursive call on all the final states so that it does not cause the * start state in transitions to be skipped when the start state is * visited by the traversal. */ startState->stateBits |= STB_ISMARKED; /* Delete all states that are not marked * and unmark the ones that are marked. */ StateAp *state = stateList.head; while ( state != 0 ) { StateAp *next = state->next; if ( state->stateBits & STB_ISMARKED ) state->stateBits &= ~ STB_ISMARKED; else { detachState( state ); stateList.detach( state ); delete state; } state = next; } } /* Remove states on the misfit list. To work properly misfit accounting should * be on when this is called. The detaching of a state will likely cause * another misfit to be collected and it can then be removed. */ void FsmAp::removeMisfits() { while ( misfitList.length() > 0 ) { /* Get the first state. */ StateAp *state = misfitList.head; /* Detach and delete. */ detachState( state ); /* The state was previously on the misfit list and detaching can only * remove in transitions so the state must still be on the misfit * list. */ misfitList.detach( state ); delete state; } } /* Fuse src into dest because they have been deemed equivalent states. * Involves moving transitions into src to go into dest and invoking * callbacks. Src is deleted detached from the graph and deleted. */ void FsmAp::fuseEquivStates( StateAp *dest, StateAp *src ) { /* This would get ugly. */ assert( dest != src ); /* Cur is a duplicate. We can merge it with trail. */ inTransMove( dest, src ); detachState( src ); stateList.detach( src ); delete src; } void FsmAp::fuseUnmarkedPairs( MarkIndex &markIndex ) { StateAp *p = stateList.head, *nextP, *q; /* Definition: The primary state of an equivalence class is the first state * encounterd that belongs to the equivalence class. All equivalence * classes have primary state including equivalence classes with one state * in it. */ /* For each unmarked pair merge p into q and delete p. q is always the * primary state of it's equivalence class. We wouldn't have landed on it * here if it were not, because it would have been deleted. * * Proof that q is the primaray state of it's equivalence class: Assume q * is not the primary state of it's equivalence class, then it would be * merged into some state that came before it and thus p would be * equivalent to that state. But q is the first state that p is equivalent * to so we have a contradiction. */ /* Walk all unordered pairs of (p, q) where p != q. * The second depth of the walk stops before reaching p. This * gives us all unordered pairs of states (p, q) where p != q. */ while ( p != 0 ) { nextP = p->next; q = stateList.head; while ( q != p ) { /* If one of p or q is a final state then mark. */ if ( ! markIndex.isPairMarked( p->alg.stateNum, q->alg.stateNum ) ) { fuseEquivStates( q, p ); break; } q = q->next; } p = nextP; } } void FsmAp::fusePartitions( MinPartition *parts, int numParts ) { /* For each partition, fuse state 2, 3, ... into state 1. */ for ( int p = 0; p < numParts; p++ ) { /* Assume that there will always be at least one state. */ StateAp *first = parts[p].list.head, *toFuse = first->next; /* Put the first state back onto the main state list. Don't bother * removing it from the partition list first. */ stateList.append( first ); /* Fuse the rest of the state into the first. */ while ( toFuse != 0 ) { /* Save the next. We will trash it before it is needed. */ StateAp *next = toFuse->next; /* Put the state to be fused in to the first back onto the main * list before it is fuse. the graph. The state needs to be on * the main list for the detach from the graph to work. Don't * bother removing the state from the partition list first. We * need not maintain it. */ stateList.append( toFuse ); /* Now fuse to the first. */ fuseEquivStates( first, toFuse ); /* Go to the next that we saved before trashing the next pointer. */ toFuse = next; } /* We transfered the states from the partition list into the main list without * removing the states from the partition list first. Clean it up. */ parts[p].list.abandon(); } } /* Merge neighboring transitions go to the same state and have the same * transitions data. */ void FsmAp::compressTransitions() { for ( StateList::Iter st = stateList; st.lte(); st++ ) { if ( st->outList.length() > 1 ) { for ( TransList::Iter trans = st->outList, next = trans.next(); next.lte(); ) { Key nextLow = next->lowKey; nextLow.decrement(); if ( trans->highKey == nextLow && trans->toState == next->toState && CmpActionTable::compare( trans->actionTable, next->actionTable ) == 0 ) { trans->highKey = next->highKey; st->outList.detach( next ); detachTrans( next->fromState, next->toState, next ); delete next; next = trans.next(); } else { trans.increment(); next.increment(); } } } } } ragel-6.8/ragel/mlgoto.cpp0000664000175000017500000005556012106050031012502 00000000000000/* * Copyright 2001-2006 Adrian Thurston * 2004 Erich Ocean * 2005 Alan West */ /* This file is part of Ragel. * * Ragel is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Ragel is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Ragel; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "ragel.h" #include "mlgoto.h" #include "redfsm.h" #include "bstmap.h" #include "gendata.h" /* Emit the goto to take for a given transition. */ std::ostream &OCamlGotoCodeGen::TRANS_GOTO( RedTransAp *trans, int level ) { out << TABS(level) << "tr" << trans->id << " ()"; return out; } std::ostream &OCamlGotoCodeGen::TO_STATE_ACTION_SWITCH() { /* Walk the list of functions, printing the cases. */ for ( GenActionList::Iter act = actionList; act.lte(); act++ ) { /* Write out referenced actions. */ if ( act->numToStateRefs > 0 ) { /* Write the case label, the action and the case break. */ out << "\t| " << act->actionId << " ->\n"; ACTION( out, act, 0, false ); out << "\t()\n"; } } genLineDirective( out ); return out; } std::ostream &OCamlGotoCodeGen::FROM_STATE_ACTION_SWITCH() { /* Walk the list of functions, printing the cases. */ for ( GenActionList::Iter act = actionList; act.lte(); act++ ) { /* Write out referenced actions. */ if ( act->numFromStateRefs > 0 ) { /* Write the case label, the action and the case break. */ out << "\t| " << act->actionId << " ->\n"; ACTION( out, act, 0, false ); out << "\t()\n"; } } genLineDirective( out ); return out; } std::ostream &OCamlGotoCodeGen::EOF_ACTION_SWITCH() { /* Walk the list of functions, printing the cases. */ for ( GenActionList::Iter act = actionList; act.lte(); act++ ) { /* Write out referenced actions. */ if ( act->numEofRefs > 0 ) { /* Write the case label, the action and the case break. */ out << "\t| " << act->actionId << " ->\n"; ACTION( out, act, 0, true ); out << "\t()\n"; } } genLineDirective( out ); return out; } std::ostream &OCamlGotoCodeGen::ACTION_SWITCH() { /* Walk the list of functions, printing the cases. */ for ( GenActionList::Iter act = actionList; act.lte(); act++ ) { /* Write out referenced actions. */ if ( act->numTransRefs > 0 ) { /* Write the case label, the action and the case break. */ out << "\t| " << act->actionId << " ->\n"; ACTION( out, act, 0, false ); out << "\t()\n"; } } genLineDirective( out ); return out; } void OCamlGotoCodeGen::GOTO_HEADER( RedStateAp *state ) { /* Label the state. */ out << "| " << state->id << " ->\n"; } void OCamlGotoCodeGen::emitSingleSwitch( RedStateAp *state ) { /* Load up the singles. */ int numSingles = state->outSingle.length(); RedTransEl *data = state->outSingle.data; if ( numSingles == 1 ) { /* If there is a single single key then write it out as an if. */ out << "\tif " << GET_WIDE_KEY(state) << " = " << KEY(data[0].lowKey) << " then\n\t\t"; /* Virtual function for writing the target of the transition. */ TRANS_GOTO(data[0].value, 0) << " else\n"; } else if ( numSingles > 1 ) { /* Write out single keys in a switch if there is more than one. */ out << "\tmatch " << GET_WIDE_KEY(state) << " with\n"; /* Write out the single indicies. */ for ( int j = 0; j < numSingles; j++ ) { out << "\t\t| " << ALPHA_KEY(data[j].lowKey) << " -> "; TRANS_GOTO(data[j].value, 0) << "\n"; } out << "\t\t| _ ->\n"; } } void OCamlGotoCodeGen::emitRangeBSearch( RedStateAp *state, int level, int low, int high, RedTransAp* def) { /* Get the mid position, staying on the lower end of the range. */ int mid = (low + high) >> 1; RedTransEl *data = state->outRange.data; /* Determine if we need to look higher or lower. */ bool anyLower = mid > low; bool anyHigher = mid < high; /* Determine if the keys at mid are the limits of the alphabet. */ bool limitLow = data[mid].lowKey == keyOps->minKey; bool limitHigh = data[mid].highKey == keyOps->maxKey; if ( anyLower && anyHigher ) { /* Can go lower and higher than mid. */ out << TABS(level) << "if " << GET_WIDE_KEY(state) << " < " << KEY(data[mid].lowKey) << " then begin\n"; emitRangeBSearch( state, level+1, low, mid-1, def ); out << TABS(level) << " end else if " << GET_WIDE_KEY(state) << " > " << KEY(data[mid].highKey) << " then begin\n"; emitRangeBSearch( state, level+1, mid+1, high, def ); out << TABS(level) << " end else\n"; TRANS_GOTO(data[mid].value, level+1) << "\n"; } else if ( anyLower && !anyHigher ) { /* Can go lower than mid but not higher. */ out << TABS(level) << "if " << GET_WIDE_KEY(state) << " < " << KEY(data[mid].lowKey) << " then begin\n"; emitRangeBSearch( state, level+1, low, mid-1, def ); /* if the higher is the highest in the alphabet then there is no * sense testing it. */ if ( limitHigh ) { out << TABS(level) << " end else\n"; TRANS_GOTO(data[mid].value, level+1) << "\n"; } else { out << TABS(level) << " end else if " << GET_WIDE_KEY(state) << " <= " << KEY(data[mid].highKey) << " then\n"; TRANS_GOTO(data[mid].value, level+1) << "\n" << TABS(level) << "else\n"; TRANS_GOTO(def, level+1) << "\n"; } } else if ( !anyLower && anyHigher ) { /* Can go higher than mid but not lower. */ out << TABS(level) << "if " << GET_WIDE_KEY(state) << " > " << KEY(data[mid].highKey) << " then begin\n"; emitRangeBSearch( state, level+1, mid+1, high, def ); /* If the lower end is the lowest in the alphabet then there is no * sense testing it. */ if ( limitLow ) { out << TABS(level) << " end else\n"; TRANS_GOTO(data[mid].value, level+1) << "\n"; } else { out << TABS(level) << " end else if " << GET_WIDE_KEY(state) << " >= " << KEY(data[mid].lowKey) << " then\n"; TRANS_GOTO(data[mid].value, level+1) << "\n" << TABS(level) << "else\n"; TRANS_GOTO(def, level+1) << "\n"; } } else { /* Cannot go higher or lower than mid. It's mid or bust. What * tests to do depends on limits of alphabet. */ if ( !limitLow && !limitHigh ) { out << TABS(level) << "if " << KEY(data[mid].lowKey) << " <= " << GET_WIDE_KEY(state) << " && " << GET_WIDE_KEY(state) << " <= " << KEY(data[mid].highKey) << " then\n"; TRANS_GOTO(data[mid].value, level+1) << "\n" << TABS(level) << "else\n"; TRANS_GOTO(def, level+1) << "\n"; } else if ( limitLow && !limitHigh ) { out << TABS(level) << "if " << GET_WIDE_KEY(state) << " <= " << KEY(data[mid].highKey) << " then\n"; TRANS_GOTO(data[mid].value, level+1) << "\n" << TABS(level) << "else\n"; TRANS_GOTO(def, level+1) << "\n"; } else if ( !limitLow && limitHigh ) { out << TABS(level) << "if " << KEY(data[mid].lowKey) << " <= " << GET_WIDE_KEY(state) << " then\n"; TRANS_GOTO(data[mid].value, level+1) << "\n" << TABS(level) << "else\n"; TRANS_GOTO(def, level+1) << "\n"; } else { /* Both high and low are at the limit. No tests to do. */ TRANS_GOTO(data[mid].value, level+1) << "\n"; } } } void OCamlGotoCodeGen::STATE_GOTO_ERROR() { /* Label the state and bail immediately. */ outLabelUsed = true; RedStateAp *state = redFsm->errState; out << "| " << state->id << " ->\n"; out << " do_out ()\n"; } void OCamlGotoCodeGen::COND_TRANSLATE( GenStateCond *stateCond, int level ) { GenCondSpace *condSpace = stateCond->condSpace; out << TABS(level) << "_widec = " << CAST(WIDE_ALPH_TYPE()) << "(" << KEY(condSpace->baseKey) << " + (" << GET_KEY() << " - " << KEY(keyOps->minKey) << "));\n"; for ( GenCondSet::Iter csi = condSpace->condSet; csi.lte(); csi++ ) { out << TABS(level) << "if ( "; CONDITION( out, *csi ); Size condValOffset = ((1 << csi.pos()) * keyOps->alphSize()); out << " ) _widec += " << condValOffset << ";\n"; } } void OCamlGotoCodeGen::emitCondBSearch( RedStateAp *state, int level, int low, int high ) { /* Get the mid position, staying on the lower end of the range. */ int mid = (low + high) >> 1; GenStateCond **data = state->stateCondVect.data; /* Determine if we need to look higher or lower. */ bool anyLower = mid > low; bool anyHigher = mid < high; /* Determine if the keys at mid are the limits of the alphabet. */ bool limitLow = data[mid]->lowKey == keyOps->minKey; bool limitHigh = data[mid]->highKey == keyOps->maxKey; if ( anyLower && anyHigher ) { /* Can go lower and higher than mid. */ out << TABS(level) << "if ( " << GET_KEY() << " < " << KEY(data[mid]->lowKey) << " ) {\n"; emitCondBSearch( state, level+1, low, mid-1 ); out << TABS(level) << "} else if ( " << GET_KEY() << " > " << KEY(data[mid]->highKey) << " ) {\n"; emitCondBSearch( state, level+1, mid+1, high ); out << TABS(level) << "} else {\n"; COND_TRANSLATE(data[mid], level+1); out << TABS(level) << "}\n"; } else if ( anyLower && !anyHigher ) { /* Can go lower than mid but not higher. */ out << TABS(level) << "if ( " << GET_KEY() << " < " << KEY(data[mid]->lowKey) << " ) {\n"; emitCondBSearch( state, level+1, low, mid-1 ); /* if the higher is the highest in the alphabet then there is no * sense testing it. */ if ( limitHigh ) { out << TABS(level) << "} else {\n"; COND_TRANSLATE(data[mid], level+1); out << TABS(level) << "}\n"; } else { out << TABS(level) << "} else if ( " << GET_KEY() << " <= " << KEY(data[mid]->highKey) << " ) {\n"; COND_TRANSLATE(data[mid], level+1); out << TABS(level) << "}\n"; } } else if ( !anyLower && anyHigher ) { /* Can go higher than mid but not lower. */ out << TABS(level) << "if ( " << GET_KEY() << " > " << KEY(data[mid]->highKey) << " ) {\n"; emitCondBSearch( state, level+1, mid+1, high ); /* If the lower end is the lowest in the alphabet then there is no * sense testing it. */ if ( limitLow ) { out << TABS(level) << "} else {\n"; COND_TRANSLATE(data[mid], level+1); out << TABS(level) << "}\n"; } else { out << TABS(level) << "} else if ( " << GET_KEY() << " >= " << KEY(data[mid]->lowKey) << " ) {\n"; COND_TRANSLATE(data[mid], level+1); out << TABS(level) << "}\n"; } } else { /* Cannot go higher or lower than mid. It's mid or bust. What * tests to do depends on limits of alphabet. */ if ( !limitLow && !limitHigh ) { out << TABS(level) << "if ( " << KEY(data[mid]->lowKey) << " <= " << GET_KEY() << " && " << GET_KEY() << " <= " << KEY(data[mid]->highKey) << " ) {\n"; COND_TRANSLATE(data[mid], level+1); out << TABS(level) << "}\n"; } else if ( limitLow && !limitHigh ) { out << TABS(level) << "if ( " << GET_KEY() << " <= " << KEY(data[mid]->highKey) << " ) {\n"; COND_TRANSLATE(data[mid], level+1); out << TABS(level) << "}\n"; } else if ( !limitLow && limitHigh ) { out << TABS(level) << "if ( " << KEY(data[mid]->lowKey) << " <= " << GET_KEY() << " )\n {"; COND_TRANSLATE(data[mid], level+1); out << TABS(level) << "}\n"; } else { /* Both high and low are at the limit. No tests to do. */ COND_TRANSLATE(data[mid], level); } } } std::ostream &OCamlGotoCodeGen::STATE_GOTOS() { for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { if ( st == redFsm->errState ) STATE_GOTO_ERROR(); else { /* Writing code above state gotos. */ GOTO_HEADER( st ); out << "\tbegin\n"; if ( st->stateCondVect.length() > 0 ) { out << " _widec = " << GET_KEY() << ";\n"; emitCondBSearch( st, 1, 0, st->stateCondVect.length() - 1 ); } /* Try singles. */ if ( st->outSingle.length() > 0 ) emitSingleSwitch( st ); /* Default case is to binary search for the ranges, if that fails then */ if ( st->outRange.length() > 0 ) emitRangeBSearch( st, 1, 0, st->outRange.length() - 1, st->defTrans ); else /* Write the default transition. */ TRANS_GOTO( st->defTrans, 1 ) << "\n"; out << "\tend\n"; } } return out; } std::ostream &OCamlGotoCodeGen::TRANSITIONS() { /* Emit any transitions that have functions and that go to * this state. */ for ( TransApSet::Iter trans = redFsm->transSet; trans.lte(); trans++ ) { /* Write the label for the transition so it can be jumped to. */ out << " and tr" << trans->id << " () = "; /* Destination state. */ if ( trans->action != 0 && trans->action->anyCurStateRef() ) out << "_ps = " << vCS() << ";"; out << vCS() << " <- " << trans->targ->id << "; "; if ( trans->action != 0 ) { /* Write out the transition func. */ out << "f" << trans->action->actListId << " ()\n"; } else { /* No code to execute, just loop around. */ out << "do_again ()\n"; } } return out; } std::ostream &OCamlGotoCodeGen::EXEC_FUNCS() { /* Make labels that set acts and jump to execFuncs. Loop func indicies. */ for ( GenActionTableMap::Iter redAct = redFsm->actionMap; redAct.lte(); redAct++ ) { if ( redAct->numTransRefs > 0 ) { out << " and f" << redAct->actListId << " () = " << "state.acts <- " << itoa( redAct->location+1 ) << "; " "execFuncs ()\n"; } } out << "\n" "and execFuncs () =\n" " state.nacts <- " << AT( A(), POST_INCR( "state.acts") ) << ";\n" " begin try while " << POST_DECR("state.nacts") << " > 0 do\n" " match " << AT( A(), POST_INCR("state.acts") ) << " with\n"; ACTION_SWITCH(); SWITCH_DEFAULT() << " done with Goto_again -> () end;\n" " do_again ()\n"; return out; } unsigned int OCamlGotoCodeGen::TO_STATE_ACTION( RedStateAp *state ) { int act = 0; if ( state->toStateAction != 0 ) act = state->toStateAction->location+1; return act; } unsigned int OCamlGotoCodeGen::FROM_STATE_ACTION( RedStateAp *state ) { int act = 0; if ( state->fromStateAction != 0 ) act = state->fromStateAction->location+1; return act; } unsigned int OCamlGotoCodeGen::EOF_ACTION( RedStateAp *state ) { int act = 0; if ( state->eofAction != 0 ) act = state->eofAction->location+1; return act; } std::ostream &OCamlGotoCodeGen::TO_STATE_ACTIONS() { /* Take one off for the psuedo start state. */ int numStates = redFsm->stateList.length(); unsigned int *vals = new unsigned int[numStates]; memset( vals, 0, sizeof(unsigned int)*numStates ); for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) vals[st->id] = TO_STATE_ACTION(st); out << "\t"; for ( int st = 0; st < redFsm->nextStateId; st++ ) { /* Write any eof action. */ out << vals[st]; if ( st < numStates-1 ) { out << ARR_SEP(); if ( (st+1) % IALL == 0 ) out << "\n\t"; } } out << "\n"; delete[] vals; return out; } std::ostream &OCamlGotoCodeGen::FROM_STATE_ACTIONS() { /* Take one off for the psuedo start state. */ int numStates = redFsm->stateList.length(); unsigned int *vals = new unsigned int[numStates]; memset( vals, 0, sizeof(unsigned int)*numStates ); for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) vals[st->id] = FROM_STATE_ACTION(st); out << "\t"; for ( int st = 0; st < redFsm->nextStateId; st++ ) { /* Write any eof action. */ out << vals[st]; if ( st < numStates-1 ) { out << ARR_SEP(); if ( (st+1) % IALL == 0 ) out << "\n\t"; } } out << "\n"; delete[] vals; return out; } std::ostream &OCamlGotoCodeGen::EOF_ACTIONS() { /* Take one off for the psuedo start state. */ int numStates = redFsm->stateList.length(); unsigned int *vals = new unsigned int[numStates]; memset( vals, 0, sizeof(unsigned int)*numStates ); for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) vals[st->id] = EOF_ACTION(st); out << "\t"; for ( int st = 0; st < redFsm->nextStateId; st++ ) { /* Write any eof action. */ out << vals[st]; if ( st < numStates-1 ) { out << ARR_SEP(); if ( (st+1) % IALL == 0 ) out << "\n\t"; } } out << "\n"; delete[] vals; return out; } std::ostream &OCamlGotoCodeGen::FINISH_CASES() { for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { /* States that are final and have an out action need a case. */ if ( st->eofAction != 0 ) { /* Write the case label. */ out << "\t\t| " << st->id << " -> "; /* Write the goto func. */ out << "f" << st->eofAction->actListId << " ()\n"; } } return out; } void OCamlGotoCodeGen::GOTO( ostream &ret, int gotoDest, bool inFinish ) { ret << "begin " << vCS() << " <- " << gotoDest << "; " << CTRL_FLOW() << "raise Goto_again end"; } void OCamlGotoCodeGen::GOTO_EXPR( ostream &ret, GenInlineItem *ilItem, bool inFinish ) { ret << "begin " << vCS() << " <- ("; INLINE_LIST( ret, ilItem->children, 0, inFinish ); ret << "); " << CTRL_FLOW() << "raise Goto_again end"; } void OCamlGotoCodeGen::CURS( ostream &ret, bool inFinish ) { ret << "(_ps)"; } void OCamlGotoCodeGen::TARGS( ostream &ret, bool inFinish, int targState ) { ret << "(" << vCS() << ")"; } void OCamlGotoCodeGen::NEXT( ostream &ret, int nextDest, bool inFinish ) { ret << vCS() << " <- " << nextDest << ";"; } void OCamlGotoCodeGen::NEXT_EXPR( ostream &ret, GenInlineItem *ilItem, bool inFinish ) { ret << vCS() << " <- ("; INLINE_LIST( ret, ilItem->children, 0, inFinish ); ret << ");"; } void OCamlGotoCodeGen::CALL( ostream &ret, int callDest, int targState, bool inFinish ) { if ( prePushExpr != 0 ) { ret << "begin "; INLINE_LIST( ret, prePushExpr, 0, false ); } ret << "begin " << AT( STACK(), POST_INCR(TOP()) ) << " <- " << vCS() << "; "; ret << vCS() << " <- " << callDest << "; " << CTRL_FLOW() << "raise Goto_again end "; if ( prePushExpr != 0 ) ret << "end"; } void OCamlGotoCodeGen::CALL_EXPR( ostream &ret, GenInlineItem *ilItem, int targState, bool inFinish ) { if ( prePushExpr != 0 ) { ret << "begin "; INLINE_LIST( ret, prePushExpr, 0, false ); } ret << "begin " << AT(STACK(), POST_INCR(TOP()) ) << " <- " << vCS() << "; " << vCS() << " <- ("; INLINE_LIST( ret, ilItem->children, targState, inFinish ); ret << "); " << CTRL_FLOW() << "raise Goto_again end "; if ( prePushExpr != 0 ) ret << "end"; } void OCamlGotoCodeGen::RET( ostream &ret, bool inFinish ) { ret << "begin " << vCS() << " <- " << AT(STACK(), PRE_DECR(TOP()) ) << "; "; if ( postPopExpr != 0 ) { ret << "begin "; INLINE_LIST( ret, postPopExpr, 0, false ); ret << "end "; } ret << CTRL_FLOW() << "raise Goto_again end"; } void OCamlGotoCodeGen::BREAK( ostream &ret, int targState ) { outLabelUsed = true; ret << "begin " << P() << " <- " << P() << " + 1; " << CTRL_FLOW() << "raise Goto_out end"; } void OCamlGotoCodeGen::writeData() { if ( redFsm->anyActions() ) { OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActArrItem), A() ); ACTIONS_ARRAY(); CLOSE_ARRAY() << "\n"; } if ( redFsm->anyToStateActions() ) { OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActionLoc), TSA() ); TO_STATE_ACTIONS(); CLOSE_ARRAY() << "\n"; } if ( redFsm->anyFromStateActions() ) { OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActionLoc), FSA() ); FROM_STATE_ACTIONS(); CLOSE_ARRAY() << "\n"; } if ( redFsm->anyEofActions() ) { OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActionLoc), EA() ); EOF_ACTIONS(); CLOSE_ARRAY() << "\n"; } STATE_IDS(); out << "type state = { mutable acts : " << ARRAY_TYPE(redFsm->maxActionLoc) << " ; mutable nacts : " << ARRAY_TYPE(redFsm->maxActArrItem) << "; }" << TOP_SEP(); out << "exception Goto_again" << TOP_SEP(); } void OCamlGotoCodeGen::writeExec() { testEofUsed = false; outLabelUsed = false; out << " begin\n"; // if ( redFsm->anyRegCurStateRef() ) // out << " int _ps = 0;\n"; if ( redFsm->anyToStateActions() || redFsm->anyRegActions() || redFsm->anyFromStateActions() ) { out << " let state = { acts = 0; nacts = 0; } in\n"; } // if ( redFsm->anyConditions() ) // out << " " << WIDE_ALPH_TYPE() << " _widec;\n"; out << "\n"; out << " let rec do_start () =\n"; if ( !noEnd ) { testEofUsed = true; out << " if " << P() << " = " << PE() << " then\n" " do_test_eof ()\n" "\telse\n"; } if ( redFsm->errState != 0 ) { outLabelUsed = true; out << " if " << vCS() << " = " << redFsm->errState->id << " then\n" " do_out ()\n" "\telse\n"; } out << "\tdo_resume ()\n"; out << "and do_resume () =\n"; if ( redFsm->anyFromStateActions() ) { out << " state.acts <- " << AT( FSA(), vCS() ) << ";\n" " state.nacts <- " << AT( A(), POST_INCR("state.acts") ) << ";\n" " while " << POST_DECR("state.nacts") << " > 0 do\n" " begin match " << AT( A(), POST_INCR("state.acts") ) << " with\n"; FROM_STATE_ACTION_SWITCH(); SWITCH_DEFAULT() << " end\n" " done;\n" "\n"; } out << " begin match " << vCS() << " with\n"; STATE_GOTOS(); SWITCH_DEFAULT() << " end\n" "\n"; TRANSITIONS() << "\n"; if ( redFsm->anyRegActions() ) EXEC_FUNCS() << "\n"; // if ( redFsm->anyRegActions() || redFsm->anyActionGotos() || // redFsm->anyActionCalls() || redFsm->anyActionRets() ) out << "\tand do_again () =\n"; if ( redFsm->anyToStateActions() ) { out << " state.acts <- " << AT( TSA(), vCS() ) << ";\n" " state.nacts <- " << AT( A(), POST_INCR("state.acts") ) << ";\n" " while " << POST_DECR("state.nacts") << " > 0 do\n" " begin match " << AT( A(), POST_INCR("state.acts") ) << " with\n"; TO_STATE_ACTION_SWITCH(); SWITCH_DEFAULT() << " end\n" " done;\n" "\n"; } if ( redFsm->errState != 0 ) { outLabelUsed = true; out << " match " << vCS() << " with\n" "\t| " << redFsm->errState->id << " -> do_out ()\n" "\t| _ ->\n"; } out << "\t" << P() << " <- " << P() << " + 1;\n"; if ( !noEnd ) { out << " if " << P() << " <> " << PE() << " then\n" " do_resume ()\n" "\telse do_test_eof ()\n"; } else { out << " do_resume ()\n"; } // if ( testEofUsed ) out << "and do_test_eof () =\n"; if ( redFsm->anyEofTrans() || redFsm->anyEofActions() ) { out << " if " << P() << " = " << vEOF() << " then\n" " begin\n"; if ( redFsm->anyEofTrans() ) { out << " match " << vCS() << " with\n"; for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { if ( st->eofTrans != 0 ) out << " | " << st->id << " -> tr" << st->eofTrans->id << " ()\n"; } out << "\t| _ -> ();\n"; } if ( redFsm->anyEofActions() ) { out << " let __acts = ref " << AT( EA(), vCS() ) << " in\n" " let __nacts = ref " << AT( A(), "!__acts" ) << " in\n" " incr __acts;\n" " begin try while !__nacts > 0 do\n" " decr __nacts;\n" " begin match " << AT( A(), POST_INCR("__acts.contents") ) << " with\n"; EOF_ACTION_SWITCH(); SWITCH_DEFAULT() << " end;\n" " done with Goto_again -> do_again () end;\n"; } out << " end\n" "\n"; } else { out << "\t()\n"; } if ( outLabelUsed ) out << " and do_out () = ()\n"; out << "\tin do_start ()\n"; out << " end;\n"; } ragel-6.8/ragel/gocodegen.h0000664000175000017500000001404712106050031012573 00000000000000/* * Copyright 2001-2006 Adrian Thurston * 2004 Erich Ocean * 2005 Alan West */ /* This file is part of Ragel. * * Ragel is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Ragel is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Ragel; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef _GOCODEGEN_H #define _GOCODEGEN_H #include #include #include #include "common.h" #include "gendata.h" using std::string; using std::ostream; /* Integer array line length. */ #define IALL 8 /* Forwards. */ struct RedFsmAp; struct RedStateAp; struct CodeGenData; struct GenAction; struct NameInst; struct GenInlineItem; struct GenInlineList; struct RedAction; struct LongestMatch; struct LongestMatchPart; class GoCodeGen : public CodeGenData { public: GoCodeGen( ostream &out ) : CodeGenData(out) {} virtual ~GoCodeGen() {} virtual void finishRagelDef(); virtual void writeInit(); virtual void writeStart(); virtual void writeFirstFinal(); virtual void writeError(); virtual void writeExports(); protected: string FSM_NAME(); string START_STATE_ID(); ostream &ACTIONS_ARRAY(); string GET_WIDE_KEY(); string GET_WIDE_KEY( RedStateAp *state ); string TABS( int level ); string KEY( Key key ); string WIDE_KEY( RedStateAp *state, Key key ); string LDIR_PATH( char *path ); virtual void ACTION( ostream &ret, GenAction *action, int targState, bool inFinish, bool csForced ); void CONDITION( ostream &ret, GenAction *condition ); string ALPH_TYPE(); string WIDE_ALPH_TYPE(); string ARRAY_TYPE( unsigned long maxVal ); bool isAlphTypeSigned(); bool isWideAlphTypeSigned(); virtual string CAST( string type, string expr ); virtual string UINT(); virtual string INT(); virtual string NULL_ITEM(); virtual string GET_KEY(); string P(); string PE(); string vEOF(); string ACCESS(); string vCS(); string STACK(); string TOP(); string TOKSTART(); string TOKEND(); string ACT(); string DATA(); string DATA_PREFIX(); string PM() { return "_" + DATA_PREFIX() + "partition_map"; } string C() { return "_" + DATA_PREFIX() + "cond_spaces"; } string CK() { return "_" + DATA_PREFIX() + "cond_keys"; } string K() { return "_" + DATA_PREFIX() + "trans_keys"; } string I() { return "_" + DATA_PREFIX() + "indicies"; } string CO() { return "_" + DATA_PREFIX() + "cond_offsets"; } string KO() { return "_" + DATA_PREFIX() + "key_offsets"; } string IO() { return "_" + DATA_PREFIX() + "index_offsets"; } string CL() { return "_" + DATA_PREFIX() + "cond_lengths"; } string SL() { return "_" + DATA_PREFIX() + "single_lengths"; } string RL() { return "_" + DATA_PREFIX() + "range_lengths"; } string A() { return "_" + DATA_PREFIX() + "actions"; } string TA() { return "_" + DATA_PREFIX() + "trans_actions"; } string TT() { return "_" + DATA_PREFIX() + "trans_targs"; } string TSA() { return "_" + DATA_PREFIX() + "to_state_actions"; } string FSA() { return "_" + DATA_PREFIX() + "from_state_actions"; } string EA() { return "_" + DATA_PREFIX() + "eof_actions"; } string ET() { return "_" + DATA_PREFIX() + "eof_trans"; } string SP() { return "_" + DATA_PREFIX() + "key_spans"; } string CSP() { return "_" + DATA_PREFIX() + "cond_key_spans"; } string START() { return DATA_PREFIX() + "start"; } string ERROR() { return DATA_PREFIX() + "error"; } string FIRST_FINAL() { return DATA_PREFIX() + "first_final"; } string CTXDATA() { return DATA_PREFIX() + "ctxdata"; } void INLINE_LIST( ostream &ret, GenInlineList *inlineList, int targState, bool inFinish, bool csForced ); virtual void GOTO( ostream &ret, int gotoDest, bool inFinish ) = 0; virtual void CALL( ostream &ret, int callDest, int targState, bool inFinish ) = 0; virtual void NEXT( ostream &ret, int nextDest, bool inFinish ) = 0; virtual void GOTO_EXPR( ostream &ret, GenInlineItem *ilItem, bool inFinish ) = 0; virtual void NEXT_EXPR( ostream &ret, GenInlineItem *ilItem, bool inFinish ) = 0; virtual void CALL_EXPR( ostream &ret, GenInlineItem *ilItem, int targState, bool inFinish ) = 0; virtual void RET( ostream &ret, bool inFinish ) = 0; virtual void BREAK( ostream &ret, int targState, bool csForced ) = 0; virtual void CURS( ostream &ret, bool inFinish ) = 0; virtual void TARGS( ostream &ret, bool inFinish, int targState ) = 0; void EXEC( ostream &ret, GenInlineItem *item, int targState, int inFinish ); void LM_SWITCH( ostream &ret, GenInlineItem *item, int targState, int inFinish, bool csForced ); void SET_ACT( ostream &ret, GenInlineItem *item ); void INIT_TOKSTART( ostream &ret, GenInlineItem *item ); void INIT_ACT( ostream &ret, GenInlineItem *item ); void SET_TOKSTART( ostream &ret, GenInlineItem *item ); void SET_TOKEND( ostream &ret, GenInlineItem *item ); void GET_TOKEND( ostream &ret, GenInlineItem *item ); virtual void SUB_ACTION( ostream &ret, GenInlineItem *item, int targState, bool inFinish, bool csForced ); void STATE_IDS(); string ERROR_STATE(); string FIRST_FINAL_STATE(); virtual ostream &OPEN_ARRAY( string type, string name ); virtual ostream &CLOSE_ARRAY(); virtual ostream &STATIC_VAR( string type, string name ); virtual ostream &CONST( string type, string name ); ostream &source_warning(const InputLoc &loc); ostream &source_error(const InputLoc &loc); unsigned int arrayTypeSize( unsigned long maxVal ); bool outLabelUsed; bool testEofUsed; bool againLabelUsed; bool useIndicies; void genLineDirective( ostream &out ); public: /* Determine if we should use indicies. */ virtual void calcIndexSize() {} }; #endif ragel-6.8/ragel/cdfgoto.h0000664000175000017500000000414512106050031012264 00000000000000/* * Copyright 2001-2006 Adrian Thurston * 2004 Erich Ocean * 2005 Alan West */ /* This file is part of Ragel. * * Ragel is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Ragel is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Ragel; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef _CDFGOTO_H #define _CDFGOTO_H #include #include "cdgoto.h" /* Forwards. */ struct CodeGenData; /* * class FGotoCodeGen */ class FGotoCodeGen : public GotoCodeGen { public: FGotoCodeGen( ostream &out ) : FsmCodeGen(out), GotoCodeGen(out) {} std::ostream &EXEC_ACTIONS(); std::ostream &TO_STATE_ACTION_SWITCH(); std::ostream &FROM_STATE_ACTION_SWITCH(); std::ostream &FINISH_CASES(); std::ostream &EOF_ACTION_SWITCH(); unsigned int TO_STATE_ACTION( RedStateAp *state ); unsigned int FROM_STATE_ACTION( RedStateAp *state ); unsigned int EOF_ACTION( RedStateAp *state ); virtual void writeData(); virtual void writeExec(); }; /* * class CFGotoCodeGen */ struct CFGotoCodeGen : public FGotoCodeGen, public CCodeGen { CFGotoCodeGen( ostream &out ) : FsmCodeGen(out), FGotoCodeGen(out), CCodeGen(out) {} }; /* * class DFGotoCodeGen */ struct DFGotoCodeGen : public FGotoCodeGen, public DCodeGen { DFGotoCodeGen( ostream &out ) : FsmCodeGen(out), FGotoCodeGen(out), DCodeGen(out) {} }; /* * class DFGotoCodeGen */ struct D2FGotoCodeGen : public FGotoCodeGen, public D2CodeGen { D2FGotoCodeGen( ostream &out ) : FsmCodeGen(out), FGotoCodeGen(out), D2CodeGen(out) {} }; #endif ragel-6.8/ragel/csflat.h0000664000175000017500000000560112106050031012111 00000000000000/* * Copyright 2004-2006 Adrian Thurston * 2004 Erich Ocean * 2005 Alan West */ /* This file is part of Ragel. * * Ragel is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Ragel is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Ragel; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef _CSFLAT_H #define _CSFLAT_H #include #include "cscodegen.h" /* Forwards. */ struct CodeGenData; struct NameInst; struct RedTransAp; struct RedStateAp; /* * CSharpFlatCodeGen */ class CSharpFlatCodeGen : virtual public CSharpFsmCodeGen, public CSharpCodeGen { public: CSharpFlatCodeGen( ostream &out ) : CSharpFsmCodeGen(out), CSharpCodeGen(out) {} virtual ~CSharpFlatCodeGen() { } protected: std::ostream &TO_STATE_ACTION_SWITCH(); std::ostream &FROM_STATE_ACTION_SWITCH(); std::ostream &EOF_ACTION_SWITCH(); std::ostream &ACTION_SWITCH(); std::ostream &KEYS(); std::ostream &INDICIES(); std::ostream &FLAT_INDEX_OFFSET(); std::ostream &KEY_SPANS(); std::ostream &TO_STATE_ACTIONS(); std::ostream &FROM_STATE_ACTIONS(); std::ostream &EOF_ACTIONS(); std::ostream &EOF_TRANS(); std::ostream &TRANS_TARGS(); std::ostream &TRANS_ACTIONS(); void LOCATE_TRANS(); std::ostream &COND_INDEX_OFFSET(); void COND_TRANSLATE(); std::ostream &CONDS(); std::ostream &COND_KEYS(); std::ostream &COND_KEY_SPANS(); void GOTO( ostream &ret, int gotoDest, bool inFinish ); void CALL( ostream &ret, int callDest, int targState, bool inFinish ); void NEXT( ostream &ret, int nextDest, bool inFinish ); void GOTO_EXPR( ostream &ret, GenInlineItem *ilItem, bool inFinish ); void NEXT_EXPR( ostream &ret, GenInlineItem *ilItem, bool inFinish ); void CALL_EXPR( ostream &ret, GenInlineItem *ilItem, int targState, bool inFinish ); void CURS( ostream &ret, bool inFinish ); void TARGS( ostream &ret, bool inFinish, int targState ); void RET( ostream &ret, bool inFinish ); void BREAK( ostream &ret, int targState ); virtual std::ostream &TO_STATE_ACTION( RedStateAp *state ); virtual std::ostream &FROM_STATE_ACTION( RedStateAp *state ); virtual std::ostream &EOF_ACTION( RedStateAp *state ); virtual std::ostream &TRANS_ACTION( RedTransAp *trans ); virtual void writeData(); virtual void writeExec(); void initVarTypes(); string slenType, transType, indsType, condsType; }; #endif ragel-6.8/ragel/fsmattach.cpp0000664000175000017500000003323212106050031013143 00000000000000/* * Copyright 2001 Adrian Thurston */ /* This file is part of Ragel. * * Ragel is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Ragel is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Ragel; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #include "fsmgraph.h" #include using namespace std; /* Insert a transition into an inlist. The head must be supplied. */ void FsmAp::attachToInList( StateAp *from, StateAp *to, TransAp *&head, TransAp *trans ) { trans->ilnext = head; trans->ilprev = 0; /* If in trans list is not empty, set the head->prev to trans. */ if ( head != 0 ) head->ilprev = trans; /* Now insert ourselves at the front of the list. */ head = trans; /* Keep track of foreign transitions for from and to. */ if ( from != to ) { if ( misfitAccounting ) { /* If the number of foreign in transitions is about to go up to 1 then * move it from the misfit list to the main list. */ if ( to->foreignInTrans == 0 ) stateList.append( misfitList.detach( to ) ); } to->foreignInTrans += 1; } }; /* Detach a transition from an inlist. The head of the inlist must be supplied. */ void FsmAp::detachFromInList( StateAp *from, StateAp *to, TransAp *&head, TransAp *trans ) { /* Detach in the inTransList. */ if ( trans->ilprev == 0 ) head = trans->ilnext; else trans->ilprev->ilnext = trans->ilnext; if ( trans->ilnext != 0 ) trans->ilnext->ilprev = trans->ilprev; /* Keep track of foreign transitions for from and to. */ if ( from != to ) { to->foreignInTrans -= 1; if ( misfitAccounting ) { /* If the number of foreign in transitions goes down to 0 then move it * from the main list to the misfit list. */ if ( to->foreignInTrans == 0 ) misfitList.append( stateList.detach( to ) ); } } } /* Attach states on the default transition, range list or on out/in list key. * First makes a new transition. If there is already a transition out from * fromState on the default, then will assertion fail. */ TransAp *FsmAp::attachNewTrans( StateAp *from, StateAp *to, Key lowKey, Key highKey ) { /* Make the new transition. */ TransAp *retVal = new TransAp(); /* The transition is now attached. Remember the parties involved. */ retVal->fromState = from; retVal->toState = to; /* Make the entry in the out list for the transitions. */ from->outList.append( retVal ); /* Set the the keys of the new trans. */ retVal->lowKey = lowKey; retVal->highKey = highKey; /* Attach using inList as the head pointer. */ if ( to != 0 ) attachToInList( from, to, to->inList.head, retVal ); return retVal; } /* Attach for range lists or for the default transition. This attach should * be used when a transition already is allocated and must be attached to a * target state. Does not handle adding the transition into the out list. */ void FsmAp::attachTrans( StateAp *from, StateAp *to, TransAp *trans ) { assert( trans->fromState == 0 && trans->toState == 0 ); trans->fromState = from; trans->toState = to; if ( to != 0 ) { /* Attach using the inList pointer as the head pointer. */ attachToInList( from, to, to->inList.head, trans ); } } /* Redirect a transition away from error and towards some state. This is just * like attachTrans except it requires fromState to be set and does not touch * it. */ void FsmAp::redirectErrorTrans( StateAp *from, StateAp *to, TransAp *trans ) { assert( trans->fromState != 0 && trans->toState == 0 ); trans->toState = to; if ( to != 0 ) { /* Attach using the inList pointer as the head pointer. */ attachToInList( from, to, to->inList.head, trans ); } } /* Detach for out/in lists or for default transition. */ void FsmAp::detachTrans( StateAp *from, StateAp *to, TransAp *trans ) { assert( trans->fromState == from && trans->toState == to ); trans->fromState = 0; trans->toState = 0; if ( to != 0 ) { /* Detach using to's inList pointer as the head. */ detachFromInList( from, to, to->inList.head, trans ); } } /* Detach a state from the graph. Detaches and deletes transitions in and out * of the state. Empties inList and outList. Removes the state from the final * state set. A detached state becomes useless and should be deleted. */ void FsmAp::detachState( StateAp *state ) { /* Detach the in transitions from the inList list of transitions. */ while ( state->inList.head != 0 ) { /* Get pointers to the trans and the state. */ TransAp *trans = state->inList.head; StateAp *fromState = trans->fromState; /* Detach the transitions from the source state. */ detachTrans( fromState, state, trans ); /* Ok to delete the transition. */ fromState->outList.detach( trans ); delete trans; } /* Remove the entry points in on the machine. */ while ( state->entryIds.length() > 0 ) unsetEntry( state->entryIds[0], state ); /* Detach out range transitions. */ for ( TransList::Iter trans = state->outList; trans.lte(); ) { TransList::Iter next = trans.next(); detachTrans( state, trans->toState, trans ); delete trans; trans = next; } /* Delete all of the out range pointers. */ state->outList.abandon(); /* Unset final stateness before detaching from graph. */ if ( state->stateBits & STB_ISFINAL ) finStateSet.remove( state ); } /* Duplicate a transition. Makes a new transition that is attached to the same * dest as srcTrans. The new transition has functions and priority taken from * srcTrans. Used for merging a transition in to a free spot. The trans can * just be dropped in. It does not conflict with an existing trans and need * not be crossed. Returns the new transition. */ TransAp *FsmAp::dupTrans( StateAp *from, TransAp *srcTrans ) { /* Make a new transition. */ TransAp *newTrans = new TransAp(); /* We can attach the transition, one does not exist. */ attachTrans( from, srcTrans->toState, newTrans ); /* Call the user callback to add in the original source transition. */ addInTrans( newTrans, srcTrans ); return newTrans; } /* In crossing, src trans and dest trans both go to existing states. Make one * state from the sets of states that src and dest trans go to. */ TransAp *FsmAp::fsmAttachStates( MergeData &md, StateAp *from, TransAp *destTrans, TransAp *srcTrans ) { /* The priorities are equal. We must merge the transitions. Does the * existing trans go to the state we are to attach to? ie, are we to * simply double up the transition? */ StateAp *toState = srcTrans->toState; StateAp *existingState = destTrans->toState; if ( existingState == toState ) { /* The transition is a double up to the same state. Copy the src * trans into itself. We don't need to merge in the from out trans * data, that was done already. */ addInTrans( destTrans, srcTrans ); } else { /* The trans is not a double up. Dest trans cannot be the same as src * trans. Set up the state set. */ StateSet stateSet; /* We go to all the states the existing trans goes to, plus... */ if ( existingState->stateDictEl == 0 ) stateSet.insert( existingState ); else stateSet.insert( existingState->stateDictEl->stateSet ); /* ... all the states that we have been told to go to. */ if ( toState->stateDictEl == 0 ) stateSet.insert( toState ); else stateSet.insert( toState->stateDictEl->stateSet ); /* Look for the state. If it is not there already, make it. */ StateDictEl *lastFound; if ( md.stateDict.insert( stateSet, &lastFound ) ) { /* Make a new state representing the combination of states in * stateSet. It gets added to the fill list. This means that we * need to fill in it's transitions sometime in the future. We * don't do that now (ie, do not recurse). */ StateAp *combinState = addState(); /* Link up the dict element and the state. */ lastFound->targState = combinState; combinState->stateDictEl = lastFound; /* Add to the fill list. */ md.fillListAppend( combinState ); } /* Get the state insertted/deleted. */ StateAp *targ = lastFound->targState; /* Detach the state from existing state. */ detachTrans( from, existingState, destTrans ); /* Re-attach to the new target. */ attachTrans( from, targ, destTrans ); /* Add in src trans to the existing transition that we redirected to * the new state. We don't need to merge in the from out trans data, * that was done already. */ addInTrans( destTrans, srcTrans ); } return destTrans; } /* Two transitions are to be crossed, handle the possibility of either going * to the error state. */ TransAp *FsmAp::mergeTrans( MergeData &md, StateAp *from, TransAp *destTrans, TransAp *srcTrans ) { TransAp *retTrans = 0; if ( destTrans->toState == 0 && srcTrans->toState == 0 ) { /* Error added into error. */ addInTrans( destTrans, srcTrans ); retTrans = destTrans; } else if ( destTrans->toState == 0 && srcTrans->toState != 0 ) { /* Non error added into error we need to detach and reattach, */ detachTrans( from, destTrans->toState, destTrans ); attachTrans( from, srcTrans->toState, destTrans ); addInTrans( destTrans, srcTrans ); retTrans = destTrans; } else if ( srcTrans->toState == 0 ) { /* Dest goes somewhere but src doesn't, just add it it in. */ addInTrans( destTrans, srcTrans ); retTrans = destTrans; } else { /* Both go somewhere, run the actual cross. */ retTrans = fsmAttachStates( md, from, destTrans, srcTrans ); } return retTrans; } /* Find the trans with the higher priority. If src is lower priority then dest then * src is ignored. If src is higher priority than dest, then src overwrites dest. If * the priorities are equal, then they are merged. */ TransAp *FsmAp::crossTransitions( MergeData &md, StateAp *from, TransAp *destTrans, TransAp *srcTrans ) { TransAp *retTrans; /* Compare the priority of the dest and src transitions. */ int compareRes = comparePrior( destTrans->priorTable, srcTrans->priorTable ); if ( compareRes < 0 ) { /* Src trans has a higher priority than dest, src overwrites dest. * Detach dest and return a copy of src. */ detachTrans( from, destTrans->toState, destTrans ); retTrans = dupTrans( from, srcTrans ); } else if ( compareRes > 0 ) { /* The dest trans has a higher priority, use dest. */ retTrans = destTrans; } else { /* Src trans and dest trans have the same priority, they must be merged. */ retTrans = mergeTrans( md, from, destTrans, srcTrans ); } /* Return the transition that resulted from the cross. */ return retTrans; } /* Copy the transitions in srcList to the outlist of dest. The srcList should * not be the outList of dest, otherwise you would be copying the contents of * srcList into itself as it's iterated: bad news. */ void FsmAp::outTransCopy( MergeData &md, StateAp *dest, TransAp *srcList ) { /* The destination list. */ TransList destList; /* Set up an iterator to stop at breaks. */ PairIter outPair( dest->outList.head, srcList ); for ( ; !outPair.end(); outPair++ ) { switch ( outPair.userState ) { case RangeInS1: { /* The pair iter is the authority on the keys. It may have needed * to break the dest range. */ TransAp *destTrans = outPair.s1Tel.trans; destTrans->lowKey = outPair.s1Tel.lowKey; destTrans->highKey = outPair.s1Tel.highKey; destList.append( destTrans ); break; } case RangeInS2: { /* Src range may get crossed with dest's default transition. */ TransAp *newTrans = dupTrans( dest, outPair.s2Tel.trans ); /* Set up the transition's keys and append to the dest list. */ newTrans->lowKey = outPair.s2Tel.lowKey; newTrans->highKey = outPair.s2Tel.highKey; destList.append( newTrans ); break; } case RangeOverlap: { /* Exact overlap, cross them. */ TransAp *newTrans = crossTransitions( md, dest, outPair.s1Tel.trans, outPair.s2Tel.trans ); /* Set up the transition's keys and append to the dest list. */ newTrans->lowKey = outPair.s1Tel.lowKey; newTrans->highKey = outPair.s1Tel.highKey; destList.append( newTrans ); break; } case BreakS1: { /* Since we are always writing to the dest trans, the dest needs * to be copied when it is broken. The copy goes into the first * half of the break to "break it off". */ outPair.s1Tel.trans = dupTrans( dest, outPair.s1Tel.trans ); break; } case BreakS2: break; } } /* Abandon the old outList and transfer destList into it. */ dest->outList.transfer( destList ); } /* Move all the transitions that go into src so that they go into dest. */ void FsmAp::inTransMove( StateAp *dest, StateAp *src ) { /* Do not try to move in trans to and from the same state. */ assert( dest != src ); /* If src is the start state, dest becomes the start state. */ if ( src == startState ) { unsetStartState(); setStartState( dest ); } /* For each entry point into, create an entry point into dest, when the * state is detached, the entry points to src will be removed. */ for ( EntryIdSet::Iter enId = src->entryIds; enId.lte(); enId++ ) changeEntry( *enId, dest, src ); /* Move the transitions in inList. */ while ( src->inList.head != 0 ) { /* Get trans and from state. */ TransAp *trans = src->inList.head; StateAp *fromState = trans->fromState; /* Detach from src, reattach to dest. */ detachTrans( fromState, src, trans ); attachTrans( fromState, dest, trans ); } } ragel-6.8/ragel/Makefile.am0000664000175000017500000000374512106050031012527 00000000000000 INCLUDES = -I$(top_srcdir)/aapl bin_PROGRAMS = ragel ragel_CXXFLAGS = -Wall ragel_SOURCES = \ buffer.h cdgoto.h cscodegen.h csipgoto.h inputdata.h rbxgoto.h \ rubyflat.h cdcodegen.h cdipgoto.h csfflat.h cssplit.h javacodegen.h \ redfsm.h rubyftable.h cdfflat.h cdsplit.h csfgoto.h cstable.h \ parsedata.h rlparse.h rubytable.h cdfgoto.h cdtable.h csflat.h \ dotcodegen.h parsetree.h rlscan.h version.h cdflat.h common.h \ csftable.h fsmgraph.h pcheck.h rubycodegen.h xmlcodegen.h cdftable.h \ csgoto.h gendata.h ragel.h rubyfflat.h \ gocodegen.h gotable.h goftable.h goflat.h gofflat.h gogoto.h gofgoto.h \ goipgoto.h gotablish.h \ mlcodegen.h mltable.h mlftable.h mlflat.h mlfflat.h mlgoto.h \ main.cpp parsetree.cpp parsedata.cpp fsmstate.cpp fsmbase.cpp \ fsmattach.cpp fsmmin.cpp fsmgraph.cpp fsmap.cpp rlscan.cpp rlparse.cpp \ inputdata.cpp common.cpp redfsm.cpp gendata.cpp cdcodegen.cpp \ cdtable.cpp cdftable.cpp cdflat.cpp cdfflat.cpp cdgoto.cpp cdfgoto.cpp \ cdipgoto.cpp cdsplit.cpp javacodegen.cpp rubycodegen.cpp rubytable.cpp \ rubyftable.cpp rubyflat.cpp rubyfflat.cpp rbxgoto.cpp cscodegen.cpp \ cstable.cpp csftable.cpp csflat.cpp csfflat.cpp csgoto.cpp csfgoto.cpp \ csipgoto.cpp cssplit.cpp dotcodegen.cpp xmlcodegen.cpp \ gocodegen.cpp gotable.cpp goftable.cpp goflat.cpp gofflat.cpp gogoto.cpp gofgoto.cpp \ goipgoto.cpp gotablish.cpp \ mlcodegen.cpp mltable.cpp mlftable.cpp mlflat.cpp mlfflat.cpp mlgoto.cpp BUILT_SOURCES = \ rlscan.cpp rlparse.h rlparse.cpp version.h version.h: Makefile echo '#define VERSION "$(PACKAGE_VERSION)"' > version.h echo '#define PUBDATE "$(PUBDATE)"' >> version.h EXTRA_DIST = rlscan.rl rlparse.kh rlparse.kl if BUILD_PARSERS CLEANFILES = \ rlscan.cpp rlparse.h rlparse.cpp rlparse.h: rlparse.kh kelbt -o $@ $< rlparse.cpp: rlparse.kl rlparse.kh kelbt -o $@ $< # This dependency comes from the import of the parser defines # into the scanner. rlscan.cpp: rlparse.h rlscan.cpp: rlscan.rl ragel -G2 -I$(builddir) -o $@ $< endif ragel-6.8/ragel/rlparse.kl0000664000175000017500000012246112106050031012470 00000000000000/* * Copyright 2001-2007 Adrian Thurston */ /* This file is part of Ragel. * * Ragel is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Ragel is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Ragel; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "rlparse.h" #include "ragel.h" #include #include #include using std::cout; using std::cerr; using std::endl; %%{ parser Parser; include "rlparse.kh"; start: section_list; section_list: section_list statement_list TK_EndSection; section_list: ; statement_list: statement_list statement; statement_list: ; statement: assignment commit; statement: instantiation commit; statement: action_spec commit; statement: alphtype_spec commit; statement: range_spec commit; statement: getkey_spec commit; statement: access_spec commit; statement: variable_spec commit; statement: export_block commit; statement: pre_push_spec commit; statement: post_pop_spec commit; statement: length_spec commit; length_spec: KW_Length TK_Word ';' final { LengthDef *lengthDef = new LengthDef( $2->data ); pd->lengthDefList.append( lengthDef ); /* Generic creation of machine for instantiation and assignment. */ MachineDef *machineDef = new MachineDef( lengthDef ); tryMachineDef( $2->loc, $2->data, machineDef, false ); }; pre_push_spec: KW_PrePush '{' inline_block '}' final { if ( pd->prePushExpr != 0 ) { /* Recover by just ignoring the duplicate. */ error($2->loc) << "pre_push code already defined" << endl; } pd->prePushExpr = $3->inlineList; }; post_pop_spec: KW_PostPop '{' inline_block '}' final { if ( pd->postPopExpr != 0 ) { /* Recover by just ignoring the duplicate. */ error($2->loc) << "post_pop code already defined" << endl; } pd->postPopExpr = $3->inlineList; }; export_open: KW_Export final { exportContext.append( true ); }; nonterm opt_export { bool isSet; }; opt_export: export_open final { $$->isSet = true; }; opt_export: final { $$->isSet = false; }; export_block: export_open '{' statement_list '}' final { exportContext.remove( exportContext.length()-1 ); }; assignment: opt_export machine_name '=' join ';' final { /* Main machine must be an instance. */ bool isInstance = false; if ( strcmp($2->token.data, mainMachine) == 0 ) { warning($2->token.loc) << "main machine will be implicitly instantiated" << endl; isInstance = true; } /* Generic creation of machine for instantiation and assignment. */ MachineDef *machineDef = new MachineDef( $4->join ); tryMachineDef( $2->token.loc, $2->token.data, machineDef, isInstance ); if ( $1->isSet ) exportContext.remove( exportContext.length()-1 ); $4->join->loc = $3->loc; }; instantiation: opt_export machine_name TK_ColonEquals join_or_lm ';' final { /* Generic creation of machine for instantiation and assignment. */ tryMachineDef( $2->token.loc, $2->token.data, $4->machineDef, true ); if ( $1->isSet ) exportContext.remove( exportContext.length()-1 ); /* Pass a location to join_or_lm */ if ( $4->machineDef->join != 0 ) $4->machineDef->join->loc = $3->loc; }; type token_type { Token token; }; nonterm machine_name uses token_type; machine_name: TK_Word final { /* Make/get the priority key. The name may have already been referenced * and therefore exist. */ PriorDictEl *priorDictEl; if ( pd->priorDict.insert( $1->data, pd->nextPriorKey, &priorDictEl ) ) pd->nextPriorKey += 1; pd->curDefPriorKey = priorDictEl->value; /* Make/get the local error key. */ LocalErrDictEl *localErrDictEl; if ( pd->localErrDict.insert( $1->data, pd->nextLocalErrKey, &localErrDictEl ) ) pd->nextLocalErrKey += 1; pd->curDefLocalErrKey = localErrDictEl->value; $$->token = *$1; }; action_spec: KW_Action TK_Word '{' inline_block '}' final { if ( pd->actionDict.find( $2->data ) ) { /* Recover by just ignoring the duplicate. */ error($2->loc) << "action \"" << $2->data << "\" already defined" << endl; } else { //cerr << "NEW ACTION " << $2->data << " " << $4->inlineList << endl; /* Add the action to the list of actions. */ Action *newAction = new Action( $3->loc, $2->data, $4->inlineList, pd->nextCondId++ ); /* Insert to list and dict. */ pd->actionList.append( newAction ); pd->actionDict.insert( newAction ); } }; # Specifies the data type of the input alphabet. One or two words followed by a # semi-colon. alphtype_spec: KW_AlphType TK_Word TK_Word ';' final { if ( ! pd->setAlphType( $1->loc, $2->data, $3->data ) ) { // Recover by ignoring the alphtype statement. error($2->loc) << "\"" << $2->data << " " << $3->data << "\" is not a valid alphabet type" << endl; } }; alphtype_spec: KW_AlphType TK_Word ';' final { if ( ! pd->setAlphType( $1->loc, $2->data ) ) { // Recover by ignoring the alphtype statement. error($2->loc) << "\"" << $2->data << "\" is not a valid alphabet type" << endl; } }; # Specifies a range to assume that the input characters will fall into. range_spec: KW_Range alphabet_num alphabet_num ';' final { // Save the upper and lower ends of the range and emit the line number. pd->lowerNum = $2->token.data; pd->upperNum = $3->token.data; pd->rangeLowLoc = $2->token.loc; pd->rangeHighLoc = $3->token.loc; }; getkey_spec: KW_GetKey inline_expr ';' final { pd->getKeyExpr = $2->inlineList; }; access_spec: KW_Access inline_expr ';' final { pd->accessExpr = $2->inlineList; }; variable_spec: KW_Variable opt_whitespace TK_Word inline_expr ';' final { /* FIXME: Need to implement the rest of this. */ bool wasSet = pd->setVariable( $3->data, $4->inlineList ); if ( !wasSet ) error($3->loc) << "bad variable name" << endl; }; opt_whitespace: opt_whitespace IL_WhiteSpace; opt_whitespace: ; # # Expressions # nonterm join_or_lm { MachineDef *machineDef; }; join_or_lm: join final { $$->machineDef = new MachineDef( $1->join ); }; join_or_lm: TK_BarStar lm_part_list '*' '|' final { /* Create a new factor going to a longest match structure. Record * in the parse data that we have a longest match. */ LongestMatch *lm = new LongestMatch( $1->loc, $2->lmPartList ); pd->lmList.append( lm ); for ( LmPartList::Iter lmp = *($2->lmPartList); lmp.lte(); lmp++ ) lmp->longestMatch = lm; $$->machineDef = new MachineDef( lm ); }; nonterm lm_part_list { LmPartList *lmPartList; }; lm_part_list: lm_part_list longest_match_part final { if ( $2->lmPart != 0 ) $1->lmPartList->append( $2->lmPart ); $$->lmPartList = $1->lmPartList; }; lm_part_list: longest_match_part final { /* Create a new list with the part. */ $$->lmPartList = new LmPartList; if ( $1->lmPart != 0 ) $$->lmPartList->append( $1->lmPart ); }; nonterm longest_match_part { LongestMatchPart *lmPart; }; longest_match_part: action_spec final { $$->lmPart = 0; }; longest_match_part: assignment final { $$->lmPart = 0; }; longest_match_part: join opt_lm_part_action ';' final { $$->lmPart = 0; Action *action = $2->action; if ( action != 0 ) action->isLmAction = true; $$->lmPart = new LongestMatchPart( $1->join, action, $3->loc, pd->nextLongestMatchId++ ); /* Provide a location to join. Unfortunately We don't * have the start of the join as in other occurances. Use the end. */ $1->join->loc = $3->loc; }; nonterm opt_lm_part_action { Action *action; }; opt_lm_part_action: TK_DoubleArrow action_embed final { $$->action = $2->action; }; opt_lm_part_action: action_embed_block final { $$->action = $1->action; }; opt_lm_part_action: final { $$->action = 0; }; nonterm join { Join *join; }; join: join ',' expression final { /* Append the expression to the list and return it. */ $1->join->exprList.append( $3->expression ); $$->join = $1->join; }; join: expression final { $$->join = new Join( $1->expression ); }; nonterm expression { Expression *expression; }; expression: expression '|' term_short final { $$->expression = new Expression( $1->expression, $3->term, Expression::OrType ); }; expression: expression '&' term_short final { $$->expression = new Expression( $1->expression, $3->term, Expression::IntersectType ); }; expression: expression '-' term_short final { $$->expression = new Expression( $1->expression, $3->term, Expression::SubtractType ); }; expression: expression TK_DashDash term_short final { $$->expression = new Expression( $1->expression, $3->term, Expression::StrongSubtractType ); }; expression: term_short final { $$->expression = new Expression( $1->term ); }; # This is where we resolve the ambiguity involving -. By default ragel tries to # do a longest match, which gives precedence to a concatenation because it is # innermost. What we need is to force term into a shortest match so that when - # is seen it doesn't try to extend term with a concatenation, but ends term and # goes for a subtraction. # # The shortest tag overrides the default longest match action ordering strategy # and instead forces a shortest match stragegy. The wrap the term production in # a new nonterminal 'term_short' to guarantee the shortest match behaviour. shortest term_short; nonterm term_short { Term *term; }; term_short: term final { $$->term = $1->term; }; nonterm term { Term *term; }; term: term factor_with_label final { $$->term = new Term( $1->term, $2->factorWithAug ); }; term: term '.' factor_with_label final { $$->term = new Term( $1->term, $3->factorWithAug ); }; term: term TK_ColonGt factor_with_label final { $$->term = new Term( $1->term, $3->factorWithAug, Term::RightStartType ); }; term: term TK_ColonGtGt factor_with_label final { $$->term = new Term( $1->term, $3->factorWithAug, Term::RightFinishType ); }; term: term TK_LtColon factor_with_label final { $$->term = new Term( $1->term, $3->factorWithAug, Term::LeftType ); }; term: factor_with_label final { $$->term = new Term( $1->factorWithAug ); }; nonterm factor_with_label { FactorWithAug *factorWithAug; }; factor_with_label: TK_Word ':' factor_with_label final { /* Add the label to the list and pass the factor up. */ $3->factorWithAug->labels.prepend( Label($1->loc, $1->data) ); $$->factorWithAug = $3->factorWithAug; }; factor_with_label: factor_with_ep final { $$->factorWithAug = $1->factorWithAug; }; nonterm factor_with_ep { FactorWithAug *factorWithAug; }; factor_with_ep: factor_with_ep TK_Arrow local_state_ref final { /* Add the target to the list and return the factor object. */ $1->factorWithAug->epsilonLinks.append( EpsilonLink( $2->loc, nameRef ) ); $$->factorWithAug = $1->factorWithAug; }; factor_with_ep: factor_with_aug final { $$->factorWithAug = $1->factorWithAug; }; nonterm factor_with_aug { FactorWithAug *factorWithAug; }; factor_with_aug: factor_with_aug aug_type_base action_embed final { /* Append the action to the factorWithAug, record the refernce from * factorWithAug to the action and pass up the factorWithAug. */ $1->factorWithAug->actions.append( ParserAction( $2->loc, $2->augType, 0, $3->action ) ); $$->factorWithAug = $1->factorWithAug; }; factor_with_aug: factor_with_aug aug_type_base priority_aug final { /* Append the named priority to the factorWithAug and pass it up. */ $1->factorWithAug->priorityAugs.append( PriorityAug( $2->augType, pd->curDefPriorKey, $3->priorityNum ) ); $$->factorWithAug = $1->factorWithAug; }; factor_with_aug: factor_with_aug aug_type_base '(' priority_name ',' priority_aug ')' final { /* Append the priority using a default name. */ $1->factorWithAug->priorityAugs.append( PriorityAug( $2->augType, $4->priorityName, $6->priorityNum ) ); $$->factorWithAug = $1->factorWithAug; }; factor_with_aug: factor_with_aug aug_type_cond action_embed final { $1->factorWithAug->conditions.append( ConditionTest( $2->loc, $2->augType, $3->action, true ) ); $$->factorWithAug = $1->factorWithAug; }; factor_with_aug: factor_with_aug aug_type_cond '!' action_embed final { $1->factorWithAug->conditions.append( ConditionTest( $2->loc, $2->augType, $4->action, false ) ); $$->factorWithAug = $1->factorWithAug; }; factor_with_aug: factor_with_aug aug_type_to_state action_embed final { /* Append the action, pass it up. */ $1->factorWithAug->actions.append( ParserAction( $2->loc, $2->augType, 0, $3->action ) ); $$->factorWithAug = $1->factorWithAug; }; factor_with_aug: factor_with_aug aug_type_from_state action_embed final { /* Append the action, pass it up. */ $1->factorWithAug->actions.append( ParserAction( $2->loc, $2->augType, 0, $3->action ) ); $$->factorWithAug = $1->factorWithAug; }; factor_with_aug: factor_with_aug aug_type_eof action_embed final { /* Append the action, pass it up. */ $1->factorWithAug->actions.append( ParserAction( $2->loc, $2->augType, 0, $3->action ) ); $$->factorWithAug = $1->factorWithAug; }; factor_with_aug: factor_with_aug aug_type_gbl_error action_embed final { /* Append the action to the factorWithAug, record the refernce from * factorWithAug to the action and pass up the factorWithAug. */ $1->factorWithAug->actions.append( ParserAction( $2->loc, $2->augType, pd->curDefLocalErrKey, $3->action ) ); $$->factorWithAug = $1->factorWithAug; }; factor_with_aug: factor_with_aug aug_type_local_error action_embed final { /* Append the action to the factorWithAug, record the refernce from * factorWithAug to the action and pass up the factorWithAug. */ $1->factorWithAug->actions.append( ParserAction( $2->loc, $2->augType, pd->curDefLocalErrKey, $3->action ) ); $$->factorWithAug = $1->factorWithAug; }; factor_with_aug: factor_with_aug aug_type_local_error '(' local_err_name ',' action_embed ')' final { /* Append the action to the factorWithAug, record the refernce from * factorWithAug to the action and pass up the factorWithAug. */ $1->factorWithAug->actions.append( ParserAction( $2->loc, $2->augType, $4->error_name, $6->action ) ); $$->factorWithAug = $1->factorWithAug; }; factor_with_aug: factor_with_rep final { $$->factorWithAug = new FactorWithAug( $1->factorWithRep ); }; type aug_type { InputLoc loc; AugType augType; }; # Classes of transtions on which to embed actions or change priorities. nonterm aug_type_base uses aug_type; aug_type_base: '@' final { $$->loc = $1->loc; $$->augType = at_finish; }; aug_type_base: '%' final { $$->loc = $1->loc; $$->augType = at_leave; }; aug_type_base: '$' final { $$->loc = $1->loc; $$->augType = at_all; }; aug_type_base: '>' final { $$->loc = $1->loc; $$->augType = at_start; }; # Embedding conditions. nonterm aug_type_cond uses aug_type; aug_type_cond: TK_StartCond final { $$->loc = $1->loc; $$->augType = at_start; }; aug_type_cond: '>' KW_When final { $$->loc = $1->loc; $$->augType = at_start; }; aug_type_cond: TK_AllCond final { $$->loc = $1->loc; $$->augType = at_all; }; aug_type_cond: '$' KW_When final { $$->loc = $1->loc; $$->augType = at_all; }; aug_type_cond: TK_LeavingCond final { $$->loc = $1->loc; $$->augType = at_leave; }; aug_type_cond: '%' KW_When final { $$->loc = $1->loc; $$->augType = at_leave; }; aug_type_cond: KW_When final { $$->loc = $1->loc; $$->augType = at_all; }; aug_type_cond: KW_InWhen final { $$->loc = $1->loc; $$->augType = at_start; }; aug_type_cond: KW_OutWhen final { $$->loc = $1->loc; $$->augType = at_leave; }; # # To state actions. # nonterm aug_type_to_state uses aug_type; aug_type_to_state: TK_StartToState final { $$->loc = $1->loc; $$->augType = at_start_to_state; }; aug_type_to_state: '>' KW_To final { $$->loc = $1->loc; $$->augType = at_start_to_state; }; aug_type_to_state: TK_NotStartToState final { $$->loc = $1->loc; $$->augType = at_not_start_to_state; }; aug_type_to_state: '<' KW_To final { $$->loc = $1->loc; $$->augType = at_not_start_to_state; }; aug_type_to_state: TK_AllToState final { $$->loc = $1->loc; $$->augType = at_all_to_state; }; aug_type_to_state: '$' KW_To final { $$->loc = $1->loc; $$->augType = at_all_to_state; }; aug_type_to_state: TK_FinalToState final { $$->loc = $1->loc; $$->augType = at_final_to_state; }; aug_type_to_state: '%' KW_To final { $$->loc = $1->loc; $$->augType = at_final_to_state; }; aug_type_to_state: TK_NotFinalToState final { $$->loc = $1->loc; $$->augType = at_not_final_to_state; }; aug_type_to_state: '@' KW_To final { $$->loc = $1->loc; $$->augType = at_not_final_to_state; }; aug_type_to_state: TK_MiddleToState final { $$->loc = $1->loc; $$->augType = at_middle_to_state; }; aug_type_to_state: TK_Middle KW_To final { $$->loc = $1->loc; $$->augType = at_middle_to_state; }; # # From state actions. # nonterm aug_type_from_state uses aug_type; aug_type_from_state: TK_StartFromState final { $$->loc = $1->loc; $$->augType = at_start_from_state; }; aug_type_from_state: '>' KW_From final { $$->loc = $1->loc; $$->augType = at_start_from_state; }; aug_type_from_state: TK_NotStartFromState final { $$->loc = $1->loc; $$->augType = at_not_start_from_state; }; aug_type_from_state: '<' KW_From final { $$->loc = $1->loc; $$->augType = at_not_start_from_state; }; aug_type_from_state: TK_AllFromState final { $$->loc = $1->loc; $$->augType = at_all_from_state; }; aug_type_from_state: '$' KW_From final { $$->loc = $1->loc; $$->augType = at_all_from_state; }; aug_type_from_state: TK_FinalFromState final { $$->loc = $1->loc; $$->augType = at_final_from_state; }; aug_type_from_state: '%' KW_From final { $$->loc = $1->loc; $$->augType = at_final_from_state; }; aug_type_from_state: TK_NotFinalFromState final { $$->loc = $1->loc; $$->augType = at_not_final_from_state; }; aug_type_from_state: '@' KW_From final { $$->loc = $1->loc; $$->augType = at_not_final_from_state; }; aug_type_from_state: TK_MiddleFromState final { $$->loc = $1->loc; $$->augType = at_middle_from_state; }; aug_type_from_state: TK_Middle KW_From final { $$->loc = $1->loc; $$->augType = at_middle_from_state; }; # # Eof state actions. # nonterm aug_type_eof uses aug_type; aug_type_eof: TK_StartEOF final { $$->loc = $1->loc; $$->augType = at_start_eof; }; aug_type_eof: '>' KW_Eof final { $$->loc = $1->loc; $$->augType = at_start_eof; }; aug_type_eof: TK_NotStartEOF final { $$->loc = $1->loc; $$->augType = at_not_start_eof; }; aug_type_eof: '<' KW_Eof final { $$->loc = $1->loc; $$->augType = at_not_start_eof; }; aug_type_eof: TK_AllEOF final { $$->loc = $1->loc; $$->augType = at_all_eof; }; aug_type_eof: '$' KW_Eof final { $$->loc = $1->loc; $$->augType = at_all_eof; }; aug_type_eof: TK_FinalEOF final { $$->loc = $1->loc; $$->augType = at_final_eof; }; aug_type_eof: '%' KW_Eof final { $$->loc = $1->loc; $$->augType = at_final_eof; }; aug_type_eof: TK_NotFinalEOF final { $$->loc = $1->loc; $$->augType = at_not_final_eof; }; aug_type_eof: '@' KW_Eof final { $$->loc = $1->loc; $$->augType = at_not_final_eof; }; aug_type_eof: TK_MiddleEOF final { $$->loc = $1->loc; $$->augType = at_middle_eof; }; aug_type_eof: TK_Middle KW_Eof final { $$->loc = $1->loc; $$->augType = at_middle_eof; }; # # Global error actions. # nonterm aug_type_gbl_error uses aug_type; aug_type_gbl_error: TK_StartGblError final { $$->loc = $1->loc; $$->augType = at_start_gbl_error; }; aug_type_gbl_error: '>' KW_Err final { $$->loc = $1->loc; $$->augType = at_start_gbl_error; }; aug_type_gbl_error: TK_NotStartGblError final { $$->loc = $1->loc; $$->augType = at_not_start_gbl_error; }; aug_type_gbl_error: '<' KW_Err final { $$->loc = $1->loc; $$->augType = at_not_start_gbl_error; }; aug_type_gbl_error: TK_AllGblError final { $$->loc = $1->loc; $$->augType = at_all_gbl_error; }; aug_type_gbl_error: '$' KW_Err final { $$->loc = $1->loc; $$->augType = at_all_gbl_error; }; aug_type_gbl_error: TK_FinalGblError final { $$->loc = $1->loc; $$->augType = at_final_gbl_error; }; aug_type_gbl_error: '%' KW_Err final { $$->loc = $1->loc; $$->augType = at_final_gbl_error; }; aug_type_gbl_error: TK_NotFinalGblError final { $$->loc = $1->loc; $$->augType = at_not_final_gbl_error; }; aug_type_gbl_error: '@' KW_Err final { $$->loc = $1->loc; $$->augType = at_not_final_gbl_error; }; aug_type_gbl_error: TK_MiddleGblError final { $$->loc = $1->loc; $$->augType = at_middle_gbl_error; }; aug_type_gbl_error: TK_Middle KW_Err final { $$->loc = $1->loc; $$->augType = at_middle_gbl_error; }; # # Local error actions. # nonterm aug_type_local_error uses aug_type; aug_type_local_error: TK_StartLocalError final { $$->loc = $1->loc; $$->augType = at_start_local_error; }; aug_type_local_error: '>' KW_Lerr final { $$->loc = $1->loc; $$->augType = at_start_local_error; }; aug_type_local_error: TK_NotStartLocalError final { $$->loc = $1->loc; $$->augType = at_not_start_local_error; }; aug_type_local_error: '<' KW_Lerr final { $$->loc = $1->loc; $$->augType = at_not_start_local_error; }; aug_type_local_error: TK_AllLocalError final { $$->loc = $1->loc; $$->augType = at_all_local_error; }; aug_type_local_error: '$' KW_Lerr final { $$->loc = $1->loc; $$->augType = at_all_local_error; }; aug_type_local_error: TK_FinalLocalError final { $$->loc = $1->loc; $$->augType = at_final_local_error; }; aug_type_local_error: '%' KW_Lerr final { $$->loc = $1->loc; $$->augType = at_final_local_error; }; aug_type_local_error: TK_NotFinalLocalError final { $$->loc = $1->loc; $$->augType = at_not_final_local_error; }; aug_type_local_error: '@' KW_Lerr final { $$->loc = $1->loc; $$->augType = at_not_final_local_error; }; aug_type_local_error: TK_MiddleLocalError final { $$->loc = $1->loc; $$->augType = at_middle_local_error; }; aug_type_local_error: TK_Middle KW_Lerr final { $$->loc = $1->loc; $$->augType = at_middle_local_error; }; type action_ref { Action *action; }; # Different ways to embed actions. A TK_Word is reference to an action given by # the user as a statement in the fsm specification. An action can also be # specified immediately. nonterm action_embed uses action_ref; action_embed: action_embed_word final { $$->action = $1->action; }; action_embed: '(' action_embed_word ')' final { $$->action = $2->action; }; action_embed: action_embed_block final { $$->action = $1->action; }; nonterm action_embed_word uses action_ref; action_embed_word: TK_Word final { /* Set the name in the actionDict. */ Action *action = pd->actionDict.find( $1->data ); if ( action != 0 ) { /* Pass up the action element */ $$->action = action; } else { /* Will recover by returning null as the action. */ error($1->loc) << "action lookup of \"" << $1->data << "\" failed" << endl; $$->action = 0; } }; nonterm action_embed_block uses action_ref; action_embed_block: '{' inline_block '}' final { /* Create the action, add it to the list and pass up. */ Action *newAction = new Action( $1->loc, 0, $2->inlineList, pd->nextCondId++ ); pd->actionList.append( newAction ); $$->action = newAction; }; nonterm priority_name { int priorityName; }; # A specified priority name. Looks up the name in the current priority # dictionary. priority_name: TK_Word final { // Lookup/create the priority key. PriorDictEl *priorDictEl; if ( pd->priorDict.insert( $1->data, pd->nextPriorKey, &priorDictEl ) ) pd->nextPriorKey += 1; // Use the inserted/found priority key. $$->priorityName = priorDictEl->value; }; nonterm priority_aug { int priorityNum; }; # Priority change specs. priority_aug: priority_aug_num final { // Convert the priority number to a long. Check for overflow. errno = 0; //cerr << "PRIOR AUG: " << $1->token.data << endl; long aug = strtol( $1->token.data, 0, 10 ); if ( errno == ERANGE && aug == LONG_MAX ) { /* Priority number too large. Recover by setting the priority to 0. */ error($1->token.loc) << "priority number " << $1->token.data << " overflows" << endl; $$->priorityNum = 0; } else if ( errno == ERANGE && aug == LONG_MIN ) { /* Priority number too large in the neg. Recover by using 0. */ error($1->token.loc) << "priority number " << $1->token.data << " underflows" << endl; $$->priorityNum = 0; } else { /* No overflow or underflow. */ $$->priorityNum = aug; } }; nonterm priority_aug_num uses token_type; priority_aug_num: TK_UInt final { $$->token = *$1; }; priority_aug_num: '+' TK_UInt final { $$->token.set( "+", 1 ); $$->token.loc = $1->loc; $$->token.append( *$2 ); }; priority_aug_num: '-' TK_UInt final { $$->token.set( "-", 1 ); $$->token.loc = $1->loc; $$->token.append( *$2 ); }; nonterm local_err_name { int error_name; }; local_err_name: TK_Word final { /* Lookup/create the priority key. */ LocalErrDictEl *localErrDictEl; if ( pd->localErrDict.insert( $1->data, pd->nextLocalErrKey, &localErrDictEl ) ) pd->nextLocalErrKey += 1; /* Use the inserted/found priority key. */ $$->error_name = localErrDictEl->value; }; # The fourth level of precedence. These are the trailing unary operators that # allow for repetition. nonterm factor_with_rep { FactorWithRep *factorWithRep; }; factor_with_rep: factor_with_rep '*' final { $$->factorWithRep = new FactorWithRep( $2->loc, $1->factorWithRep, 0, 0, FactorWithRep::StarType ); }; factor_with_rep: factor_with_rep TK_StarStar final { $$->factorWithRep = new FactorWithRep( $2->loc, $1->factorWithRep, 0, 0, FactorWithRep::StarStarType ); }; factor_with_rep: factor_with_rep '?' final { $$->factorWithRep = new FactorWithRep( $2->loc, $1->factorWithRep, 0, 0, FactorWithRep::OptionalType ); }; factor_with_rep: factor_with_rep '+' final { $$->factorWithRep = new FactorWithRep( $2->loc, $1->factorWithRep, 0, 0, FactorWithRep::PlusType ); }; factor_with_rep: factor_with_rep '{' factor_rep_num '}' final { $$->factorWithRep = new FactorWithRep( $2->loc, $1->factorWithRep, $3->rep, 0, FactorWithRep::ExactType ); }; factor_with_rep: factor_with_rep '{' ',' factor_rep_num '}' final { $$->factorWithRep = new FactorWithRep( $2->loc, $1->factorWithRep, 0, $4->rep, FactorWithRep::MaxType ); }; factor_with_rep: factor_with_rep '{' factor_rep_num ',' '}' final { $$->factorWithRep = new FactorWithRep( $2->loc, $1->factorWithRep, $3->rep, 0, FactorWithRep::MinType ); }; factor_with_rep: factor_with_rep '{' factor_rep_num ',' factor_rep_num '}' final { $$->factorWithRep = new FactorWithRep( $2->loc, $1->factorWithRep, $3->rep, $5->rep, FactorWithRep::RangeType ); }; factor_with_rep: factor_with_neg final { $$->factorWithRep = new FactorWithRep( $1->factorWithNeg ); }; nonterm factor_rep_num { int rep; }; factor_rep_num: TK_UInt final { // Convert the priority number to a long. Check for overflow. errno = 0; long rep = strtol( $1->data, 0, 10 ); if ( errno == ERANGE && rep == LONG_MAX ) { // Repetition too large. Recover by returing repetition 1. */ error($1->loc) << "repetition number " << $1->data << " overflows" << endl; $$->rep = 1; } else { // Cannot be negative, so no overflow. $$->rep = rep; } }; # # The fifth level up in precedence. Negation. # nonterm factor_with_neg { FactorWithNeg *factorWithNeg; }; factor_with_neg: '!' factor_with_neg final { $$->factorWithNeg = new FactorWithNeg( $1->loc, $2->factorWithNeg, FactorWithNeg::NegateType ); }; factor_with_neg: '^' factor_with_neg final { $$->factorWithNeg = new FactorWithNeg( $1->loc, $2->factorWithNeg, FactorWithNeg::CharNegateType ); }; factor_with_neg: factor final { $$->factorWithNeg = new FactorWithNeg( $1->factor ); }; nonterm factor { Factor *factor; }; factor: TK_Literal final { /* Create a new factor node going to a concat literal. */ $$->factor = new Factor( new Literal( *$1, Literal::LitString ) ); }; factor: alphabet_num final { /* Create a new factor node going to a literal number. */ $$->factor = new Factor( new Literal( $1->token, Literal::Number ) ); }; factor: TK_Word final { /* Find the named graph. */ GraphDictEl *gdNode = pd->graphDict.find( $1->data ); if ( gdNode == 0 ) { /* Recover by returning null as the factor node. */ error($1->loc) << "graph lookup of \"" << $1->data << "\" failed" << endl; $$->factor = 0; } else if ( gdNode->isInstance ) { /* Recover by retuning null as the factor node. */ error($1->loc) << "references to graph instantiations not allowed " "in expressions" << endl; $$->factor = 0; } else { /* Create a factor node that is a lookup of an expression. */ $$->factor = new Factor( $1->loc, gdNode->value ); } }; factor: RE_SqOpen regular_expr_or_data RE_SqClose final { /* Create a new factor node going to an OR expression. */ $$->factor = new Factor( new ReItem( $1->loc, $2->reOrBlock, ReItem::OrBlock ) ); }; factor: RE_SqOpenNeg regular_expr_or_data RE_SqClose final { /* Create a new factor node going to a negated OR expression. */ $$->factor = new Factor( new ReItem( $1->loc, $2->reOrBlock, ReItem::NegOrBlock ) ); }; factor: RE_Slash regular_expr RE_Slash final { if ( $3->length > 1 ) { for ( char *p = $3->data; *p != 0; p++ ) { if ( *p == 'i' ) $2->regExpr->caseInsensitive = true; } } /* Create a new factor node going to a regular exp. */ $$->factor = new Factor( $2->regExpr ); }; factor: range_lit TK_DotDot range_lit final { /* Create a new factor node going to a range. */ $$->factor = new Factor( new Range( $1->literal, $3->literal ) ); }; factor: '(' join ')' final { /* Create a new factor going to a parenthesized join. */ $$->factor = new Factor( $2->join ); $2->join->loc = $1->loc; }; nonterm range_lit { Literal *literal; }; # Literals which can be the end points of ranges. range_lit: TK_Literal final { /* Range literas must have only one char. We restrict this in the parse tree. */ $$->literal = new Literal( *$1, Literal::LitString ); }; range_lit: alphabet_num final { /* Create a new literal number. */ $$->literal = new Literal( $1->token, Literal::Number ); }; nonterm alphabet_num uses token_type; # Any form of a number that can be used as a basic machine. */ alphabet_num: TK_UInt final { $$->token = *$1; }; alphabet_num: '-' TK_UInt final { $$->token.set( "-", 1 ); $$->token.loc = $1->loc; $$->token.append( *$2 ); }; alphabet_num: TK_Hex final { $$->token = *$1; }; # # Regular Expressions. # nonterm regular_expr { RegExpr *regExpr; }; # Parser for regular expression fsms. Any number of expression items which # generally gives a machine one character long or one character long stared. regular_expr: regular_expr regular_expr_item final { /* An optimization to lessen the tree size. If a non-starred char is * directly under the left side on the right and the right side is * another non-starred char then paste them together and return the * left side. Otherwise just put the two under a new reg exp node. */ if ( $2->reItem->type == ReItem::Data && !$2->reItem->star && $1->regExpr->type == RegExpr::RecurseItem && $1->regExpr->item->type == ReItem::Data && !$1->regExpr->item->star ) { /* Append the right side to the right side of the left and toss the * right side. */ $1->regExpr->item->token.append( $2->reItem->token ); delete $2->reItem; $$->regExpr = $1->regExpr; } else { $$->regExpr = new RegExpr( $1->regExpr, $2->reItem ); } }; regular_expr: final { /* Can't optimize the tree. */ $$->regExpr = new RegExpr(); }; nonterm regular_expr_item { ReItem *reItem; }; # RegularExprItems can be a character spec with an optional staring of the char. regular_expr_item: regular_expr_char RE_Star final { $1->reItem->star = true; $$->reItem = $1->reItem; }; regular_expr_item: regular_expr_char final { $$->reItem = $1->reItem; }; nonterm regular_expr_char { ReItem *reItem; }; # A character spec can be a set of characters inside of square parenthesis, a # dot specifying any character or some explicitly stated character. regular_expr_char: RE_SqOpen regular_expr_or_data RE_SqClose final { $$->reItem = new ReItem( $1->loc, $2->reOrBlock, ReItem::OrBlock ); }; regular_expr_char: RE_SqOpenNeg regular_expr_or_data RE_SqClose final { $$->reItem = new ReItem( $1->loc, $2->reOrBlock, ReItem::NegOrBlock ); }; regular_expr_char: RE_Dot final { $$->reItem = new ReItem( $1->loc, ReItem::Dot ); }; regular_expr_char: RE_Char final { $$->reItem = new ReItem( $1->loc, *$1 ); }; # The data inside of a [] expression in a regular expression. Accepts any # number of characters or ranges. */ nonterm regular_expr_or_data { ReOrBlock *reOrBlock; }; regular_expr_or_data: regular_expr_or_data regular_expr_or_char final { /* An optimization to lessen the tree size. If an or char is directly * under the left side on the right and the right side is another or * char then paste them together and return the left side. Otherwise * just put the two under a new or data node. */ if ( $2->reOrItem->type == ReOrItem::Data && $1->reOrBlock->type == ReOrBlock::RecurseItem && $1->reOrBlock->item->type == ReOrItem::Data ) { /* Append the right side to right side of the left and toss the * right side. */ $1->reOrBlock->item->token.append( $2->reOrItem->token ); delete $2->reOrItem; $$->reOrBlock = $1->reOrBlock; } else { /* Can't optimize, put the left and right under a new node. */ $$->reOrBlock = new ReOrBlock( $1->reOrBlock, $2->reOrItem ); } }; regular_expr_or_data: final { $$->reOrBlock = new ReOrBlock(); }; # A single character inside of an or expression. Can either be a character or a # set of characters. nonterm regular_expr_or_char { ReOrItem *reOrItem; }; regular_expr_or_char: RE_Char final { $$->reOrItem = new ReOrItem( $1->loc, *$1 ); }; regular_expr_or_char: RE_Char RE_Dash RE_Char final { $$->reOrItem = new ReOrItem( $2->loc, $1->data[0], $3->data[0] ); }; # # Inline Lists for inline host code. # type inline_list { InlineList *inlineList; }; nonterm inline_block uses inline_list; inline_block: inline_block inline_block_item final { /* Append the item to the list, return the list. */ $$->inlineList = $1->inlineList; $$->inlineList->append( $2->inlineItem ); }; inline_block: final { /* Start with empty list. */ $$->inlineList = new InlineList; }; type inline_item { InlineItem *inlineItem; }; nonterm inline_block_item uses inline_item; nonterm inline_block_interpret uses inline_item; inline_block_item: inline_expr_any final { $$->inlineItem = new InlineItem( $1->token.loc, $1->token.data, InlineItem::Text ); }; inline_block_item: inline_block_symbol final { $$->inlineItem = new InlineItem( $1->token.loc, $1->token.data, InlineItem::Text ); }; inline_block_item: inline_block_interpret final { /* Pass the inline item up. */ $$->inlineItem = $1->inlineItem; }; nonterm inline_block_symbol uses token_type; inline_block_symbol: ',' final { $$->token = *$1; }; inline_block_symbol: ';' final { $$->token = *$1; }; inline_block_symbol: '(' final { $$->token = *$1; }; inline_block_symbol: ')' final { $$->token = *$1; }; inline_block_symbol: '*' final { $$->token = *$1; }; inline_block_symbol: TK_NameSep final { $$->token = *$1; }; # Interpreted statements in a struct block. */ inline_block_interpret: inline_expr_interpret final { /* Pass up interpreted items of inline expressions. */ $$->inlineItem = $1->inlineItem; }; inline_block_interpret: KW_Hold ';' final { $$->inlineItem = new InlineItem( $1->loc, InlineItem::Hold ); }; inline_block_interpret: KW_Exec inline_expr ';' final { $$->inlineItem = new InlineItem( $1->loc, InlineItem::Exec ); $$->inlineItem->children = $2->inlineList; }; inline_block_interpret: KW_Goto state_ref ';' final { $$->inlineItem = new InlineItem( $1->loc, new NameRef(nameRef), InlineItem::Goto ); }; inline_block_interpret: KW_Goto '*' inline_expr ';' final { $$->inlineItem = new InlineItem( $1->loc, InlineItem::GotoExpr ); $$->inlineItem->children = $3->inlineList; }; inline_block_interpret: KW_Next state_ref ';' final { $$->inlineItem = new InlineItem( $1->loc, new NameRef(nameRef), InlineItem::Next ); }; inline_block_interpret: KW_Next '*' inline_expr ';' final { $$->inlineItem = new InlineItem( $1->loc, InlineItem::NextExpr ); $$->inlineItem->children = $3->inlineList; }; inline_block_interpret: KW_Call state_ref ';' final { $$->inlineItem = new InlineItem( $1->loc, new NameRef(nameRef), InlineItem::Call ); }; inline_block_interpret: KW_Call '*' inline_expr ';' final { $$->inlineItem = new InlineItem( $1->loc, InlineItem::CallExpr ); $$->inlineItem->children = $3->inlineList; }; inline_block_interpret: KW_Ret ';' final { $$->inlineItem = new InlineItem( $1->loc, InlineItem::Ret ); }; inline_block_interpret: KW_Break ';' final { $$->inlineItem = new InlineItem( $1->loc, InlineItem::Break ); }; nonterm inline_expr uses inline_list; inline_expr: inline_expr inline_expr_item final { $$->inlineList = $1->inlineList; $$->inlineList->append( $2->inlineItem ); }; inline_expr: final { /* Init the list used for this expr. */ $$->inlineList = new InlineList; }; nonterm inline_expr_item uses inline_item; inline_expr_item: inline_expr_any final { /* Return a text segment. */ $$->inlineItem = new InlineItem( $1->token.loc, $1->token.data, InlineItem::Text ); }; inline_expr_item: inline_expr_symbol final { /* Return a text segment, must heap alloc the text. */ $$->inlineItem = new InlineItem( $1->token.loc, $1->token.data, InlineItem::Text ); }; inline_expr_item: inline_expr_interpret final{ /* Pass the inline item up. */ $$->inlineItem = $1->inlineItem; }; nonterm inline_expr_any uses token_type; inline_expr_any: IL_WhiteSpace try { $$->token = *$1; }; inline_expr_any: IL_Comment try { $$->token = *$1; }; inline_expr_any: IL_Literal try { $$->token = *$1; }; inline_expr_any: IL_Symbol try { $$->token = *$1; }; inline_expr_any: TK_UInt try { $$->token = *$1; }; inline_expr_any: TK_Hex try { $$->token = *$1; }; inline_expr_any: TK_Word try { $$->token = *$1; }; # Anything in a ExecValExpr that is not dynamically allocated. This includes # all special symbols caught in inline code except the semi. nonterm inline_expr_symbol uses token_type; inline_expr_symbol: ',' try { $$->token = *$1; }; inline_expr_symbol: '(' try { $$->token = *$1; }; inline_expr_symbol: ')' try { $$->token = *$1; }; inline_expr_symbol: '*' try { $$->token = *$1; }; inline_expr_symbol: TK_NameSep try { $$->token = *$1; }; nonterm inline_expr_interpret uses inline_item; inline_expr_interpret: KW_PChar final { $$->inlineItem = new InlineItem( $1->loc, InlineItem::PChar ); }; inline_expr_interpret: KW_Char final { $$->inlineItem = new InlineItem( $1->loc, InlineItem::Char ); }; inline_expr_interpret: KW_CurState final { $$->inlineItem = new InlineItem( $1->loc, InlineItem::Curs ); }; inline_expr_interpret: KW_TargState final { $$->inlineItem = new InlineItem( $1->loc, InlineItem::Targs ); }; inline_expr_interpret: KW_Entry '(' state_ref ')' final { $$->inlineItem = new InlineItem( $1->loc, new NameRef(nameRef), InlineItem::Entry ); }; # A local state reference. Cannot have :: prefix. local_state_ref: no_name_sep state_ref_names; # Clear the name ref structure. no_name_sep: final { nameRef.empty(); }; # A qualified state reference. state_ref: opt_name_sep state_ref_names; # Optional leading name separator. opt_name_sep: TK_NameSep final { /* Insert an initial null pointer val to indicate the existence of the * initial name seperator. */ nameRef.setAs( 0 ); }; opt_name_sep: final { nameRef.empty(); }; # List of names separated by :: state_ref_names: state_ref_names TK_NameSep TK_Word final { nameRef.append( $3->data ); }; state_ref_names: TK_Word final { nameRef.append( $1->data ); }; }%% %%{ write types; write data; }%% void Parser::init() { %% write init; } int Parser::parseLangEl( int type, const Token *token ) { %% write exec; return errCount == 0 ? 0 : -1; } void Parser::tryMachineDef( InputLoc &loc, char *name, MachineDef *machineDef, bool isInstance ) { GraphDictEl *newEl = pd->graphDict.insert( name ); if ( newEl != 0 ) { /* New element in the dict, all good. */ newEl->value = new VarDef( name, machineDef ); newEl->isInstance = isInstance; newEl->loc = loc; newEl->value->isExport = exportContext[exportContext.length()-1]; /* It it is an instance, put on the instance list. */ if ( isInstance ) pd->instanceList.append( newEl ); } else { // Recover by ignoring the duplicate. error(loc) << "fsm \"" << name << "\" previously defined" << endl; } } ostream &Parser::parse_error( int tokId, Token &token ) { /* Maintain the error count. */ gblErrorCount += 1; cerr << token.loc << ": "; cerr << "at token "; if ( tokId < 128 ) cerr << "\"" << Parser_lelNames[tokId] << "\""; else cerr << Parser_lelNames[tokId]; if ( token.data != 0 ) cerr << " with data \"" << token.data << "\""; cerr << ": "; return cerr; } int Parser::token( InputLoc &loc, int tokId, char *tokstart, int toklen ) { Token token; token.data = tokstart; token.length = toklen; token.loc = loc; int res = parseLangEl( tokId, &token ); if ( res < 0 ) { parse_error(tokId, token) << "parse error" << endl; exit(1); } return res; } ragel-6.8/ragel/rlscan.rl0000664000175000017500000007424512106050031012317 00000000000000/* * Copyright 2006-2007 Adrian Thurston * Copyright 2011 Josef Goettgens */ /* This file is part of Ragel. * * Ragel is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Ragel is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Ragel; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #include #include "ragel.h" #include "rlscan.h" #include "inputdata.h" //#define LOG_TOKENS using std::ifstream; using std::istream; using std::ostream; using std::cout; using std::cerr; using std::endl; enum InlineBlockType { CurlyDelimited, SemiTerminated }; #ifdef _WIN32 #define PATH_SEP '\\' #else #define PATH_SEP '/' #endif /* * The Scanner for Importing */ %%{ machine inline_token_scan; alphtype int; access tok_; # Import scanner tokens. import "rlparse.h"; main := |* # Define of number. IMP_Define IMP_Word IMP_UInt => { int base = tok_ts - token_data; int nameOff = 1; int numOff = 2; directToParser( inclToParser, fileName, line, column, TK_Word, token_strings[base+nameOff], token_lens[base+nameOff] ); directToParser( inclToParser, fileName, line, column, '=', 0, 0 ); directToParser( inclToParser, fileName, line, column, TK_UInt, token_strings[base+numOff], token_lens[base+numOff] ); directToParser( inclToParser, fileName, line, column, ';', 0, 0 ); }; # Assignment of number. IMP_Word '=' IMP_UInt => { int base = tok_ts - token_data; int nameOff = 0; int numOff = 2; directToParser( inclToParser, fileName, line, column, TK_Word, token_strings[base+nameOff], token_lens[base+nameOff] ); directToParser( inclToParser, fileName, line, column, '=', 0, 0 ); directToParser( inclToParser, fileName, line, column, TK_UInt, token_strings[base+numOff], token_lens[base+numOff] ); directToParser( inclToParser, fileName, line, column, ';', 0, 0 ); }; # Define of literal. IMP_Define IMP_Word IMP_Literal => { int base = tok_ts - token_data; int nameOff = 1; int litOff = 2; directToParser( inclToParser, fileName, line, column, TK_Word, token_strings[base+nameOff], token_lens[base+nameOff] ); directToParser( inclToParser, fileName, line, column, '=', 0, 0 ); directToParser( inclToParser, fileName, line, column, TK_Literal, token_strings[base+litOff], token_lens[base+litOff] ); directToParser( inclToParser, fileName, line, column, ';', 0, 0 ); }; # Assignment of literal. IMP_Word '=' IMP_Literal => { int base = tok_ts - token_data; int nameOff = 0; int litOff = 2; directToParser( inclToParser, fileName, line, column, TK_Word, token_strings[base+nameOff], token_lens[base+nameOff] ); directToParser( inclToParser, fileName, line, column, '=', 0, 0 ); directToParser( inclToParser, fileName, line, column, TK_Literal, token_strings[base+litOff], token_lens[base+litOff] ); directToParser( inclToParser, fileName, line, column, ';', 0, 0 ); }; # Catch everything else. any; *|; }%% %% write data; void Scanner::flushImport() { int *p = token_data; int *pe = token_data + cur_token; int *eof = 0; %%{ machine inline_token_scan; write init; write exec; }%% if ( tok_ts == 0 ) cur_token = 0; else { cur_token = pe - tok_ts; int ts_offset = tok_ts - token_data; memmove( token_data, token_data+ts_offset, cur_token*sizeof(token_data[0]) ); memmove( token_strings, token_strings+ts_offset, cur_token*sizeof(token_strings[0]) ); memmove( token_lens, token_lens+ts_offset, cur_token*sizeof(token_lens[0]) ); } } void Scanner::directToParser( Parser *toParser, const char *tokFileName, int tokLine, int tokColumn, int type, char *tokdata, int toklen ) { InputLoc loc; #ifdef LOG_TOKENS cerr << "scanner:" << tokLine << ":" << tokColumn << ": sending token to the parser " << Parser_lelNames[type]; cerr << " " << toklen; if ( tokdata != 0 ) cerr << " " << tokdata; cerr << endl; #endif loc.fileName = tokFileName; loc.line = tokLine; loc.col = tokColumn; toParser->token( loc, type, tokdata, toklen ); } void Scanner::importToken( int token, char *start, char *end ) { if ( cur_token == max_tokens ) flushImport(); token_data[cur_token] = token; if ( start == 0 ) { token_strings[cur_token] = 0; token_lens[cur_token] = 0; } else { int toklen = end-start; token_lens[cur_token] = toklen; token_strings[cur_token] = new char[toklen+1]; memcpy( token_strings[cur_token], start, toklen ); token_strings[cur_token][toklen] = 0; } cur_token++; } void Scanner::pass( int token, char *start, char *end ) { if ( importMachines ) importToken( token, start, end ); pass(); } void Scanner::pass() { updateCol(); /* If no errors and we are at the bottom of the include stack (the * source file listed on the command line) then write out the data. */ if ( includeDepth == 0 && machineSpec == 0 && machineName == 0 ) id.inputItems.tail->data.write( ts, te-ts ); } /* * The scanner for processing sections, includes, imports, etc. */ %%{ machine section_parse; alphtype int; write data; }%% void Scanner::init( ) { %% write init; } bool Scanner::active() { if ( ignoreSection ) return false; if ( parser == 0 && ! parserExistsError ) { scan_error() << "this specification has no name, nor does any previous" " specification" << endl; parserExistsError = true; } if ( parser == 0 ) return false; return true; } ostream &Scanner::scan_error() { /* Maintain the error count. */ gblErrorCount += 1; cerr << makeInputLoc( fileName, line, column ) << ": "; return cerr; } /* An approximate check for duplicate includes. Due to aliasing of files it's * possible for duplicates to creep in. */ bool Scanner::duplicateInclude( char *inclFileName, char *inclSectionName ) { for ( IncludeHistory::Iter hi = parser->includeHistory; hi.lte(); hi++ ) { if ( strcmp( hi->fileName, inclFileName ) == 0 && strcmp( hi->sectionName, inclSectionName ) == 0 ) { return true; } } return false; } void Scanner::updateCol() { char *from = lastnl; if ( from == 0 ) from = ts; //cerr << "adding " << te - from << " to column" << endl; column += te - from; lastnl = 0; } void Scanner::handleMachine() { /* Assign a name to the machine. */ char *machine = word; if ( !importMachines && inclSectionTarg == 0 ) { ignoreSection = false; ParserDictEl *pdEl = id.parserDict.find( machine ); if ( pdEl == 0 ) { pdEl = new ParserDictEl( machine ); pdEl->value = new Parser( fileName, machine, sectionLoc ); pdEl->value->init(); id.parserDict.insert( pdEl ); id.parserList.append( pdEl->value ); } parser = pdEl->value; } else if ( !importMachines && strcmp( inclSectionTarg, machine ) == 0 ) { /* found include target */ ignoreSection = false; parser = inclToParser; } else { /* ignoring section */ ignoreSection = true; parser = 0; } } void Scanner::handleInclude() { if ( active() ) { char *inclSectionName = word; char **includeChecks = 0; /* Implement defaults for the input file and section name. */ if ( inclSectionName == 0 ) inclSectionName = parser->sectionName; if ( lit != 0 ) includeChecks = makeIncludePathChecks( fileName, lit, lit_len ); else { char *test = new char[strlen(fileName)+1]; strcpy( test, fileName ); includeChecks = new char*[2]; includeChecks[0] = test; includeChecks[1] = 0; } long found = 0; ifstream *inFile = tryOpenInclude( includeChecks, found ); if ( inFile == 0 ) { scan_error() << "include: failed to locate file" << endl; char **tried = includeChecks; while ( *tried != 0 ) scan_error() << "include: attempted: \"" << *tried++ << '\"' << endl; } else { /* Don't include anything that's already been included. */ if ( !duplicateInclude( includeChecks[found], inclSectionName ) ) { parser->includeHistory.append( IncludeHistoryItem( includeChecks[found], inclSectionName ) ); Scanner scanner( id, includeChecks[found], *inFile, parser, inclSectionName, includeDepth+1, false ); scanner.do_scan( ); delete inFile; } } } } void Scanner::handleImport() { if ( active() ) { char **importChecks = makeIncludePathChecks( fileName, lit, lit_len ); /* Open the input file for reading. */ long found = 0; ifstream *inFile = tryOpenInclude( importChecks, found ); if ( inFile == 0 ) { scan_error() << "import: could not open import file " << "for reading" << endl; char **tried = importChecks; while ( *tried != 0 ) scan_error() << "import: attempted: \"" << *tried++ << '\"' << endl; } Scanner scanner( id, importChecks[found], *inFile, parser, 0, includeDepth+1, true ); scanner.do_scan( ); scanner.importToken( 0, 0, 0 ); scanner.flushImport(); delete inFile; } } %%{ machine section_parse; # Need the defines representing tokens. import "rlparse.h"; action clear_words { word = lit = 0; word_len = lit_len = 0; } action store_word { word = tokdata; word_len = toklen; } action store_lit { lit = tokdata; lit_len = toklen; } action mach_err { scan_error() << "bad machine statement" << endl; } action incl_err { scan_error() << "bad include statement" << endl; } action import_err { scan_error() << "bad import statement" << endl; } action write_err { scan_error() << "bad write statement" << endl; } action handle_machine { handleMachine(); } action handle_include { handleInclude(); } action handle_import { handleImport(); } machine_stmt = ( KW_Machine TK_Word @store_word ';' ) @handle_machine <>err mach_err <>eof mach_err; include_names = ( TK_Word @store_word ( TK_Literal @store_lit )? | TK_Literal @store_lit ) >clear_words; include_stmt = ( KW_Include include_names ';' ) @handle_include <>err incl_err <>eof incl_err; import_stmt = ( KW_Import TK_Literal @store_lit ';' ) @handle_import <>err import_err <>eof import_err; action write_command { if ( active() && machineSpec == 0 && machineName == 0 ) { InputItem *inputItem = new InputItem; inputItem->type = InputItem::Write; inputItem->loc.fileName = fileName; inputItem->loc.line = line; inputItem->loc.col = column; inputItem->name = parser->sectionName; inputItem->pd = parser->pd; id.inputItems.append( inputItem ); } } action write_arg { if ( active() && machineSpec == 0 && machineName == 0 ) id.inputItems.tail->writeArgs.append( strdup(tokdata) ); } action write_close { if ( active() && machineSpec == 0 && machineName == 0 ) id.inputItems.tail->writeArgs.append( 0 ); } write_stmt = ( KW_Write @write_command ( TK_Word @write_arg )+ ';' @write_close ) <>err write_err <>eof write_err; action handle_token { /* Send the token off to the parser. */ if ( active() ) directToParser( parser, fileName, line, column, type, tokdata, toklen ); } # Catch everything else. everything_else = ^( KW_Machine | KW_Include | KW_Import | KW_Write ) @handle_token; main := ( machine_stmt | include_stmt | import_stmt | write_stmt | everything_else )*; }%% void Scanner::token( int type, char c ) { token( type, &c, &c + 1 ); } void Scanner::token( int type ) { token( type, 0, 0 ); } void Scanner::token( int type, char *start, char *end ) { char *tokdata = 0; int toklen = 0; if ( start != 0 ) { toklen = end-start; tokdata = new char[toklen+1]; memcpy( tokdata, start, toklen ); tokdata[toklen] = 0; } processToken( type, tokdata, toklen ); } void Scanner::processToken( int type, char *tokdata, int toklen ) { int *p, *pe, *eof; if ( type < 0 ) p = pe = eof = 0; else { p = &type; pe = &type + 1; eof = 0; } %%{ machine section_parse; write exec; }%% updateCol(); /* Record the last token for use in controlling the scan of subsequent * tokens. */ lastToken = type; } void Scanner::startSection( ) { parserExistsError = false; sectionLoc.fileName = fileName; sectionLoc.line = line; sectionLoc.col = column; } void Scanner::endSection( ) { /* Execute the eof actions for the section parser. */ processToken( -1, 0, 0 ); /* Close off the section with the parser. */ if ( active() ) { InputLoc loc; loc.fileName = fileName; loc.line = line; loc.col = column; parser->token( loc, TK_EndSection, 0, 0 ); } if ( includeDepth == 0 ) { if ( machineSpec == 0 && machineName == 0 ) { /* The end section may include a newline on the end, so * we use the last line, which will count the newline. */ InputItem *inputItem = new InputItem; inputItem->type = InputItem::HostData; inputItem->loc.line = line; inputItem->loc.col = column; id.inputItems.append( inputItem ); } } } bool isAbsolutePath( const char *path ) { #ifdef _WIN32 return isalpha( path[0] ) && path[1] == ':' && path[2] == '\\'; #else return path[0] == '/'; #endif } char **Scanner::makeIncludePathChecks( const char *thisFileName, const char *fileName, int fnlen ) { char **checks = 0; long nextCheck = 0; long length = 0; bool caseInsensitive = false; char *data = prepareLitString( InputLoc(), fileName, fnlen, length, caseInsensitive ); /* Absolute path? */ if ( isAbsolutePath( data ) ) { checks = new char*[2]; checks[nextCheck++] = data; } else { checks = new char*[2 + id.includePaths.length()]; /* Search from the the location of the current file. */ const char *lastSlash = strrchr( thisFileName, PATH_SEP ); if ( lastSlash == 0 ) checks[nextCheck++] = data; else { long givenPathLen = (lastSlash - thisFileName) + 1; long checklen = givenPathLen + length; char *check = new char[checklen+1]; memcpy( check, thisFileName, givenPathLen ); memcpy( check+givenPathLen, data, length ); check[checklen] = 0; checks[nextCheck++] = check; } /* Search from the include paths given on the command line. */ for ( ArgsVector::Iter incp = id.includePaths; incp.lte(); incp++ ) { long pathLen = strlen( *incp ); long checkLen = pathLen + 1 + length; char *check = new char[checkLen+1]; memcpy( check, *incp, pathLen ); check[pathLen] = PATH_SEP; memcpy( check+pathLen+1, data, length ); check[checkLen] = 0; checks[nextCheck++] = check; } } checks[nextCheck] = 0; return checks; } ifstream *Scanner::tryOpenInclude( char **pathChecks, long &found ) { char **check = pathChecks; ifstream *inFile = new ifstream; while ( *check != 0 ) { inFile->open( *check ); if ( inFile->is_open() ) { found = check - pathChecks; return inFile; } /* * 03/26/2011 jg: * Don't rely on sloppy runtime behaviour: reset the state of the stream explicitly. * If inFile->open() fails, which happens when include dirs are tested, the fail bit * is set by the runtime library. Currently the VS runtime library opens new files, * but when it comes to reading it refuses to work. */ inFile->clear(); check += 1; } found = -1; delete inFile; return 0; } %%{ machine rlscan; # This is sent by the driver code. EOF = 0; action inc_nl { lastnl = p; column = 0; line++; } NL = '\n' @inc_nl; # Identifiers, numbers, commetns, and other common things. ident = ( alpha | '_' ) ( alpha |digit |'_' )*; number = digit+; hex_number = '0x' [0-9a-fA-F]+; c_comment = '/*' ( any | NL )* :>> '*/'; cpp_comment = '//' [^\n]* NL; c_cpp_comment = c_comment | cpp_comment; ruby_comment = '#' [^\n]* NL; # These literal forms are common to host code and ragel. s_literal = "'" ([^'\\] | NL | '\\' (any | NL))* "'"; d_literal = '"' ([^"\\] | NL | '\\' (any | NL))* '"'; host_re_literal = '/' ([^/\\] | NL | '\\' (any | NL))* '/'; whitespace = [ \t] | NL; pound_comment = '#' [^\n]* NL; # An inline block of code for Ruby. inline_code_ruby := |* # Inline expression keywords. "fpc" => { token( KW_PChar ); }; "fc" => { token( KW_Char ); }; "fcurs" => { token( KW_CurState ); }; "ftargs" => { token( KW_TargState ); }; "fentry" => { whitespaceOn = false; token( KW_Entry ); }; # Inline statement keywords. "fhold" => { whitespaceOn = false; token( KW_Hold ); }; "fexec" => { token( KW_Exec, 0, 0 ); }; "fgoto" => { whitespaceOn = false; token( KW_Goto ); }; "fnext" => { whitespaceOn = false; token( KW_Next ); }; "fcall" => { whitespaceOn = false; token( KW_Call ); }; "fret" => { whitespaceOn = false; token( KW_Ret ); }; "fbreak" => { whitespaceOn = false; token( KW_Break ); }; ident => { token( TK_Word, ts, te ); }; number => { token( TK_UInt, ts, te ); }; hex_number => { token( TK_Hex, ts, te ); }; ( s_literal | d_literal | host_re_literal ) => { token( IL_Literal, ts, te ); }; whitespace+ => { if ( whitespaceOn ) token( IL_WhiteSpace, ts, te ); }; ruby_comment => { token( IL_Comment, ts, te ); }; "::" => { token( TK_NameSep, ts, te ); }; # Some symbols need to go to the parser as with their cardinal value as # the token type (as opposed to being sent as anonymous symbols) # because they are part of the sequences which we interpret. The * ) ; # symbols cause whitespace parsing to come back on. This gets turned # off by some keywords. ";" => { whitespaceOn = true; token( *ts, ts, te ); if ( inlineBlockType == SemiTerminated ) fret; }; [*)] => { whitespaceOn = true; token( *ts, ts, te ); }; [,(] => { token( *ts, ts, te ); }; '{' => { token( IL_Symbol, ts, te ); curly_count += 1; }; '}' => { if ( --curly_count == 0 && inlineBlockType == CurlyDelimited ) { /* Inline code block ends. */ token( '}' ); fret; } else { /* Either a semi terminated inline block or only the closing * brace of some inner scope, not the block's closing brace. */ token( IL_Symbol, ts, te ); } }; EOF => { scan_error() << "unterminated code block" << endl; }; # Send every other character as a symbol. any => { token( IL_Symbol, ts, te ); }; *|; # An inline block of code for languages other than Ruby. inline_code := |* # Inline expression keywords. "fpc" => { token( KW_PChar ); }; "fc" => { token( KW_Char ); }; "fcurs" => { token( KW_CurState ); }; "ftargs" => { token( KW_TargState ); }; "fentry" => { whitespaceOn = false; token( KW_Entry ); }; # Inline statement keywords. "fhold" => { whitespaceOn = false; token( KW_Hold ); }; "fexec" => { token( KW_Exec, 0, 0 ); }; "fgoto" => { whitespaceOn = false; token( KW_Goto ); }; "fnext" => { whitespaceOn = false; token( KW_Next ); }; "fcall" => { whitespaceOn = false; token( KW_Call ); }; "fret" => { whitespaceOn = false; token( KW_Ret ); }; "fbreak" => { whitespaceOn = false; token( KW_Break ); }; ident => { token( TK_Word, ts, te ); }; number => { token( TK_UInt, ts, te ); }; hex_number => { token( TK_Hex, ts, te ); }; ( s_literal | d_literal ) => { token( IL_Literal, ts, te ); }; whitespace+ => { if ( whitespaceOn ) token( IL_WhiteSpace, ts, te ); }; c_cpp_comment => { token( IL_Comment, ts, te ); }; "::" => { token( TK_NameSep, ts, te ); }; # Some symbols need to go to the parser as with their cardinal value as # the token type (as opposed to being sent as anonymous symbols) # because they are part of the sequences which we interpret. The * ) ; # symbols cause whitespace parsing to come back on. This gets turned # off by some keywords. ";" => { whitespaceOn = true; token( *ts, ts, te ); if ( inlineBlockType == SemiTerminated ) fret; }; [*)] => { whitespaceOn = true; token( *ts, ts, te ); }; [,(] => { token( *ts, ts, te ); }; '{' => { token( IL_Symbol, ts, te ); curly_count += 1; }; '}' => { if ( --curly_count == 0 && inlineBlockType == CurlyDelimited ) { /* Inline code block ends. */ token( '}' ); fret; } else { /* Either a semi terminated inline block or only the closing * brace of some inner scope, not the block's closing brace. */ token( IL_Symbol, ts, te ); } }; EOF => { scan_error() << "unterminated code block" << endl; }; # Send every other character as a symbol. any => { token( IL_Symbol, ts, te ); }; *|; or_literal := |* # Escape sequences in OR expressions. '\\0' => { token( RE_Char, '\0' ); }; '\\a' => { token( RE_Char, '\a' ); }; '\\b' => { token( RE_Char, '\b' ); }; '\\t' => { token( RE_Char, '\t' ); }; '\\n' => { token( RE_Char, '\n' ); }; '\\v' => { token( RE_Char, '\v' ); }; '\\f' => { token( RE_Char, '\f' ); }; '\\r' => { token( RE_Char, '\r' ); }; '\\\n' => { updateCol(); }; '\\' any => { token( RE_Char, ts+1, te ); }; # Range dash in an OR expression. '-' => { token( RE_Dash, 0, 0 ); }; # Terminate an OR expression. ']' => { token( RE_SqClose ); fret; }; EOF => { scan_error() << "unterminated OR literal" << endl; }; # Characters in an OR expression. [^\]] => { token( RE_Char, ts, te ); }; *|; ragel_re_literal := |* # Escape sequences in regular expressions. '\\0' => { token( RE_Char, '\0' ); }; '\\a' => { token( RE_Char, '\a' ); }; '\\b' => { token( RE_Char, '\b' ); }; '\\t' => { token( RE_Char, '\t' ); }; '\\n' => { token( RE_Char, '\n' ); }; '\\v' => { token( RE_Char, '\v' ); }; '\\f' => { token( RE_Char, '\f' ); }; '\\r' => { token( RE_Char, '\r' ); }; '\\\n' => { updateCol(); }; '\\' any => { token( RE_Char, ts+1, te ); }; # Terminate an OR expression. '/' [i]? => { token( RE_Slash, ts, te ); fgoto parser_def; }; # Special characters. '.' => { token( RE_Dot ); }; '*' => { token( RE_Star ); }; '[' => { token( RE_SqOpen ); fcall or_literal; }; '[^' => { token( RE_SqOpenNeg ); fcall or_literal; }; EOF => { scan_error() << "unterminated regular expression" << endl; }; # Characters in an OR expression. [^\/] => { token( RE_Char, ts, te ); }; *|; # We need a separate token space here to avoid the ragel keywords. write_statement := |* ident => { token( TK_Word, ts, te ); } ; [ \t\n]+ => { updateCol(); }; ';' => { token( ';' ); fgoto parser_def; }; EOF => { scan_error() << "unterminated write statement" << endl; }; *|; # Parser definitions. parser_def := |* #'length_cond' => { token( KW_Length ); }; 'machine' => { token( KW_Machine ); }; 'include' => { token( KW_Include ); }; 'import' => { token( KW_Import ); }; 'write' => { token( KW_Write ); fgoto write_statement; }; 'action' => { token( KW_Action ); }; 'alphtype' => { token( KW_AlphType ); }; 'prepush' => { token( KW_PrePush ); }; 'postpop' => { token( KW_PostPop ); }; # FIXME: Enable this post 5.17. # 'range' => { token( KW_Range ); }; 'getkey' => { token( KW_GetKey ); inlineBlockType = SemiTerminated; if ( hostLang->lang == HostLang::Ruby ) fcall inline_code_ruby; else fcall inline_code; }; 'access' => { token( KW_Access ); inlineBlockType = SemiTerminated; if ( hostLang->lang == HostLang::Ruby ) fcall inline_code_ruby; else fcall inline_code; }; 'variable' => { token( KW_Variable ); inlineBlockType = SemiTerminated; if ( hostLang->lang == HostLang::Ruby ) fcall inline_code_ruby; else fcall inline_code; }; 'when' => { token( KW_When ); }; 'inwhen' => { token( KW_InWhen ); }; 'outwhen' => { token( KW_OutWhen ); }; 'eof' => { token( KW_Eof ); }; 'err' => { token( KW_Err ); }; 'lerr' => { token( KW_Lerr ); }; 'to' => { token( KW_To ); }; 'from' => { token( KW_From ); }; 'export' => { token( KW_Export ); }; # Identifiers. ident => { token( TK_Word, ts, te ); } ; # Numbers number => { token( TK_UInt, ts, te ); }; hex_number => { token( TK_Hex, ts, te ); }; # Literals, with optionals. ( s_literal | d_literal ) [i]? => { token( TK_Literal, ts, te ); }; '[' => { token( RE_SqOpen ); fcall or_literal; }; '[^' => { token( RE_SqOpenNeg ); fcall or_literal; }; '/' => { token( RE_Slash ); fgoto ragel_re_literal; }; # Ignore. pound_comment => { updateCol(); }; ':=' => { token( TK_ColonEquals ); }; # To State Actions. ">~" => { token( TK_StartToState ); }; "$~" => { token( TK_AllToState ); }; "%~" => { token( TK_FinalToState ); }; "<~" => { token( TK_NotStartToState ); }; "@~" => { token( TK_NotFinalToState ); }; "<>~" => { token( TK_MiddleToState ); }; # From State actions ">*" => { token( TK_StartFromState ); }; "$*" => { token( TK_AllFromState ); }; "%*" => { token( TK_FinalFromState ); }; "<*" => { token( TK_NotStartFromState ); }; "@*" => { token( TK_NotFinalFromState ); }; "<>*" => { token( TK_MiddleFromState ); }; # EOF Actions. ">/" => { token( TK_StartEOF ); }; "$/" => { token( TK_AllEOF ); }; "%/" => { token( TK_FinalEOF ); }; " { token( TK_NotStartEOF ); }; "@/" => { token( TK_NotFinalEOF ); }; "<>/" => { token( TK_MiddleEOF ); }; # Global Error actions. ">!" => { token( TK_StartGblError ); }; "$!" => { token( TK_AllGblError ); }; "%!" => { token( TK_FinalGblError ); }; " { token( TK_NotStartGblError ); }; "@!" => { token( TK_NotFinalGblError ); }; "<>!" => { token( TK_MiddleGblError ); }; # Local error actions. ">^" => { token( TK_StartLocalError ); }; "$^" => { token( TK_AllLocalError ); }; "%^" => { token( TK_FinalLocalError ); }; "<^" => { token( TK_NotStartLocalError ); }; "@^" => { token( TK_NotFinalLocalError ); }; "<>^" => { token( TK_MiddleLocalError ); }; # Middle. "<>" => { token( TK_Middle ); }; # Conditions. '>?' => { token( TK_StartCond ); }; '$?' => { token( TK_AllCond ); }; '%?' => { token( TK_LeavingCond ); }; '..' => { token( TK_DotDot ); }; '**' => { token( TK_StarStar ); }; '--' => { token( TK_DashDash ); }; '->' => { token( TK_Arrow ); }; '=>' => { token( TK_DoubleArrow ); }; ":>" => { token( TK_ColonGt ); }; ":>>" => { token( TK_ColonGtGt ); }; "<:" => { token( TK_LtColon ); }; # Opening of longest match. "|*" => { token( TK_BarStar ); }; # Separater for name references. "::" => { token( TK_NameSep, ts, te ); }; '}%%' => { updateCol(); endSection(); fret; }; [ \t\r]+ => { updateCol(); }; # If we are in a single line machine then newline may end the spec. NL => { updateCol(); if ( singleLineSpec ) { endSection(); fret; } }; '{' => { if ( lastToken == KW_Export || lastToken == KW_Entry ) token( '{' ); else { token( '{' ); curly_count = 1; inlineBlockType = CurlyDelimited; if ( hostLang->lang == HostLang::Ruby ) fcall inline_code_ruby; else fcall inline_code; } }; EOF => { scan_error() << "unterminated ragel section" << endl; }; any => { token( *ts ); } ; *|; # Outside code scanner. These tokens get passed through. main_ruby := |* ident => { pass( IMP_Word, ts, te ); }; number => { pass( IMP_UInt, ts, te ); }; ruby_comment => { pass(); }; ( s_literal | d_literal | host_re_literal ) => { pass( IMP_Literal, ts, te ); }; '%%{' => { updateCol(); singleLineSpec = false; startSection(); fcall parser_def; }; '%%' => { updateCol(); singleLineSpec = true; startSection(); fcall parser_def; }; whitespace+ => { pass(); }; EOF; any => { pass( *ts, 0, 0 ); }; *|; # Outside code scanner. These tokens get passed through. main := |* 'define' => { pass( IMP_Define, 0, 0 ); }; ident => { pass( IMP_Word, ts, te ); }; number => { pass( IMP_UInt, ts, te ); }; c_cpp_comment => { pass(); }; ( s_literal | d_literal ) => { pass( IMP_Literal, ts, te ); }; '%%{' => { updateCol(); singleLineSpec = false; startSection(); fcall parser_def; }; '%%' => { updateCol(); singleLineSpec = true; startSection(); fcall parser_def; }; whitespace+ => { pass(); }; EOF; any => { pass( *ts, 0, 0 ); }; *|; }%% %% write data; void Scanner::do_scan() { int bufsize = 8; char *buf = new char[bufsize]; int cs, act, have = 0; int top; /* The stack is two deep, one level for going into ragel defs from the main * machines which process outside code, and another for going into or literals * from either a ragel spec, or a regular expression. */ int stack[2]; int curly_count = 0; bool execute = true; bool singleLineSpec = false; InlineBlockType inlineBlockType = CurlyDelimited; /* Init the section parser and the character scanner. */ init(); %% write init; /* Set up the start state. FIXME: After 5.20 is released the nocs write * init option should be used, the main machine eliminated and this statement moved * above the write init. */ if ( hostLang->lang == HostLang::Ruby ) cs = rlscan_en_main_ruby; else cs = rlscan_en_main; while ( execute ) { char *p = buf + have; int space = bufsize - have; if ( space == 0 ) { /* We filled up the buffer trying to scan a token. Grow it. */ bufsize = bufsize * 2; char *newbuf = new char[bufsize]; /* Recompute p and space. */ p = newbuf + have; space = bufsize - have; /* Patch up pointers possibly in use. */ if ( ts != 0 ) ts = newbuf + ( ts - buf ); te = newbuf + ( te - buf ); /* Copy the new buffer in. */ memcpy( newbuf, buf, have ); delete[] buf; buf = newbuf; } input.read( p, space ); int len = input.gcount(); char *pe = p + len; /* If we see eof then append the eof var. */ char *eof = 0; if ( len == 0 ) { eof = pe; execute = false; } %% write exec; /* Check if we failed. */ if ( cs == rlscan_error ) { /* Machine failed before finding a token. I'm not yet sure if this * is reachable. */ scan_error() << "scanner error" << endl; exit(1); } /* Decide if we need to preserve anything. */ char *preserve = ts; /* Now set up the prefix. */ if ( preserve == 0 ) have = 0; else { /* There is data that needs to be shifted over. */ have = pe - preserve; memmove( buf, preserve, have ); unsigned int shiftback = preserve - buf; if ( ts != 0 ) ts -= shiftback; te -= shiftback; preserve = buf; } } delete[] buf; } ragel-6.8/ragel/rubyftable.cpp0000664000175000017500000002770712106050031013342 00000000000000/* * 2007 Victor Hugo Borja * Copyright 2001-2007 Adrian Thurston */ /* This file is part of Ragel. * * Ragel is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Ragel is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Ragel; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #include "redfsm.h" #include "gendata.h" #include "ragel.h" #include "rubyftable.h" using std::ostream; using std::ostringstream; using std::string; using std::cerr; using std::endl; void RubyFTabCodeGen::GOTO( ostream &out, int gotoDest, bool inFinish ) { out << " begin\n" " " << vCS() << " = " << gotoDest << "\n" " _goto_level = _again\n" " next\n" " end\n"; } void RubyFTabCodeGen::GOTO_EXPR( ostream &out, GenInlineItem *ilItem, bool inFinish ) { out << " begin\n" " " << vCS() << " = ("; INLINE_LIST( out, ilItem->children, 0, inFinish ); out << ")\n"; out << " _goto_level = _again\n" " next\n" " end\n"; } void RubyFTabCodeGen::CALL( ostream &out, int callDest, int targState, bool inFinish ) { if ( prePushExpr != 0 ) { out << "begin\n"; INLINE_LIST( out, prePushExpr, 0, false ); } out << " begin\n" " " << STACK() << "[" << TOP() << "] = " << vCS() << "\n" " " << TOP() << "+= 1\n" " " << vCS() << " = " << callDest << "\n" " _goto_level = _again\n" " next\n" " end\n"; if ( prePushExpr != 0 ) out << "end\n"; } void RubyFTabCodeGen::CALL_EXPR(ostream &out, GenInlineItem *ilItem, int targState, bool inFinish ) { if ( prePushExpr != 0 ) { out << "begin\n"; INLINE_LIST( out, prePushExpr, 0, false ); } out << " begin\n" " " << STACK() << "[" << TOP() << "] = " << vCS() << "\n" " " << TOP() << " += 1\n" " " << vCS() << " = ("; INLINE_LIST( out, ilItem->children, targState, inFinish ); out << ")\n"; out << " _goto_level = _again\n" " next\n" " end\n"; if ( prePushExpr != 0 ) out << "end\n"; } void RubyFTabCodeGen::RET( ostream &out, bool inFinish ) { out << " begin\n" " " << TOP() << " -= 1\n" " " << vCS() << " = " << STACK() << "[" << TOP() << "]\n"; if ( postPopExpr != 0 ) { out << "begin\n"; INLINE_LIST( out, postPopExpr, 0, false ); out << "end\n"; } out << " _goto_level = _again\n" " next\n" " end\n"; } void RubyFTabCodeGen::BREAK( ostream &out, int targState ) { out << " begin\n" " " << P() << " += 1\n" " _goto_level = _out\n" " next\n" " end\n"; } std::ostream &RubyFTabCodeGen::TO_STATE_ACTION_SWITCH() { /* Loop the actions. */ for ( GenActionTableMap::Iter redAct = redFsm->actionMap; redAct.lte(); redAct++ ) { if ( redAct->numToStateRefs > 0 ) { /* Write the entry label. */ out << "\twhen " << redAct->actListId+1 << " then\n"; /* Write each action in the list of action items. */ for ( GenActionTable::Iter item = redAct->key; item.lte(); item++ ) ACTION( out, item->value, 0, false ); } } genLineDirective( out ); return out; } /* Write out the function switch. This switch is keyed on the values * of the func index. */ std::ostream &RubyFTabCodeGen::FROM_STATE_ACTION_SWITCH() { /* Loop the actions. */ for ( GenActionTableMap::Iter redAct = redFsm->actionMap; redAct.lte(); redAct++ ) { if ( redAct->numFromStateRefs > 0 ) { /* Write the entry label. */ out << "\twhen " << redAct->actListId+1 << " then\n"; /* Write each action in the list of action items. */ for ( GenActionTable::Iter item = redAct->key; item.lte(); item++ ) ACTION( out, item->value, 0, false ); } } genLineDirective( out ); return out; } std::ostream &RubyFTabCodeGen::EOF_ACTION_SWITCH() { /* Loop the actions. */ for ( GenActionTableMap::Iter redAct = redFsm->actionMap; redAct.lte(); redAct++ ) { if ( redAct->numEofRefs > 0 ) { /* Write the entry label. */ out << "\twhen " << redAct->actListId+1 << " then\n"; /* Write each action in the list of action items. */ for ( GenActionTable::Iter item = redAct->key; item.lte(); item++ ) ACTION( out, item->value, 0, true ); } } genLineDirective( out ); return out; } /* Write out the function switch. This switch is keyed on the values * of the func index. */ std::ostream &RubyFTabCodeGen::ACTION_SWITCH() { /* Loop the actions. */ for ( GenActionTableMap::Iter redAct = redFsm->actionMap; redAct.lte(); redAct++ ) { if ( redAct->numTransRefs > 0 ) { /* Write the entry label. */ out << "\twhen " << redAct->actListId+1 << " then\n"; /* Write each action in the list of action items. */ for ( GenActionTable::Iter item = redAct->key; item.lte(); item++ ) ACTION( out, item->value, 0, false ); } } genLineDirective( out ); return out; } int RubyFTabCodeGen::TO_STATE_ACTION( RedStateAp *state ) { int act = 0; if ( state->toStateAction != 0 ) act = state->toStateAction->actListId+1; return act; } int RubyFTabCodeGen::FROM_STATE_ACTION( RedStateAp *state ) { int act = 0; if ( state->fromStateAction != 0 ) act = state->fromStateAction->actListId+1; return act; } int RubyFTabCodeGen::EOF_ACTION( RedStateAp *state ) { int act = 0; if ( state->eofAction != 0 ) act = state->eofAction->actListId+1; return act; } /* Write out the function for a transition. */ int RubyFTabCodeGen::TRANS_ACTION( RedTransAp *trans ) { int action = 0; if ( trans->action != 0 ) action = trans->action->actListId+1; return action; } void RubyFTabCodeGen::writeData() { if ( redFsm->anyConditions() ) { OPEN_ARRAY( ARRAY_TYPE(redFsm->maxCondOffset), CO() ); COND_OFFSETS(); CLOSE_ARRAY() << "\n"; OPEN_ARRAY( ARRAY_TYPE(redFsm->maxCondLen), CL() ); COND_LENS(); CLOSE_ARRAY() << "\n"; OPEN_ARRAY( WIDE_ALPH_TYPE(), CK() ); COND_KEYS(); CLOSE_ARRAY() << "\n"; OPEN_ARRAY( ARRAY_TYPE(redFsm->maxCondSpaceId), C() ); COND_SPACES(); CLOSE_ARRAY() << "\n"; } OPEN_ARRAY( ARRAY_TYPE(redFsm->maxKeyOffset), KO() ); KEY_OFFSETS(); CLOSE_ARRAY() << "\n"; OPEN_ARRAY( WIDE_ALPH_TYPE(), K() ); KEYS(); CLOSE_ARRAY() << "\n"; OPEN_ARRAY( ARRAY_TYPE(redFsm->maxSingleLen), SL() ); SINGLE_LENS(); CLOSE_ARRAY() << "\n"; OPEN_ARRAY( ARRAY_TYPE(redFsm->maxRangeLen), RL() ); RANGE_LENS(); CLOSE_ARRAY() << "\n"; OPEN_ARRAY( ARRAY_TYPE(redFsm->maxIndexOffset), IO() ); INDEX_OFFSETS(); CLOSE_ARRAY() << "\n"; if ( useIndicies ) { OPEN_ARRAY( ARRAY_TYPE(redFsm->maxIndex), I() ); INDICIES(); CLOSE_ARRAY() << "\n"; OPEN_ARRAY( ARRAY_TYPE(redFsm->maxState), TT() ); TRANS_TARGS_WI(); CLOSE_ARRAY() << "\n"; if ( redFsm->anyActions() ) { OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActListId), TA() ); TRANS_ACTIONS_WI(); CLOSE_ARRAY() << "\n"; } } else { OPEN_ARRAY( ARRAY_TYPE(redFsm->maxState), TT() ); TRANS_TARGS(); CLOSE_ARRAY() << "\n"; if ( redFsm->anyActions() ) { OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActListId), TA() ); TRANS_ACTIONS(); CLOSE_ARRAY() << "\n"; } } if ( redFsm->anyToStateActions() ) { OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActionLoc), TSA() ); TO_STATE_ACTIONS(); CLOSE_ARRAY() << "\n"; } if ( redFsm->anyFromStateActions() ) { OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActionLoc), FSA() ); FROM_STATE_ACTIONS(); CLOSE_ARRAY() << "\n"; } if ( redFsm->anyEofActions() ) { OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActListId), EA() ); EOF_ACTIONS(); CLOSE_ARRAY() << "\n"; } if ( redFsm->anyEofTrans() ) { OPEN_ARRAY( ARRAY_TYPE(redFsm->maxIndexOffset+1), ET() ); EOF_TRANS(); CLOSE_ARRAY() << "\n"; } STATE_IDS(); } void RubyFTabCodeGen::writeExec() { out << "begin\n" " testEof = false\n" " _klen, _trans, _keys"; if ( redFsm->anyRegCurStateRef() ) out << ", _ps"; if ( redFsm->anyConditions() ) out << ", _widec"; out << " = nil\n"; out << " _goto_level = 0\n" " _resume = 10\n" " _eof_trans = 15\n" " _again = 20\n" " _test_eof = 30\n" " _out = 40\n"; out << " while true\n" " if _goto_level <= 0\n"; if ( !noEnd ) { out << " if " << P() << " == " << PE() << "\n" " _goto_level = _test_eof\n" " next\n" " end\n"; } if ( redFsm->errState != 0 ) { out << " if " << vCS() << " == " << redFsm->errState->id << "\n" " _goto_level = _out\n" " next\n" " end\n"; } /* The resume label. */ out << " end\n" " if _goto_level <= _resume\n"; if ( redFsm->anyFromStateActions() ) { out << " case " << FSA() << "[" << vCS() << "] \n"; FROM_STATE_ACTION_SWITCH() << " end # from state action switch \n" "\n"; } if ( redFsm->anyConditions() ) COND_TRANSLATE(); LOCATE_TRANS(); if ( useIndicies ) out << " _trans = " << I() << "[_trans];\n"; if ( redFsm->anyEofTrans() ) { out << " end\n" " if _goto_level <= _eof_trans\n"; } if ( redFsm->anyRegCurStateRef() ) out << " _ps = " << vCS() << ";\n"; out << " " << vCS() << " = " << TT() << "[_trans];\n" "\n"; if ( redFsm->anyRegActions() ) { out << " if " << TA() << "[_trans] != 0\n" "\n" " case " << TA() << "[_trans] \n"; ACTION_SWITCH() << " end # action switch \n" " end\n" "\n"; } /* The again label. */ out << " end\n" " if _goto_level <= _again\n"; if ( redFsm->anyToStateActions() ) { out << " case " << TSA() << "[" << vCS() << "] \n"; TO_STATE_ACTION_SWITCH() << " end\n" "\n"; } if ( redFsm->errState != 0 ) { out << " if " << vCS() << " == " << redFsm->errState->id << "\n" " _goto_level = _out\n" " next\n" " end\n"; } out << " " << P() << " += 1\n"; if ( !noEnd ) { out << " if " << P() << " != " << PE() << "\n" " _goto_level = _resume\n" " next\n" " end\n"; } else { out << " _goto_level = _resume\n" " next\n"; } /* The test eof label. */ out << " end\n" " if _goto_level <= _test_eof\n"; if ( redFsm->anyEofTrans() || redFsm->anyEofActions() ) { out << " if " << P() << " == " << vEOF() << "\n"; if ( redFsm->anyEofTrans() ) { out << " if " << ET() << "[" << vCS() << "] > 0\n" " _trans = " << ET() << "[" << vCS() << "] - 1;\n" " _goto_level = _eof_trans\n" " next;\n" " end\n"; } if ( redFsm->anyEofActions() ) { out << " begin\n" " case ( " << EA() << "[" << vCS() << "] )\n"; EOF_ACTION_SWITCH() << " end\n" " end\n"; } out << " end\n" "\n"; } out << " end\n" " if _goto_level <= _out\n" " break\n" " end\n" "end\n"; /* Wrapping the execute block. */ out << " end\n"; } void RubyFTabCodeGen::calcIndexSize() { int sizeWithInds = 0, sizeWithoutInds = 0; /* Calculate cost of using with indicies. */ for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { int totalIndex = st->outSingle.length() + st->outRange.length() + (st->defTrans == 0 ? 0 : 1); sizeWithInds += arrayTypeSize(redFsm->maxIndex) * totalIndex; } sizeWithInds += arrayTypeSize(redFsm->maxState) * redFsm->transSet.length(); if ( redFsm->anyActions() ) sizeWithInds += arrayTypeSize(redFsm->maxActListId) * redFsm->transSet.length(); /* Calculate the cost of not using indicies. */ for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { int totalIndex = st->outSingle.length() + st->outRange.length() + (st->defTrans == 0 ? 0 : 1); sizeWithoutInds += arrayTypeSize(redFsm->maxState) * totalIndex; if ( redFsm->anyActions() ) sizeWithoutInds += arrayTypeSize(redFsm->maxActListId) * totalIndex; } /* If using indicies reduces the size, use them. */ useIndicies = sizeWithInds < sizeWithoutInds; } /* * Local Variables: * mode: c++ * indent-tabs-mode: 1 * c-file-style: "bsd" * End: */ ragel-6.8/ragel/rubycodegen.cpp0000664000175000017500000004373612106050031013511 00000000000000/* * 2007 Victor Hugo Borja * Copyright 2001-2007 Adrian Thurston */ /* This file is part of Ragel. * * Ragel is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Ragel is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Ragel; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #include "redfsm.h" #include "gendata.h" #include "ragel.h" #include "rubycodegen.h" #include "pcheck.h" #include "vector.h" #include "version.h" #include "common.h" #include "ragel.h" #include "rubytable.h" #include "rubyftable.h" #include "rubyflat.h" #include "rubyfflat.h" #include "rbxgoto.h" using std::ostream; using std::ostringstream; using std::string; using std::cerr; using std::endl; using std::istream; using std::ifstream; using std::ostream; using std::ios; using std::cin; using std::cout; using std::cerr; using std::endl; /* Target ruby impl */ /* Target language and output style. */ extern CodeStyle codeStyle; extern int numSplitPartitions; extern bool noLineDirectives; /* * Callbacks invoked by the XML data parser. */ void rubyLineDirective( ostream &out, const char *fileName, int line ) { if ( noLineDirectives ) return; /* Write a comment containing line info. */ out << "# line " << line << " \""; for ( const char *pc = fileName; *pc != 0; pc++ ) { if ( *pc == '\\' ) out << "\\\\"; else out << *pc; } out << "\"\n"; } void RubyCodeGen::genLineDirective( ostream &out ) { std::streambuf *sbuf = out.rdbuf(); output_filter *filter = static_cast(sbuf); rubyLineDirective( out, filter->fileName, filter->line + 1 ); } string RubyCodeGen::DATA_PREFIX() { if ( !noPrefix ) return FSM_NAME() + "_"; return ""; } std::ostream &RubyCodeGen::STATIC_VAR( string type, string name ) { out << "class << self\n" " attr_accessor :" << name << "\n" "end\n" "self." << name; return out; } std::ostream &RubyCodeGen::OPEN_ARRAY( string type, string name ) { out << "class << self\n" " attr_accessor :" << name << "\n" " private :" << name << ", :" << name << "=\n" "end\n" "self." << name << " = [\n"; return out; } std::ostream &RubyCodeGen::CLOSE_ARRAY() { out << "]\n"; return out; } string RubyCodeGen::ARR_OFF( string ptr, string offset ) { return ptr + "[" + offset + "]"; } string RubyCodeGen::NULL_ITEM() { return "nil"; } string RubyCodeGen::P() { ostringstream ret; if ( pExpr == 0 ) ret << "p"; else { //ret << "("; INLINE_LIST( ret, pExpr, 0, false ); //ret << ")"; } return ret.str(); } string RubyCodeGen::PE() { ostringstream ret; if ( peExpr == 0 ) ret << "pe"; else { //ret << "("; INLINE_LIST( ret, peExpr, 0, false ); //ret << ")"; } return ret.str(); } string RubyCodeGen::vEOF() { ostringstream ret; if ( eofExpr == 0 ) ret << "eof"; else { //ret << "("; INLINE_LIST( ret, eofExpr, 0, false ); //ret << ")"; } return ret.str(); } string RubyCodeGen::vCS() { ostringstream ret; if ( csExpr == 0 ) ret << ACCESS() << "cs"; else { //ret << "("; INLINE_LIST( ret, csExpr, 0, false ); //ret << ")"; } return ret.str(); } string RubyCodeGen::TOP() { ostringstream ret; if ( topExpr == 0 ) ret << ACCESS() + "top"; else { //ret << "("; INLINE_LIST( ret, topExpr, 0, false ); //ret << ")"; } return ret.str(); } string RubyCodeGen::STACK() { ostringstream ret; if ( stackExpr == 0 ) ret << ACCESS() + "stack"; else { //ret << "("; INLINE_LIST( ret, stackExpr, 0, false ); //ret << ")"; } return ret.str(); } string RubyCodeGen::ACT() { ostringstream ret; if ( actExpr == 0 ) ret << ACCESS() + "act"; else { //ret << "("; INLINE_LIST( ret, actExpr, 0, false ); //ret << ")"; } return ret.str(); } string RubyCodeGen::TOKSTART() { ostringstream ret; if ( tokstartExpr == 0 ) ret << ACCESS() + "ts"; else { //ret << "("; INLINE_LIST( ret, tokstartExpr, 0, false ); //ret << ")"; } return ret.str(); } string RubyCodeGen::TOKEND() { ostringstream ret; if ( tokendExpr == 0 ) ret << ACCESS() + "te"; else { //ret << "("; INLINE_LIST( ret, tokendExpr, 0, false ); //ret << ")"; } return ret.str(); } string RubyCodeGen::DATA() { ostringstream ret; if ( dataExpr == 0 ) ret << ACCESS() + "data"; else { //ret << "("; INLINE_LIST( ret, dataExpr, 0, false ); //ret << ")"; } return ret.str(); } /* Write out the fsm name. */ string RubyCodeGen::FSM_NAME() { return fsmName; } void RubyCodeGen::ACTION( ostream &ret, GenAction *action, int targState, bool inFinish ) { /* Write the preprocessor line info for going into the source file. */ rubyLineDirective( ret, action->loc.fileName, action->loc.line ); /* Write the block and close it off. */ ret << " begin\n"; INLINE_LIST( ret, action->inlineList, targState, inFinish ); ret << " end\n"; } string RubyCodeGen::GET_WIDE_KEY() { if ( redFsm->anyConditions() ) return "_widec"; else return GET_KEY(); } string RubyCodeGen::GET_WIDE_KEY( RedStateAp *state ) { if ( state->stateCondList.length() > 0 ) return "_widec"; else return GET_KEY(); } string RubyCodeGen::GET_KEY() { ostringstream ret; if ( getKeyExpr != 0 ) { /* Emit the user supplied method of retrieving the key. */ ret << "("; INLINE_LIST( ret, getKeyExpr, 0, false ); ret << ")"; } else { /* Expression for retrieving the key, use dereference and read ordinal, * for compatibility with Ruby 1.9. */ ret << DATA() << "[" << P() << "].ord"; } return ret.str(); } string RubyCodeGen::KEY( Key key ) { ostringstream ret; if ( keyOps->isSigned || !hostLang->explicitUnsigned ) ret << key.getVal(); else ret << (unsigned long) key.getVal(); return ret.str(); } /* Write out level number of tabs. Makes the nested binary search nice * looking. */ string RubyCodeGen::TABS( int level ) { string result; while ( level-- > 0 ) result += "\t"; return result; } string RubyCodeGen::INT( int i ) { ostringstream ret; ret << i; return ret.str(); } void RubyCodeGen::CONDITION( ostream &ret, GenAction *condition ) { ret << "\n"; rubyLineDirective( ret, condition->loc.fileName, condition->loc.line ); INLINE_LIST( ret, condition->inlineList, 0, false ); } /* Emit the alphabet data type. */ string RubyCodeGen::ALPH_TYPE() { string ret = keyOps->alphType->data1; if ( keyOps->alphType->data2 != 0 ) { ret += " "; ret += + keyOps->alphType->data2; } return ret; } /* Emit the alphabet data type. */ string RubyCodeGen::WIDE_ALPH_TYPE() { string ret; if ( redFsm->maxKey <= keyOps->maxKey ) ret = ALPH_TYPE(); else { long long maxKeyVal = redFsm->maxKey.getLongLong(); HostType *wideType = keyOps->typeSubsumes( keyOps->isSigned, maxKeyVal ); assert( wideType != 0 ); ret = wideType->data1; if ( wideType->data2 != 0 ) { ret += " "; ret += wideType->data2; } } return ret; } string RubyCodeGen::ARRAY_TYPE( unsigned long maxVal ) { long long maxValLL = (long long) maxVal; HostType *arrayType = keyOps->typeSubsumes( maxValLL ); assert( arrayType != 0 ); string ret = arrayType->data1; if ( arrayType->data2 != 0 ) { ret += " "; ret += arrayType->data2; } return ret; } /* Write out the array of actions. */ std::ostream &RubyCodeGen::ACTIONS_ARRAY() { START_ARRAY_LINE(); int totalActions = 0; ARRAY_ITEM( INT(0), ++totalActions, false ); for ( GenActionTableMap::Iter act = redFsm->actionMap; act.lte(); act++ ) { /* Write out the length, which will never be the last character. */ ARRAY_ITEM( INT(act->key.length()), ++totalActions, false ); for ( GenActionTable::Iter item = act->key; item.lte(); item++ ) { ARRAY_ITEM( INT(item->value->actionId), ++totalActions, (act.last() && item.last()) ); } } END_ARRAY_LINE(); return out; } void RubyCodeGen::STATE_IDS() { if ( redFsm->startState != 0 ) STATIC_VAR( "int", START() ) << " = " << START_STATE_ID() << ";\n"; if ( !noFinal ) STATIC_VAR( "int" , FIRST_FINAL() ) << " = " << FIRST_FINAL_STATE() << ";\n"; if ( !noError ) STATIC_VAR( "int", ERROR() ) << " = " << ERROR_STATE() << ";\n"; out << "\n"; if ( entryPointNames.length() > 0 ) { for ( EntryNameVect::Iter en = entryPointNames; en.lte(); en++ ) { STATIC_VAR( "int", DATA_PREFIX() + "en_" + *en ) << " = " << entryPointIds[en.pos()] << ";\n"; } out << "\n"; } } std::ostream &RubyCodeGen::START_ARRAY_LINE() { out << "\t"; return out; } std::ostream &RubyCodeGen::ARRAY_ITEM( string item, int count, bool last ) { out << item; if ( !last ) { out << ", "; if ( count % IALL == 0 ) { END_ARRAY_LINE(); START_ARRAY_LINE(); } } return out; } std::ostream &RubyCodeGen::END_ARRAY_LINE() { out << "\n"; return out; } /* Emit the offset of the start state as a decimal integer. */ string RubyCodeGen::START_STATE_ID() { ostringstream ret; ret << redFsm->startState->id; return ret.str(); }; string RubyCodeGen::ERROR_STATE() { ostringstream ret; if ( redFsm->errState != 0 ) ret << redFsm->errState->id; else ret << "-1"; return ret.str(); } string RubyCodeGen::FIRST_FINAL_STATE() { ostringstream ret; if ( redFsm->firstFinState != 0 ) ret << redFsm->firstFinState->id; else ret << redFsm->nextStateId; return ret.str(); } string RubyCodeGen::ACCESS() { ostringstream ret; if ( accessExpr != 0 ) INLINE_LIST( ret, accessExpr, 0, false ); return ret.str(); } /* Write out an inline tree structure. Walks the list and possibly calls out * to virtual functions than handle language specific items in the tree. */ void RubyCodeGen::INLINE_LIST( ostream &ret, GenInlineList *inlineList, int targState, bool inFinish ) { for ( GenInlineList::Iter item = *inlineList; item.lte(); item++ ) { switch ( item->type ) { case GenInlineItem::Text: ret << item->data; break; case GenInlineItem::Goto: GOTO( ret, item->targState->id, inFinish ); break; case GenInlineItem::Call: CALL( ret, item->targState->id, targState, inFinish ); break; case GenInlineItem::Next: NEXT( ret, item->targState->id, inFinish ); break; case GenInlineItem::Ret: RET( ret, inFinish ); break; case GenInlineItem::PChar: ret << P(); break; case GenInlineItem::Char: ret << GET_KEY(); break; case GenInlineItem::Hold: ret << P() << " = " << P() << " - 1;"; break; case GenInlineItem::Exec: EXEC( ret, item, targState, inFinish ); break; case GenInlineItem::Curs: ret << "(_ps)"; break; case GenInlineItem::Targs: ret << "(" << vCS() << ")"; break; case GenInlineItem::Entry: ret << item->targState->id; break; case GenInlineItem::GotoExpr: GOTO_EXPR( ret, item, inFinish ); break; case GenInlineItem::CallExpr: CALL_EXPR( ret, item, targState, inFinish ); break; case GenInlineItem::NextExpr: NEXT_EXPR( ret, item, inFinish ); break; case GenInlineItem::LmSwitch: LM_SWITCH( ret, item, targState, inFinish ); break; case GenInlineItem::LmSetActId: SET_ACT( ret, item ); break; case GenInlineItem::LmSetTokEnd: SET_TOKEND( ret, item ); break; case GenInlineItem::LmGetTokEnd: GET_TOKEND( ret, item ); break; case GenInlineItem::LmInitTokStart: INIT_TOKSTART( ret, item ); break; case GenInlineItem::LmInitAct: INIT_ACT( ret, item ); break; case GenInlineItem::LmSetTokStart: SET_TOKSTART( ret, item ); break; case GenInlineItem::SubAction: SUB_ACTION( ret, item, targState, inFinish ); break; case GenInlineItem::Break: BREAK( ret, targState ); break; } } } void RubyCodeGen::EXEC( ostream &ret, GenInlineItem *item, int targState, int inFinish ) { /* The parser gives fexec two children. The double brackets are for D * code. If the inline list is a single word it will get interpreted as a * C-style cast by the D compiler. */ ret << " begin " << P() << " = (("; INLINE_LIST( ret, item->children, targState, inFinish ); ret << "))-1; end\n"; } void RubyCodeGen::LM_SWITCH( ostream &ret, GenInlineItem *item, int targState, int inFinish ) { ret << " case " << ACT() << "\n"; for ( GenInlineList::Iter lma = *item->children; lma.lte(); lma++ ) { /* Write the case label, the action and the case break. */ if ( lma->lmId < 0 ) ret << " else\n"; else ret << " when " << lma->lmId << " then\n"; /* Write the block and close it off. */ ret << " begin"; INLINE_LIST( ret, lma->children, targState, inFinish ); ret << "end\n"; } ret << "end \n\t"; } void RubyCodeGen::SET_ACT( ostream &ret, GenInlineItem *item ) { ret << ACT() << " = " << item->lmId << ";"; } void RubyCodeGen::INIT_TOKSTART( ostream &ret, GenInlineItem *item ) { ret << TOKSTART() << " = " << NULL_ITEM() << ";"; } void RubyCodeGen::INIT_ACT( ostream &ret, GenInlineItem *item ) { ret << ACT() << " = 0\n"; } void RubyCodeGen::SET_TOKSTART( ostream &ret, GenInlineItem *item ) { ret << TOKSTART() << " = " << P() << "\n"; } void RubyCodeGen::SET_TOKEND( ostream &ret, GenInlineItem *item ) { /* The tokend action sets tokend. */ ret << TOKEND() << " = " << P(); if ( item->offset != 0 ) out << "+" << item->offset; out << "\n"; } void RubyCodeGen::GET_TOKEND( ostream &ret, GenInlineItem *item ) { ret << TOKEND(); } void RubyCodeGen::SUB_ACTION( ostream &ret, GenInlineItem *item, int targState, bool inFinish ) { if ( item->children->length() > 0 ) { /* Write the block and close it off. */ ret << " begin "; INLINE_LIST( ret, item->children, targState, inFinish ); ret << " end\n"; } } int RubyCodeGen::TRANS_ACTION( RedTransAp *trans ) { /* If there are actions, emit them. Otherwise emit zero. */ int act = 0; if ( trans->action != 0 ) act = trans->action->location+1; return act; } ostream &RubyCodeGen::source_warning( const InputLoc &loc ) { cerr << sourceFileName << ":" << loc.line << ":" << loc.col << ": warning: "; return cerr; } ostream &RubyCodeGen::source_error( const InputLoc &loc ) { gblErrorCount += 1; assert( sourceFileName != 0 ); cerr << sourceFileName << ":" << loc.line << ":" << loc.col << ": "; return cerr; } void RubyCodeGen::finishRagelDef() { if ( codeStyle == GenGoto || codeStyle == GenFGoto || codeStyle == GenIpGoto || codeStyle == GenSplit ) { /* For directly executable machines there is no required state * ordering. Choose a depth-first ordering to increase the * potential for fall-throughs. */ redFsm->depthFirstOrdering(); } else { /* The frontend will do this for us, but it may be a good idea to * force it if the intermediate file is edited. */ redFsm->sortByStateId(); } /* Choose default transitions and the single transition. */ redFsm->chooseDefaultSpan(); /* Maybe do flat expand, otherwise choose single. */ if ( codeStyle == GenFlat || codeStyle == GenFFlat ) redFsm->makeFlat(); else redFsm->chooseSingle(); /* If any errors have occured in the input file then don't write anything. */ if ( gblErrorCount > 0 ) return; if ( codeStyle == GenSplit ) redFsm->partitionFsm( numSplitPartitions ); if ( codeStyle == GenIpGoto || codeStyle == GenSplit ) redFsm->setInTrans(); /* Anlayze Machine will find the final action reference counts, among * other things. We will use these in reporting the usage * of fsm directives in action code. */ analyzeMachine(); /* Determine if we should use indicies. */ calcIndexSize(); } /* Determine if we should use indicies or not. */ void RubyCodeGen::calcIndexSize() { int sizeWithInds = 0, sizeWithoutInds = 0; /* Calculate cost of using with indicies. */ for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { int totalIndex = st->outSingle.length() + st->outRange.length() + (st->defTrans == 0 ? 0 : 1); sizeWithInds += arrayTypeSize(redFsm->maxIndex) * totalIndex; } sizeWithInds += arrayTypeSize(redFsm->maxState) * redFsm->transSet.length(); if ( redFsm->anyActions() ) sizeWithInds += arrayTypeSize(redFsm->maxActionLoc) * redFsm->transSet.length(); /* Calculate the cost of not using indicies. */ for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { int totalIndex = st->outSingle.length() + st->outRange.length() + (st->defTrans == 0 ? 0 : 1); sizeWithoutInds += arrayTypeSize(redFsm->maxState) * totalIndex; if ( redFsm->anyActions() ) sizeWithoutInds += arrayTypeSize(redFsm->maxActionLoc) * totalIndex; } /* If using indicies reduces the size, use them. */ useIndicies = sizeWithInds < sizeWithoutInds; } unsigned int RubyCodeGen::arrayTypeSize( unsigned long maxVal ) { long long maxValLL = (long long) maxVal; HostType *arrayType = keyOps->typeSubsumes( maxValLL ); assert( arrayType != 0 ); return arrayType->size; } void RubyCodeGen::writeInit() { out << "begin\n"; out << " " << P() << " ||= 0\n"; if ( !noEnd ) out << " " << PE() << " ||= " << DATA() << ".length\n"; if ( !noCS ) out << " " << vCS() << " = " << START() << "\n"; /* If there are any calls, then the stack top needs initialization. */ if ( redFsm->anyActionCalls() || redFsm->anyActionRets() ) out << " " << TOP() << " = 0\n"; if ( hasLongestMatch ) { out << " " << TOKSTART() << " = " << NULL_ITEM() << "\n" " " << TOKEND() << " = " << NULL_ITEM() << "\n" " " << ACT() << " = 0\n"; } out << "end\n"; } void RubyCodeGen::writeExports() { if ( exportList.length() > 0 ) { for ( ExportList::Iter ex = exportList; ex.lte(); ex++ ) { STATIC_VAR( ALPH_TYPE(), DATA_PREFIX() + "ex_" + ex->name ) << " = " << KEY(ex->key) << "\n"; } out << "\n"; } } void RubyCodeGen::writeStart() { out << START_STATE_ID(); } void RubyCodeGen::writeFirstFinal() { out << FIRST_FINAL_STATE(); } void RubyCodeGen::writeError() { out << ERROR_STATE(); } /* * Local Variables: * mode: c++ * indent-tabs-mode: 1 * c-file-style: "bsd" * End: */ ragel-6.8/ragel/gofgoto.cpp0000664000175000017500000001613112106050031012634 00000000000000/* * Copyright 2001-2006 Adrian Thurston * 2004 Erich Ocean * 2005 Alan West */ /* This file is part of Ragel. * * Ragel is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Ragel is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Ragel; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "ragel.h" #include "gofgoto.h" #include "redfsm.h" #include "gendata.h" #include "bstmap.h" using std::endl; std::ostream &GoFGotoCodeGen::EXEC_ACTIONS() { /* Loop the actions. */ for ( GenActionTableMap::Iter redAct = redFsm->actionMap; redAct.lte(); redAct++ ) { if ( redAct->numTransRefs > 0 ) { /* We are at the start of a glob, write the case. */ out << "f" << redAct->actListId << ":" << endl; /* Write each action in the list of action items. */ for ( GenActionTable::Iter item = redAct->key; item.lte(); item++ ) ACTION( out, item->value, 0, false, false ); out << TABS(1) << "goto _again" << endl; } } return out; } /* Write out the function switch. This switch is keyed on the values * of the func index. */ std::ostream &GoFGotoCodeGen::TO_STATE_ACTION_SWITCH( int level ) { /* Loop the actions. */ for ( GenActionTableMap::Iter redAct = redFsm->actionMap; redAct.lte(); redAct++ ) { if ( redAct->numToStateRefs > 0 ) { /* Write the entry label. */ out << TABS(level) << "case " << redAct->actListId+1 << ":" << endl; /* Write each action in the list of action items. */ for ( GenActionTable::Iter item = redAct->key; item.lte(); item++ ) ACTION( out, item->value, 0, false, false ); } } genLineDirective( out ); return out; } /* Write out the function switch. This switch is keyed on the values * of the func index. */ std::ostream &GoFGotoCodeGen::FROM_STATE_ACTION_SWITCH( int level ) { /* Loop the actions. */ for ( GenActionTableMap::Iter redAct = redFsm->actionMap; redAct.lte(); redAct++ ) { if ( redAct->numFromStateRefs > 0 ) { /* Write the entry label. */ out << TABS(level) << "case " << redAct->actListId+1 << ":" << endl; /* Write each action in the list of action items. */ for ( GenActionTable::Iter item = redAct->key; item.lte(); item++ ) ACTION( out, item->value, 0, false, false ); } } genLineDirective( out ); return out; } std::ostream &GoFGotoCodeGen::EOF_ACTION_SWITCH( int level ) { /* Loop the actions. */ for ( GenActionTableMap::Iter redAct = redFsm->actionMap; redAct.lte(); redAct++ ) { if ( redAct->numEofRefs > 0 ) { /* Write the entry label. */ out << TABS(level) << "case " << redAct->actListId+1 << ":" << endl; /* Write each action in the list of action items. */ for ( GenActionTable::Iter item = redAct->key; item.lte(); item++ ) ACTION( out, item->value, 0, true, false ); } } genLineDirective( out ); return out; } std::ostream &GoFGotoCodeGen::FINISH_CASES() { for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { /* States that are final and have an out action need a case. */ if ( st->eofAction != 0 ) { /* Write the case label. */ out << TABS(2) << "case " << st->id << ":" << endl; /* Jump to the func. */ out << TABS(3) << "goto f" << st->eofAction->actListId << endl; } } return out; } unsigned int GoFGotoCodeGen::TO_STATE_ACTION( RedStateAp *state ) { int act = 0; if ( state->toStateAction != 0 ) act = state->toStateAction->actListId+1; return act; } unsigned int GoFGotoCodeGen::FROM_STATE_ACTION( RedStateAp *state ) { int act = 0; if ( state->fromStateAction != 0 ) act = state->fromStateAction->actListId+1; return act; } unsigned int GoFGotoCodeGen::EOF_ACTION( RedStateAp *state ) { int act = 0; if ( state->eofAction != 0 ) act = state->eofAction->actListId+1; return act; } void GoFGotoCodeGen::writeData() { if ( redFsm->anyToStateActions() ) { OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActionLoc), TSA() ); TO_STATE_ACTIONS(); CLOSE_ARRAY() << endl; } if ( redFsm->anyFromStateActions() ) { OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActionLoc), FSA() ); FROM_STATE_ACTIONS(); CLOSE_ARRAY() << endl; } if ( redFsm->anyEofActions() ) { OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActionLoc), EA() ); EOF_ACTIONS(); CLOSE_ARRAY() << endl; } STATE_IDS(); } void GoFGotoCodeGen::writeExec() { testEofUsed = false; outLabelUsed = false; out << " {" << endl; if ( redFsm->anyRegCurStateRef() ) out << " var _ps " << INT() << " = 0" << endl; if ( redFsm->anyConditions() ) out << " var _widec " << WIDE_ALPH_TYPE() << endl; if ( !noEnd ) { testEofUsed = true; out << " if " << P() << " == " << PE() << " {" << endl << " goto _test_eof" << endl << " }" << endl; } if ( redFsm->errState != 0 ) { outLabelUsed = true; out << " if " << vCS() << " == " << redFsm->errState->id << " {" << endl << " goto _out" << endl << " }" << endl; } out << "_resume:" << endl; if ( redFsm->anyFromStateActions() ) { out << " switch " << FSA() << "[" << vCS() << "] {" << endl; FROM_STATE_ACTION_SWITCH(1); out << " }" << endl << endl; } out << " switch " << vCS() << " {" << endl; STATE_GOTOS(1); out << " }" << endl << endl; TRANSITIONS() << endl; if ( redFsm->anyRegActions() ) EXEC_ACTIONS() << endl; out << "_again:" << endl; if ( redFsm->anyToStateActions() ) { out << " switch " << TSA() << "[" << vCS() << "] {" << endl; TO_STATE_ACTION_SWITCH(1); out << " }" << endl << endl; } if ( redFsm->errState != 0 ) { outLabelUsed = true; out << " if " << vCS() << " == " << redFsm->errState->id << " {" << endl << " goto _out" << endl << " }" << endl; } if ( !noEnd ) { out << " if " << P() << "++; " << P() << " != " << PE() << " {" << endl << " goto _resume" << endl << " }" << endl; } else { out << " " << P() << "++" << endl << " goto _resume" << endl; } if ( testEofUsed ) out << " _test_eof: {}" << endl; if ( redFsm->anyEofTrans() || redFsm->anyEofActions() ) { out << " if " << P() << " == " << vEOF() << " {" << endl; if ( redFsm->anyEofTrans() ) { out << " switch " << vCS() << " {" << endl; for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { if ( st->eofTrans != 0 ) out << " case " << st->id << ":" << endl << " goto tr" << st->eofTrans->id << endl; } out << " }" << endl; } if ( redFsm->anyEofActions() ) { out << " switch " << EA() << "[" << vCS() << "] {" << endl; EOF_ACTION_SWITCH(2); out << " }" << endl; } out << " }" << endl << endl; } if ( outLabelUsed ) out << " _out: {}" << endl; out << " }" << endl; } ragel-6.8/ragel/mlcodegen.h0000664000175000017500000001470712106050031012601 00000000000000/* * Copyright 2001-2006 Adrian Thurston * 2004 Erich Ocean * 2005 Alan West */ /* This file is part of Ragel. * * Ragel is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Ragel is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Ragel; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef _MLCODEGEN_H #define _MLCODEGEN_H #include #include #include #include "common.h" #include "gendata.h" using std::string; using std::ostream; /* Forwards. */ /* struct RedFsmAp; struct RedStateAp; struct CodeGenData; struct GenAction; struct NameInst; struct GenInlineItem; struct GenInlineList; struct RedAction; struct LongestMatch; struct LongestMatchPart; */ /* Integer array line length. */ #define IALL 8 //string itoa( int i ); /* * class OCamlCodeGen */ class OCamlCodeGen : public CodeGenData { public: OCamlCodeGen( ostream &out ); virtual ~OCamlCodeGen() {} virtual void finishRagelDef(); virtual void writeInit(); virtual void writeStart(); virtual void writeFirstFinal(); virtual void writeError(); protected: string data_prefix; string FSM_NAME(); string START_STATE_ID(); ostream &ACTIONS_ARRAY(); string GET_WIDE_KEY(); string GET_WIDE_KEY( RedStateAp *state ); string TABS( int level ); string KEY( Key key ); string ALPHA_KEY( Key key ); string LDIR_PATH( char *path ); void ACTION( ostream &ret, GenAction *action, int targState, bool inFinish ); void CONDITION( ostream &ret, GenAction *condition ); string ALPH_TYPE(); string WIDE_ALPH_TYPE(); string ARRAY_TYPE( unsigned long maxVal ); string ARRAY_TYPE( unsigned long maxVal, bool forceSigned ); virtual string ARR_OFF( string ptr, string offset ); virtual string CAST( string type ); virtual string UINT(); virtual string NULL_ITEM(); virtual string POINTER(); virtual string GET_KEY(); virtual ostream &SWITCH_DEFAULT(); string P(); string PE(); string vEOF(); // string ACCESS(); string vCS(); string STACK(); string TOP(); string TOKSTART(); string TOKEND(); string ACT(); // ++x string PRE_INCR(string); string PRE_DECR(string); // x++ string POST_INCR(string); string POST_DECR(string); string DATA_PREFIX(); string PM() { return "_" + DATA_PREFIX() + "partition_map"; } string C() { return "_" + DATA_PREFIX() + "cond_spaces"; } string CK() { return "_" + DATA_PREFIX() + "cond_keys"; } string K() { return "_" + DATA_PREFIX() + "trans_keys"; } string I() { return "_" + DATA_PREFIX() + "indicies"; } string CO() { return "_" + DATA_PREFIX() + "cond_offsets"; } string KO() { return "_" + DATA_PREFIX() + "key_offsets"; } string IO() { return "_" + DATA_PREFIX() + "index_offsets"; } string CL() { return "_" + DATA_PREFIX() + "cond_lengths"; } string SL() { return "_" + DATA_PREFIX() + "single_lengths"; } string RL() { return "_" + DATA_PREFIX() + "range_lengths"; } string A() { return "_" + DATA_PREFIX() + "actions"; } string TA() { return "_" + DATA_PREFIX() + "trans_actions"; } string TT() { return "_" + DATA_PREFIX() + "trans_targs"; } string TSA() { return "_" + DATA_PREFIX() + "to_state_actions"; } string FSA() { return "_" + DATA_PREFIX() + "from_state_actions"; } string EA() { return "_" + DATA_PREFIX() + "eof_actions"; } string ET() { return "_" + DATA_PREFIX() + "eof_trans"; } string SP() { return "_" + DATA_PREFIX() + "key_spans"; } string CSP() { return "_" + DATA_PREFIX() + "cond_key_spans"; } string START() { return DATA_PREFIX() + "start"; } string ERROR() { return DATA_PREFIX() + "error"; } string FIRST_FINAL() { return DATA_PREFIX() + "first_final"; } string CTXDATA() { return DATA_PREFIX() + "ctxdata"; } void INLINE_LIST( ostream &ret, GenInlineList *inlineList, int targState, bool inFinish ); virtual void GOTO( ostream &ret, int gotoDest, bool inFinish ) = 0; virtual void CALL( ostream &ret, int callDest, int targState, bool inFinish ) = 0; virtual void NEXT( ostream &ret, int nextDest, bool inFinish ) = 0; virtual void GOTO_EXPR( ostream &ret, GenInlineItem *ilItem, bool inFinish ) = 0; virtual void NEXT_EXPR( ostream &ret, GenInlineItem *ilItem, bool inFinish ) = 0; virtual void CALL_EXPR( ostream &ret, GenInlineItem *ilItem, int targState, bool inFinish ) = 0; virtual void RET( ostream &ret, bool inFinish ) = 0; virtual void BREAK( ostream &ret, int targState ) = 0; virtual void CURS( ostream &ret, bool inFinish ) = 0; virtual void TARGS( ostream &ret, bool inFinish, int targState ) = 0; void EXEC( ostream &ret, GenInlineItem *item, int targState, int inFinish ); void LM_SWITCH( ostream &ret, GenInlineItem *item, int targState, int inFinish ); void SET_ACT( ostream &ret, GenInlineItem *item ); void INIT_TOKSTART( ostream &ret, GenInlineItem *item ); void INIT_ACT( ostream &ret, GenInlineItem *item ); void SET_TOKSTART( ostream &ret, GenInlineItem *item ); void SET_TOKEND( ostream &ret, GenInlineItem *item ); void GET_TOKEND( ostream &ret, GenInlineItem *item ); void SUB_ACTION( ostream &ret, GenInlineItem *item, int targState, bool inFinish ); void STATE_IDS(); string ERROR_STATE(); string FIRST_FINAL_STATE(); virtual string PTR_CONST(); virtual ostream &OPEN_ARRAY( string type, string name ); virtual ostream &CLOSE_ARRAY(); virtual ostream &STATIC_VAR( string type, string name ); virtual string CTRL_FLOW(); // toplevel phrase separator string TOP_SEP(); // array elements separator string ARR_SEP(); // access array string AT(const string& array, const string& index); string make_access(char const* name, GenInlineList* x, bool prefix); ostream &source_warning(const InputLoc &loc); ostream &source_error(const InputLoc &loc); unsigned int arrayTypeSize( unsigned long maxVal ); bool outLabelUsed; bool testEofUsed; bool againLabelUsed; bool useIndicies; public: /* Determine if we should use indicies. */ virtual void calcIndexSize() {} void genLineDirective( ostream &out ); }; #define MAX(a, b) (a > b ? a : b) #endif ragel-6.8/ragel/csfflat.cpp0000664000175000017500000002123712106050031012615 00000000000000/* * Copyright 2004-2006 Adrian Thurston * 2004 Erich Ocean * 2005 Alan West */ /* This file is part of Ragel. * * Ragel is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Ragel is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Ragel; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "ragel.h" #include "csfflat.h" #include "redfsm.h" #include "gendata.h" std::ostream &CSharpFFlatCodeGen::TO_STATE_ACTION( RedStateAp *state ) { int act = 0; if ( state->toStateAction != 0 ) act = state->toStateAction->actListId+1; out << act; return out; } std::ostream &CSharpFFlatCodeGen::FROM_STATE_ACTION( RedStateAp *state ) { int act = 0; if ( state->fromStateAction != 0 ) act = state->fromStateAction->actListId+1; out << act; return out; } std::ostream &CSharpFFlatCodeGen::EOF_ACTION( RedStateAp *state ) { int act = 0; if ( state->eofAction != 0 ) act = state->eofAction->actListId+1; out << act; return out; } /* Write out the function for a transition. */ std::ostream &CSharpFFlatCodeGen::TRANS_ACTION( RedTransAp *trans ) { int action = 0; if ( trans->action != 0 ) action = trans->action->actListId+1; out << action; return out; } /* Write out the function switch. This switch is keyed on the values * of the func index. */ std::ostream &CSharpFFlatCodeGen::TO_STATE_ACTION_SWITCH() { /* Loop the actions. */ for ( GenActionTableMap::Iter redAct = redFsm->actionMap; redAct.lte(); redAct++ ) { if ( redAct->numToStateRefs > 0 ) { /* Write the entry label. */ out << "\tcase " << redAct->actListId+1 << ":\n"; /* Write each action in the list of action items. */ for ( GenActionTable::Iter item = redAct->key; item.lte(); item++ ) ACTION( out, item->value, 0, false ); out << "\tbreak;\n"; } } genLineDirective( out ); return out; } /* Write out the function switch. This switch is keyed on the values * of the func index. */ std::ostream &CSharpFFlatCodeGen::FROM_STATE_ACTION_SWITCH() { /* Loop the actions. */ for ( GenActionTableMap::Iter redAct = redFsm->actionMap; redAct.lte(); redAct++ ) { if ( redAct->numFromStateRefs > 0 ) { /* Write the entry label. */ out << "\tcase " << redAct->actListId+1 << ":\n"; /* Write each action in the list of action items. */ for ( GenActionTable::Iter item = redAct->key; item.lte(); item++ ) ACTION( out, item->value, 0, false ); out << "\tbreak;\n"; } } genLineDirective( out ); return out; } std::ostream &CSharpFFlatCodeGen::EOF_ACTION_SWITCH() { /* Loop the actions. */ for ( GenActionTableMap::Iter redAct = redFsm->actionMap; redAct.lte(); redAct++ ) { if ( redAct->numEofRefs > 0 ) { /* Write the entry label. */ out << "\tcase " << redAct->actListId+1 << ":\n"; /* Write each action in the list of action items. */ for ( GenActionTable::Iter item = redAct->key; item.lte(); item++ ) ACTION( out, item->value, 0, true ); out << "\tbreak;\n"; } } genLineDirective( out ); return out; } /* Write out the function switch. This switch is keyed on the values * of the func index. */ std::ostream &CSharpFFlatCodeGen::ACTION_SWITCH() { /* Loop the actions. */ for ( GenActionTableMap::Iter redAct = redFsm->actionMap; redAct.lte(); redAct++ ) { if ( redAct->numTransRefs > 0 ) { /* Write the entry label. */ out << "\tcase " << redAct->actListId+1 << ":\n"; /* Write each action in the list of action items. */ for ( GenActionTable::Iter item = redAct->key; item.lte(); item++ ) ACTION( out, item->value, 0, false ); out << "\tbreak;\n"; } } genLineDirective( out ); return out; } void CSharpFFlatCodeGen::writeData() { if ( redFsm->anyConditions() ) { OPEN_ARRAY( WIDE_ALPH_TYPE(), CK() ); COND_KEYS(); CLOSE_ARRAY() << "\n"; OPEN_ARRAY( ARRAY_TYPE(redFsm->maxCondSpan), CSP() ); COND_KEY_SPANS(); CLOSE_ARRAY() << "\n"; OPEN_ARRAY( ARRAY_TYPE(redFsm->maxCond), C() ); CONDS(); CLOSE_ARRAY() << "\n"; OPEN_ARRAY( ARRAY_TYPE(redFsm->maxCondIndexOffset), CO() ); COND_INDEX_OFFSET(); CLOSE_ARRAY() << "\n"; } OPEN_ARRAY( WIDE_ALPH_TYPE(), K() ); KEYS(); CLOSE_ARRAY() << "\n"; OPEN_ARRAY( ARRAY_TYPE(redFsm->maxSpan), SP() ); KEY_SPANS(); CLOSE_ARRAY() << "\n"; OPEN_ARRAY( ARRAY_TYPE(redFsm->maxFlatIndexOffset), IO() ); FLAT_INDEX_OFFSET(); CLOSE_ARRAY() << "\n"; OPEN_ARRAY( ARRAY_TYPE(redFsm->maxIndex), I() ); INDICIES(); CLOSE_ARRAY() << "\n"; OPEN_ARRAY( ARRAY_TYPE(redFsm->maxState), TT() ); TRANS_TARGS(); CLOSE_ARRAY() << "\n"; if ( redFsm->anyActions() ) { OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActListId), TA() ); TRANS_ACTIONS(); CLOSE_ARRAY() << "\n"; } if ( redFsm->anyToStateActions() ) { OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActionLoc), TSA() ); TO_STATE_ACTIONS(); CLOSE_ARRAY() << "\n"; } if ( redFsm->anyFromStateActions() ) { OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActionLoc), FSA() ); FROM_STATE_ACTIONS(); CLOSE_ARRAY() << "\n"; } if ( redFsm->anyEofActions() ) { OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActListId), EA() ); EOF_ACTIONS(); CLOSE_ARRAY() << "\n"; } if ( redFsm->anyEofTrans() ) { OPEN_ARRAY( ARRAY_TYPE(redFsm->maxIndexOffset+1), ET() ); EOF_TRANS(); CLOSE_ARRAY() << "\n"; } STATE_IDS(); } void CSharpFFlatCodeGen::writeExec() { testEofUsed = false; outLabelUsed = false; initVarTypes(); out << " {\n" " " << slenType << " _slen"; if ( redFsm->anyRegCurStateRef() ) out << ", _ps"; out << ";\n"; out << " " << transType << " _trans"; if ( redFsm->anyConditions() ) out << ", _cond"; out << ";\n"; out << " " << "int _keys;\n" " " << indsType << " _inds;\n"; /* " " << PTR_CONST() << WIDE_ALPH_TYPE() << POINTER() << "_keys;\n" " " << PTR_CONST() << ARRAY_TYPE(redFsm->maxIndex) << POINTER() << "_inds;\n";*/ if ( redFsm->anyConditions() ) { out << " " << condsType << " _conds;\n" " " << WIDE_ALPH_TYPE() << " _widec;\n"; } if ( !noEnd ) { testEofUsed = true; out << " if ( " << P() << " == " << PE() << " )\n" " goto _test_eof;\n"; } if ( redFsm->errState != 0 ) { outLabelUsed = true; out << " if ( " << vCS() << " == " << redFsm->errState->id << " )\n" " goto _out;\n"; } out << "_resume:\n"; if ( redFsm->anyFromStateActions() ) { out << " switch ( " << FSA() << "[" << vCS() << "] ) {\n"; FROM_STATE_ACTION_SWITCH(); SWITCH_DEFAULT() << " }\n" "\n"; } if ( redFsm->anyConditions() ) COND_TRANSLATE(); LOCATE_TRANS(); if ( redFsm->anyEofTrans() ) out << "_eof_trans:\n"; if ( redFsm->anyRegCurStateRef() ) out << " _ps = " << vCS() << ";\n"; out << " " << vCS() << " = " << TT() << "[_trans];\n\n"; if ( redFsm->anyRegActions() ) { out << " if ( " << TA() << "[_trans] == 0 )\n" " goto _again;\n" "\n" " switch ( " << TA() << "[_trans] ) {\n"; ACTION_SWITCH(); SWITCH_DEFAULT() << " }\n" "\n"; } if ( redFsm->anyRegActions() || redFsm->anyActionGotos() || redFsm->anyActionCalls() || redFsm->anyActionRets() ) out << "_again:\n"; if ( redFsm->anyToStateActions() ) { out << " switch ( " << TSA() << "[" << vCS() << "] ) {\n"; TO_STATE_ACTION_SWITCH(); SWITCH_DEFAULT() << " }\n" "\n"; } if ( redFsm->errState != 0 ) { outLabelUsed = true; out << " if ( " << vCS() << " == " << redFsm->errState->id << " )\n" " goto _out;\n"; } if ( !noEnd ) { out << " if ( ++" << P() << " != " << PE() << " )\n" " goto _resume;\n"; } else { out << " " << P() << " += 1;\n" " goto _resume;\n"; } if ( testEofUsed ) out << " _test_eof: {}\n"; if ( redFsm->anyEofTrans() || redFsm->anyEofActions() ) { out << " if ( " << P() << " == " << vEOF() << " )\n" " {\n"; if ( redFsm->anyEofTrans() ) { out << " if ( " << ET() << "[" << vCS() << "] > 0 ) {\n" " _trans = " << CAST(transType) << " (" << ET() << "[" << vCS() << "] - 1);\n" " goto _eof_trans;\n" " }\n"; } if ( redFsm->anyEofActions() ) { out << " switch ( " << EA() << "[" << vCS() << "] ) {\n"; EOF_ACTION_SWITCH(); SWITCH_DEFAULT() << " }\n"; } out << " }\n" "\n"; } if ( outLabelUsed ) out << " _out: {}\n"; out << " }\n"; } ragel-6.8/ragel/rubyfflat.h0000664000175000017500000000370212106050031012633 00000000000000/* * 2007 Victor Hugo Borja * Copyright 2001-2007 Adrian Thurston */ /* This file is part of Ragel. * * Ragel is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Ragel is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Ragel; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef _RUBY_FFLATCODEGEN_H #define _RUBY_FFLATCODEGEN_H #include #include "rubyflat.h" class RubyFFlatCodeGen : public RubyFlatCodeGen { public: RubyFFlatCodeGen( ostream &out ) : RubyFlatCodeGen(out) {} protected: std::ostream &TO_STATE_ACTION_SWITCH(); std::ostream &FROM_STATE_ACTION_SWITCH(); std::ostream &EOF_ACTION_SWITCH(); std::ostream &ACTION_SWITCH(); void GOTO( ostream &out, int gotoDest, bool inFinish ); void GOTO_EXPR( ostream &out, GenInlineItem *ilItem, bool inFinish ); void CALL( ostream &out, int callDest, int targState, bool inFinish ); void CALL_EXPR(ostream &out, GenInlineItem *ilItem, int targState, bool inFinish ); void RET( ostream &out, bool inFinish ); void BREAK( ostream &out, int targState ); virtual int TO_STATE_ACTION( RedStateAp *state ); virtual int FROM_STATE_ACTION( RedStateAp *state ); virtual int EOF_ACTION( RedStateAp *state ); virtual int TRANS_ACTION( RedTransAp *trans ); virtual void writeData(); virtual void writeExec(); }; /* * Local Variables: * mode: c++ * indent-tabs-mode: 1 * c-file-style: "bsd" * End: */ #endif ragel-6.8/ragel/csgoto.cpp0000664000175000017500000005275012106050031012475 00000000000000/* * Copyright 2001-2006 Adrian Thurston * 2004 Erich Ocean * 2005 Alan West */ /* This file is part of Ragel. * * Ragel is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Ragel is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Ragel; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "ragel.h" #include "csgoto.h" #include "redfsm.h" #include "bstmap.h" #include "gendata.h" /* Emit the goto to take for a given transition. */ std::ostream &CSharpGotoCodeGen::TRANS_GOTO( RedTransAp *trans, int level ) { out << TABS(level) << "goto tr" << trans->id << ";"; return out; } std::ostream &CSharpGotoCodeGen::TO_STATE_ACTION_SWITCH() { /* Walk the list of functions, printing the cases. */ for ( GenActionList::Iter act = actionList; act.lte(); act++ ) { /* Write out referenced actions. */ if ( act->numToStateRefs > 0 ) { /* Write the case label, the action and the case break. */ out << "\tcase " << act->actionId << ":\n"; ACTION( out, act, 0, false ); out << "\tbreak;\n"; } } genLineDirective( out ); return out; } std::ostream &CSharpGotoCodeGen::FROM_STATE_ACTION_SWITCH() { /* Walk the list of functions, printing the cases. */ for ( GenActionList::Iter act = actionList; act.lte(); act++ ) { /* Write out referenced actions. */ if ( act->numFromStateRefs > 0 ) { /* Write the case label, the action and the case break. */ out << "\tcase " << act->actionId << ":\n"; ACTION( out, act, 0, false ); out << "\tbreak;\n"; } } genLineDirective( out ); return out; } std::ostream &CSharpGotoCodeGen::EOF_ACTION_SWITCH() { /* Walk the list of functions, printing the cases. */ for ( GenActionList::Iter act = actionList; act.lte(); act++ ) { /* Write out referenced actions. */ if ( act->numEofRefs > 0 ) { /* Write the case label, the action and the case break. */ out << "\tcase " << act->actionId << ":\n"; ACTION( out, act, 0, true ); out << "\tbreak;\n"; } } genLineDirective( out ); return out; } std::ostream &CSharpGotoCodeGen::ACTION_SWITCH() { /* Walk the list of functions, printing the cases. */ for ( GenActionList::Iter act = actionList; act.lte(); act++ ) { /* Write out referenced actions. */ if ( act->numTransRefs > 0 ) { /* Write the case label, the action and the case break. */ out << "\tcase " << act->actionId << ":\n"; ACTION( out, act, 0, false ); out << "\tbreak;\n"; } } genLineDirective( out ); return out; } void CSharpGotoCodeGen::GOTO_HEADER( RedStateAp *state ) { /* Label the state. */ out << "case " << state->id << ":\n"; } void CSharpGotoCodeGen::emitSingleSwitch( RedStateAp *state ) { /* Load up the singles. */ int numSingles = state->outSingle.length(); RedTransEl *data = state->outSingle.data; if ( numSingles == 1 ) { /* If there is a single single key then write it out as an if. */ out << "\tif ( " << GET_WIDE_KEY(state) << " == " << KEY(data[0].lowKey) << " )\n\t\t"; /* Virtual function for writing the target of the transition. */ TRANS_GOTO(data[0].value, 0) << "\n"; } else if ( numSingles > 1 ) { /* Write out single keys in a switch if there is more than one. */ out << "\tswitch( " << GET_WIDE_KEY(state) << " ) {\n"; /* Write out the single indicies. */ for ( int j = 0; j < numSingles; j++ ) { out << "\t\tcase " << ALPHA_KEY(data[j].lowKey) << ": "; TRANS_GOTO(data[j].value, 0) << "\n"; } /* Emits a default case for D code. */ SWITCH_DEFAULT(); /* Close off the transition switch. */ out << "\t}\n"; } } void CSharpGotoCodeGen::emitRangeBSearch( RedStateAp *state, int level, int low, int high ) { /* Get the mid position, staying on the lower end of the range. */ int mid = (low + high) >> 1; RedTransEl *data = state->outRange.data; /* Determine if we need to look higher or lower. */ bool anyLower = mid > low; bool anyHigher = mid < high; /* Determine if the keys at mid are the limits of the alphabet. */ bool limitLow = data[mid].lowKey == keyOps->minKey; bool limitHigh = data[mid].highKey == keyOps->maxKey; if ( anyLower && anyHigher ) { /* Can go lower and higher than mid. */ out << TABS(level) << "if ( " << GET_WIDE_KEY(state) << " < " << KEY(data[mid].lowKey) << " ) {\n"; emitRangeBSearch( state, level+1, low, mid-1 ); out << TABS(level) << "} else if ( " << GET_WIDE_KEY(state) << " > " << KEY(data[mid].highKey) << " ) {\n"; emitRangeBSearch( state, level+1, mid+1, high ); out << TABS(level) << "} else\n"; TRANS_GOTO(data[mid].value, level+1) << "\n"; } else if ( anyLower && !anyHigher ) { /* Can go lower than mid but not higher. */ out << TABS(level) << "if ( " << GET_WIDE_KEY(state) << " < " << KEY(data[mid].lowKey) << " ) {\n"; emitRangeBSearch( state, level+1, low, mid-1 ); /* if the higher is the highest in the alphabet then there is no * sense testing it. */ if ( limitHigh ) { out << TABS(level) << "} else\n"; TRANS_GOTO(data[mid].value, level+1) << "\n"; } else { out << TABS(level) << "} else if ( " << GET_WIDE_KEY(state) << " <= " << KEY(data[mid].highKey) << " )\n"; TRANS_GOTO(data[mid].value, level+1) << "\n"; } } else if ( !anyLower && anyHigher ) { /* Can go higher than mid but not lower. */ out << TABS(level) << "if ( " << GET_WIDE_KEY(state) << " > " << KEY(data[mid].highKey) << " ) {\n"; emitRangeBSearch( state, level+1, mid+1, high ); /* If the lower end is the lowest in the alphabet then there is no * sense testing it. */ if ( limitLow ) { out << TABS(level) << "} else\n"; TRANS_GOTO(data[mid].value, level+1) << "\n"; } else { out << TABS(level) << "} else if ( " << GET_WIDE_KEY(state) << " >= " << KEY(data[mid].lowKey) << " )\n"; TRANS_GOTO(data[mid].value, level+1) << "\n"; } } else { /* Cannot go higher or lower than mid. It's mid or bust. What * tests to do depends on limits of alphabet. */ if ( !limitLow && !limitHigh ) { out << TABS(level) << "if ( " << KEY(data[mid].lowKey) << " <= " << GET_WIDE_KEY(state) << " && " << GET_WIDE_KEY(state) << " <= " << KEY(data[mid].highKey) << " )\n"; TRANS_GOTO(data[mid].value, level+1) << "\n"; } else if ( limitLow && !limitHigh ) { out << TABS(level) << "if ( " << GET_WIDE_KEY(state) << " <= " << KEY(data[mid].highKey) << " )\n"; TRANS_GOTO(data[mid].value, level+1) << "\n"; } else if ( !limitLow && limitHigh ) { out << TABS(level) << "if ( " << KEY(data[mid].lowKey) << " <= " << GET_WIDE_KEY(state) << " )\n"; TRANS_GOTO(data[mid].value, level+1) << "\n"; } else { /* Both high and low are at the limit. No tests to do. */ TRANS_GOTO(data[mid].value, level+1) << "\n"; } } } void CSharpGotoCodeGen::STATE_GOTO_ERROR() { /* Label the state and bail immediately. */ outLabelUsed = true; RedStateAp *state = redFsm->errState; out << "case " << state->id << ":\n"; out << " goto _out;\n"; } void CSharpGotoCodeGen::COND_TRANSLATE( GenStateCond *stateCond, int level ) { GenCondSpace *condSpace = stateCond->condSpace; out << TABS(level) << "_widec = " << CAST(WIDE_ALPH_TYPE()) << "(" << KEY(condSpace->baseKey) << " + (" << GET_KEY() << " - " << KEY(keyOps->minKey) << "));\n"; for ( GenCondSet::Iter csi = condSpace->condSet; csi.lte(); csi++ ) { out << TABS(level) << "if ( "; CONDITION( out, *csi ); Size condValOffset = ((1 << csi.pos()) * keyOps->alphSize()); out << " ) _widec += " << condValOffset << ";\n"; } } void CSharpGotoCodeGen::emitCondBSearch( RedStateAp *state, int level, int low, int high ) { /* Get the mid position, staying on the lower end of the range. */ int mid = (low + high) >> 1; GenStateCond **data = state->stateCondVect.data; /* Determine if we need to look higher or lower. */ bool anyLower = mid > low; bool anyHigher = mid < high; /* Determine if the keys at mid are the limits of the alphabet. */ bool limitLow = data[mid]->lowKey == keyOps->minKey; bool limitHigh = data[mid]->highKey == keyOps->maxKey; if ( anyLower && anyHigher ) { /* Can go lower and higher than mid. */ out << TABS(level) << "if ( " << GET_KEY() << " < " << KEY(data[mid]->lowKey) << " ) {\n"; emitCondBSearch( state, level+1, low, mid-1 ); out << TABS(level) << "} else if ( " << GET_KEY() << " > " << KEY(data[mid]->highKey) << " ) {\n"; emitCondBSearch( state, level+1, mid+1, high ); out << TABS(level) << "} else {\n"; COND_TRANSLATE(data[mid], level+1); out << TABS(level) << "}\n"; } else if ( anyLower && !anyHigher ) { /* Can go lower than mid but not higher. */ out << TABS(level) << "if ( " << GET_KEY() << " < " << KEY(data[mid]->lowKey) << " ) {\n"; emitCondBSearch( state, level+1, low, mid-1 ); /* if the higher is the highest in the alphabet then there is no * sense testing it. */ if ( limitHigh ) { out << TABS(level) << "} else {\n"; COND_TRANSLATE(data[mid], level+1); out << TABS(level) << "}\n"; } else { out << TABS(level) << "} else if ( " << GET_KEY() << " <= " << KEY(data[mid]->highKey) << " ) {\n"; COND_TRANSLATE(data[mid], level+1); out << TABS(level) << "}\n"; } } else if ( !anyLower && anyHigher ) { /* Can go higher than mid but not lower. */ out << TABS(level) << "if ( " << GET_KEY() << " > " << KEY(data[mid]->highKey) << " ) {\n"; emitCondBSearch( state, level+1, mid+1, high ); /* If the lower end is the lowest in the alphabet then there is no * sense testing it. */ if ( limitLow ) { out << TABS(level) << "} else {\n"; COND_TRANSLATE(data[mid], level+1); out << TABS(level) << "}\n"; } else { out << TABS(level) << "} else if ( " << GET_KEY() << " >= " << KEY(data[mid]->lowKey) << " ) {\n"; COND_TRANSLATE(data[mid], level+1); out << TABS(level) << "}\n"; } } else { /* Cannot go higher or lower than mid. It's mid or bust. What * tests to do depends on limits of alphabet. */ if ( !limitLow && !limitHigh ) { out << TABS(level) << "if ( " << KEY(data[mid]->lowKey) << " <= " << GET_KEY() << " && " << GET_KEY() << " <= " << KEY(data[mid]->highKey) << " ) {\n"; COND_TRANSLATE(data[mid], level+1); out << TABS(level) << "}\n"; } else if ( limitLow && !limitHigh ) { out << TABS(level) << "if ( " << GET_KEY() << " <= " << KEY(data[mid]->highKey) << " ) {\n"; COND_TRANSLATE(data[mid], level+1); out << TABS(level) << "}\n"; } else if ( !limitLow && limitHigh ) { out << TABS(level) << "if ( " << KEY(data[mid]->lowKey) << " <= " << GET_KEY() << " )\n {"; COND_TRANSLATE(data[mid], level+1); out << TABS(level) << "}\n"; } else { /* Both high and low are at the limit. No tests to do. */ COND_TRANSLATE(data[mid], level); } } } std::ostream &CSharpGotoCodeGen::STATE_GOTOS() { for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { if ( st == redFsm->errState ) STATE_GOTO_ERROR(); else { /* Writing code above state gotos. */ GOTO_HEADER( st ); if ( st->stateCondVect.length() > 0 ) { out << " _widec = " << GET_KEY() << ";\n"; emitCondBSearch( st, 1, 0, st->stateCondVect.length() - 1 ); } /* Try singles. */ if ( st->outSingle.length() > 0 ) emitSingleSwitch( st ); /* Default case is to binary search for the ranges, if that fails then */ if ( st->outRange.length() > 0 ) emitRangeBSearch( st, 1, 0, st->outRange.length() - 1 ); /* Write the default transition. */ TRANS_GOTO( st->defTrans, 1 ) << "\n"; } } return out; } std::ostream &CSharpGotoCodeGen::TRANSITIONS() { /* Emit any transitions that have functions and that go to * this state. */ for ( TransApSet::Iter trans = redFsm->transSet; trans.lte(); trans++ ) { /* Write the label for the transition so it can be jumped to. */ out << " tr" << trans->id << ": "; /* Destination state. */ if ( trans->action != 0 && trans->action->anyCurStateRef() ) out << "_ps = " << vCS() << ";"; out << vCS() << " = " << trans->targ->id << "; "; if ( trans->action != 0 ) { /* Write out the transition func. */ out << "goto f" << trans->action->actListId << ";\n"; } else { /* No code to execute, just loop around. */ out << "goto _again;\n"; } } return out; } std::ostream &CSharpGotoCodeGen::EXEC_FUNCS() { /* Make labels that set acts and jump to execFuncs. Loop func indicies. */ for ( GenActionTableMap::Iter redAct = redFsm->actionMap; redAct.lte(); redAct++ ) { if ( redAct->numTransRefs > 0 ) { out << " f" << redAct->actListId << ": " << "_acts = " << itoa( redAct->location+1 ) << ";" " goto execFuncs;\n"; } } out << "\n" "execFuncs:\n" " _nacts = " << A() << "[_acts++];\n" " while ( _nacts-- > 0 ) {\n" " switch ( " << A() << "[_acts++] ) {\n"; ACTION_SWITCH(); SWITCH_DEFAULT() << " }\n" " }\n" " goto _again;\n"; return out; } unsigned int CSharpGotoCodeGen::TO_STATE_ACTION( RedStateAp *state ) { int act = 0; if ( state->toStateAction != 0 ) act = state->toStateAction->location+1; return act; } unsigned int CSharpGotoCodeGen::FROM_STATE_ACTION( RedStateAp *state ) { int act = 0; if ( state->fromStateAction != 0 ) act = state->fromStateAction->location+1; return act; } unsigned int CSharpGotoCodeGen::EOF_ACTION( RedStateAp *state ) { int act = 0; if ( state->eofAction != 0 ) act = state->eofAction->location+1; return act; } std::ostream &CSharpGotoCodeGen::TO_STATE_ACTIONS() { /* Take one off for the psuedo start state. */ int numStates = redFsm->stateList.length(); unsigned int *vals = new unsigned int[numStates]; memset( vals, 0, sizeof(unsigned int)*numStates ); for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) vals[st->id] = TO_STATE_ACTION(st); out << "\t"; for ( int st = 0; st < redFsm->nextStateId; st++ ) { /* Write any eof action. */ out << vals[st]; if ( st < numStates-1 ) { out << ", "; if ( (st+1) % IALL == 0 ) out << "\n\t"; } } out << "\n"; delete[] vals; return out; } std::ostream &CSharpGotoCodeGen::FROM_STATE_ACTIONS() { /* Take one off for the psuedo start state. */ int numStates = redFsm->stateList.length(); unsigned int *vals = new unsigned int[numStates]; memset( vals, 0, sizeof(unsigned int)*numStates ); for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) vals[st->id] = FROM_STATE_ACTION(st); out << "\t"; for ( int st = 0; st < redFsm->nextStateId; st++ ) { /* Write any eof action. */ out << vals[st]; if ( st < numStates-1 ) { out << ", "; if ( (st+1) % IALL == 0 ) out << "\n\t"; } } out << "\n"; delete[] vals; return out; } std::ostream &CSharpGotoCodeGen::EOF_ACTIONS() { /* Take one off for the psuedo start state. */ int numStates = redFsm->stateList.length(); unsigned int *vals = new unsigned int[numStates]; memset( vals, 0, sizeof(unsigned int)*numStates ); for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) vals[st->id] = EOF_ACTION(st); out << "\t"; for ( int st = 0; st < redFsm->nextStateId; st++ ) { /* Write any eof action. */ out << vals[st]; if ( st < numStates-1 ) { out << ", "; if ( (st+1) % IALL == 0 ) out << "\n\t"; } } out << "\n"; delete[] vals; return out; } std::ostream &CSharpGotoCodeGen::FINISH_CASES() { for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { /* States that are final and have an out action need a case. */ if ( st->eofAction != 0 ) { /* Write the case label. */ out << "\t\tcase " << st->id << ": "; /* Write the goto func. */ out << "goto f" << st->eofAction->actListId << ";\n"; } } return out; } void CSharpGotoCodeGen::GOTO( ostream &ret, int gotoDest, bool inFinish ) { ret << "{" << vCS() << " = " << gotoDest << "; " << CTRL_FLOW() << "goto _again;}"; } void CSharpGotoCodeGen::GOTO_EXPR( ostream &ret, GenInlineItem *ilItem, bool inFinish ) { ret << "{" << vCS() << " = ("; INLINE_LIST( ret, ilItem->children, 0, inFinish ); ret << "); " << CTRL_FLOW() << "goto _again;}"; } void CSharpGotoCodeGen::CURS( ostream &ret, bool inFinish ) { ret << "(_ps)"; } void CSharpGotoCodeGen::TARGS( ostream &ret, bool inFinish, int targState ) { ret << "(" << vCS() << ")"; } void CSharpGotoCodeGen::NEXT( ostream &ret, int nextDest, bool inFinish ) { ret << vCS() << " = " << nextDest << ";"; } void CSharpGotoCodeGen::NEXT_EXPR( ostream &ret, GenInlineItem *ilItem, bool inFinish ) { ret << vCS() << " = ("; INLINE_LIST( ret, ilItem->children, 0, inFinish ); ret << ");"; } void CSharpGotoCodeGen::CALL( ostream &ret, int callDest, int targState, bool inFinish ) { if ( prePushExpr != 0 ) { ret << "{"; INLINE_LIST( ret, prePushExpr, 0, false ); } ret << "{" << STACK() << "[" << TOP() << "++] = " << vCS() << "; " << vCS() << " = " << callDest << "; " << CTRL_FLOW() << "goto _again;}"; if ( prePushExpr != 0 ) ret << "}"; } void CSharpGotoCodeGen::CALL_EXPR( ostream &ret, GenInlineItem *ilItem, int targState, bool inFinish ) { if ( prePushExpr != 0 ) { ret << "{"; INLINE_LIST( ret, prePushExpr, 0, false ); } ret << "{" << STACK() << "[" << TOP() << "++] = " << vCS() << "; " << vCS() << " = ("; INLINE_LIST( ret, ilItem->children, targState, inFinish ); ret << "); " << CTRL_FLOW() << "goto _again;}"; if ( prePushExpr != 0 ) ret << "}"; } void CSharpGotoCodeGen::RET( ostream &ret, bool inFinish ) { ret << "{" << vCS() << " = " << STACK() << "[--" << TOP() << "];"; if ( postPopExpr != 0 ) { ret << "{"; INLINE_LIST( ret, postPopExpr, 0, false ); ret << "}"; } ret << CTRL_FLOW() << "goto _again;}"; } void CSharpGotoCodeGen::BREAK( ostream &ret, int targState ) { outLabelUsed = true; ret << "{" << P() << "++; " << CTRL_FLOW() << "goto _out; }"; } void CSharpGotoCodeGen::writeData() { if ( redFsm->anyActions() ) { OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActArrItem), A() ); ACTIONS_ARRAY(); CLOSE_ARRAY() << "\n"; } if ( redFsm->anyToStateActions() ) { OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActionLoc), TSA() ); TO_STATE_ACTIONS(); CLOSE_ARRAY() << "\n"; } if ( redFsm->anyFromStateActions() ) { OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActionLoc), FSA() ); FROM_STATE_ACTIONS(); CLOSE_ARRAY() << "\n"; } if ( redFsm->anyEofActions() ) { OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActionLoc), EA() ); EOF_ACTIONS(); CLOSE_ARRAY() << "\n"; } STATE_IDS(); } void CSharpGotoCodeGen::writeExec() { testEofUsed = false; outLabelUsed = false; out << " {\n"; if ( redFsm->anyRegCurStateRef() ) out << " int _ps = 0;\n"; if ( redFsm->anyToStateActions() || redFsm->anyRegActions() || redFsm->anyFromStateActions() ) { out << " " << ARRAY_TYPE(redFsm->maxActionLoc) << " _acts;\n" " " << ARRAY_TYPE(redFsm->maxActArrItem) << " _nacts;\n"; } if ( redFsm->anyConditions() ) out << " " << WIDE_ALPH_TYPE() << " _widec;\n"; out << "\n"; if ( !noEnd ) { testEofUsed = true; out << " if ( " << P() << " == " << PE() << " )\n" " goto _test_eof;\n"; } if ( redFsm->errState != 0 ) { outLabelUsed = true; out << " if ( " << vCS() << " == " << redFsm->errState->id << " )\n" " goto _out;\n"; } out << "_resume:\n"; if ( redFsm->anyFromStateActions() ) { out << " _acts = " << FSA() << "[" << vCS() << "];\n" " _nacts = " << A() << "[_acts++];\n" " while ( _nacts-- > 0 ) {\n" " switch ( " << A() << "[_acts++] ) {\n"; FROM_STATE_ACTION_SWITCH(); SWITCH_DEFAULT() << " }\n" " }\n" "\n"; } out << " switch ( " << vCS() << " ) {\n"; STATE_GOTOS(); SWITCH_DEFAULT() << " }\n" "\n"; TRANSITIONS() << "\n"; if ( redFsm->anyRegActions() ) EXEC_FUNCS() << "\n"; out << "_again:\n"; if ( redFsm->anyToStateActions() ) { out << " _acts = " << TSA() << "[" << vCS() << "];\n" " _nacts = " << A() << "[_acts++];\n" " while ( _nacts-- > 0 ) {\n" " switch ( " << A() << "[_acts++] ) {\n"; TO_STATE_ACTION_SWITCH(); SWITCH_DEFAULT() << " }\n" " }\n" "\n"; } if ( redFsm->errState != 0 ) { outLabelUsed = true; out << " if ( " << vCS() << " == " << redFsm->errState->id << " )\n" " goto _out;\n"; } if ( !noEnd ) { out << " if ( ++" << P() << " != " << PE() << " )\n" " goto _resume;\n"; } else { out << " " << P() << " += 1;\n" " goto _resume;\n"; } if ( testEofUsed ) out << " _test_eof: {}\n"; if ( redFsm->anyEofTrans() || redFsm->anyEofActions() ) { out << " if ( " << P() << " == " << vEOF() << " )\n" " {\n"; if ( redFsm->anyEofTrans() ) { out << " switch ( " << vCS() << " ) {\n"; for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { if ( st->eofTrans != 0 ) out << " case " << st->id << ": goto tr" << st->eofTrans->id << ";\n"; } SWITCH_DEFAULT() << " }\n"; } if ( redFsm->anyEofActions() ) { out << " " << ARRAY_TYPE(redFsm->maxActionLoc) << " __acts = " << EA() << "[" << vCS() << "];\n" " " << ARRAY_TYPE(redFsm->maxActArrItem) << " __nacts = " << A() << "[__acts++];\n" " while ( __nacts-- > 0 ) {\n" " switch ( " << A() << "[__acts++] ) {\n"; EOF_ACTION_SWITCH(); SWITCH_DEFAULT() << " }\n" " }\n"; } out << " }\n" "\n"; } if ( outLabelUsed ) out << " _out: {}\n"; out << " }\n"; } ragel-6.8/ragel/rlparse.cpp0000664000175000017500000065502012106307076012664 00000000000000/* Automatically generated by Kelbt from "rlparse.kl". * * Parts of this file are copied from Kelbt source covered by the GNU * GPL. As a special exception, you may use the parts of this file copied * from Kelbt source without restriction. The remainder is derived from * "rlparse.kl" and inherits the copyright status of that file. */ #line 1 "rlparse.kl" /* * Copyright 2001-2007 Adrian Thurston */ /* This file is part of Ragel. * * Ragel is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Ragel is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Ragel; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "rlparse.h" #include "ragel.h" #include #include #include using std::cout; using std::cerr; using std::endl; #line 102 "rlparse.kh" #line 105 "rlparse.kh" #line 140 "rlparse.kh" #line 1444 "rlparse.kl" #line 48 "rlparse.cpp" struct Parser_Lel_action_ref { #line 755 "rlparse.kl" Action *action; #line 54 "rlparse.cpp" }; struct Parser_Lel_aug_type { #line 546 "rlparse.kl" InputLoc loc; AugType augType; #line 65 "rlparse.cpp" }; struct Parser_Lel_expression { #line 338 "rlparse.kl" Expression *expression; #line 75 "rlparse.cpp" }; struct Parser_Lel_factor { #line 975 "rlparse.kl" Factor *factor; #line 85 "rlparse.cpp" }; struct Parser_Lel_factor_rep_num { #line 929 "rlparse.kl" int rep; #line 95 "rlparse.cpp" }; struct Parser_Lel_factor_with_aug { #line 452 "rlparse.kl" FactorWithAug *factorWithAug; #line 105 "rlparse.cpp" }; struct Parser_Lel_factor_with_ep { #line 436 "rlparse.kl" FactorWithAug *factorWithAug; #line 115 "rlparse.cpp" }; struct Parser_Lel_factor_with_label { #line 420 "rlparse.kl" FactorWithAug *factorWithAug; #line 125 "rlparse.cpp" }; struct Parser_Lel_factor_with_neg { #line 939 "rlparse.kl" FactorWithNeg *factorWithNeg; #line 135 "rlparse.cpp" }; struct Parser_Lel_factor_with_rep { #line 868 "rlparse.kl" FactorWithRep *factorWithRep; #line 145 "rlparse.cpp" }; struct Parser_Lel_inline_item { #line 1234 "rlparse.kl" InlineItem *inlineItem; #line 155 "rlparse.cpp" }; struct Parser_Lel_inline_list { #line 1213 "rlparse.kl" InlineList *inlineList; #line 165 "rlparse.cpp" }; struct Parser_Lel_join { #line 321 "rlparse.kl" Join *join; #line 175 "rlparse.cpp" }; struct Parser_Lel_join_or_lm { #line 229 "rlparse.kl" MachineDef *machineDef; #line 185 "rlparse.cpp" }; struct Parser_Lel_lm_part_list { #line 253 "rlparse.kl" LmPartList *lmPartList; #line 195 "rlparse.cpp" }; struct Parser_Lel_local_err_name { #line 856 "rlparse.kl" int error_name; #line 205 "rlparse.cpp" }; struct Parser_Lel_longest_match_part { #line 277 "rlparse.kl" LongestMatchPart *lmPart; #line 215 "rlparse.cpp" }; struct Parser_Lel_opt_export { #line 95 "rlparse.kl" bool isSet; #line 225 "rlparse.cpp" }; struct Parser_Lel_opt_lm_part_action { #line 294 "rlparse.kl" Action *action; #line 235 "rlparse.cpp" }; struct Parser_Lel_priority_aug { #line 803 "rlparse.kl" int priorityNum; #line 245 "rlparse.cpp" }; struct Parser_Lel_priority_name { #line 788 "rlparse.kl" int priorityName; #line 255 "rlparse.cpp" }; struct Parser_Lel_range_lit { #line 1042 "rlparse.kl" Literal *literal; #line 265 "rlparse.cpp" }; struct Parser_Lel_regular_expr { #line 1079 "rlparse.kl" RegExpr *regExpr; #line 275 "rlparse.cpp" }; struct Parser_Lel_regular_expr_char { #line 1131 "rlparse.kl" ReItem *reItem; #line 285 "rlparse.cpp" }; struct Parser_Lel_regular_expr_item { #line 1114 "rlparse.kl" ReItem *reItem; #line 295 "rlparse.cpp" }; struct Parser_Lel_regular_expr_or_char { #line 1188 "rlparse.kl" ReOrItem *reOrItem; #line 305 "rlparse.cpp" }; struct Parser_Lel_regular_expr_or_data { #line 1155 "rlparse.kl" ReOrBlock *reOrBlock; #line 315 "rlparse.cpp" }; struct Parser_Lel_term { #line 389 "rlparse.kl" Term *term; #line 325 "rlparse.cpp" }; struct Parser_Lel_term_short { #line 368 "rlparse.kl" Term *term; #line 335 "rlparse.cpp" }; struct Parser_Lel_token_type { #line 146 "rlparse.kl" Token token; #line 345 "rlparse.cpp" }; union Parser_UserData { struct Parser_Lel_action_ref action_ref; struct Parser_Lel_aug_type aug_type; struct Parser_Lel_expression expression; struct Parser_Lel_factor factor; struct Parser_Lel_factor_rep_num factor_rep_num; struct Parser_Lel_factor_with_aug factor_with_aug; struct Parser_Lel_factor_with_ep factor_with_ep; struct Parser_Lel_factor_with_label factor_with_label; struct Parser_Lel_factor_with_neg factor_with_neg; struct Parser_Lel_factor_with_rep factor_with_rep; struct Parser_Lel_inline_item inline_item; struct Parser_Lel_inline_list inline_list; struct Parser_Lel_join join; struct Parser_Lel_join_or_lm join_or_lm; struct Parser_Lel_lm_part_list lm_part_list; struct Parser_Lel_local_err_name local_err_name; struct Parser_Lel_longest_match_part longest_match_part; struct Parser_Lel_opt_export opt_export; struct Parser_Lel_opt_lm_part_action opt_lm_part_action; struct Parser_Lel_priority_aug priority_aug; struct Parser_Lel_priority_name priority_name; struct Parser_Lel_range_lit range_lit; struct Parser_Lel_regular_expr regular_expr; struct Parser_Lel_regular_expr_char regular_expr_char; struct Parser_Lel_regular_expr_item regular_expr_item; struct Parser_Lel_regular_expr_or_char regular_expr_or_char; struct Parser_Lel_regular_expr_or_data regular_expr_or_data; struct Parser_Lel_term term; struct Parser_Lel_term_short term_short; struct Parser_Lel_token_type token_type; struct Token token; }; struct Parser_LangEl { char *file; int line; int type; int reduction; int state; int causeReduce; union Parser_UserData user; unsigned int retry; struct Parser_LangEl *next, *child, *prev; }; struct Parser_Block { struct Parser_LangEl data[8128]; struct Parser_Block *next; }; #line 404 "rlparse.cpp" unsigned int Parser_startState = 0; short Parser_indicies[] = { 152, -1, -1, 152, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 152, 152, 152, 152, -1, -1, -1, -1, -1, -1, -1, -1, 152, 152, 152, 152, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 152, 152, 152, 1, 0, 404, 154, -1, -1, 154, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 154, 154, 154, 154, -1, -1, -1, -1, -1, -1, -1, -1, 154, 154, 154, 154, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 154, 154, 150, -1, -1, 2, 161, -1, -1, 151, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 4, 5, 6, 7, -1, -1, -1, -1, -1, -1, -1, -1, 158, 11, 12, 13, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 9, 8, -1, -1, -1, -1, 153, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, -1, 10, 3, 165, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 26, 14, 15, 17, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 326, 328, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 16, 364, 364, 364, -1, 364, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 364, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 364, -1, -1, -1, 364, 364, -1, -1, -1, -1, -1, -1, -1, -1, 364, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 364, 364, 364, 364, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 364, 364, -1, -1, -1, 364, 364, 364, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 19, 364, 364, 364, -1, 364, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 364, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 364, -1, -1, -1, 364, 364, -1, -1, -1, -1, -1, -1, -1, -1, 364, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 364, 364, 364, 364, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 364, 364, -1, -1, -1, 364, 364, 364, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 24, 174, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 174, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 23, 25, -1, -1, -1, -1, 159, 20, 21, 22, 27, 168, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 28, 17, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 326, 328, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 29, 327, 376, 377, 378, -1, 375, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 170, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 374, -1, -1, -1, 372, 373, -1, -1, -1, -1, -1, -1, -1, -1, 379, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 368, 369, 370, 371, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 380, 381, -1, -1, -1, 382, 383, 30, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 365, -1, 367, -1, 363, 366, 342, 342, 342, -1, 342, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 342, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 342, -1, -1, 342, -1, -1, -1, 342, 342, -1, -1, -1, -1, -1, -1, -1, -1, 342, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 342, 342, 342, 342, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 342, 342, 342, 342, 342, 342, 342, 342, 342, 342, 342, 342, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 31, 342, 342, 342, -1, 342, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 342, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 342, -1, -1, 342, -1, -1, -1, 342, 342, -1, -1, -1, -1, -1, -1, -1, -1, 342, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 342, 342, 342, 342, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 342, 342, 342, 342, 342, 342, 342, 342, 342, 342, 342, 342, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 32, 155, 33, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 173, 376, 377, 378, -1, 375, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 171, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 374, -1, -1, -1, 372, 373, -1, -1, -1, -1, -1, -1, -1, -1, 379, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 368, 369, 370, 371, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 380, 381, -1, -1, -1, 382, 383, 30, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 365, -1, 367, -1, 363, 366, 154, -1, -1, 154, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 154, 154, 154, 154, -1, -1, -1, -1, -1, -1, -1, -1, 154, 154, 154, 154, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 154, 154, -1, -1, -1, 34, 35, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 36, 342, 342, 342, -1, 342, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 342, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 342, -1, -1, 342, -1, -1, -1, 342, 342, -1, -1, -1, -1, -1, -1, -1, -1, 342, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 342, 342, 342, 342, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 342, 342, 342, 342, 342, 342, 342, 342, 342, 342, 342, 342, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 37, 167, 169, 38, 348, 349, 350, -1, 346, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 347, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 156, -1, -1, 374, -1, -1, -1, 372, 373, -1, -1, -1, -1, -1, -1, -1, -1, 351, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 368, 369, 370, 371, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 45, 40, 39, 380, 381, 41, 43, 44, 382, 383, 30, 42, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 341, 345, 343, 344, 352, 348, 349, 350, -1, 346, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 347, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 157, -1, -1, 374, -1, -1, -1, 372, 373, -1, -1, -1, -1, -1, -1, -1, -1, 351, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 368, 369, 370, 371, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 45, 40, 39, 380, 381, 41, 43, 44, 382, 383, 30, 42, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 341, 345, 343, 344, 352, 364, 364, 364, -1, 364, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 364, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 364, -1, -1, -1, 364, 364, -1, -1, -1, -1, -1, -1, -1, -1, 364, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 364, 364, 364, 364, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 364, 364, -1, -1, -1, 364, 364, 364, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 46, 162, -1, -1, 161, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 4, 5, 6, 7, -1, -1, -1, -1, -1, -1, -1, -1, 158, 11, 12, 13, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 9, 8, -1, -1, -1, -1, 153, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, -1, 10, 3, 55, -1, -1, -1, -1, -1, -1, 63, -1, -1, -1, -1, 17, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 56, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 50, 57, -1, -1, 326, 328, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 61, 59, 60, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 47, -1, 58, -1, -1, -1, -1, -1, -1, -1, 48, 191, 49, 198, 52, -1, 53, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 54, -1, -1, -1, 308, 312, -1, -1, 62, 55, -1, -1, -1, -1, -1, -1, 63, -1, -1, -1, -1, 17, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 56, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 50, 57, -1, -1, 326, 328, -1, -1, -1, -1, -1, -1, -1, -1, -1, 66, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 61, 59, 60, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 65, 64, 58, -1, -1, -1, -1, -1, -1, -1, 48, 191, 49, 198, 52, -1, 53, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 54, -1, -1, -1, 308, 312, -1, -1, 62, 348, 349, 350, -1, 346, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 347, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 166, -1, -1, 374, -1, -1, -1, 372, 373, -1, -1, -1, -1, -1, -1, -1, -1, 351, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 368, 369, 370, 371, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 45, 40, 39, 380, 381, 41, 43, 44, 382, 383, 30, 42, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 341, 345, 343, 344, 352, 389, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 388, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 67, -1, -1, -1, -1, 68, 353, 364, 364, 364, -1, 364, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 364, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 364, -1, -1, -1, 364, 364, -1, -1, -1, -1, -1, -1, -1, -1, 364, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 364, 364, 364, 364, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 364, 364, -1, -1, -1, 364, 364, 364, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 69, 71, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 389, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 388, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 70, -1, -1, -1, -1, 68, 75, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 389, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 388, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 74, -1, -1, -1, -1, 68, 73, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 389, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 388, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 72, -1, -1, -1, -1, 68, 361, 362, 376, 377, 378, -1, 375, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 172, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 374, -1, -1, -1, 372, 373, -1, -1, -1, -1, -1, -1, -1, -1, 379, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 368, 369, 370, 371, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 380, 381, -1, -1, -1, 382, 383, 30, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 365, -1, 367, -1, 363, 366, 81, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 163, 83, -1, -1, 186, -1, -1, 186, 84, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 186, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 186, 82, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 186, -1, -1, -1, -1, 85, 55, -1, -1, -1, -1, 192, -1, 63, 192, -1, -1, 192, 18, 86, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 192, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 56, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 192, 192, -1, -1, -1, 50, 57, -1, -1, 326, 328, -1, 87, 88, 89, -1, 192, -1, -1, -1, -1, 192, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 61, 59, 60, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 58, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 193, 52, -1, 53, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 54, -1, -1, -1, 308, 312, -1, -1, 62, 315, -1, -1, 315, 315, 315, -1, 315, 315, 315, 315, 315, 315, 315, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 77, 315, 315, -1, 315, 315, 315, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 315, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 315, 315, -1, -1, -1, 315, 315, -1, -1, 315, 315, -1, 315, 315, 315, 315, 315, 315, -1, -1, -1, 315, 315, 315, 315, 315, 315, 315, 315, 315, 315, 315, 315, 315, 315, 315, 315, 315, 315, 315, 315, 315, 315, 315, 315, 315, 315, 315, 315, 315, 315, 315, 315, 315, 315, 315, 315, 315, 315, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 315, 315, 315, 200, -1, -1, -1, -1, 200, -1, 200, 200, -1, -1, 200, 200, 200, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 200, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 200, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 200, 200, -1, -1, -1, 200, 200, -1, -1, 200, 200, -1, 200, 200, 200, 90, 200, -1, -1, -1, -1, 200, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 200, 200, 200, 202, -1, -1, 100, 99, 202, -1, 202, 202, -1, -1, 202, 202, 202, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 202, 102, -1, 101, -1, 98, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 202, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 202, 202, -1, -1, -1, 202, 202, -1, -1, 202, 202, -1, 202, 202, 202, 202, 202, -1, -1, -1, -1, 202, 219, 221, 223, 103, 264, 268, 270, 272, 266, 274, 276, 280, 282, 284, 278, 286, 252, 256, 258, 260, 254, 262, 228, 232, 234, 236, 230, 238, 240, 244, 246, 248, 242, 250, 202, 202, 202, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 226, 225, 227, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 91, -1, -1, 92, 93, 94, 95, 96, 97, 214, -1, -1, 214, 214, 214, -1, 214, 214, 300, 303, 214, 214, 214, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 214, 214, -1, 214, 302, 214, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 214, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 104, 214, -1, -1, -1, 214, 214, -1, -1, 214, 214, -1, 214, 214, 214, 214, 214, 301, -1, -1, -1, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 214, 214, 214, 55, -1, -1, -1, -1, -1, -1, 63, -1, -1, -1, -1, 17, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 56, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 316, 57, -1, -1, 326, 328, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 61, 59, 60, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 58, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 310, 312, -1, -1, 62, 55, -1, -1, -1, -1, -1, -1, 63, -1, -1, -1, -1, 17, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 56, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 316, 57, -1, -1, 326, 328, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 61, 59, 60, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 58, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 311, 312, -1, -1, 62, 313, -1, -1, 313, 313, 313, -1, 313, 313, 313, 313, 313, 313, 313, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 313, 313, -1, 313, 313, 313, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 313, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 313, 313, -1, -1, -1, 313, 313, -1, -1, 313, 313, 322, 313, 313, 313, 313, 313, 313, -1, -1, -1, 313, 313, 313, 313, 313, 313, 313, 313, 313, 313, 313, 313, 313, 313, 313, 313, 313, 313, 313, 313, 313, 313, 313, 313, 313, 313, 313, 313, 313, 313, 313, 313, 313, 313, 313, 313, 313, 313, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 313, 313, 313, 314, -1, -1, 314, 314, 314, -1, 314, 314, 314, 314, 314, 314, 314, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 314, 314, -1, 314, 314, 314, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 314, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 314, 314, -1, -1, -1, 314, 314, -1, -1, 314, 314, 324, 314, 314, 314, 314, 314, 314, -1, -1, -1, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 314, 314, 314, 338, -1, -1, -1, 338, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 79, 338, -1, -1, -1, 338, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 80, 330, 330, 330, -1, 330, -1, -1, 330, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 78, 105, 55, -1, -1, -1, -1, -1, -1, 63, -1, -1, -1, -1, 17, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 56, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 50, 57, -1, -1, 326, 328, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 61, 59, 60, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 76, -1, 58, -1, -1, -1, -1, -1, -1, -1, 48, 191, 49, 198, 52, -1, 53, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 54, -1, -1, -1, 308, 312, -1, -1, 62, 164, 81, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 175, 55, -1, -1, -1, -1, -1, -1, 63, -1, -1, -1, -1, 17, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 56, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 51, 57, -1, -1, 326, 328, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 61, 59, 60, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 158, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 180, -1, 179, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 160, 108, -1, 107, -1, 58, -1, -1, 106, 178, -1, -1, -1, 48, 191, 49, 198, 52, -1, 53, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 54, -1, -1, -1, 308, 312, -1, -1, 62, 384, 391, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 109, 376, 377, 378, -1, 375, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 354, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 374, -1, -1, -1, 372, 373, -1, -1, -1, -1, -1, -1, -1, -1, 379, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 368, 369, 370, 371, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 380, 381, -1, -1, -1, 382, 383, 30, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 365, -1, 367, -1, 363, 366, 355, 364, 364, 364, -1, 364, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 364, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 364, -1, -1, -1, 364, 364, -1, -1, -1, -1, -1, -1, -1, -1, 364, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 364, 364, 364, 364, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 364, 364, -1, -1, -1, 364, 364, 364, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 110, 359, 364, 364, 364, -1, 364, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 364, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 364, -1, -1, -1, 364, 364, -1, -1, -1, -1, -1, -1, -1, -1, 364, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 364, 364, 364, 364, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 364, 364, -1, -1, -1, 364, 364, 364, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 111, 357, 364, 364, 364, -1, 364, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 364, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 364, -1, -1, -1, 364, 364, -1, -1, -1, -1, -1, -1, -1, -1, 364, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 364, 364, 364, 364, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 364, 364, -1, -1, -1, 364, 364, 364, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 112, 321, -1, -1, 81, 55, -1, -1, -1, -1, -1, -1, 63, -1, -1, -1, -1, 17, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 56, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 50, 57, -1, -1, 326, 328, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 61, 59, 60, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 58, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 199, 52, -1, 53, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 54, -1, -1, -1, 308, 312, -1, -1, 62, 319, 114, 115, -1, 335, -1, -1, 336, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 329, 113, 317, -1, -1, -1, 116, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 337, 318, -1, -1, -1, 116, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 337, 55, -1, -1, -1, -1, -1, -1, 63, -1, -1, -1, -1, 17, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 56, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 50, 57, -1, -1, 326, 328, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 61, 59, 60, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 58, -1, -1, -1, -1, -1, -1, -1, 117, 191, 49, 198, 52, -1, 53, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 54, -1, -1, -1, 308, 312, -1, -1, 62, 55, -1, -1, -1, -1, -1, -1, 63, -1, -1, -1, -1, 17, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 56, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 50, 57, -1, -1, 326, 328, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 61, 59, 60, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 58, -1, -1, -1, -1, -1, -1, -1, -1, 187, 49, 198, 52, -1, 53, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 54, -1, -1, -1, 308, 312, -1, -1, 62, 55, -1, -1, -1, -1, -1, -1, 63, -1, -1, -1, -1, 17, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 56, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 50, 57, -1, -1, 326, 328, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 61, 59, 60, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 58, -1, -1, -1, -1, -1, -1, -1, -1, 188, 49, 198, 52, -1, 53, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 54, -1, -1, -1, 308, 312, -1, -1, 62, 55, -1, -1, -1, -1, -1, -1, 63, -1, -1, -1, -1, 17, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 56, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 50, 57, -1, -1, 326, 328, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 61, 59, 60, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 58, -1, -1, -1, -1, -1, -1, -1, -1, 189, 49, 198, 52, -1, 53, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 54, -1, -1, -1, 308, 312, -1, -1, 62, 55, -1, -1, -1, -1, -1, -1, 63, -1, -1, -1, -1, 17, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 56, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 50, 57, -1, -1, 326, 328, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 61, 59, 60, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 58, -1, -1, -1, -1, -1, -1, -1, -1, 190, 49, 198, 52, -1, 53, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 54, -1, -1, -1, 308, 312, -1, -1, 62, 55, -1, -1, -1, -1, -1, -1, 63, -1, -1, -1, -1, 17, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 56, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 50, 57, -1, -1, 326, 328, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 61, 59, 60, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 58, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 194, 52, -1, 53, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 54, -1, -1, -1, 308, 312, -1, -1, 62, 55, -1, -1, -1, -1, -1, -1, 63, -1, -1, -1, -1, 17, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 56, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 50, 57, -1, -1, 326, 328, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 61, 59, 60, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 58, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 195, 52, -1, 53, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 54, -1, -1, -1, 308, 312, -1, -1, 62, 55, -1, -1, -1, -1, -1, -1, 63, -1, -1, -1, -1, 17, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 56, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 50, 57, -1, -1, 326, 328, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 61, 59, 60, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 58, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 196, 52, -1, 53, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 54, -1, -1, -1, 308, 312, -1, -1, 62, 55, -1, -1, -1, -1, -1, -1, 63, -1, -1, -1, -1, 17, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 56, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 50, 57, -1, -1, 326, 328, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 61, 59, 60, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 58, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 197, 52, -1, 53, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 54, -1, -1, -1, 308, 312, -1, -1, 62, 386, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 201, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 118, 119, -1, -1, 121, -1, 122, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 120, -1, -1, -1, -1, 292, -1, -1, -1, 296, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 203, 290, -1, -1, -1, -1, -1, -1, -1, -1, 204, -1, -1, -1, -1, -1, -1, -1, -1, -1, 288, 295, 123, -1, -1, -1, -1, -1, -1, 124, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 120, -1, -1, -1, -1, 292, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 206, 290, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 288, 124, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 120, -1, -1, -1, -1, 292, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 208, 290, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 288, 124, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 120, -1, -1, -1, -1, 292, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 209, 290, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 288, 124, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 120, -1, -1, -1, -1, 292, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 210, 290, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 288, 124, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 120, -1, -1, -1, -1, 292, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 211, 290, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 288, 125, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 120, -1, -1, -1, -1, 292, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 212, 290, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 288, 215, -1, -1, 215, -1, 215, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 215, -1, -1, -1, -1, 215, -1, -1, -1, 215, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 261, 273, 285, 237, 249, 216, -1, -1, 216, -1, 216, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 216, -1, -1, -1, -1, 216, -1, -1, -1, 216, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 224, -1, 259, 271, 283, 235, 247, 217, -1, -1, 217, -1, 217, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 217, -1, -1, -1, -1, 217, -1, -1, -1, 217, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 222, -1, 257, 269, 281, 233, 245, 218, -1, -1, 218, -1, 218, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 218, -1, -1, -1, -1, 218, -1, -1, -1, 218, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 220, -1, 253, 265, 277, 229, 241, 255, 267, 279, 231, 243, 263, 275, 287, 239, 251, 127, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 309, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 126, 17, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 323, -1, -1, 326, 328, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 325, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, 55, -1, -1, -1, -1, -1, -1, 63, -1, 131, -1, -1, 17, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 56, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 51, 57, -1, -1, 326, 328, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 61, 59, 60, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 158, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 180, -1, 179, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 160, 108, -1, 107, -1, 58, -1, -1, -1, 177, -1, -1, -1, 48, 191, 49, 198, 52, -1, 53, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 54, -1, -1, -1, 308, 312, -1, -1, 62, 81, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 184, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 120, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 130, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 129, -1, 183, 165, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 128, 387, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 387, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 132, 376, 377, 378, -1, 375, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 356, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 374, -1, -1, -1, 372, 373, -1, -1, -1, -1, -1, -1, -1, -1, 379, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 368, 369, 370, 371, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 380, 381, -1, -1, -1, 382, 383, 30, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 365, -1, 367, -1, 363, 366, 376, 377, 378, -1, 375, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 360, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 374, -1, -1, -1, 372, 373, -1, -1, -1, -1, -1, -1, -1, -1, 379, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 368, 369, 370, 371, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 380, 381, -1, -1, -1, 382, 383, 30, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 365, -1, 367, -1, 363, 366, 376, 377, 378, -1, 375, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 358, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 374, -1, -1, -1, 372, 373, -1, -1, -1, -1, -1, -1, -1, -1, 379, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 368, 369, 370, 371, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 380, 381, -1, -1, -1, 382, 383, 30, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 365, -1, 367, -1, 363, 366, 332, 332, 332, -1, 332, 331, -1, 332, 338, -1, -1, -1, 338, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 133, 338, -1, -1, -1, 338, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 134, 339, -1, -1, 135, 339, 83, -1, -1, 185, -1, -1, 185, 84, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 185, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 185, 82, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 185, -1, -1, -1, -1, 85, 391, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 136, 139, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 137, -1, -1, -1, -1, -1, -1, -1, -1, 138, 342, 342, 342, -1, 342, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 342, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 342, -1, -1, 342, -1, -1, -1, 342, 342, -1, -1, -1, -1, -1, -1, -1, -1, 342, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 342, 342, 342, 342, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 342, 342, 342, 342, 342, 342, 342, 342, 342, 342, 342, 342, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 140, 297, 298, 124, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 120, -1, -1, -1, -1, 292, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 207, 290, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 288, 292, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 138, 142, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 141, -1, 138, 144, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 304, 309, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 143, 35, 181, 124, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 120, -1, -1, -1, -1, 292, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 182, 290, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 288, 176, 390, 333, -1, -1, -1, 116, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 337, 334, -1, -1, -1, 116, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 337, 340, 385, -1, -1, -1, -1, 385, -1, 385, 385, -1, -1, 385, 385, 385, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 385, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 385, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 385, 385, -1, -1, -1, 385, 385, -1, -1, 385, 385, -1, 385, 385, 385, 385, 385, -1, -1, 132, -1, 385, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 385, 385, 385, 145, 289, 291, -1, -1, 294, 348, 349, 350, -1, 346, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 347, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 293, -1, -1, 374, -1, -1, -1, 372, 373, -1, -1, -1, -1, -1, -1, -1, -1, 351, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 368, 369, 370, 371, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 45, 40, 39, 380, 381, 41, 43, 44, 382, 383, 30, 42, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 341, 345, 343, 344, 352, 146, 291, -1, -1, 299, 305, 306, -1, -1, -1, -1, -1, -1, 309, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 147, 121, -1, 122, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 296, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 148, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 295, 124, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 120, -1, -1, -1, -1, 292, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 149, 290, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 288, 307, 205, 213, }; unsigned short Parser_keys[] = { 128, 227, 225, 225, 128, 228, 128, 244, 128, 245, 128, 128, 128, 128, 45, 248, 40, 249, 40, 249, 128, 250, 123, 128, 123, 123, 123, 123, 128, 128, 123, 123, 59, 128, 45, 248, 132, 132, 40, 292, 40, 242, 40, 242, 59, 59, 128, 187, 40, 292, 125, 228, 61, 141, 40, 242, 59, 59, 59, 59, 40, 40, 40, 289, 40, 289, 40, 249, 125, 244, 33, 281, 33, 281, 40, 289, 128, 295, 59, 59, 40, 249, 42, 295, 42, 295, 42, 295, 59, 59, 59, 59, 40, 292, 44, 59, 38, 144, 33, 281, 33, 201, 33, 181, 33, 271, 33, 201, 33, 281, 33, 281, 33, 201, 33, 201, 182, 279, 182, 279, 179, 280, 134, 134, 33, 281, 59, 59, 44, 59, 33, 281, 41, 41, 128, 294, 40, 292, 59, 59, 40, 249, 59, 59, 40, 249, 59, 59, 40, 249, 41, 44, 33, 281, 179, 283, 182, 284, 182, 284, 33, 281, 33, 281, 33, 281, 33, 281, 33, 281, 33, 281, 33, 281, 33, 281, 33, 281, 128, 293, 40, 275, 33, 274, 40, 274, 40, 274, 40, 274, 40, 274, 40, 274, 40, 206, 40, 206, 40, 206, 40, 206, 202, 206, 202, 206, 44, 276, 45, 281, 33, 281, 44, 255, 128, 245, 41, 142, 40, 292, 40, 292, 40, 292, 179, 186, 182, 279, 182, 279, 182, 186, 38, 144, 128, 294, 128, 274, 40, 242, 132, 132, 132, 132, 40, 274, 128, 274, 128, 274, 44, 125, 132, 276, 61, 61, 59, 59, 40, 274, 124, 124, 128, 128, 182, 284, 182, 284, 186, 186, 33, 181, 44, 44, 41, 41, 41, 44, 40, 289, 44, 44, 41, 44, 125, 125, 125, 276, 43, 275, 40, 274, 125, 125, 41, 41, 41, 41, 0, 0 }; unsigned int Parser_offsets[] = { 0, 100, 101, 202, 319, 437, 438, 439, 643, 853, 1063, 1186, 1192, 1193, 1194, 1195, 1196, 1266, 1470, 1471, 1724, 1927, 2130, 2131, 2191, 2444, 2548, 2629, 2832, 2833, 2834, 2835, 3085, 3335, 3545, 3665, 3914, 4163, 4413, 4581, 4582, 4792, 5046, 5300, 5554, 5555, 5556, 5809, 5825, 5932, 6181, 6350, 6499, 6738, 6907, 7156, 7405, 7574, 7743, 7841, 7939, 8041, 8042, 8291, 8292, 8308, 8557, 8558, 8725, 8978, 8979, 9189, 9190, 9400, 9401, 9611, 9615, 9864, 9969, 10072, 10175, 10424, 10673, 10922, 11171, 11420, 11669, 11918, 12167, 12416, 12582, 12818, 13060, 13295, 13530, 13765, 14000, 14235, 14402, 14569, 14736, 14903, 14908, 14913, 15146, 15383, 15632, 15844, 15962, 16064, 16317, 16570, 16823, 16831, 16929, 17027, 17032, 17139, 17306, 17453, 17656, 17657, 17658, 17893, 18040, 18187, 18269, 18414, 18415, 18416, 18651, 18652, 18653, 18756, 18859, 18860, 19009, 19010, 19011, 19015, 19265, 19266, 19270, 19271, 19423, 19656, 19891, 19892, 19893, 19894 }; unsigned short Parser_targs[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149 }; unsigned int Parser_actInds[] = { 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 39, 41, 43, 45, 47, 49, 51, 53, 55, 57, 59, 61, 63, 65, 67, 69, 71, 73, 75, 77, 79, 81, 83, 85, 87, 89, 91, 93, 95, 97, 99, 101, 103, 106, 108, 110, 112, 114, 116, 118, 120, 122, 124, 126, 128, 130, 132, 134, 136, 138, 140, 142, 144, 146, 148, 150, 152, 154, 156, 158, 160, 162, 164, 166, 168, 170, 172, 174, 176, 178, 180, 182, 184, 186, 188, 190, 192, 194, 196, 198, 200, 202, 204, 206, 208, 210, 213, 215, 217, 219, 221, 223, 225, 227, 229, 231, 233, 235, 237, 239, 241, 243, 245, 247, 249, 251, 253, 255, 257, 259, 261, 263, 265, 267, 269, 271, 273, 275, 277, 279, 281, 283, 285, 287, 289, 291, 293, 295, 297, 299, 301, 303, 305, 307, 309, 311, 313, 315, 317, 319, 321, 323, 325, 327, 329, 331, 333, 335, 337, 339, 341, 343, 345, 347, 349, 351, 353, 355, 357, 359, 361, 363, 365, 367, 369, 371, 373, 375, 377, 379, 381, 383, 385, 387, 389, 391, 393, 395, 397, 399, 401, 403, 405, 407, 409, 411, 413, 415, 417, 419, 421, 423, 425, 427, 429, 431, 433, 435, 437, 439, 441, 443, 445, 447, 449, 451, 453, 455, 457, 459, 461, 463, 465, 467, 469, 471, 473, 475, 477, 479, 481, 483, 485, 487, 489, 491, 493, 495, 497, 499, 501, 503, 505, 507, 509, 511, 513, 515, 517, 519, 521, 523, 525, 527, 529, 531, 533, 535, 537, 539, 541, 543, 545, 547, 549, 551, 553, 555, 557, 559, 561, 563, 565, 567, 569, 571, 573, 575, 577, 579, 581, 583, 585, 587, 589, 591, 593, 595, 597, 599, 601, 603, 605, 607, 609, 611, 613, 615, 617, 619, 621, 623, 625, 627, 629, 631, 633, 635, 637, 639, 641, 643, 645, 647, 649, 651, 653, 655, 657, 659, 661, 663, 665, 667, 669, 671, 673, 675, 677, 679, 681, 683, 685, 687, 689, 691, 693, 695, 697, 699, 701, 703, 705, 707, 709, 711, 713, 715, 717, 719, 721, 723, 725, 727, 729, 731, 733, 735, 737, 739, 741, 743, 745, 747, 749, 751, 753, 755, 757, 759, 761, 763, 765, 767, 769, 771, 773, 775, 777, 779, 781, 783, 785, 787, 789, 791, 793, 795, 797, 799, 801, 803, 805, 807, 809, 811 }; unsigned int Parser_actions[] = { 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 214, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 90, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 302, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 2, 0, 7, 0, 10, 0, 15, 0, 18, 0, 71, 0, 75, 0, 79, 0, 83, 0, 86, 0, 87, 0, 90, 0, 95, 0, 99, 0, 103, 0, 107, 0, 111, 0, 115, 0, 119, 0, 123, 0, 127, 0, 131, 0, 135, 0, 139, 0, 142, 0, 146, 0, 151, 0, 155, 0, 159, 0, 163, 0, 167, 0, 171, 0, 175, 0, 179, 0, 182, 0, 186, 0, 190, 0, 195, 0, 199, 0, 203, 0, 207, 0, 211, 0, 214, 0, 219, 0, 223, 0, 227, 0, 231, 0, 235, 0, 239, 0, 243, 0, 246, 0, 251, 0, 254, 0, 259, 0, 263, 0, 267, 0, 271, 0, 275, 0, 279, 0, 283, 0, 287, 0, 291, 0, 295, 0, 299, 0, 302, 0, 306, 0, 310, 0, 314, 0, 318, 0, 323, 0, 327, 0, 331, 0, 335, 0, 339, 0, 343, 0, 347, 0, 351, 0, 355, 0, 359, 0, 363, 0, 367, 0, 371, 0, 375, 0, 379, 0, 383, 0, 387, 0, 391, 0, 395, 0, 399, 0, 403, 0, 407, 0, 411, 0, 415, 0, 419, 0, 423, 0, 427, 0, 431, 0, 435, 0, 439, 0, 443, 0, 447, 0, 451, 0, 455, 0, 459, 0, 463, 0, 467, 0, 471, 0, 475, 0, 479, 0, 483, 0, 487, 0, 491, 0, 495, 0, 499, 0, 503, 0, 507, 0, 511, 0, 515, 0, 519, 0, 523, 0, 527, 0, 531, 0, 535, 0, 539, 0, 543, 0, 547, 0, 551, 0, 555, 0, 559, 0, 563, 0, 567, 0, 571, 0, 575, 0, 579, 0, 583, 0, 587, 0, 591, 0, 595, 0, 599, 0, 603, 0, 607, 0, 610, 0, 611, 0, 615, 0, 618, 0, 623, 0, 627, 0, 631, 0, 635, 0, 638, 0, 643, 0, 647, 0, 651, 0, 655, 0, 659, 0, 663, 0, 667, 0, 671, 0, 675, 0, 679, 0, 683, 0, 687, 0, 691, 0, 694, 0, 698, 0, 702, 0, 703, 0, 707, 0, 711, 0, 715, 0, 719, 0, 723, 0, 726, 0, 727, 0, 730, 0, 731, 0, 735, 0, 739, 0, 743, 0, 747, 0, 750, 0, 755, 0, 758, 0, 763, 0, 767, 0, 771, 0, 775, 0, 779, 0, 782, 0, 786, 0, 791, 0, 795, 0, 798, 0, 803, 0, 807, 0, 811, 0, 815, 0, 819, 0, 823, 0, 827, 0, 831, 0, 835, 0, 839, 0, 843, 0, 847, 0, 851, 0, 855, 0, 859, 0, 863, 0, 867, 0, 871, 0, 875, 0, 879, 0, 883, 0, 886, 0, 891, 0, 895, 0, 899, 0, 903, 0, 907, 0, 911, 0, 915, 0, 919, 0, 923, 0, 927, 0, 931, 0, 935, 0, 939, 0, 943, 0, 947, 0, 951, 0, 955, 0, 959, 0, 963, 0, 967, 0, 970, 0, 974, 0, 978, 0, 983, 0, 986, 0, 991, 0, 995, 0, 23, 0, 27, 0, 31, 0, 35, 0, 39, 0, 43, 0, 47, 0, 51, 0, 55, 0, 59, 0, 63, 0, 67, 0, 1, 0 }; int Parser_commitLen[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2 }; char Parser_prodLengths[] = { 1, 3, 0, 2, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 4, 4, 1, 1, 0, 4, 5, 5, 1, 5, 4, 3, 4, 3, 3, 5, 2, 0, 1, 4, 2, 1, 1, 1, 3, 2, 1, 0, 3, 1, 3, 3, 3, 3, 1, 1, 2, 3, 3, 3, 3, 1, 3, 1, 3, 1, 3, 3, 7, 3, 4, 3, 3, 3, 3, 3, 7, 1, 1, 1, 1, 1, 1, 2, 1, 2, 1, 2, 1, 1, 1, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 3, 1, 1, 3, 1, 1, 1, 2, 2, 1, 2, 2, 2, 2, 4, 5, 5, 6, 1, 1, 2, 2, 1, 1, 1, 1, 3, 3, 3, 3, 3, 1, 1, 1, 2, 1, 2, 0, 2, 1, 3, 3, 1, 1, 2, 0, 1, 3, 2, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, 3, 4, 3, 4, 3, 4, 2, 2, 2, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 4, 2, 0, 2, 1, 0, 3, 1, 1 }; unsigned short Parser_prodLhsIds[] = { 227, 226, 226, 228, 228, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 241, 239, 240, 243, 244, 244, 238, 230, 231, 245, 232, 233, 233, 234, 235, 236, 237, 250, 250, 247, 247, 251, 251, 252, 252, 252, 253, 253, 253, 246, 246, 256, 256, 256, 256, 256, 257, 258, 258, 258, 258, 258, 258, 259, 259, 260, 260, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 263, 263, 263, 263, 266, 266, 266, 266, 266, 266, 266, 266, 266, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, 269, 269, 269, 269, 269, 269, 269, 269, 269, 269, 269, 269, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 271, 271, 271, 271, 271, 271, 271, 271, 271, 271, 271, 271, 254, 254, 254, 274, 255, 265, 264, 275, 275, 275, 272, 273, 273, 273, 273, 273, 273, 273, 273, 273, 276, 277, 277, 277, 278, 278, 278, 278, 278, 278, 278, 278, 281, 281, 248, 248, 248, 280, 280, 282, 282, 283, 283, 283, 283, 279, 279, 284, 284, 242, 242, 285, 285, 285, 288, 288, 288, 288, 288, 288, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 249, 249, 291, 291, 291, 287, 287, 287, 287, 287, 287, 287, 292, 292, 292, 292, 292, 289, 289, 289, 289, 289, 261, 293, 290, 295, 295, 294, 294, 296 }; const char *Parser_prodNames[] = { "start-1", "section_list-1", "section_list-2", "statement_list-1", "statement_list-2", "statement-1", "statement-2", "statement-3", "statement-4", "statement-5", "statement-6", "statement-7", "statement-8", "statement-9", "statement-10", "statement-11", "statement-12", "length_spec-1", "pre_push_spec-1", "post_pop_spec-1", "export_open-1", "opt_export-1", "opt_export-2", "export_block-1", "assignment-1", "instantiation-1", "machine_name-1", "action_spec-1", "alphtype_spec-1", "alphtype_spec-2", "range_spec-1", "getkey_spec-1", "access_spec-1", "variable_spec-1", "opt_whitespace-1", "opt_whitespace-2", "join_or_lm-1", "join_or_lm-2", "lm_part_list-1", "lm_part_list-2", "longest_match_part-1", "longest_match_part-2", "longest_match_part-3", "opt_lm_part_action-1", "opt_lm_part_action-2", "opt_lm_part_action-3", "join-1", "join-2", "expression-1", "expression-2", "expression-3", "expression-4", "expression-5", "term_short-1", "term-1", "term-2", "term-3", "term-4", "term-5", "term-6", "factor_with_label-1", "factor_with_label-2", "factor_with_ep-1", "factor_with_ep-2", "factor_with_aug-1", "factor_with_aug-2", "factor_with_aug-3", "factor_with_aug-4", "factor_with_aug-5", "factor_with_aug-6", "factor_with_aug-7", "factor_with_aug-8", "factor_with_aug-9", "factor_with_aug-10", "factor_with_aug-11", "factor_with_aug-12", "aug_type_base-1", "aug_type_base-2", "aug_type_base-3", "aug_type_base-4", "aug_type_cond-1", "aug_type_cond-2", "aug_type_cond-3", "aug_type_cond-4", "aug_type_cond-5", "aug_type_cond-6", "aug_type_cond-7", "aug_type_cond-8", "aug_type_cond-9", "aug_type_to_state-1", "aug_type_to_state-2", "aug_type_to_state-3", "aug_type_to_state-4", "aug_type_to_state-5", "aug_type_to_state-6", "aug_type_to_state-7", "aug_type_to_state-8", "aug_type_to_state-9", "aug_type_to_state-10", "aug_type_to_state-11", "aug_type_to_state-12", "aug_type_from_state-1", "aug_type_from_state-2", "aug_type_from_state-3", "aug_type_from_state-4", "aug_type_from_state-5", "aug_type_from_state-6", "aug_type_from_state-7", "aug_type_from_state-8", "aug_type_from_state-9", "aug_type_from_state-10", "aug_type_from_state-11", "aug_type_from_state-12", "aug_type_eof-1", "aug_type_eof-2", "aug_type_eof-3", "aug_type_eof-4", "aug_type_eof-5", "aug_type_eof-6", "aug_type_eof-7", "aug_type_eof-8", "aug_type_eof-9", "aug_type_eof-10", "aug_type_eof-11", "aug_type_eof-12", "aug_type_gbl_error-1", "aug_type_gbl_error-2", "aug_type_gbl_error-3", "aug_type_gbl_error-4", "aug_type_gbl_error-5", "aug_type_gbl_error-6", "aug_type_gbl_error-7", "aug_type_gbl_error-8", "aug_type_gbl_error-9", "aug_type_gbl_error-10", "aug_type_gbl_error-11", "aug_type_gbl_error-12", "aug_type_local_error-1", "aug_type_local_error-2", "aug_type_local_error-3", "aug_type_local_error-4", "aug_type_local_error-5", "aug_type_local_error-6", "aug_type_local_error-7", "aug_type_local_error-8", "aug_type_local_error-9", "aug_type_local_error-10", "aug_type_local_error-11", "aug_type_local_error-12", "action_embed-1", "action_embed-2", "action_embed-3", "action_embed_word-1", "action_embed_block-1", "priority_name-1", "priority_aug-1", "priority_aug_num-1", "priority_aug_num-2", "priority_aug_num-3", "local_err_name-1", "factor_with_rep-1", "factor_with_rep-2", "factor_with_rep-3", "factor_with_rep-4", "factor_with_rep-5", "factor_with_rep-6", "factor_with_rep-7", "factor_with_rep-8", "factor_with_rep-9", "factor_rep_num-1", "factor_with_neg-1", "factor_with_neg-2", "factor_with_neg-3", "factor-1", "factor-2", "factor-3", "factor-4", "factor-5", "factor-6", "factor-7", "factor-8", "range_lit-1", "range_lit-2", "alphabet_num-1", "alphabet_num-2", "alphabet_num-3", "regular_expr-1", "regular_expr-2", "regular_expr_item-1", "regular_expr_item-2", "regular_expr_char-1", "regular_expr_char-2", "regular_expr_char-3", "regular_expr_char-4", "regular_expr_or_data-1", "regular_expr_or_data-2", "regular_expr_or_char-1", "regular_expr_or_char-2", "inline_block-1", "inline_block-2", "inline_block_item-1", "inline_block_item-2", "inline_block_item-3", "inline_block_symbol-1", "inline_block_symbol-2", "inline_block_symbol-3", "inline_block_symbol-4", "inline_block_symbol-5", "inline_block_symbol-6", "inline_block_interpret-1", "inline_block_interpret-2", "inline_block_interpret-3", "inline_block_interpret-4", "inline_block_interpret-5", "inline_block_interpret-6", "inline_block_interpret-7", "inline_block_interpret-8", "inline_block_interpret-9", "inline_block_interpret-10", "inline_block_interpret-11", "inline_expr-1", "inline_expr-2", "inline_expr_item-1", "inline_expr_item-2", "inline_expr_item-3", "inline_expr_any-1", "inline_expr_any-2", "inline_expr_any-3", "inline_expr_any-4", "inline_expr_any-5", "inline_expr_any-6", "inline_expr_any-7", "inline_expr_symbol-1", "inline_expr_symbol-2", "inline_expr_symbol-3", "inline_expr_symbol-4", "inline_expr_symbol-5", "inline_expr_interpret-1", "inline_expr_interpret-2", "inline_expr_interpret-3", "inline_expr_interpret-4", "inline_expr_interpret-5", "local_state_ref-1", "no_name_sep-1", "state_ref-1", "opt_name_sep-1", "opt_name_sep-2", "state_ref_names-1", "state_ref_names-2", "_start-1" }; const char *Parser_lelNames[] = { "D-0", "D-1", "D-2", "D-3", "D-4", "D-5", "D-6", "D-7", "D-8", "D-9", "D-10", "D-11", "D-12", "D-13", "D-14", "D-15", "D-16", "D-17", "D-18", "D-19", "D-20", "D-21", "D-22", "D-23", "D-24", "D-25", "D-26", "D-27", "D-28", "D-29", "D-30", "D-31", "D-32", "!", "\"", "#", "$", "%", "&", "'", "(", ")", "*", "+", ",", "-", ".", "/", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", ":", ";", "<", "=", ">", "?", "@", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "[", "\\", "]", "^", "_", "`", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "{", "|", "}", "~", "D-127", "TK_Word", "TK_Literal", "TK_Number", "TK_EndSection", "TK_UInt", "TK_Hex", "TK_DotDot", "TK_ColonGt", "TK_ColonGtGt", "TK_LtColon", "TK_Arrow", "TK_DoubleArrow", "TK_StarStar", "TK_ColonEquals", "TK_NameSep", "TK_BarStar", "TK_DashDash", "TK_StartCond", "TK_AllCond", "TK_LeavingCond", "TK_Middle", "TK_StartGblError", "TK_AllGblError", "TK_FinalGblError", "TK_NotFinalGblError", "TK_NotStartGblError", "TK_MiddleGblError", "TK_StartLocalError", "TK_AllLocalError", "TK_FinalLocalError", "TK_NotFinalLocalError", "TK_NotStartLocalError", "TK_MiddleLocalError", "TK_StartEOF", "TK_AllEOF", "TK_FinalEOF", "TK_NotFinalEOF", "TK_NotStartEOF", "TK_MiddleEOF", "TK_StartToState", "TK_AllToState", "TK_FinalToState", "TK_NotFinalToState", "TK_NotStartToState", "TK_MiddleToState", "TK_StartFromState", "TK_AllFromState", "TK_FinalFromState", "TK_NotFinalFromState", "TK_NotStartFromState", "TK_MiddleFromState", "RE_Slash", "RE_SqOpen", "RE_SqOpenNeg", "RE_SqClose", "RE_Dot", "RE_Star", "RE_Dash", "RE_Char", "IL_WhiteSpace", "IL_Comment", "IL_Literal", "IL_Symbol", "KW_Machine", "KW_Include", "KW_Import", "KW_Write", "KW_Action", "KW_AlphType", "KW_Range", "KW_GetKey", "KW_InWhen", "KW_When", "KW_OutWhen", "KW_Eof", "KW_Err", "KW_Lerr", "KW_To", "KW_From", "KW_Export", "KW_PrePush", "KW_PostPop", "KW_Length", "KW_Break", "KW_Exec", "KW_Hold", "KW_PChar", "KW_Char", "KW_Goto", "KW_Call", "KW_Ret", "KW_CurState", "KW_TargState", "KW_Entry", "KW_Next", "KW_Variable", "KW_Access", "Parser_tk_eof", "section_list", "start", "statement_list", "statement", "assignment", "instantiation", "action_spec", "alphtype_spec", "range_spec", "getkey_spec", "access_spec", "variable_spec", "export_block", "pre_push_spec", "post_pop_spec", "length_spec", "inline_block", "export_open", "opt_export", "machine_name", "join", "join_or_lm", "alphabet_num", "inline_expr", "opt_whitespace", "lm_part_list", "longest_match_part", "opt_lm_part_action", "action_embed", "action_embed_block", "expression", "term_short", "term", "factor_with_label", "factor_with_ep", "local_state_ref", "factor_with_aug", "aug_type_base", "priority_aug", "priority_name", "aug_type_cond", "aug_type_to_state", "aug_type_from_state", "aug_type_eof", "aug_type_gbl_error", "aug_type_local_error", "local_err_name", "factor_with_rep", "action_embed_word", "priority_aug_num", "factor_rep_num", "factor_with_neg", "factor", "regular_expr_or_data", "regular_expr", "range_lit", "regular_expr_item", "regular_expr_char", "regular_expr_or_char", "inline_block_item", "inline_block_interpret", "inline_expr_any", "inline_block_symbol", "inline_expr_interpret", "state_ref", "inline_expr_item", "inline_expr_symbol", "no_name_sep", "state_ref_names", "opt_name_sep", "_start" }; #line 1449 "rlparse.kl" void Parser::init() { #line 3855 "rlparse.cpp" curs = Parser_startState; pool = 0; block = (struct Parser_Block*) malloc( sizeof(struct Parser_Block) ); block->next = 0; freshEl = block->data; #ifdef KELBT_LOG_ACTIONS cerr << "allocating 8128 LangEls" << endl; #endif stackTop = freshEl; stackTop->type = 0; stackTop->state = -1; stackTop->next = 0; stackTop->child = 0; stackTop->causeReduce = 0; freshPos = 1; lastFinal = stackTop; numRetry = 0; numNodes = 0; errCount = 0; #line 1454 "rlparse.kl" } int Parser::parseLangEl( int type, const Token *token ) { #line 3880 "rlparse.cpp" #define reject() induceReject = 1 int pos, targState; unsigned int *action; int rhsLen; struct Parser_LangEl *rhs[32]; struct Parser_LangEl *lel = 0; struct Parser_LangEl *input = 0; struct Parser_LangEl *queue = 0; char induceReject; if ( curs < 0 ) return 0; if ( pool == 0 ) { if ( freshPos == 8128 ) { struct Parser_Block* newBlock = (struct Parser_Block*) malloc( sizeof(struct Parser_Block) ); newBlock->next = block; block = newBlock; freshEl = newBlock->data; #ifdef KELBT_LOG_ACTIONS cerr << "allocating 8128 LangEls" << endl; #endif freshPos = 0; } queue = freshEl + freshPos++; } else { queue = pool; pool = pool->next; } numNodes += 1; queue->type = type; queue->user.token = *token; queue->next = 0; queue->retry = 0; queue->child = 0; queue->causeReduce = 0; again: if ( input == 0 ) { if ( queue == 0 ) goto _out; input = queue; queue = queue->next; input->next = 0; } lel = input; if ( lel->type < Parser_keys[curs<<1] || lel->type > Parser_keys[(curs<<1)+1] ) goto parseError; pos = Parser_indicies[Parser_offsets[curs] + (lel->type - Parser_keys[curs<<1])]; if ( pos < 0 ) goto parseError; induceReject = 0; targState = Parser_targs[pos]; action = Parser_actions + Parser_actInds[pos]; if ( lel->retry & 0x0000ffff ) action += (lel->retry & 0x0000ffff); if ( *action & 0x1 ) { #ifdef KELBT_LOG_ACTIONS cerr << "shifted: " << Parser_lelNames[lel->type]; #endif input = input->next; lel->state = curs; lel->next = stackTop; stackTop = lel; if ( action[1] == 0 ) lel->retry &= 0xffff0000; else { lel->retry += 1; numRetry += 1; #ifdef KELBT_LOG_ACTIONS cerr << " retry: " << stackTop; #endif } #ifdef KELBT_LOG_ACTIONS cerr << endl; #endif } if ( Parser_commitLen[pos] != 0 ) { struct Parser_LangEl *commitHead = stackTop, *lel; int sp = 0, doExec = 0; #ifdef KELBT_LOG_ACTIONS cerr << "commit encountered, executing final actions" << endl; #endif if ( Parser_commitLen[pos] < 0 ) commitHead = commitHead->next; lel = commitHead; commit_head: if ( lel == lastFinal ) { doExec = 1; goto commit_base; } if ( lel->next != 0 ) { sp += 1; lel->next->prev = lel; lel = lel->next; lel->retry = 0; goto commit_head; } commit_reverse: if ( lel->child != 0 ) { sp += 1; lel->child->prev = lel; lel = lel->child; lel->retry = 1; goto commit_head; } commit_upwards: if ( doExec ) { if ( lel->type < 226 ) { } else { struct Parser_LangEl *redLel = lel; if ( redLel->child != 0 ) { int r = Parser_prodLengths[redLel->reduction] - 1; struct Parser_LangEl *rhsEl = redLel->child; while ( rhsEl != 0 ) { rhs[r--] = rhsEl; rhsEl = rhsEl->next; } } switch ( lel->reduction ) { case 17: { Token *__ref0 = (Token*)&rhs[1]->user.token; Token *__ref1 = (Token*)&rhs[1]->user.token; Token *__ref2 = (Token*)&rhs[1]->user.token; #line 61 "rlparse.kl" LengthDef *lengthDef = new LengthDef( (__ref0)->data ); pd->lengthDefList.append( lengthDef ); /* Generic creation of machine for instantiation and assignment. */ MachineDef *machineDef = new MachineDef( lengthDef ); tryMachineDef( (__ref1)->loc, (__ref2)->data, machineDef, false ); #line 4031 "rlparse.cpp" } break; case 18: { Token *__ref0 = (Token*)&rhs[1]->user.token; Parser_Lel_inline_list *__ref1 = (Parser_Lel_inline_list*)&rhs[2]->user.inline_list; #line 72 "rlparse.kl" if ( pd->prePushExpr != 0 ) { /* Recover by just ignoring the duplicate. */ error((__ref0)->loc) << "pre_push code already defined" << endl; } pd->prePushExpr = (__ref1)->inlineList; #line 4046 "rlparse.cpp" } break; case 19: { Token *__ref0 = (Token*)&rhs[1]->user.token; Parser_Lel_inline_list *__ref1 = (Parser_Lel_inline_list*)&rhs[2]->user.inline_list; #line 84 "rlparse.kl" if ( pd->postPopExpr != 0 ) { /* Recover by just ignoring the duplicate. */ error((__ref0)->loc) << "post_pop code already defined" << endl; } pd->postPopExpr = (__ref1)->inlineList; #line 4061 "rlparse.cpp" } break; case 20: { #line 95 "rlparse.kl" exportContext.append( true ); #line 4069 "rlparse.cpp" } break; case 21: { Parser_Lel_opt_export *__ref0 = (Parser_Lel_opt_export*)&redLel->user.opt_export; #line 104 "rlparse.kl" (__ref0)->isSet = true; #line 4076 "rlparse.cpp" } break; case 22: { Parser_Lel_opt_export *__ref0 = (Parser_Lel_opt_export*)&redLel->user.opt_export; #line 105 "rlparse.kl" (__ref0)->isSet = false; #line 4083 "rlparse.cpp" } break; case 23: { #line 108 "rlparse.kl" exportContext.remove( exportContext.length()-1 ); #line 4091 "rlparse.cpp" } break; case 24: { Parser_Lel_token_type *__ref0 = (Parser_Lel_token_type*)&rhs[1]->user.token_type; Parser_Lel_token_type *__ref1 = (Parser_Lel_token_type*)&rhs[1]->user.token_type; Parser_Lel_join *__ref2 = (Parser_Lel_join*)&rhs[3]->user.join; Parser_Lel_token_type *__ref3 = (Parser_Lel_token_type*)&rhs[1]->user.token_type; Parser_Lel_token_type *__ref4 = (Parser_Lel_token_type*)&rhs[1]->user.token_type; Parser_Lel_opt_export *__ref5 = (Parser_Lel_opt_export*)&rhs[0]->user.opt_export; Parser_Lel_join *__ref6 = (Parser_Lel_join*)&rhs[3]->user.join; Token *__ref7 = (Token*)&rhs[2]->user.token; #line 113 "rlparse.kl" /* Main machine must be an instance. */ bool isInstance = false; if ( strcmp((__ref0)->token.data, mainMachine) == 0 ) { warning((__ref1)->token.loc) << "main machine will be implicitly instantiated" << endl; isInstance = true; } /* Generic creation of machine for instantiation and assignment. */ MachineDef *machineDef = new MachineDef( (__ref2)->join ); tryMachineDef( (__ref3)->token.loc, (__ref4)->token.data, machineDef, isInstance ); if ( (__ref5)->isSet ) exportContext.remove( exportContext.length()-1 ); (__ref6)->join->loc = (__ref7)->loc; #line 4122 "rlparse.cpp" } break; case 25: { Parser_Lel_token_type *__ref0 = (Parser_Lel_token_type*)&rhs[1]->user.token_type; Parser_Lel_token_type *__ref1 = (Parser_Lel_token_type*)&rhs[1]->user.token_type; Parser_Lel_join_or_lm *__ref2 = (Parser_Lel_join_or_lm*)&rhs[3]->user.join_or_lm; Parser_Lel_opt_export *__ref3 = (Parser_Lel_opt_export*)&rhs[0]->user.opt_export; Parser_Lel_join_or_lm *__ref4 = (Parser_Lel_join_or_lm*)&rhs[3]->user.join_or_lm; Parser_Lel_join_or_lm *__ref5 = (Parser_Lel_join_or_lm*)&rhs[3]->user.join_or_lm; Token *__ref6 = (Token*)&rhs[2]->user.token; #line 133 "rlparse.kl" /* Generic creation of machine for instantiation and assignment. */ tryMachineDef( (__ref0)->token.loc, (__ref1)->token.data, (__ref2)->machineDef, true ); if ( (__ref3)->isSet ) exportContext.remove( exportContext.length()-1 ); /* Pass a location to join_or_lm */ if ( (__ref4)->machineDef->join != 0 ) (__ref5)->machineDef->join->loc = (__ref6)->loc; #line 4145 "rlparse.cpp" } break; case 26: { Token *__ref0 = (Token*)&rhs[0]->user.token; Token *__ref1 = (Token*)&rhs[0]->user.token; Parser_Lel_token_type *__ref2 = (Parser_Lel_token_type*)&redLel->user.token_type; Token *__ref3 = (Token*)&rhs[0]->user.token; #line 153 "rlparse.kl" /* Make/get the priority key. The name may have already been referenced * and therefore exist. */ PriorDictEl *priorDictEl; if ( pd->priorDict.insert( (__ref0)->data, pd->nextPriorKey, &priorDictEl ) ) pd->nextPriorKey += 1; pd->curDefPriorKey = priorDictEl->value; /* Make/get the local error key. */ LocalErrDictEl *localErrDictEl; if ( pd->localErrDict.insert( (__ref1)->data, pd->nextLocalErrKey, &localErrDictEl ) ) pd->nextLocalErrKey += 1; pd->curDefLocalErrKey = localErrDictEl->value; (__ref2)->token = *(__ref3); #line 4170 "rlparse.cpp" } break; case 27: { Token *__ref0 = (Token*)&rhs[1]->user.token; Token *__ref1 = (Token*)&rhs[1]->user.token; Token *__ref2 = (Token*)&rhs[1]->user.token; Token *__ref3 = (Token*)&rhs[2]->user.token; Token *__ref4 = (Token*)&rhs[1]->user.token; Parser_Lel_inline_list *__ref5 = (Parser_Lel_inline_list*)&rhs[3]->user.inline_list; #line 171 "rlparse.kl" if ( pd->actionDict.find( (__ref0)->data ) ) { /* Recover by just ignoring the duplicate. */ error((__ref1)->loc) << "action \"" << (__ref2)->data << "\" already defined" << endl; } else { //cerr << "NEW ACTION " << $2->data << " " << $4->inlineList << endl; /* Add the action to the list of actions. */ Action *newAction = new Action( (__ref3)->loc, (__ref4)->data, (__ref5)->inlineList, pd->nextCondId++ ); /* Insert to list and dict. */ pd->actionList.append( newAction ); pd->actionDict.insert( newAction ); } #line 4197 "rlparse.cpp" } break; case 28: { Token *__ref0 = (Token*)&rhs[0]->user.token; Token *__ref1 = (Token*)&rhs[1]->user.token; Token *__ref2 = (Token*)&rhs[2]->user.token; Token *__ref3 = (Token*)&rhs[1]->user.token; Token *__ref4 = (Token*)&rhs[1]->user.token; Token *__ref5 = (Token*)&rhs[2]->user.token; #line 191 "rlparse.kl" if ( ! pd->setAlphType( (__ref0)->loc, (__ref1)->data, (__ref2)->data ) ) { // Recover by ignoring the alphtype statement. error((__ref3)->loc) << "\"" << (__ref4)->data << " " << (__ref5)->data << "\" is not a valid alphabet type" << endl; } #line 4215 "rlparse.cpp" } break; case 29: { Token *__ref0 = (Token*)&rhs[0]->user.token; Token *__ref1 = (Token*)&rhs[1]->user.token; Token *__ref2 = (Token*)&rhs[1]->user.token; Token *__ref3 = (Token*)&rhs[1]->user.token; #line 200 "rlparse.kl" if ( ! pd->setAlphType( (__ref0)->loc, (__ref1)->data ) ) { // Recover by ignoring the alphtype statement. error((__ref2)->loc) << "\"" << (__ref3)->data << "\" is not a valid alphabet type" << endl; } #line 4231 "rlparse.cpp" } break; case 30: { Parser_Lel_token_type *__ref0 = (Parser_Lel_token_type*)&rhs[1]->user.token_type; Parser_Lel_token_type *__ref1 = (Parser_Lel_token_type*)&rhs[2]->user.token_type; Parser_Lel_token_type *__ref2 = (Parser_Lel_token_type*)&rhs[1]->user.token_type; Parser_Lel_token_type *__ref3 = (Parser_Lel_token_type*)&rhs[2]->user.token_type; #line 210 "rlparse.kl" // Save the upper and lower ends of the range and emit the line number. pd->lowerNum = (__ref0)->token.data; pd->upperNum = (__ref1)->token.data; pd->rangeLowLoc = (__ref2)->token.loc; pd->rangeHighLoc = (__ref3)->token.loc; #line 4247 "rlparse.cpp" } break; case 31: { Parser_Lel_inline_list *__ref0 = (Parser_Lel_inline_list*)&rhs[1]->user.inline_list; #line 219 "rlparse.kl" pd->getKeyExpr = (__ref0)->inlineList; #line 4256 "rlparse.cpp" } break; case 32: { Parser_Lel_inline_list *__ref0 = (Parser_Lel_inline_list*)&rhs[1]->user.inline_list; #line 224 "rlparse.kl" pd->accessExpr = (__ref0)->inlineList; #line 4265 "rlparse.cpp" } break; case 33: { Token *__ref0 = (Token*)&rhs[2]->user.token; Parser_Lel_inline_list *__ref1 = (Parser_Lel_inline_list*)&rhs[3]->user.inline_list; Token *__ref2 = (Token*)&rhs[2]->user.token; #line 229 "rlparse.kl" /* FIXME: Need to implement the rest of this. */ bool wasSet = pd->setVariable( (__ref0)->data, (__ref1)->inlineList ); if ( !wasSet ) error((__ref2)->loc) << "bad variable name" << endl; #line 4279 "rlparse.cpp" } break; case 36: { Parser_Lel_join_or_lm *__ref0 = (Parser_Lel_join_or_lm*)&redLel->user.join_or_lm; Parser_Lel_join *__ref1 = (Parser_Lel_join*)&rhs[0]->user.join; #line 249 "rlparse.kl" (__ref0)->machineDef = new MachineDef( (__ref1)->join ); #line 4289 "rlparse.cpp" } break; case 37: { Token *__ref0 = (Token*)&rhs[0]->user.token; Parser_Lel_lm_part_list *__ref1 = (Parser_Lel_lm_part_list*)&rhs[1]->user.lm_part_list; Parser_Lel_lm_part_list *__ref2 = (Parser_Lel_lm_part_list*)&rhs[1]->user.lm_part_list; Parser_Lel_join_or_lm *__ref3 = (Parser_Lel_join_or_lm*)&redLel->user.join_or_lm; #line 253 "rlparse.kl" /* Create a new factor going to a longest match structure. Record * in the parse data that we have a longest match. */ LongestMatch *lm = new LongestMatch( (__ref0)->loc, (__ref1)->lmPartList ); pd->lmList.append( lm ); for ( LmPartList::Iter lmp = *((__ref2)->lmPartList); lmp.lte(); lmp++ ) lmp->longestMatch = lm; (__ref3)->machineDef = new MachineDef( lm ); #line 4307 "rlparse.cpp" } break; case 38: { Parser_Lel_longest_match_part *__ref0 = (Parser_Lel_longest_match_part*)&rhs[1]->user.longest_match_part; Parser_Lel_lm_part_list *__ref1 = (Parser_Lel_lm_part_list*)&rhs[0]->user.lm_part_list; Parser_Lel_longest_match_part *__ref2 = (Parser_Lel_longest_match_part*)&rhs[1]->user.longest_match_part; Parser_Lel_lm_part_list *__ref3 = (Parser_Lel_lm_part_list*)&redLel->user.lm_part_list; Parser_Lel_lm_part_list *__ref4 = (Parser_Lel_lm_part_list*)&rhs[0]->user.lm_part_list; #line 270 "rlparse.kl" if ( (__ref0)->lmPart != 0 ) (__ref1)->lmPartList->append( (__ref2)->lmPart ); (__ref3)->lmPartList = (__ref4)->lmPartList; #line 4322 "rlparse.cpp" } break; case 39: { Parser_Lel_lm_part_list *__ref0 = (Parser_Lel_lm_part_list*)&redLel->user.lm_part_list; Parser_Lel_longest_match_part *__ref1 = (Parser_Lel_longest_match_part*)&rhs[0]->user.longest_match_part; Parser_Lel_lm_part_list *__ref2 = (Parser_Lel_lm_part_list*)&redLel->user.lm_part_list; Parser_Lel_longest_match_part *__ref3 = (Parser_Lel_longest_match_part*)&rhs[0]->user.longest_match_part; #line 277 "rlparse.kl" /* Create a new list with the part. */ (__ref0)->lmPartList = new LmPartList; if ( (__ref1)->lmPart != 0 ) (__ref2)->lmPartList->append( (__ref3)->lmPart ); #line 4337 "rlparse.cpp" } break; case 40: { Parser_Lel_longest_match_part *__ref0 = (Parser_Lel_longest_match_part*)&redLel->user.longest_match_part; #line 290 "rlparse.kl" (__ref0)->lmPart = 0; #line 4344 "rlparse.cpp" } break; case 41: { Parser_Lel_longest_match_part *__ref0 = (Parser_Lel_longest_match_part*)&redLel->user.longest_match_part; #line 292 "rlparse.kl" (__ref0)->lmPart = 0; #line 4351 "rlparse.cpp" } break; case 42: { Parser_Lel_longest_match_part *__ref0 = (Parser_Lel_longest_match_part*)&redLel->user.longest_match_part; Parser_Lel_opt_lm_part_action *__ref1 = (Parser_Lel_opt_lm_part_action*)&rhs[1]->user.opt_lm_part_action; Parser_Lel_longest_match_part *__ref2 = (Parser_Lel_longest_match_part*)&redLel->user.longest_match_part; Parser_Lel_join *__ref3 = (Parser_Lel_join*)&rhs[0]->user.join; Token *__ref4 = (Token*)&rhs[2]->user.token; Parser_Lel_join *__ref5 = (Parser_Lel_join*)&rhs[0]->user.join; Token *__ref6 = (Token*)&rhs[2]->user.token; #line 294 "rlparse.kl" (__ref0)->lmPart = 0; Action *action = (__ref1)->action; if ( action != 0 ) action->isLmAction = true; (__ref2)->lmPart = new LongestMatchPart( (__ref3)->join, action, (__ref4)->loc, pd->nextLongestMatchId++ ); /* Provide a location to join. Unfortunately We don't * have the start of the join as in other occurances. Use the end. */ (__ref5)->join->loc = (__ref6)->loc; #line 4375 "rlparse.cpp" } break; case 43: { Parser_Lel_opt_lm_part_action *__ref0 = (Parser_Lel_opt_lm_part_action*)&redLel->user.opt_lm_part_action; Parser_Lel_action_ref *__ref1 = (Parser_Lel_action_ref*)&rhs[1]->user.action_ref; #line 313 "rlparse.kl" (__ref0)->action = (__ref1)->action; #line 4385 "rlparse.cpp" } break; case 44: { Parser_Lel_opt_lm_part_action *__ref0 = (Parser_Lel_opt_lm_part_action*)&redLel->user.opt_lm_part_action; Parser_Lel_action_ref *__ref1 = (Parser_Lel_action_ref*)&rhs[0]->user.action_ref; #line 317 "rlparse.kl" (__ref0)->action = (__ref1)->action; #line 4395 "rlparse.cpp" } break; case 45: { Parser_Lel_opt_lm_part_action *__ref0 = (Parser_Lel_opt_lm_part_action*)&redLel->user.opt_lm_part_action; #line 321 "rlparse.kl" (__ref0)->action = 0; #line 4404 "rlparse.cpp" } break; case 46: { Parser_Lel_join *__ref0 = (Parser_Lel_join*)&rhs[0]->user.join; Parser_Lel_expression *__ref1 = (Parser_Lel_expression*)&rhs[2]->user.expression; Parser_Lel_join *__ref2 = (Parser_Lel_join*)&redLel->user.join; Parser_Lel_join *__ref3 = (Parser_Lel_join*)&rhs[0]->user.join; #line 332 "rlparse.kl" /* Append the expression to the list and return it. */ (__ref0)->join->exprList.append( (__ref1)->expression ); (__ref2)->join = (__ref3)->join; #line 4418 "rlparse.cpp" } break; case 47: { Parser_Lel_join *__ref0 = (Parser_Lel_join*)&redLel->user.join; Parser_Lel_expression *__ref1 = (Parser_Lel_expression*)&rhs[0]->user.expression; #line 338 "rlparse.kl" (__ref0)->join = new Join( (__ref1)->expression ); #line 4428 "rlparse.cpp" } break; case 48: { Parser_Lel_expression *__ref0 = (Parser_Lel_expression*)&redLel->user.expression; Parser_Lel_expression *__ref1 = (Parser_Lel_expression*)&rhs[0]->user.expression; Parser_Lel_term_short *__ref2 = (Parser_Lel_term_short*)&rhs[2]->user.term_short; #line 348 "rlparse.kl" (__ref0)->expression = new Expression( (__ref1)->expression, (__ref2)->term, Expression::OrType ); #line 4440 "rlparse.cpp" } break; case 49: { Parser_Lel_expression *__ref0 = (Parser_Lel_expression*)&redLel->user.expression; Parser_Lel_expression *__ref1 = (Parser_Lel_expression*)&rhs[0]->user.expression; Parser_Lel_term_short *__ref2 = (Parser_Lel_term_short*)&rhs[2]->user.term_short; #line 353 "rlparse.kl" (__ref0)->expression = new Expression( (__ref1)->expression, (__ref2)->term, Expression::IntersectType ); #line 4452 "rlparse.cpp" } break; case 50: { Parser_Lel_expression *__ref0 = (Parser_Lel_expression*)&redLel->user.expression; Parser_Lel_expression *__ref1 = (Parser_Lel_expression*)&rhs[0]->user.expression; Parser_Lel_term_short *__ref2 = (Parser_Lel_term_short*)&rhs[2]->user.term_short; #line 358 "rlparse.kl" (__ref0)->expression = new Expression( (__ref1)->expression, (__ref2)->term, Expression::SubtractType ); #line 4464 "rlparse.cpp" } break; case 51: { Parser_Lel_expression *__ref0 = (Parser_Lel_expression*)&redLel->user.expression; Parser_Lel_expression *__ref1 = (Parser_Lel_expression*)&rhs[0]->user.expression; Parser_Lel_term_short *__ref2 = (Parser_Lel_term_short*)&rhs[2]->user.term_short; #line 363 "rlparse.kl" (__ref0)->expression = new Expression( (__ref1)->expression, (__ref2)->term, Expression::StrongSubtractType ); #line 4476 "rlparse.cpp" } break; case 52: { Parser_Lel_expression *__ref0 = (Parser_Lel_expression*)&redLel->user.expression; Parser_Lel_term_short *__ref1 = (Parser_Lel_term_short*)&rhs[0]->user.term_short; #line 368 "rlparse.kl" (__ref0)->expression = new Expression( (__ref1)->term ); #line 4486 "rlparse.cpp" } break; case 53: { Parser_Lel_term_short *__ref0 = (Parser_Lel_term_short*)&redLel->user.term_short; Parser_Lel_term *__ref1 = (Parser_Lel_term*)&rhs[0]->user.term; #line 389 "rlparse.kl" (__ref0)->term = (__ref1)->term; #line 4496 "rlparse.cpp" } break; case 54: { Parser_Lel_term *__ref0 = (Parser_Lel_term*)&redLel->user.term; Parser_Lel_term *__ref1 = (Parser_Lel_term*)&rhs[0]->user.term; Parser_Lel_factor_with_label *__ref2 = (Parser_Lel_factor_with_label*)&rhs[1]->user.factor_with_label; #line 399 "rlparse.kl" (__ref0)->term = new Term( (__ref1)->term, (__ref2)->factorWithAug ); #line 4507 "rlparse.cpp" } break; case 55: { Parser_Lel_term *__ref0 = (Parser_Lel_term*)&redLel->user.term; Parser_Lel_term *__ref1 = (Parser_Lel_term*)&rhs[0]->user.term; Parser_Lel_factor_with_label *__ref2 = (Parser_Lel_factor_with_label*)&rhs[2]->user.factor_with_label; #line 403 "rlparse.kl" (__ref0)->term = new Term( (__ref1)->term, (__ref2)->factorWithAug ); #line 4518 "rlparse.cpp" } break; case 56: { Parser_Lel_term *__ref0 = (Parser_Lel_term*)&redLel->user.term; Parser_Lel_term *__ref1 = (Parser_Lel_term*)&rhs[0]->user.term; Parser_Lel_factor_with_label *__ref2 = (Parser_Lel_factor_with_label*)&rhs[2]->user.factor_with_label; #line 407 "rlparse.kl" (__ref0)->term = new Term( (__ref1)->term, (__ref2)->factorWithAug, Term::RightStartType ); #line 4529 "rlparse.cpp" } break; case 57: { Parser_Lel_term *__ref0 = (Parser_Lel_term*)&redLel->user.term; Parser_Lel_term *__ref1 = (Parser_Lel_term*)&rhs[0]->user.term; Parser_Lel_factor_with_label *__ref2 = (Parser_Lel_factor_with_label*)&rhs[2]->user.factor_with_label; #line 411 "rlparse.kl" (__ref0)->term = new Term( (__ref1)->term, (__ref2)->factorWithAug, Term::RightFinishType ); #line 4540 "rlparse.cpp" } break; case 58: { Parser_Lel_term *__ref0 = (Parser_Lel_term*)&redLel->user.term; Parser_Lel_term *__ref1 = (Parser_Lel_term*)&rhs[0]->user.term; Parser_Lel_factor_with_label *__ref2 = (Parser_Lel_factor_with_label*)&rhs[2]->user.factor_with_label; #line 415 "rlparse.kl" (__ref0)->term = new Term( (__ref1)->term, (__ref2)->factorWithAug, Term::LeftType ); #line 4552 "rlparse.cpp" } break; case 59: { Parser_Lel_term *__ref0 = (Parser_Lel_term*)&redLel->user.term; Parser_Lel_factor_with_label *__ref1 = (Parser_Lel_factor_with_label*)&rhs[0]->user.factor_with_label; #line 420 "rlparse.kl" (__ref0)->term = new Term( (__ref1)->factorWithAug ); #line 4562 "rlparse.cpp" } break; case 60: { Parser_Lel_factor_with_label *__ref0 = (Parser_Lel_factor_with_label*)&rhs[2]->user.factor_with_label; Token *__ref1 = (Token*)&rhs[0]->user.token; Token *__ref2 = (Token*)&rhs[0]->user.token; Parser_Lel_factor_with_label *__ref3 = (Parser_Lel_factor_with_label*)&redLel->user.factor_with_label; Parser_Lel_factor_with_label *__ref4 = (Parser_Lel_factor_with_label*)&rhs[2]->user.factor_with_label; #line 430 "rlparse.kl" /* Add the label to the list and pass the factor up. */ (__ref0)->factorWithAug->labels.prepend( Label((__ref1)->loc, (__ref2)->data) ); (__ref3)->factorWithAug = (__ref4)->factorWithAug; #line 4577 "rlparse.cpp" } break; case 61: { Parser_Lel_factor_with_label *__ref0 = (Parser_Lel_factor_with_label*)&redLel->user.factor_with_label; Parser_Lel_factor_with_ep *__ref1 = (Parser_Lel_factor_with_ep*)&rhs[0]->user.factor_with_ep; #line 436 "rlparse.kl" (__ref0)->factorWithAug = (__ref1)->factorWithAug; #line 4587 "rlparse.cpp" } break; case 62: { Parser_Lel_factor_with_ep *__ref0 = (Parser_Lel_factor_with_ep*)&rhs[0]->user.factor_with_ep; Token *__ref1 = (Token*)&rhs[1]->user.token; Parser_Lel_factor_with_ep *__ref2 = (Parser_Lel_factor_with_ep*)&redLel->user.factor_with_ep; Parser_Lel_factor_with_ep *__ref3 = (Parser_Lel_factor_with_ep*)&rhs[0]->user.factor_with_ep; #line 446 "rlparse.kl" /* Add the target to the list and return the factor object. */ (__ref0)->factorWithAug->epsilonLinks.append( EpsilonLink( (__ref1)->loc, nameRef ) ); (__ref2)->factorWithAug = (__ref3)->factorWithAug; #line 4601 "rlparse.cpp" } break; case 63: { Parser_Lel_factor_with_ep *__ref0 = (Parser_Lel_factor_with_ep*)&redLel->user.factor_with_ep; Parser_Lel_factor_with_aug *__ref1 = (Parser_Lel_factor_with_aug*)&rhs[0]->user.factor_with_aug; #line 452 "rlparse.kl" (__ref0)->factorWithAug = (__ref1)->factorWithAug; #line 4611 "rlparse.cpp" } break; case 64: { Parser_Lel_factor_with_aug *__ref0 = (Parser_Lel_factor_with_aug*)&rhs[0]->user.factor_with_aug; Parser_Lel_aug_type *__ref1 = (Parser_Lel_aug_type*)&rhs[1]->user.aug_type; Parser_Lel_aug_type *__ref2 = (Parser_Lel_aug_type*)&rhs[1]->user.aug_type; Parser_Lel_action_ref *__ref3 = (Parser_Lel_action_ref*)&rhs[2]->user.action_ref; Parser_Lel_factor_with_aug *__ref4 = (Parser_Lel_factor_with_aug*)&redLel->user.factor_with_aug; Parser_Lel_factor_with_aug *__ref5 = (Parser_Lel_factor_with_aug*)&rhs[0]->user.factor_with_aug; #line 462 "rlparse.kl" /* Append the action to the factorWithAug, record the refernce from * factorWithAug to the action and pass up the factorWithAug. */ (__ref0)->factorWithAug->actions.append( ParserAction( (__ref1)->loc, (__ref2)->augType, 0, (__ref3)->action ) ); (__ref4)->factorWithAug = (__ref5)->factorWithAug; #line 4629 "rlparse.cpp" } break; case 65: { Parser_Lel_factor_with_aug *__ref0 = (Parser_Lel_factor_with_aug*)&rhs[0]->user.factor_with_aug; Parser_Lel_aug_type *__ref1 = (Parser_Lel_aug_type*)&rhs[1]->user.aug_type; Parser_Lel_priority_aug *__ref2 = (Parser_Lel_priority_aug*)&rhs[2]->user.priority_aug; Parser_Lel_factor_with_aug *__ref3 = (Parser_Lel_factor_with_aug*)&redLel->user.factor_with_aug; Parser_Lel_factor_with_aug *__ref4 = (Parser_Lel_factor_with_aug*)&rhs[0]->user.factor_with_aug; #line 470 "rlparse.kl" /* Append the named priority to the factorWithAug and pass it up. */ (__ref0)->factorWithAug->priorityAugs.append( PriorityAug( (__ref1)->augType, pd->curDefPriorKey, (__ref2)->priorityNum ) ); (__ref3)->factorWithAug = (__ref4)->factorWithAug; #line 4645 "rlparse.cpp" } break; case 66: { Parser_Lel_factor_with_aug *__ref0 = (Parser_Lel_factor_with_aug*)&rhs[0]->user.factor_with_aug; Parser_Lel_aug_type *__ref1 = (Parser_Lel_aug_type*)&rhs[1]->user.aug_type; Parser_Lel_priority_name *__ref2 = (Parser_Lel_priority_name*)&rhs[3]->user.priority_name; Parser_Lel_priority_aug *__ref3 = (Parser_Lel_priority_aug*)&rhs[5]->user.priority_aug; Parser_Lel_factor_with_aug *__ref4 = (Parser_Lel_factor_with_aug*)&redLel->user.factor_with_aug; Parser_Lel_factor_with_aug *__ref5 = (Parser_Lel_factor_with_aug*)&rhs[0]->user.factor_with_aug; #line 477 "rlparse.kl" /* Append the priority using a default name. */ (__ref0)->factorWithAug->priorityAugs.append( PriorityAug( (__ref1)->augType, (__ref2)->priorityName, (__ref3)->priorityNum ) ); (__ref4)->factorWithAug = (__ref5)->factorWithAug; #line 4662 "rlparse.cpp" } break; case 67: { Parser_Lel_factor_with_aug *__ref0 = (Parser_Lel_factor_with_aug*)&rhs[0]->user.factor_with_aug; Parser_Lel_aug_type *__ref1 = (Parser_Lel_aug_type*)&rhs[1]->user.aug_type; Parser_Lel_aug_type *__ref2 = (Parser_Lel_aug_type*)&rhs[1]->user.aug_type; Parser_Lel_action_ref *__ref3 = (Parser_Lel_action_ref*)&rhs[2]->user.action_ref; Parser_Lel_factor_with_aug *__ref4 = (Parser_Lel_factor_with_aug*)&redLel->user.factor_with_aug; Parser_Lel_factor_with_aug *__ref5 = (Parser_Lel_factor_with_aug*)&rhs[0]->user.factor_with_aug; #line 484 "rlparse.kl" (__ref0)->factorWithAug->conditions.append( ConditionTest( (__ref1)->loc, (__ref2)->augType, (__ref3)->action, true ) ); (__ref4)->factorWithAug = (__ref5)->factorWithAug; #line 4678 "rlparse.cpp" } break; case 68: { Parser_Lel_factor_with_aug *__ref0 = (Parser_Lel_factor_with_aug*)&rhs[0]->user.factor_with_aug; Parser_Lel_aug_type *__ref1 = (Parser_Lel_aug_type*)&rhs[1]->user.aug_type; Parser_Lel_aug_type *__ref2 = (Parser_Lel_aug_type*)&rhs[1]->user.aug_type; Parser_Lel_action_ref *__ref3 = (Parser_Lel_action_ref*)&rhs[3]->user.action_ref; Parser_Lel_factor_with_aug *__ref4 = (Parser_Lel_factor_with_aug*)&redLel->user.factor_with_aug; Parser_Lel_factor_with_aug *__ref5 = (Parser_Lel_factor_with_aug*)&rhs[0]->user.factor_with_aug; #line 490 "rlparse.kl" (__ref0)->factorWithAug->conditions.append( ConditionTest( (__ref1)->loc, (__ref2)->augType, (__ref3)->action, false ) ); (__ref4)->factorWithAug = (__ref5)->factorWithAug; #line 4694 "rlparse.cpp" } break; case 69: { Parser_Lel_factor_with_aug *__ref0 = (Parser_Lel_factor_with_aug*)&rhs[0]->user.factor_with_aug; Parser_Lel_aug_type *__ref1 = (Parser_Lel_aug_type*)&rhs[1]->user.aug_type; Parser_Lel_aug_type *__ref2 = (Parser_Lel_aug_type*)&rhs[1]->user.aug_type; Parser_Lel_action_ref *__ref3 = (Parser_Lel_action_ref*)&rhs[2]->user.action_ref; Parser_Lel_factor_with_aug *__ref4 = (Parser_Lel_factor_with_aug*)&redLel->user.factor_with_aug; Parser_Lel_factor_with_aug *__ref5 = (Parser_Lel_factor_with_aug*)&rhs[0]->user.factor_with_aug; #line 496 "rlparse.kl" /* Append the action, pass it up. */ (__ref0)->factorWithAug->actions.append( ParserAction( (__ref1)->loc, (__ref2)->augType, 0, (__ref3)->action ) ); (__ref4)->factorWithAug = (__ref5)->factorWithAug; #line 4711 "rlparse.cpp" } break; case 70: { Parser_Lel_factor_with_aug *__ref0 = (Parser_Lel_factor_with_aug*)&rhs[0]->user.factor_with_aug; Parser_Lel_aug_type *__ref1 = (Parser_Lel_aug_type*)&rhs[1]->user.aug_type; Parser_Lel_aug_type *__ref2 = (Parser_Lel_aug_type*)&rhs[1]->user.aug_type; Parser_Lel_action_ref *__ref3 = (Parser_Lel_action_ref*)&rhs[2]->user.action_ref; Parser_Lel_factor_with_aug *__ref4 = (Parser_Lel_factor_with_aug*)&redLel->user.factor_with_aug; Parser_Lel_factor_with_aug *__ref5 = (Parser_Lel_factor_with_aug*)&rhs[0]->user.factor_with_aug; #line 503 "rlparse.kl" /* Append the action, pass it up. */ (__ref0)->factorWithAug->actions.append( ParserAction( (__ref1)->loc, (__ref2)->augType, 0, (__ref3)->action ) ); (__ref4)->factorWithAug = (__ref5)->factorWithAug; #line 4728 "rlparse.cpp" } break; case 71: { Parser_Lel_factor_with_aug *__ref0 = (Parser_Lel_factor_with_aug*)&rhs[0]->user.factor_with_aug; Parser_Lel_aug_type *__ref1 = (Parser_Lel_aug_type*)&rhs[1]->user.aug_type; Parser_Lel_aug_type *__ref2 = (Parser_Lel_aug_type*)&rhs[1]->user.aug_type; Parser_Lel_action_ref *__ref3 = (Parser_Lel_action_ref*)&rhs[2]->user.action_ref; Parser_Lel_factor_with_aug *__ref4 = (Parser_Lel_factor_with_aug*)&redLel->user.factor_with_aug; Parser_Lel_factor_with_aug *__ref5 = (Parser_Lel_factor_with_aug*)&rhs[0]->user.factor_with_aug; #line 510 "rlparse.kl" /* Append the action, pass it up. */ (__ref0)->factorWithAug->actions.append( ParserAction( (__ref1)->loc, (__ref2)->augType, 0, (__ref3)->action ) ); (__ref4)->factorWithAug = (__ref5)->factorWithAug; #line 4745 "rlparse.cpp" } break; case 72: { Parser_Lel_factor_with_aug *__ref0 = (Parser_Lel_factor_with_aug*)&rhs[0]->user.factor_with_aug; Parser_Lel_aug_type *__ref1 = (Parser_Lel_aug_type*)&rhs[1]->user.aug_type; Parser_Lel_aug_type *__ref2 = (Parser_Lel_aug_type*)&rhs[1]->user.aug_type; Parser_Lel_action_ref *__ref3 = (Parser_Lel_action_ref*)&rhs[2]->user.action_ref; Parser_Lel_factor_with_aug *__ref4 = (Parser_Lel_factor_with_aug*)&redLel->user.factor_with_aug; Parser_Lel_factor_with_aug *__ref5 = (Parser_Lel_factor_with_aug*)&rhs[0]->user.factor_with_aug; #line 517 "rlparse.kl" /* Append the action to the factorWithAug, record the refernce from * factorWithAug to the action and pass up the factorWithAug. */ (__ref0)->factorWithAug->actions.append( ParserAction( (__ref1)->loc, (__ref2)->augType, pd->curDefLocalErrKey, (__ref3)->action ) ); (__ref4)->factorWithAug = (__ref5)->factorWithAug; #line 4763 "rlparse.cpp" } break; case 73: { Parser_Lel_factor_with_aug *__ref0 = (Parser_Lel_factor_with_aug*)&rhs[0]->user.factor_with_aug; Parser_Lel_aug_type *__ref1 = (Parser_Lel_aug_type*)&rhs[1]->user.aug_type; Parser_Lel_aug_type *__ref2 = (Parser_Lel_aug_type*)&rhs[1]->user.aug_type; Parser_Lel_action_ref *__ref3 = (Parser_Lel_action_ref*)&rhs[2]->user.action_ref; Parser_Lel_factor_with_aug *__ref4 = (Parser_Lel_factor_with_aug*)&redLel->user.factor_with_aug; Parser_Lel_factor_with_aug *__ref5 = (Parser_Lel_factor_with_aug*)&rhs[0]->user.factor_with_aug; #line 525 "rlparse.kl" /* Append the action to the factorWithAug, record the refernce from * factorWithAug to the action and pass up the factorWithAug. */ (__ref0)->factorWithAug->actions.append( ParserAction( (__ref1)->loc, (__ref2)->augType, pd->curDefLocalErrKey, (__ref3)->action ) ); (__ref4)->factorWithAug = (__ref5)->factorWithAug; #line 4781 "rlparse.cpp" } break; case 74: { Parser_Lel_factor_with_aug *__ref0 = (Parser_Lel_factor_with_aug*)&rhs[0]->user.factor_with_aug; Parser_Lel_aug_type *__ref1 = (Parser_Lel_aug_type*)&rhs[1]->user.aug_type; Parser_Lel_aug_type *__ref2 = (Parser_Lel_aug_type*)&rhs[1]->user.aug_type; Parser_Lel_local_err_name *__ref3 = (Parser_Lel_local_err_name*)&rhs[3]->user.local_err_name; Parser_Lel_action_ref *__ref4 = (Parser_Lel_action_ref*)&rhs[5]->user.action_ref; Parser_Lel_factor_with_aug *__ref5 = (Parser_Lel_factor_with_aug*)&redLel->user.factor_with_aug; Parser_Lel_factor_with_aug *__ref6 = (Parser_Lel_factor_with_aug*)&rhs[0]->user.factor_with_aug; #line 533 "rlparse.kl" /* Append the action to the factorWithAug, record the refernce from * factorWithAug to the action and pass up the factorWithAug. */ (__ref0)->factorWithAug->actions.append( ParserAction( (__ref1)->loc, (__ref2)->augType, (__ref3)->error_name, (__ref4)->action ) ); (__ref5)->factorWithAug = (__ref6)->factorWithAug; #line 4800 "rlparse.cpp" } break; case 75: { Parser_Lel_factor_with_aug *__ref0 = (Parser_Lel_factor_with_aug*)&redLel->user.factor_with_aug; Parser_Lel_factor_with_rep *__ref1 = (Parser_Lel_factor_with_rep*)&rhs[0]->user.factor_with_rep; #line 541 "rlparse.kl" (__ref0)->factorWithAug = new FactorWithAug( (__ref1)->factorWithRep ); #line 4810 "rlparse.cpp" } break; case 76: { Parser_Lel_aug_type *__ref0 = (Parser_Lel_aug_type*)&redLel->user.aug_type; Token *__ref1 = (Token*)&rhs[0]->user.token; Parser_Lel_aug_type *__ref2 = (Parser_Lel_aug_type*)&redLel->user.aug_type; #line 554 "rlparse.kl" (__ref0)->loc = (__ref1)->loc; (__ref2)->augType = at_finish; #line 4819 "rlparse.cpp" } break; case 77: { Parser_Lel_aug_type *__ref0 = (Parser_Lel_aug_type*)&redLel->user.aug_type; Token *__ref1 = (Token*)&rhs[0]->user.token; Parser_Lel_aug_type *__ref2 = (Parser_Lel_aug_type*)&redLel->user.aug_type; #line 555 "rlparse.kl" (__ref0)->loc = (__ref1)->loc; (__ref2)->augType = at_leave; #line 4828 "rlparse.cpp" } break; case 78: { Parser_Lel_aug_type *__ref0 = (Parser_Lel_aug_type*)&redLel->user.aug_type; Token *__ref1 = (Token*)&rhs[0]->user.token; Parser_Lel_aug_type *__ref2 = (Parser_Lel_aug_type*)&redLel->user.aug_type; #line 556 "rlparse.kl" (__ref0)->loc = (__ref1)->loc; (__ref2)->augType = at_all; #line 4837 "rlparse.cpp" } break; case 79: { Parser_Lel_aug_type *__ref0 = (Parser_Lel_aug_type*)&redLel->user.aug_type; Token *__ref1 = (Token*)&rhs[0]->user.token; Parser_Lel_aug_type *__ref2 = (Parser_Lel_aug_type*)&redLel->user.aug_type; #line 557 "rlparse.kl" (__ref0)->loc = (__ref1)->loc; (__ref2)->augType = at_start; #line 4846 "rlparse.cpp" } break; case 80: { Parser_Lel_aug_type *__ref0 = (Parser_Lel_aug_type*)&redLel->user.aug_type; Token *__ref1 = (Token*)&rhs[0]->user.token; Parser_Lel_aug_type *__ref2 = (Parser_Lel_aug_type*)&redLel->user.aug_type; #line 562 "rlparse.kl" (__ref0)->loc = (__ref1)->loc; (__ref2)->augType = at_start; #line 4855 "rlparse.cpp" } break; case 81: { Parser_Lel_aug_type *__ref0 = (Parser_Lel_aug_type*)&redLel->user.aug_type; Token *__ref1 = (Token*)&rhs[0]->user.token; Parser_Lel_aug_type *__ref2 = (Parser_Lel_aug_type*)&redLel->user.aug_type; #line 563 "rlparse.kl" (__ref0)->loc = (__ref1)->loc; (__ref2)->augType = at_start; #line 4864 "rlparse.cpp" } break; case 82: { Parser_Lel_aug_type *__ref0 = (Parser_Lel_aug_type*)&redLel->user.aug_type; Token *__ref1 = (Token*)&rhs[0]->user.token; Parser_Lel_aug_type *__ref2 = (Parser_Lel_aug_type*)&redLel->user.aug_type; #line 564 "rlparse.kl" (__ref0)->loc = (__ref1)->loc; (__ref2)->augType = at_all; #line 4873 "rlparse.cpp" } break; case 83: { Parser_Lel_aug_type *__ref0 = (Parser_Lel_aug_type*)&redLel->user.aug_type; Token *__ref1 = (Token*)&rhs[0]->user.token; Parser_Lel_aug_type *__ref2 = (Parser_Lel_aug_type*)&redLel->user.aug_type; #line 565 "rlparse.kl" (__ref0)->loc = (__ref1)->loc; (__ref2)->augType = at_all; #line 4882 "rlparse.cpp" } break; case 84: { Parser_Lel_aug_type *__ref0 = (Parser_Lel_aug_type*)&redLel->user.aug_type; Token *__ref1 = (Token*)&rhs[0]->user.token; Parser_Lel_aug_type *__ref2 = (Parser_Lel_aug_type*)&redLel->user.aug_type; #line 566 "rlparse.kl" (__ref0)->loc = (__ref1)->loc; (__ref2)->augType = at_leave; #line 4891 "rlparse.cpp" } break; case 85: { Parser_Lel_aug_type *__ref0 = (Parser_Lel_aug_type*)&redLel->user.aug_type; Token *__ref1 = (Token*)&rhs[0]->user.token; Parser_Lel_aug_type *__ref2 = (Parser_Lel_aug_type*)&redLel->user.aug_type; #line 567 "rlparse.kl" (__ref0)->loc = (__ref1)->loc; (__ref2)->augType = at_leave; #line 4900 "rlparse.cpp" } break; case 86: { Parser_Lel_aug_type *__ref0 = (Parser_Lel_aug_type*)&redLel->user.aug_type; Token *__ref1 = (Token*)&rhs[0]->user.token; Parser_Lel_aug_type *__ref2 = (Parser_Lel_aug_type*)&redLel->user.aug_type; #line 568 "rlparse.kl" (__ref0)->loc = (__ref1)->loc; (__ref2)->augType = at_all; #line 4909 "rlparse.cpp" } break; case 87: { Parser_Lel_aug_type *__ref0 = (Parser_Lel_aug_type*)&redLel->user.aug_type; Token *__ref1 = (Token*)&rhs[0]->user.token; Parser_Lel_aug_type *__ref2 = (Parser_Lel_aug_type*)&redLel->user.aug_type; #line 569 "rlparse.kl" (__ref0)->loc = (__ref1)->loc; (__ref2)->augType = at_start; #line 4918 "rlparse.cpp" } break; case 88: { Parser_Lel_aug_type *__ref0 = (Parser_Lel_aug_type*)&redLel->user.aug_type; Token *__ref1 = (Token*)&rhs[0]->user.token; Parser_Lel_aug_type *__ref2 = (Parser_Lel_aug_type*)&redLel->user.aug_type; #line 570 "rlparse.kl" (__ref0)->loc = (__ref1)->loc; (__ref2)->augType = at_leave; #line 4927 "rlparse.cpp" } break; case 89: { Parser_Lel_aug_type *__ref0 = (Parser_Lel_aug_type*)&redLel->user.aug_type; Token *__ref1 = (Token*)&rhs[0]->user.token; Parser_Lel_aug_type *__ref2 = (Parser_Lel_aug_type*)&redLel->user.aug_type; #line 579 "rlparse.kl" (__ref0)->loc = (__ref1)->loc; (__ref2)->augType = at_start_to_state; #line 4936 "rlparse.cpp" } break; case 90: { Parser_Lel_aug_type *__ref0 = (Parser_Lel_aug_type*)&redLel->user.aug_type; Token *__ref1 = (Token*)&rhs[0]->user.token; Parser_Lel_aug_type *__ref2 = (Parser_Lel_aug_type*)&redLel->user.aug_type; #line 581 "rlparse.kl" (__ref0)->loc = (__ref1)->loc; (__ref2)->augType = at_start_to_state; #line 4945 "rlparse.cpp" } break; case 91: { Parser_Lel_aug_type *__ref0 = (Parser_Lel_aug_type*)&redLel->user.aug_type; Token *__ref1 = (Token*)&rhs[0]->user.token; Parser_Lel_aug_type *__ref2 = (Parser_Lel_aug_type*)&redLel->user.aug_type; #line 584 "rlparse.kl" (__ref0)->loc = (__ref1)->loc; (__ref2)->augType = at_not_start_to_state; #line 4954 "rlparse.cpp" } break; case 92: { Parser_Lel_aug_type *__ref0 = (Parser_Lel_aug_type*)&redLel->user.aug_type; Token *__ref1 = (Token*)&rhs[0]->user.token; Parser_Lel_aug_type *__ref2 = (Parser_Lel_aug_type*)&redLel->user.aug_type; #line 586 "rlparse.kl" (__ref0)->loc = (__ref1)->loc; (__ref2)->augType = at_not_start_to_state; #line 4963 "rlparse.cpp" } break; case 93: { Parser_Lel_aug_type *__ref0 = (Parser_Lel_aug_type*)&redLel->user.aug_type; Token *__ref1 = (Token*)&rhs[0]->user.token; Parser_Lel_aug_type *__ref2 = (Parser_Lel_aug_type*)&redLel->user.aug_type; #line 589 "rlparse.kl" (__ref0)->loc = (__ref1)->loc; (__ref2)->augType = at_all_to_state; #line 4972 "rlparse.cpp" } break; case 94: { Parser_Lel_aug_type *__ref0 = (Parser_Lel_aug_type*)&redLel->user.aug_type; Token *__ref1 = (Token*)&rhs[0]->user.token; Parser_Lel_aug_type *__ref2 = (Parser_Lel_aug_type*)&redLel->user.aug_type; #line 591 "rlparse.kl" (__ref0)->loc = (__ref1)->loc; (__ref2)->augType = at_all_to_state; #line 4981 "rlparse.cpp" } break; case 95: { Parser_Lel_aug_type *__ref0 = (Parser_Lel_aug_type*)&redLel->user.aug_type; Token *__ref1 = (Token*)&rhs[0]->user.token; Parser_Lel_aug_type *__ref2 = (Parser_Lel_aug_type*)&redLel->user.aug_type; #line 594 "rlparse.kl" (__ref0)->loc = (__ref1)->loc; (__ref2)->augType = at_final_to_state; #line 4990 "rlparse.cpp" } break; case 96: { Parser_Lel_aug_type *__ref0 = (Parser_Lel_aug_type*)&redLel->user.aug_type; Token *__ref1 = (Token*)&rhs[0]->user.token; Parser_Lel_aug_type *__ref2 = (Parser_Lel_aug_type*)&redLel->user.aug_type; #line 596 "rlparse.kl" (__ref0)->loc = (__ref1)->loc; (__ref2)->augType = at_final_to_state; #line 4999 "rlparse.cpp" } break; case 97: { Parser_Lel_aug_type *__ref0 = (Parser_Lel_aug_type*)&redLel->user.aug_type; Token *__ref1 = (Token*)&rhs[0]->user.token; Parser_Lel_aug_type *__ref2 = (Parser_Lel_aug_type*)&redLel->user.aug_type; #line 599 "rlparse.kl" (__ref0)->loc = (__ref1)->loc; (__ref2)->augType = at_not_final_to_state; #line 5008 "rlparse.cpp" } break; case 98: { Parser_Lel_aug_type *__ref0 = (Parser_Lel_aug_type*)&redLel->user.aug_type; Token *__ref1 = (Token*)&rhs[0]->user.token; Parser_Lel_aug_type *__ref2 = (Parser_Lel_aug_type*)&redLel->user.aug_type; #line 601 "rlparse.kl" (__ref0)->loc = (__ref1)->loc; (__ref2)->augType = at_not_final_to_state; #line 5017 "rlparse.cpp" } break; case 99: { Parser_Lel_aug_type *__ref0 = (Parser_Lel_aug_type*)&redLel->user.aug_type; Token *__ref1 = (Token*)&rhs[0]->user.token; Parser_Lel_aug_type *__ref2 = (Parser_Lel_aug_type*)&redLel->user.aug_type; #line 604 "rlparse.kl" (__ref0)->loc = (__ref1)->loc; (__ref2)->augType = at_middle_to_state; #line 5026 "rlparse.cpp" } break; case 100: { Parser_Lel_aug_type *__ref0 = (Parser_Lel_aug_type*)&redLel->user.aug_type; Token *__ref1 = (Token*)&rhs[0]->user.token; Parser_Lel_aug_type *__ref2 = (Parser_Lel_aug_type*)&redLel->user.aug_type; #line 606 "rlparse.kl" (__ref0)->loc = (__ref1)->loc; (__ref2)->augType = at_middle_to_state; #line 5035 "rlparse.cpp" } break; case 101: { Parser_Lel_aug_type *__ref0 = (Parser_Lel_aug_type*)&redLel->user.aug_type; Token *__ref1 = (Token*)&rhs[0]->user.token; Parser_Lel_aug_type *__ref2 = (Parser_Lel_aug_type*)&redLel->user.aug_type; #line 615 "rlparse.kl" (__ref0)->loc = (__ref1)->loc; (__ref2)->augType = at_start_from_state; #line 5044 "rlparse.cpp" } break; case 102: { Parser_Lel_aug_type *__ref0 = (Parser_Lel_aug_type*)&redLel->user.aug_type; Token *__ref1 = (Token*)&rhs[0]->user.token; Parser_Lel_aug_type *__ref2 = (Parser_Lel_aug_type*)&redLel->user.aug_type; #line 617 "rlparse.kl" (__ref0)->loc = (__ref1)->loc; (__ref2)->augType = at_start_from_state; #line 5053 "rlparse.cpp" } break; case 103: { Parser_Lel_aug_type *__ref0 = (Parser_Lel_aug_type*)&redLel->user.aug_type; Token *__ref1 = (Token*)&rhs[0]->user.token; Parser_Lel_aug_type *__ref2 = (Parser_Lel_aug_type*)&redLel->user.aug_type; #line 620 "rlparse.kl" (__ref0)->loc = (__ref1)->loc; (__ref2)->augType = at_not_start_from_state; #line 5062 "rlparse.cpp" } break; case 104: { Parser_Lel_aug_type *__ref0 = (Parser_Lel_aug_type*)&redLel->user.aug_type; Token *__ref1 = (Token*)&rhs[0]->user.token; Parser_Lel_aug_type *__ref2 = (Parser_Lel_aug_type*)&redLel->user.aug_type; #line 622 "rlparse.kl" (__ref0)->loc = (__ref1)->loc; (__ref2)->augType = at_not_start_from_state; #line 5071 "rlparse.cpp" } break; case 105: { Parser_Lel_aug_type *__ref0 = (Parser_Lel_aug_type*)&redLel->user.aug_type; Token *__ref1 = (Token*)&rhs[0]->user.token; Parser_Lel_aug_type *__ref2 = (Parser_Lel_aug_type*)&redLel->user.aug_type; #line 625 "rlparse.kl" (__ref0)->loc = (__ref1)->loc; (__ref2)->augType = at_all_from_state; #line 5080 "rlparse.cpp" } break; case 106: { Parser_Lel_aug_type *__ref0 = (Parser_Lel_aug_type*)&redLel->user.aug_type; Token *__ref1 = (Token*)&rhs[0]->user.token; Parser_Lel_aug_type *__ref2 = (Parser_Lel_aug_type*)&redLel->user.aug_type; #line 627 "rlparse.kl" (__ref0)->loc = (__ref1)->loc; (__ref2)->augType = at_all_from_state; #line 5089 "rlparse.cpp" } break; case 107: { Parser_Lel_aug_type *__ref0 = (Parser_Lel_aug_type*)&redLel->user.aug_type; Token *__ref1 = (Token*)&rhs[0]->user.token; Parser_Lel_aug_type *__ref2 = (Parser_Lel_aug_type*)&redLel->user.aug_type; #line 630 "rlparse.kl" (__ref0)->loc = (__ref1)->loc; (__ref2)->augType = at_final_from_state; #line 5098 "rlparse.cpp" } break; case 108: { Parser_Lel_aug_type *__ref0 = (Parser_Lel_aug_type*)&redLel->user.aug_type; Token *__ref1 = (Token*)&rhs[0]->user.token; Parser_Lel_aug_type *__ref2 = (Parser_Lel_aug_type*)&redLel->user.aug_type; #line 632 "rlparse.kl" (__ref0)->loc = (__ref1)->loc; (__ref2)->augType = at_final_from_state; #line 5107 "rlparse.cpp" } break; case 109: { Parser_Lel_aug_type *__ref0 = (Parser_Lel_aug_type*)&redLel->user.aug_type; Token *__ref1 = (Token*)&rhs[0]->user.token; Parser_Lel_aug_type *__ref2 = (Parser_Lel_aug_type*)&redLel->user.aug_type; #line 635 "rlparse.kl" (__ref0)->loc = (__ref1)->loc; (__ref2)->augType = at_not_final_from_state; #line 5116 "rlparse.cpp" } break; case 110: { Parser_Lel_aug_type *__ref0 = (Parser_Lel_aug_type*)&redLel->user.aug_type; Token *__ref1 = (Token*)&rhs[0]->user.token; Parser_Lel_aug_type *__ref2 = (Parser_Lel_aug_type*)&redLel->user.aug_type; #line 637 "rlparse.kl" (__ref0)->loc = (__ref1)->loc; (__ref2)->augType = at_not_final_from_state; #line 5125 "rlparse.cpp" } break; case 111: { Parser_Lel_aug_type *__ref0 = (Parser_Lel_aug_type*)&redLel->user.aug_type; Token *__ref1 = (Token*)&rhs[0]->user.token; Parser_Lel_aug_type *__ref2 = (Parser_Lel_aug_type*)&redLel->user.aug_type; #line 640 "rlparse.kl" (__ref0)->loc = (__ref1)->loc; (__ref2)->augType = at_middle_from_state; #line 5134 "rlparse.cpp" } break; case 112: { Parser_Lel_aug_type *__ref0 = (Parser_Lel_aug_type*)&redLel->user.aug_type; Token *__ref1 = (Token*)&rhs[0]->user.token; Parser_Lel_aug_type *__ref2 = (Parser_Lel_aug_type*)&redLel->user.aug_type; #line 642 "rlparse.kl" (__ref0)->loc = (__ref1)->loc; (__ref2)->augType = at_middle_from_state; #line 5143 "rlparse.cpp" } break; case 113: { Parser_Lel_aug_type *__ref0 = (Parser_Lel_aug_type*)&redLel->user.aug_type; Token *__ref1 = (Token*)&rhs[0]->user.token; Parser_Lel_aug_type *__ref2 = (Parser_Lel_aug_type*)&redLel->user.aug_type; #line 651 "rlparse.kl" (__ref0)->loc = (__ref1)->loc; (__ref2)->augType = at_start_eof; #line 5152 "rlparse.cpp" } break; case 114: { Parser_Lel_aug_type *__ref0 = (Parser_Lel_aug_type*)&redLel->user.aug_type; Token *__ref1 = (Token*)&rhs[0]->user.token; Parser_Lel_aug_type *__ref2 = (Parser_Lel_aug_type*)&redLel->user.aug_type; #line 653 "rlparse.kl" (__ref0)->loc = (__ref1)->loc; (__ref2)->augType = at_start_eof; #line 5161 "rlparse.cpp" } break; case 115: { Parser_Lel_aug_type *__ref0 = (Parser_Lel_aug_type*)&redLel->user.aug_type; Token *__ref1 = (Token*)&rhs[0]->user.token; Parser_Lel_aug_type *__ref2 = (Parser_Lel_aug_type*)&redLel->user.aug_type; #line 656 "rlparse.kl" (__ref0)->loc = (__ref1)->loc; (__ref2)->augType = at_not_start_eof; #line 5170 "rlparse.cpp" } break; case 116: { Parser_Lel_aug_type *__ref0 = (Parser_Lel_aug_type*)&redLel->user.aug_type; Token *__ref1 = (Token*)&rhs[0]->user.token; Parser_Lel_aug_type *__ref2 = (Parser_Lel_aug_type*)&redLel->user.aug_type; #line 658 "rlparse.kl" (__ref0)->loc = (__ref1)->loc; (__ref2)->augType = at_not_start_eof; #line 5179 "rlparse.cpp" } break; case 117: { Parser_Lel_aug_type *__ref0 = (Parser_Lel_aug_type*)&redLel->user.aug_type; Token *__ref1 = (Token*)&rhs[0]->user.token; Parser_Lel_aug_type *__ref2 = (Parser_Lel_aug_type*)&redLel->user.aug_type; #line 661 "rlparse.kl" (__ref0)->loc = (__ref1)->loc; (__ref2)->augType = at_all_eof; #line 5188 "rlparse.cpp" } break; case 118: { Parser_Lel_aug_type *__ref0 = (Parser_Lel_aug_type*)&redLel->user.aug_type; Token *__ref1 = (Token*)&rhs[0]->user.token; Parser_Lel_aug_type *__ref2 = (Parser_Lel_aug_type*)&redLel->user.aug_type; #line 663 "rlparse.kl" (__ref0)->loc = (__ref1)->loc; (__ref2)->augType = at_all_eof; #line 5197 "rlparse.cpp" } break; case 119: { Parser_Lel_aug_type *__ref0 = (Parser_Lel_aug_type*)&redLel->user.aug_type; Token *__ref1 = (Token*)&rhs[0]->user.token; Parser_Lel_aug_type *__ref2 = (Parser_Lel_aug_type*)&redLel->user.aug_type; #line 666 "rlparse.kl" (__ref0)->loc = (__ref1)->loc; (__ref2)->augType = at_final_eof; #line 5206 "rlparse.cpp" } break; case 120: { Parser_Lel_aug_type *__ref0 = (Parser_Lel_aug_type*)&redLel->user.aug_type; Token *__ref1 = (Token*)&rhs[0]->user.token; Parser_Lel_aug_type *__ref2 = (Parser_Lel_aug_type*)&redLel->user.aug_type; #line 668 "rlparse.kl" (__ref0)->loc = (__ref1)->loc; (__ref2)->augType = at_final_eof; #line 5215 "rlparse.cpp" } break; case 121: { Parser_Lel_aug_type *__ref0 = (Parser_Lel_aug_type*)&redLel->user.aug_type; Token *__ref1 = (Token*)&rhs[0]->user.token; Parser_Lel_aug_type *__ref2 = (Parser_Lel_aug_type*)&redLel->user.aug_type; #line 671 "rlparse.kl" (__ref0)->loc = (__ref1)->loc; (__ref2)->augType = at_not_final_eof; #line 5224 "rlparse.cpp" } break; case 122: { Parser_Lel_aug_type *__ref0 = (Parser_Lel_aug_type*)&redLel->user.aug_type; Token *__ref1 = (Token*)&rhs[0]->user.token; Parser_Lel_aug_type *__ref2 = (Parser_Lel_aug_type*)&redLel->user.aug_type; #line 673 "rlparse.kl" (__ref0)->loc = (__ref1)->loc; (__ref2)->augType = at_not_final_eof; #line 5233 "rlparse.cpp" } break; case 123: { Parser_Lel_aug_type *__ref0 = (Parser_Lel_aug_type*)&redLel->user.aug_type; Token *__ref1 = (Token*)&rhs[0]->user.token; Parser_Lel_aug_type *__ref2 = (Parser_Lel_aug_type*)&redLel->user.aug_type; #line 676 "rlparse.kl" (__ref0)->loc = (__ref1)->loc; (__ref2)->augType = at_middle_eof; #line 5242 "rlparse.cpp" } break; case 124: { Parser_Lel_aug_type *__ref0 = (Parser_Lel_aug_type*)&redLel->user.aug_type; Token *__ref1 = (Token*)&rhs[0]->user.token; Parser_Lel_aug_type *__ref2 = (Parser_Lel_aug_type*)&redLel->user.aug_type; #line 678 "rlparse.kl" (__ref0)->loc = (__ref1)->loc; (__ref2)->augType = at_middle_eof; #line 5251 "rlparse.cpp" } break; case 125: { Parser_Lel_aug_type *__ref0 = (Parser_Lel_aug_type*)&redLel->user.aug_type; Token *__ref1 = (Token*)&rhs[0]->user.token; Parser_Lel_aug_type *__ref2 = (Parser_Lel_aug_type*)&redLel->user.aug_type; #line 687 "rlparse.kl" (__ref0)->loc = (__ref1)->loc; (__ref2)->augType = at_start_gbl_error; #line 5260 "rlparse.cpp" } break; case 126: { Parser_Lel_aug_type *__ref0 = (Parser_Lel_aug_type*)&redLel->user.aug_type; Token *__ref1 = (Token*)&rhs[0]->user.token; Parser_Lel_aug_type *__ref2 = (Parser_Lel_aug_type*)&redLel->user.aug_type; #line 689 "rlparse.kl" (__ref0)->loc = (__ref1)->loc; (__ref2)->augType = at_start_gbl_error; #line 5269 "rlparse.cpp" } break; case 127: { Parser_Lel_aug_type *__ref0 = (Parser_Lel_aug_type*)&redLel->user.aug_type; Token *__ref1 = (Token*)&rhs[0]->user.token; Parser_Lel_aug_type *__ref2 = (Parser_Lel_aug_type*)&redLel->user.aug_type; #line 692 "rlparse.kl" (__ref0)->loc = (__ref1)->loc; (__ref2)->augType = at_not_start_gbl_error; #line 5278 "rlparse.cpp" } break; case 128: { Parser_Lel_aug_type *__ref0 = (Parser_Lel_aug_type*)&redLel->user.aug_type; Token *__ref1 = (Token*)&rhs[0]->user.token; Parser_Lel_aug_type *__ref2 = (Parser_Lel_aug_type*)&redLel->user.aug_type; #line 694 "rlparse.kl" (__ref0)->loc = (__ref1)->loc; (__ref2)->augType = at_not_start_gbl_error; #line 5287 "rlparse.cpp" } break; case 129: { Parser_Lel_aug_type *__ref0 = (Parser_Lel_aug_type*)&redLel->user.aug_type; Token *__ref1 = (Token*)&rhs[0]->user.token; Parser_Lel_aug_type *__ref2 = (Parser_Lel_aug_type*)&redLel->user.aug_type; #line 697 "rlparse.kl" (__ref0)->loc = (__ref1)->loc; (__ref2)->augType = at_all_gbl_error; #line 5296 "rlparse.cpp" } break; case 130: { Parser_Lel_aug_type *__ref0 = (Parser_Lel_aug_type*)&redLel->user.aug_type; Token *__ref1 = (Token*)&rhs[0]->user.token; Parser_Lel_aug_type *__ref2 = (Parser_Lel_aug_type*)&redLel->user.aug_type; #line 699 "rlparse.kl" (__ref0)->loc = (__ref1)->loc; (__ref2)->augType = at_all_gbl_error; #line 5305 "rlparse.cpp" } break; case 131: { Parser_Lel_aug_type *__ref0 = (Parser_Lel_aug_type*)&redLel->user.aug_type; Token *__ref1 = (Token*)&rhs[0]->user.token; Parser_Lel_aug_type *__ref2 = (Parser_Lel_aug_type*)&redLel->user.aug_type; #line 702 "rlparse.kl" (__ref0)->loc = (__ref1)->loc; (__ref2)->augType = at_final_gbl_error; #line 5314 "rlparse.cpp" } break; case 132: { Parser_Lel_aug_type *__ref0 = (Parser_Lel_aug_type*)&redLel->user.aug_type; Token *__ref1 = (Token*)&rhs[0]->user.token; Parser_Lel_aug_type *__ref2 = (Parser_Lel_aug_type*)&redLel->user.aug_type; #line 704 "rlparse.kl" (__ref0)->loc = (__ref1)->loc; (__ref2)->augType = at_final_gbl_error; #line 5323 "rlparse.cpp" } break; case 133: { Parser_Lel_aug_type *__ref0 = (Parser_Lel_aug_type*)&redLel->user.aug_type; Token *__ref1 = (Token*)&rhs[0]->user.token; Parser_Lel_aug_type *__ref2 = (Parser_Lel_aug_type*)&redLel->user.aug_type; #line 707 "rlparse.kl" (__ref0)->loc = (__ref1)->loc; (__ref2)->augType = at_not_final_gbl_error; #line 5332 "rlparse.cpp" } break; case 134: { Parser_Lel_aug_type *__ref0 = (Parser_Lel_aug_type*)&redLel->user.aug_type; Token *__ref1 = (Token*)&rhs[0]->user.token; Parser_Lel_aug_type *__ref2 = (Parser_Lel_aug_type*)&redLel->user.aug_type; #line 709 "rlparse.kl" (__ref0)->loc = (__ref1)->loc; (__ref2)->augType = at_not_final_gbl_error; #line 5341 "rlparse.cpp" } break; case 135: { Parser_Lel_aug_type *__ref0 = (Parser_Lel_aug_type*)&redLel->user.aug_type; Token *__ref1 = (Token*)&rhs[0]->user.token; Parser_Lel_aug_type *__ref2 = (Parser_Lel_aug_type*)&redLel->user.aug_type; #line 712 "rlparse.kl" (__ref0)->loc = (__ref1)->loc; (__ref2)->augType = at_middle_gbl_error; #line 5350 "rlparse.cpp" } break; case 136: { Parser_Lel_aug_type *__ref0 = (Parser_Lel_aug_type*)&redLel->user.aug_type; Token *__ref1 = (Token*)&rhs[0]->user.token; Parser_Lel_aug_type *__ref2 = (Parser_Lel_aug_type*)&redLel->user.aug_type; #line 714 "rlparse.kl" (__ref0)->loc = (__ref1)->loc; (__ref2)->augType = at_middle_gbl_error; #line 5359 "rlparse.cpp" } break; case 137: { Parser_Lel_aug_type *__ref0 = (Parser_Lel_aug_type*)&redLel->user.aug_type; Token *__ref1 = (Token*)&rhs[0]->user.token; Parser_Lel_aug_type *__ref2 = (Parser_Lel_aug_type*)&redLel->user.aug_type; #line 724 "rlparse.kl" (__ref0)->loc = (__ref1)->loc; (__ref2)->augType = at_start_local_error; #line 5368 "rlparse.cpp" } break; case 138: { Parser_Lel_aug_type *__ref0 = (Parser_Lel_aug_type*)&redLel->user.aug_type; Token *__ref1 = (Token*)&rhs[0]->user.token; Parser_Lel_aug_type *__ref2 = (Parser_Lel_aug_type*)&redLel->user.aug_type; #line 726 "rlparse.kl" (__ref0)->loc = (__ref1)->loc; (__ref2)->augType = at_start_local_error; #line 5377 "rlparse.cpp" } break; case 139: { Parser_Lel_aug_type *__ref0 = (Parser_Lel_aug_type*)&redLel->user.aug_type; Token *__ref1 = (Token*)&rhs[0]->user.token; Parser_Lel_aug_type *__ref2 = (Parser_Lel_aug_type*)&redLel->user.aug_type; #line 729 "rlparse.kl" (__ref0)->loc = (__ref1)->loc; (__ref2)->augType = at_not_start_local_error; #line 5386 "rlparse.cpp" } break; case 140: { Parser_Lel_aug_type *__ref0 = (Parser_Lel_aug_type*)&redLel->user.aug_type; Token *__ref1 = (Token*)&rhs[0]->user.token; Parser_Lel_aug_type *__ref2 = (Parser_Lel_aug_type*)&redLel->user.aug_type; #line 731 "rlparse.kl" (__ref0)->loc = (__ref1)->loc; (__ref2)->augType = at_not_start_local_error; #line 5395 "rlparse.cpp" } break; case 141: { Parser_Lel_aug_type *__ref0 = (Parser_Lel_aug_type*)&redLel->user.aug_type; Token *__ref1 = (Token*)&rhs[0]->user.token; Parser_Lel_aug_type *__ref2 = (Parser_Lel_aug_type*)&redLel->user.aug_type; #line 734 "rlparse.kl" (__ref0)->loc = (__ref1)->loc; (__ref2)->augType = at_all_local_error; #line 5404 "rlparse.cpp" } break; case 142: { Parser_Lel_aug_type *__ref0 = (Parser_Lel_aug_type*)&redLel->user.aug_type; Token *__ref1 = (Token*)&rhs[0]->user.token; Parser_Lel_aug_type *__ref2 = (Parser_Lel_aug_type*)&redLel->user.aug_type; #line 736 "rlparse.kl" (__ref0)->loc = (__ref1)->loc; (__ref2)->augType = at_all_local_error; #line 5413 "rlparse.cpp" } break; case 143: { Parser_Lel_aug_type *__ref0 = (Parser_Lel_aug_type*)&redLel->user.aug_type; Token *__ref1 = (Token*)&rhs[0]->user.token; Parser_Lel_aug_type *__ref2 = (Parser_Lel_aug_type*)&redLel->user.aug_type; #line 739 "rlparse.kl" (__ref0)->loc = (__ref1)->loc; (__ref2)->augType = at_final_local_error; #line 5422 "rlparse.cpp" } break; case 144: { Parser_Lel_aug_type *__ref0 = (Parser_Lel_aug_type*)&redLel->user.aug_type; Token *__ref1 = (Token*)&rhs[0]->user.token; Parser_Lel_aug_type *__ref2 = (Parser_Lel_aug_type*)&redLel->user.aug_type; #line 741 "rlparse.kl" (__ref0)->loc = (__ref1)->loc; (__ref2)->augType = at_final_local_error; #line 5431 "rlparse.cpp" } break; case 145: { Parser_Lel_aug_type *__ref0 = (Parser_Lel_aug_type*)&redLel->user.aug_type; Token *__ref1 = (Token*)&rhs[0]->user.token; Parser_Lel_aug_type *__ref2 = (Parser_Lel_aug_type*)&redLel->user.aug_type; #line 744 "rlparse.kl" (__ref0)->loc = (__ref1)->loc; (__ref2)->augType = at_not_final_local_error; #line 5440 "rlparse.cpp" } break; case 146: { Parser_Lel_aug_type *__ref0 = (Parser_Lel_aug_type*)&redLel->user.aug_type; Token *__ref1 = (Token*)&rhs[0]->user.token; Parser_Lel_aug_type *__ref2 = (Parser_Lel_aug_type*)&redLel->user.aug_type; #line 746 "rlparse.kl" (__ref0)->loc = (__ref1)->loc; (__ref2)->augType = at_not_final_local_error; #line 5449 "rlparse.cpp" } break; case 147: { Parser_Lel_aug_type *__ref0 = (Parser_Lel_aug_type*)&redLel->user.aug_type; Token *__ref1 = (Token*)&rhs[0]->user.token; Parser_Lel_aug_type *__ref2 = (Parser_Lel_aug_type*)&redLel->user.aug_type; #line 749 "rlparse.kl" (__ref0)->loc = (__ref1)->loc; (__ref2)->augType = at_middle_local_error; #line 5458 "rlparse.cpp" } break; case 148: { Parser_Lel_aug_type *__ref0 = (Parser_Lel_aug_type*)&redLel->user.aug_type; Token *__ref1 = (Token*)&rhs[0]->user.token; Parser_Lel_aug_type *__ref2 = (Parser_Lel_aug_type*)&redLel->user.aug_type; #line 751 "rlparse.kl" (__ref0)->loc = (__ref1)->loc; (__ref2)->augType = at_middle_local_error; #line 5467 "rlparse.cpp" } break; case 149: { Parser_Lel_action_ref *__ref0 = (Parser_Lel_action_ref*)&redLel->user.action_ref; Parser_Lel_action_ref *__ref1 = (Parser_Lel_action_ref*)&rhs[0]->user.action_ref; #line 764 "rlparse.kl" (__ref0)->action = (__ref1)->action; #line 5475 "rlparse.cpp" } break; case 150: { Parser_Lel_action_ref *__ref0 = (Parser_Lel_action_ref*)&redLel->user.action_ref; Parser_Lel_action_ref *__ref1 = (Parser_Lel_action_ref*)&rhs[1]->user.action_ref; #line 765 "rlparse.kl" (__ref0)->action = (__ref1)->action; #line 5483 "rlparse.cpp" } break; case 151: { Parser_Lel_action_ref *__ref0 = (Parser_Lel_action_ref*)&redLel->user.action_ref; Parser_Lel_action_ref *__ref1 = (Parser_Lel_action_ref*)&rhs[0]->user.action_ref; #line 766 "rlparse.kl" (__ref0)->action = (__ref1)->action; #line 5491 "rlparse.cpp" } break; case 152: { Token *__ref0 = (Token*)&rhs[0]->user.token; Parser_Lel_action_ref *__ref1 = (Parser_Lel_action_ref*)&redLel->user.action_ref; Token *__ref2 = (Token*)&rhs[0]->user.token; Token *__ref3 = (Token*)&rhs[0]->user.token; Parser_Lel_action_ref *__ref4 = (Parser_Lel_action_ref*)&redLel->user.action_ref; #line 771 "rlparse.kl" /* Set the name in the actionDict. */ Action *action = pd->actionDict.find( (__ref0)->data ); if ( action != 0 ) { /* Pass up the action element */ (__ref1)->action = action; } else { /* Will recover by returning null as the action. */ error((__ref2)->loc) << "action lookup of \"" << (__ref3)->data << "\" failed" << endl; (__ref4)->action = 0; } #line 5514 "rlparse.cpp" } break; case 153: { Token *__ref0 = (Token*)&rhs[0]->user.token; Parser_Lel_inline_list *__ref1 = (Parser_Lel_inline_list*)&rhs[1]->user.inline_list; Parser_Lel_action_ref *__ref2 = (Parser_Lel_action_ref*)&redLel->user.action_ref; #line 788 "rlparse.kl" /* Create the action, add it to the list and pass up. */ Action *newAction = new Action( (__ref0)->loc, 0, (__ref1)->inlineList, pd->nextCondId++ ); pd->actionList.append( newAction ); (__ref2)->action = newAction; #line 5528 "rlparse.cpp" } break; case 154: { Token *__ref0 = (Token*)&rhs[0]->user.token; Parser_Lel_priority_name *__ref1 = (Parser_Lel_priority_name*)&redLel->user.priority_name; #line 803 "rlparse.kl" // Lookup/create the priority key. PriorDictEl *priorDictEl; if ( pd->priorDict.insert( (__ref0)->data, pd->nextPriorKey, &priorDictEl ) ) pd->nextPriorKey += 1; // Use the inserted/found priority key. (__ref1)->priorityName = priorDictEl->value; #line 5544 "rlparse.cpp" } break; case 155: { Parser_Lel_token_type *__ref0 = (Parser_Lel_token_type*)&rhs[0]->user.token_type; Parser_Lel_token_type *__ref1 = (Parser_Lel_token_type*)&rhs[0]->user.token_type; Parser_Lel_token_type *__ref2 = (Parser_Lel_token_type*)&rhs[0]->user.token_type; Parser_Lel_priority_aug *__ref3 = (Parser_Lel_priority_aug*)&redLel->user.priority_aug; Parser_Lel_token_type *__ref4 = (Parser_Lel_token_type*)&rhs[0]->user.token_type; Parser_Lel_token_type *__ref5 = (Parser_Lel_token_type*)&rhs[0]->user.token_type; Parser_Lel_priority_aug *__ref6 = (Parser_Lel_priority_aug*)&redLel->user.priority_aug; Parser_Lel_priority_aug *__ref7 = (Parser_Lel_priority_aug*)&redLel->user.priority_aug; #line 820 "rlparse.kl" // Convert the priority number to a long. Check for overflow. errno = 0; //cerr << "PRIOR AUG: " << $1->token.data << endl; long aug = strtol( (__ref0)->token.data, 0, 10 ); if ( errno == ERANGE && aug == LONG_MAX ) { /* Priority number too large. Recover by setting the priority to 0. */ error((__ref1)->token.loc) << "priority number " << (__ref2)->token.data << " overflows" << endl; (__ref3)->priorityNum = 0; } else if ( errno == ERANGE && aug == LONG_MIN ) { /* Priority number too large in the neg. Recover by using 0. */ error((__ref4)->token.loc) << "priority number " << (__ref5)->token.data << " underflows" << endl; (__ref6)->priorityNum = 0; } else { /* No overflow or underflow. */ (__ref7)->priorityNum = aug; } #line 5579 "rlparse.cpp" } break; case 156: { Parser_Lel_token_type *__ref0 = (Parser_Lel_token_type*)&redLel->user.token_type; Token *__ref1 = (Token*)&rhs[0]->user.token; #line 846 "rlparse.kl" (__ref0)->token = *(__ref1); #line 5589 "rlparse.cpp" } break; case 157: { Parser_Lel_token_type *__ref0 = (Parser_Lel_token_type*)&redLel->user.token_type; Parser_Lel_token_type *__ref1 = (Parser_Lel_token_type*)&redLel->user.token_type; Token *__ref2 = (Token*)&rhs[0]->user.token; Parser_Lel_token_type *__ref3 = (Parser_Lel_token_type*)&redLel->user.token_type; Token *__ref4 = (Token*)&rhs[1]->user.token; #line 850 "rlparse.kl" (__ref0)->token.set( "+", 1 ); (__ref1)->token.loc = (__ref2)->loc; (__ref3)->token.append( *(__ref4) ); #line 5604 "rlparse.cpp" } break; case 158: { Parser_Lel_token_type *__ref0 = (Parser_Lel_token_type*)&redLel->user.token_type; Parser_Lel_token_type *__ref1 = (Parser_Lel_token_type*)&redLel->user.token_type; Token *__ref2 = (Token*)&rhs[0]->user.token; Parser_Lel_token_type *__ref3 = (Parser_Lel_token_type*)&redLel->user.token_type; Token *__ref4 = (Token*)&rhs[1]->user.token; #line 856 "rlparse.kl" (__ref0)->token.set( "-", 1 ); (__ref1)->token.loc = (__ref2)->loc; (__ref3)->token.append( *(__ref4) ); #line 5619 "rlparse.cpp" } break; case 159: { Token *__ref0 = (Token*)&rhs[0]->user.token; Parser_Lel_local_err_name *__ref1 = (Parser_Lel_local_err_name*)&redLel->user.local_err_name; #line 868 "rlparse.kl" /* Lookup/create the priority key. */ LocalErrDictEl *localErrDictEl; if ( pd->localErrDict.insert( (__ref0)->data, pd->nextLocalErrKey, &localErrDictEl ) ) pd->nextLocalErrKey += 1; /* Use the inserted/found priority key. */ (__ref1)->error_name = localErrDictEl->value; #line 5635 "rlparse.cpp" } break; case 160: { Parser_Lel_factor_with_rep *__ref0 = (Parser_Lel_factor_with_rep*)&redLel->user.factor_with_rep; Token *__ref1 = (Token*)&rhs[1]->user.token; Parser_Lel_factor_with_rep *__ref2 = (Parser_Lel_factor_with_rep*)&rhs[0]->user.factor_with_rep; #line 889 "rlparse.kl" (__ref0)->factorWithRep = new FactorWithRep( (__ref1)->loc, (__ref2)->factorWithRep, 0, 0, FactorWithRep::StarType ); #line 5647 "rlparse.cpp" } break; case 161: { Parser_Lel_factor_with_rep *__ref0 = (Parser_Lel_factor_with_rep*)&redLel->user.factor_with_rep; Token *__ref1 = (Token*)&rhs[1]->user.token; Parser_Lel_factor_with_rep *__ref2 = (Parser_Lel_factor_with_rep*)&rhs[0]->user.factor_with_rep; #line 894 "rlparse.kl" (__ref0)->factorWithRep = new FactorWithRep( (__ref1)->loc, (__ref2)->factorWithRep, 0, 0, FactorWithRep::StarStarType ); #line 5659 "rlparse.cpp" } break; case 162: { Parser_Lel_factor_with_rep *__ref0 = (Parser_Lel_factor_with_rep*)&redLel->user.factor_with_rep; Token *__ref1 = (Token*)&rhs[1]->user.token; Parser_Lel_factor_with_rep *__ref2 = (Parser_Lel_factor_with_rep*)&rhs[0]->user.factor_with_rep; #line 899 "rlparse.kl" (__ref0)->factorWithRep = new FactorWithRep( (__ref1)->loc, (__ref2)->factorWithRep, 0, 0, FactorWithRep::OptionalType ); #line 5671 "rlparse.cpp" } break; case 163: { Parser_Lel_factor_with_rep *__ref0 = (Parser_Lel_factor_with_rep*)&redLel->user.factor_with_rep; Token *__ref1 = (Token*)&rhs[1]->user.token; Parser_Lel_factor_with_rep *__ref2 = (Parser_Lel_factor_with_rep*)&rhs[0]->user.factor_with_rep; #line 904 "rlparse.kl" (__ref0)->factorWithRep = new FactorWithRep( (__ref1)->loc, (__ref2)->factorWithRep, 0, 0, FactorWithRep::PlusType ); #line 5683 "rlparse.cpp" } break; case 164: { Parser_Lel_factor_with_rep *__ref0 = (Parser_Lel_factor_with_rep*)&redLel->user.factor_with_rep; Token *__ref1 = (Token*)&rhs[1]->user.token; Parser_Lel_factor_with_rep *__ref2 = (Parser_Lel_factor_with_rep*)&rhs[0]->user.factor_with_rep; Parser_Lel_factor_rep_num *__ref3 = (Parser_Lel_factor_rep_num*)&rhs[2]->user.factor_rep_num; #line 909 "rlparse.kl" (__ref0)->factorWithRep = new FactorWithRep( (__ref1)->loc, (__ref2)->factorWithRep, (__ref3)->rep, 0, FactorWithRep::ExactType ); #line 5696 "rlparse.cpp" } break; case 165: { Parser_Lel_factor_with_rep *__ref0 = (Parser_Lel_factor_with_rep*)&redLel->user.factor_with_rep; Token *__ref1 = (Token*)&rhs[1]->user.token; Parser_Lel_factor_with_rep *__ref2 = (Parser_Lel_factor_with_rep*)&rhs[0]->user.factor_with_rep; Parser_Lel_factor_rep_num *__ref3 = (Parser_Lel_factor_rep_num*)&rhs[3]->user.factor_rep_num; #line 914 "rlparse.kl" (__ref0)->factorWithRep = new FactorWithRep( (__ref1)->loc, (__ref2)->factorWithRep, 0, (__ref3)->rep, FactorWithRep::MaxType ); #line 5709 "rlparse.cpp" } break; case 166: { Parser_Lel_factor_with_rep *__ref0 = (Parser_Lel_factor_with_rep*)&redLel->user.factor_with_rep; Token *__ref1 = (Token*)&rhs[1]->user.token; Parser_Lel_factor_with_rep *__ref2 = (Parser_Lel_factor_with_rep*)&rhs[0]->user.factor_with_rep; Parser_Lel_factor_rep_num *__ref3 = (Parser_Lel_factor_rep_num*)&rhs[2]->user.factor_rep_num; #line 919 "rlparse.kl" (__ref0)->factorWithRep = new FactorWithRep( (__ref1)->loc, (__ref2)->factorWithRep, (__ref3)->rep, 0, FactorWithRep::MinType ); #line 5722 "rlparse.cpp" } break; case 167: { Parser_Lel_factor_with_rep *__ref0 = (Parser_Lel_factor_with_rep*)&redLel->user.factor_with_rep; Token *__ref1 = (Token*)&rhs[1]->user.token; Parser_Lel_factor_with_rep *__ref2 = (Parser_Lel_factor_with_rep*)&rhs[0]->user.factor_with_rep; Parser_Lel_factor_rep_num *__ref3 = (Parser_Lel_factor_rep_num*)&rhs[2]->user.factor_rep_num; Parser_Lel_factor_rep_num *__ref4 = (Parser_Lel_factor_rep_num*)&rhs[4]->user.factor_rep_num; #line 924 "rlparse.kl" (__ref0)->factorWithRep = new FactorWithRep( (__ref1)->loc, (__ref2)->factorWithRep, (__ref3)->rep, (__ref4)->rep, FactorWithRep::RangeType ); #line 5736 "rlparse.cpp" } break; case 168: { Parser_Lel_factor_with_rep *__ref0 = (Parser_Lel_factor_with_rep*)&redLel->user.factor_with_rep; Parser_Lel_factor_with_neg *__ref1 = (Parser_Lel_factor_with_neg*)&rhs[0]->user.factor_with_neg; #line 929 "rlparse.kl" (__ref0)->factorWithRep = new FactorWithRep( (__ref1)->factorWithNeg ); #line 5746 "rlparse.cpp" } break; case 169: { Token *__ref0 = (Token*)&rhs[0]->user.token; Token *__ref1 = (Token*)&rhs[0]->user.token; Token *__ref2 = (Token*)&rhs[0]->user.token; Parser_Lel_factor_rep_num *__ref3 = (Parser_Lel_factor_rep_num*)&redLel->user.factor_rep_num; Parser_Lel_factor_rep_num *__ref4 = (Parser_Lel_factor_rep_num*)&redLel->user.factor_rep_num; #line 939 "rlparse.kl" // Convert the priority number to a long. Check for overflow. errno = 0; long rep = strtol( (__ref0)->data, 0, 10 ); if ( errno == ERANGE && rep == LONG_MAX ) { // Repetition too large. Recover by returing repetition 1. */ error((__ref1)->loc) << "repetition number " << (__ref2)->data << " overflows" << endl; (__ref3)->rep = 1; } else { // Cannot be negative, so no overflow. (__ref4)->rep = rep; } #line 5770 "rlparse.cpp" } break; case 170: { Parser_Lel_factor_with_neg *__ref0 = (Parser_Lel_factor_with_neg*)&redLel->user.factor_with_neg; Token *__ref1 = (Token*)&rhs[0]->user.token; Parser_Lel_factor_with_neg *__ref2 = (Parser_Lel_factor_with_neg*)&rhs[1]->user.factor_with_neg; #line 965 "rlparse.kl" (__ref0)->factorWithNeg = new FactorWithNeg( (__ref1)->loc, (__ref2)->factorWithNeg, FactorWithNeg::NegateType ); #line 5782 "rlparse.cpp" } break; case 171: { Parser_Lel_factor_with_neg *__ref0 = (Parser_Lel_factor_with_neg*)&redLel->user.factor_with_neg; Token *__ref1 = (Token*)&rhs[0]->user.token; Parser_Lel_factor_with_neg *__ref2 = (Parser_Lel_factor_with_neg*)&rhs[1]->user.factor_with_neg; #line 970 "rlparse.kl" (__ref0)->factorWithNeg = new FactorWithNeg( (__ref1)->loc, (__ref2)->factorWithNeg, FactorWithNeg::CharNegateType ); #line 5794 "rlparse.cpp" } break; case 172: { Parser_Lel_factor_with_neg *__ref0 = (Parser_Lel_factor_with_neg*)&redLel->user.factor_with_neg; Parser_Lel_factor *__ref1 = (Parser_Lel_factor*)&rhs[0]->user.factor; #line 975 "rlparse.kl" (__ref0)->factorWithNeg = new FactorWithNeg( (__ref1)->factor ); #line 5804 "rlparse.cpp" } break; case 173: { Parser_Lel_factor *__ref0 = (Parser_Lel_factor*)&redLel->user.factor; Token *__ref1 = (Token*)&rhs[0]->user.token; #line 985 "rlparse.kl" /* Create a new factor node going to a concat literal. */ (__ref0)->factor = new Factor( new Literal( *(__ref1), Literal::LitString ) ); #line 5815 "rlparse.cpp" } break; case 174: { Parser_Lel_factor *__ref0 = (Parser_Lel_factor*)&redLel->user.factor; Parser_Lel_token_type *__ref1 = (Parser_Lel_token_type*)&rhs[0]->user.token_type; #line 990 "rlparse.kl" /* Create a new factor node going to a literal number. */ (__ref0)->factor = new Factor( new Literal( (__ref1)->token, Literal::Number ) ); #line 5826 "rlparse.cpp" } break; case 175: { Token *__ref0 = (Token*)&rhs[0]->user.token; Token *__ref1 = (Token*)&rhs[0]->user.token; Token *__ref2 = (Token*)&rhs[0]->user.token; Parser_Lel_factor *__ref3 = (Parser_Lel_factor*)&redLel->user.factor; Token *__ref4 = (Token*)&rhs[0]->user.token; Parser_Lel_factor *__ref5 = (Parser_Lel_factor*)&redLel->user.factor; Parser_Lel_factor *__ref6 = (Parser_Lel_factor*)&redLel->user.factor; Token *__ref7 = (Token*)&rhs[0]->user.token; #line 995 "rlparse.kl" /* Find the named graph. */ GraphDictEl *gdNode = pd->graphDict.find( (__ref0)->data ); if ( gdNode == 0 ) { /* Recover by returning null as the factor node. */ error((__ref1)->loc) << "graph lookup of \"" << (__ref2)->data << "\" failed" << endl; (__ref3)->factor = 0; } else if ( gdNode->isInstance ) { /* Recover by retuning null as the factor node. */ error((__ref4)->loc) << "references to graph instantiations not allowed " "in expressions" << endl; (__ref5)->factor = 0; } else { /* Create a factor node that is a lookup of an expression. */ (__ref6)->factor = new Factor( (__ref7)->loc, gdNode->value ); } #line 5858 "rlparse.cpp" } break; case 176: { Parser_Lel_factor *__ref0 = (Parser_Lel_factor*)&redLel->user.factor; Token *__ref1 = (Token*)&rhs[0]->user.token; Parser_Lel_regular_expr_or_data *__ref2 = (Parser_Lel_regular_expr_or_data*)&rhs[1]->user.regular_expr_or_data; #line 1015 "rlparse.kl" /* Create a new factor node going to an OR expression. */ (__ref0)->factor = new Factor( new ReItem( (__ref1)->loc, (__ref2)->reOrBlock, ReItem::OrBlock ) ); #line 5870 "rlparse.cpp" } break; case 177: { Parser_Lel_factor *__ref0 = (Parser_Lel_factor*)&redLel->user.factor; Token *__ref1 = (Token*)&rhs[0]->user.token; Parser_Lel_regular_expr_or_data *__ref2 = (Parser_Lel_regular_expr_or_data*)&rhs[1]->user.regular_expr_or_data; #line 1020 "rlparse.kl" /* Create a new factor node going to a negated OR expression. */ (__ref0)->factor = new Factor( new ReItem( (__ref1)->loc, (__ref2)->reOrBlock, ReItem::NegOrBlock ) ); #line 5882 "rlparse.cpp" } break; case 178: { Token *__ref0 = (Token*)&rhs[2]->user.token; Token *__ref1 = (Token*)&rhs[2]->user.token; Parser_Lel_regular_expr *__ref2 = (Parser_Lel_regular_expr*)&rhs[1]->user.regular_expr; Parser_Lel_factor *__ref3 = (Parser_Lel_factor*)&redLel->user.factor; Parser_Lel_regular_expr *__ref4 = (Parser_Lel_regular_expr*)&rhs[1]->user.regular_expr; #line 1025 "rlparse.kl" if ( (__ref0)->length > 1 ) { for ( char *p = (__ref1)->data; *p != 0; p++ ) { if ( *p == 'i' ) (__ref2)->regExpr->caseInsensitive = true; } } /* Create a new factor node going to a regular exp. */ (__ref3)->factor = new Factor( (__ref4)->regExpr ); #line 5903 "rlparse.cpp" } break; case 179: { Parser_Lel_factor *__ref0 = (Parser_Lel_factor*)&redLel->user.factor; Parser_Lel_range_lit *__ref1 = (Parser_Lel_range_lit*)&rhs[0]->user.range_lit; Parser_Lel_range_lit *__ref2 = (Parser_Lel_range_lit*)&rhs[2]->user.range_lit; #line 1037 "rlparse.kl" /* Create a new factor node going to a range. */ (__ref0)->factor = new Factor( new Range( (__ref1)->literal, (__ref2)->literal ) ); #line 5915 "rlparse.cpp" } break; case 180: { Parser_Lel_factor *__ref0 = (Parser_Lel_factor*)&redLel->user.factor; Parser_Lel_join *__ref1 = (Parser_Lel_join*)&rhs[1]->user.join; Parser_Lel_join *__ref2 = (Parser_Lel_join*)&rhs[1]->user.join; Token *__ref3 = (Token*)&rhs[0]->user.token; #line 1042 "rlparse.kl" /* Create a new factor going to a parenthesized join. */ (__ref0)->factor = new Factor( (__ref1)->join ); (__ref2)->join->loc = (__ref3)->loc; #line 5929 "rlparse.cpp" } break; case 181: { Parser_Lel_range_lit *__ref0 = (Parser_Lel_range_lit*)&redLel->user.range_lit; Token *__ref1 = (Token*)&rhs[0]->user.token; #line 1055 "rlparse.kl" /* Range literas must have only one char. We restrict this in the parse tree. */ (__ref0)->literal = new Literal( *(__ref1), Literal::LitString ); #line 5940 "rlparse.cpp" } break; case 182: { Parser_Lel_range_lit *__ref0 = (Parser_Lel_range_lit*)&redLel->user.range_lit; Parser_Lel_token_type *__ref1 = (Parser_Lel_token_type*)&rhs[0]->user.token_type; #line 1060 "rlparse.kl" /* Create a new literal number. */ (__ref0)->literal = new Literal( (__ref1)->token, Literal::Number ); #line 5951 "rlparse.cpp" } break; case 183: { Parser_Lel_token_type *__ref0 = (Parser_Lel_token_type*)&redLel->user.token_type; Token *__ref1 = (Token*)&rhs[0]->user.token; #line 1069 "rlparse.kl" (__ref0)->token = *(__ref1); #line 5961 "rlparse.cpp" } break; case 184: { Parser_Lel_token_type *__ref0 = (Parser_Lel_token_type*)&redLel->user.token_type; Parser_Lel_token_type *__ref1 = (Parser_Lel_token_type*)&redLel->user.token_type; Token *__ref2 = (Token*)&rhs[0]->user.token; Parser_Lel_token_type *__ref3 = (Parser_Lel_token_type*)&redLel->user.token_type; Token *__ref4 = (Token*)&rhs[1]->user.token; #line 1073 "rlparse.kl" (__ref0)->token.set( "-", 1 ); (__ref1)->token.loc = (__ref2)->loc; (__ref3)->token.append( *(__ref4) ); #line 5976 "rlparse.cpp" } break; case 185: { Parser_Lel_token_type *__ref0 = (Parser_Lel_token_type*)&redLel->user.token_type; Token *__ref1 = (Token*)&rhs[0]->user.token; #line 1079 "rlparse.kl" (__ref0)->token = *(__ref1); #line 5986 "rlparse.cpp" } break; case 186: { Parser_Lel_regular_expr_item *__ref0 = (Parser_Lel_regular_expr_item*)&rhs[1]->user.regular_expr_item; Parser_Lel_regular_expr_item *__ref1 = (Parser_Lel_regular_expr_item*)&rhs[1]->user.regular_expr_item; Parser_Lel_regular_expr *__ref2 = (Parser_Lel_regular_expr*)&rhs[0]->user.regular_expr; Parser_Lel_regular_expr *__ref3 = (Parser_Lel_regular_expr*)&rhs[0]->user.regular_expr; Parser_Lel_regular_expr *__ref4 = (Parser_Lel_regular_expr*)&rhs[0]->user.regular_expr; Parser_Lel_regular_expr *__ref5 = (Parser_Lel_regular_expr*)&rhs[0]->user.regular_expr; Parser_Lel_regular_expr_item *__ref6 = (Parser_Lel_regular_expr_item*)&rhs[1]->user.regular_expr_item; Parser_Lel_regular_expr_item *__ref7 = (Parser_Lel_regular_expr_item*)&rhs[1]->user.regular_expr_item; Parser_Lel_regular_expr *__ref8 = (Parser_Lel_regular_expr*)&redLel->user.regular_expr; Parser_Lel_regular_expr *__ref9 = (Parser_Lel_regular_expr*)&rhs[0]->user.regular_expr; Parser_Lel_regular_expr *__ref10 = (Parser_Lel_regular_expr*)&redLel->user.regular_expr; Parser_Lel_regular_expr *__ref11 = (Parser_Lel_regular_expr*)&rhs[0]->user.regular_expr; Parser_Lel_regular_expr_item *__ref12 = (Parser_Lel_regular_expr_item*)&rhs[1]->user.regular_expr_item; #line 1094 "rlparse.kl" /* An optimization to lessen the tree size. If a non-starred char is * directly under the left side on the right and the right side is * another non-starred char then paste them together and return the * left side. Otherwise just put the two under a new reg exp node. */ if ( (__ref0)->reItem->type == ReItem::Data && !(__ref1)->reItem->star && (__ref2)->regExpr->type == RegExpr::RecurseItem && (__ref3)->regExpr->item->type == ReItem::Data && !(__ref4)->regExpr->item->star ) { /* Append the right side to the right side of the left and toss the * right side. */ (__ref5)->regExpr->item->token.append( (__ref6)->reItem->token ); delete (__ref7)->reItem; (__ref8)->regExpr = (__ref9)->regExpr; } else { (__ref10)->regExpr = new RegExpr( (__ref11)->regExpr, (__ref12)->reItem ); } #line 6023 "rlparse.cpp" } break; case 187: { Parser_Lel_regular_expr *__ref0 = (Parser_Lel_regular_expr*)&redLel->user.regular_expr; #line 1114 "rlparse.kl" /* Can't optimize the tree. */ (__ref0)->regExpr = new RegExpr(); #line 6033 "rlparse.cpp" } break; case 188: { Parser_Lel_regular_expr_char *__ref0 = (Parser_Lel_regular_expr_char*)&rhs[0]->user.regular_expr_char; Parser_Lel_regular_expr_item *__ref1 = (Parser_Lel_regular_expr_item*)&redLel->user.regular_expr_item; Parser_Lel_regular_expr_char *__ref2 = (Parser_Lel_regular_expr_char*)&rhs[0]->user.regular_expr_char; #line 1126 "rlparse.kl" (__ref0)->reItem->star = true; (__ref1)->reItem = (__ref2)->reItem; #line 6045 "rlparse.cpp" } break; case 189: { Parser_Lel_regular_expr_item *__ref0 = (Parser_Lel_regular_expr_item*)&redLel->user.regular_expr_item; Parser_Lel_regular_expr_char *__ref1 = (Parser_Lel_regular_expr_char*)&rhs[0]->user.regular_expr_char; #line 1131 "rlparse.kl" (__ref0)->reItem = (__ref1)->reItem; #line 6055 "rlparse.cpp" } break; case 190: { Parser_Lel_regular_expr_char *__ref0 = (Parser_Lel_regular_expr_char*)&redLel->user.regular_expr_char; Token *__ref1 = (Token*)&rhs[0]->user.token; Parser_Lel_regular_expr_or_data *__ref2 = (Parser_Lel_regular_expr_or_data*)&rhs[1]->user.regular_expr_or_data; #line 1143 "rlparse.kl" (__ref0)->reItem = new ReItem( (__ref1)->loc, (__ref2)->reOrBlock, ReItem::OrBlock ); #line 6066 "rlparse.cpp" } break; case 191: { Parser_Lel_regular_expr_char *__ref0 = (Parser_Lel_regular_expr_char*)&redLel->user.regular_expr_char; Token *__ref1 = (Token*)&rhs[0]->user.token; Parser_Lel_regular_expr_or_data *__ref2 = (Parser_Lel_regular_expr_or_data*)&rhs[1]->user.regular_expr_or_data; #line 1147 "rlparse.kl" (__ref0)->reItem = new ReItem( (__ref1)->loc, (__ref2)->reOrBlock, ReItem::NegOrBlock ); #line 6077 "rlparse.cpp" } break; case 192: { Parser_Lel_regular_expr_char *__ref0 = (Parser_Lel_regular_expr_char*)&redLel->user.regular_expr_char; Token *__ref1 = (Token*)&rhs[0]->user.token; #line 1151 "rlparse.kl" (__ref0)->reItem = new ReItem( (__ref1)->loc, ReItem::Dot ); #line 6087 "rlparse.cpp" } break; case 193: { Parser_Lel_regular_expr_char *__ref0 = (Parser_Lel_regular_expr_char*)&redLel->user.regular_expr_char; Token *__ref1 = (Token*)&rhs[0]->user.token; Token *__ref2 = (Token*)&rhs[0]->user.token; #line 1155 "rlparse.kl" (__ref0)->reItem = new ReItem( (__ref1)->loc, *(__ref2) ); #line 6098 "rlparse.cpp" } break; case 194: { Parser_Lel_regular_expr_or_char *__ref0 = (Parser_Lel_regular_expr_or_char*)&rhs[1]->user.regular_expr_or_char; Parser_Lel_regular_expr_or_data *__ref1 = (Parser_Lel_regular_expr_or_data*)&rhs[0]->user.regular_expr_or_data; Parser_Lel_regular_expr_or_data *__ref2 = (Parser_Lel_regular_expr_or_data*)&rhs[0]->user.regular_expr_or_data; Parser_Lel_regular_expr_or_data *__ref3 = (Parser_Lel_regular_expr_or_data*)&rhs[0]->user.regular_expr_or_data; Parser_Lel_regular_expr_or_char *__ref4 = (Parser_Lel_regular_expr_or_char*)&rhs[1]->user.regular_expr_or_char; Parser_Lel_regular_expr_or_char *__ref5 = (Parser_Lel_regular_expr_or_char*)&rhs[1]->user.regular_expr_or_char; Parser_Lel_regular_expr_or_data *__ref6 = (Parser_Lel_regular_expr_or_data*)&redLel->user.regular_expr_or_data; Parser_Lel_regular_expr_or_data *__ref7 = (Parser_Lel_regular_expr_or_data*)&rhs[0]->user.regular_expr_or_data; Parser_Lel_regular_expr_or_data *__ref8 = (Parser_Lel_regular_expr_or_data*)&redLel->user.regular_expr_or_data; Parser_Lel_regular_expr_or_data *__ref9 = (Parser_Lel_regular_expr_or_data*)&rhs[0]->user.regular_expr_or_data; Parser_Lel_regular_expr_or_char *__ref10 = (Parser_Lel_regular_expr_or_char*)&rhs[1]->user.regular_expr_or_char; #line 1167 "rlparse.kl" /* An optimization to lessen the tree size. If an or char is directly * under the left side on the right and the right side is another or * char then paste them together and return the left side. Otherwise * just put the two under a new or data node. */ if ( (__ref0)->reOrItem->type == ReOrItem::Data && (__ref1)->reOrBlock->type == ReOrBlock::RecurseItem && (__ref2)->reOrBlock->item->type == ReOrItem::Data ) { /* Append the right side to right side of the left and toss the * right side. */ (__ref3)->reOrBlock->item->token.append( (__ref4)->reOrItem->token ); delete (__ref5)->reOrItem; (__ref6)->reOrBlock = (__ref7)->reOrBlock; } else { /* Can't optimize, put the left and right under a new node. */ (__ref8)->reOrBlock = new ReOrBlock( (__ref9)->reOrBlock, (__ref10)->reOrItem ); } #line 6134 "rlparse.cpp" } break; case 195: { Parser_Lel_regular_expr_or_data *__ref0 = (Parser_Lel_regular_expr_or_data*)&redLel->user.regular_expr_or_data; #line 1188 "rlparse.kl" (__ref0)->reOrBlock = new ReOrBlock(); #line 6143 "rlparse.cpp" } break; case 196: { Parser_Lel_regular_expr_or_char *__ref0 = (Parser_Lel_regular_expr_or_char*)&redLel->user.regular_expr_or_char; Token *__ref1 = (Token*)&rhs[0]->user.token; Token *__ref2 = (Token*)&rhs[0]->user.token; #line 1200 "rlparse.kl" (__ref0)->reOrItem = new ReOrItem( (__ref1)->loc, *(__ref2) ); #line 6154 "rlparse.cpp" } break; case 197: { Parser_Lel_regular_expr_or_char *__ref0 = (Parser_Lel_regular_expr_or_char*)&redLel->user.regular_expr_or_char; Token *__ref1 = (Token*)&rhs[1]->user.token; Token *__ref2 = (Token*)&rhs[0]->user.token; Token *__ref3 = (Token*)&rhs[2]->user.token; #line 1204 "rlparse.kl" (__ref0)->reOrItem = new ReOrItem( (__ref1)->loc, (__ref2)->data[0], (__ref3)->data[0] ); #line 6166 "rlparse.cpp" } break; case 198: { Parser_Lel_inline_list *__ref0 = (Parser_Lel_inline_list*)&redLel->user.inline_list; Parser_Lel_inline_list *__ref1 = (Parser_Lel_inline_list*)&rhs[0]->user.inline_list; Parser_Lel_inline_list *__ref2 = (Parser_Lel_inline_list*)&redLel->user.inline_list; Parser_Lel_inline_item *__ref3 = (Parser_Lel_inline_item*)&rhs[1]->user.inline_item; #line 1221 "rlparse.kl" /* Append the item to the list, return the list. */ (__ref0)->inlineList = (__ref1)->inlineList; (__ref2)->inlineList->append( (__ref3)->inlineItem ); #line 6180 "rlparse.cpp" } break; case 199: { Parser_Lel_inline_list *__ref0 = (Parser_Lel_inline_list*)&redLel->user.inline_list; #line 1228 "rlparse.kl" /* Start with empty list. */ (__ref0)->inlineList = new InlineList; #line 6190 "rlparse.cpp" } break; case 200: { Parser_Lel_inline_item *__ref0 = (Parser_Lel_inline_item*)&redLel->user.inline_item; Parser_Lel_token_type *__ref1 = (Parser_Lel_token_type*)&rhs[0]->user.token_type; Parser_Lel_token_type *__ref2 = (Parser_Lel_token_type*)&rhs[0]->user.token_type; #line 1243 "rlparse.kl" (__ref0)->inlineItem = new InlineItem( (__ref1)->token.loc, (__ref2)->token.data, InlineItem::Text ); #line 6201 "rlparse.cpp" } break; case 201: { Parser_Lel_inline_item *__ref0 = (Parser_Lel_inline_item*)&redLel->user.inline_item; Parser_Lel_token_type *__ref1 = (Parser_Lel_token_type*)&rhs[0]->user.token_type; Parser_Lel_token_type *__ref2 = (Parser_Lel_token_type*)&rhs[0]->user.token_type; #line 1249 "rlparse.kl" (__ref0)->inlineItem = new InlineItem( (__ref1)->token.loc, (__ref2)->token.data, InlineItem::Text ); #line 6212 "rlparse.cpp" } break; case 202: { Parser_Lel_inline_item *__ref0 = (Parser_Lel_inline_item*)&redLel->user.inline_item; Parser_Lel_inline_item *__ref1 = (Parser_Lel_inline_item*)&rhs[0]->user.inline_item; #line 1255 "rlparse.kl" /* Pass the inline item up. */ (__ref0)->inlineItem = (__ref1)->inlineItem; #line 6223 "rlparse.cpp" } break; case 203: { Parser_Lel_token_type *__ref0 = (Parser_Lel_token_type*)&redLel->user.token_type; Token *__ref1 = (Token*)&rhs[0]->user.token; #line 1262 "rlparse.kl" (__ref0)->token = *(__ref1); #line 6231 "rlparse.cpp" } break; case 204: { Parser_Lel_token_type *__ref0 = (Parser_Lel_token_type*)&redLel->user.token_type; Token *__ref1 = (Token*)&rhs[0]->user.token; #line 1263 "rlparse.kl" (__ref0)->token = *(__ref1); #line 6239 "rlparse.cpp" } break; case 205: { Parser_Lel_token_type *__ref0 = (Parser_Lel_token_type*)&redLel->user.token_type; Token *__ref1 = (Token*)&rhs[0]->user.token; #line 1264 "rlparse.kl" (__ref0)->token = *(__ref1); #line 6247 "rlparse.cpp" } break; case 206: { Parser_Lel_token_type *__ref0 = (Parser_Lel_token_type*)&redLel->user.token_type; Token *__ref1 = (Token*)&rhs[0]->user.token; #line 1265 "rlparse.kl" (__ref0)->token = *(__ref1); #line 6255 "rlparse.cpp" } break; case 207: { Parser_Lel_token_type *__ref0 = (Parser_Lel_token_type*)&redLel->user.token_type; Token *__ref1 = (Token*)&rhs[0]->user.token; #line 1266 "rlparse.kl" (__ref0)->token = *(__ref1); #line 6263 "rlparse.cpp" } break; case 208: { Parser_Lel_token_type *__ref0 = (Parser_Lel_token_type*)&redLel->user.token_type; Token *__ref1 = (Token*)&rhs[0]->user.token; #line 1267 "rlparse.kl" (__ref0)->token = *(__ref1); #line 6271 "rlparse.cpp" } break; case 209: { Parser_Lel_inline_item *__ref0 = (Parser_Lel_inline_item*)&redLel->user.inline_item; Parser_Lel_inline_item *__ref1 = (Parser_Lel_inline_item*)&rhs[0]->user.inline_item; #line 1271 "rlparse.kl" /* Pass up interpreted items of inline expressions. */ (__ref0)->inlineItem = (__ref1)->inlineItem; #line 6282 "rlparse.cpp" } break; case 210: { Parser_Lel_inline_item *__ref0 = (Parser_Lel_inline_item*)&redLel->user.inline_item; Token *__ref1 = (Token*)&rhs[0]->user.token; #line 1276 "rlparse.kl" (__ref0)->inlineItem = new InlineItem( (__ref1)->loc, InlineItem::Hold ); #line 6292 "rlparse.cpp" } break; case 211: { Parser_Lel_inline_item *__ref0 = (Parser_Lel_inline_item*)&redLel->user.inline_item; Token *__ref1 = (Token*)&rhs[0]->user.token; Parser_Lel_inline_item *__ref2 = (Parser_Lel_inline_item*)&redLel->user.inline_item; Parser_Lel_inline_list *__ref3 = (Parser_Lel_inline_list*)&rhs[1]->user.inline_list; #line 1280 "rlparse.kl" (__ref0)->inlineItem = new InlineItem( (__ref1)->loc, InlineItem::Exec ); (__ref2)->inlineItem->children = (__ref3)->inlineList; #line 6305 "rlparse.cpp" } break; case 212: { Parser_Lel_inline_item *__ref0 = (Parser_Lel_inline_item*)&redLel->user.inline_item; Token *__ref1 = (Token*)&rhs[0]->user.token; #line 1285 "rlparse.kl" (__ref0)->inlineItem = new InlineItem( (__ref1)->loc, new NameRef(nameRef), InlineItem::Goto ); #line 6316 "rlparse.cpp" } break; case 213: { Parser_Lel_inline_item *__ref0 = (Parser_Lel_inline_item*)&redLel->user.inline_item; Token *__ref1 = (Token*)&rhs[0]->user.token; Parser_Lel_inline_item *__ref2 = (Parser_Lel_inline_item*)&redLel->user.inline_item; Parser_Lel_inline_list *__ref3 = (Parser_Lel_inline_list*)&rhs[2]->user.inline_list; #line 1290 "rlparse.kl" (__ref0)->inlineItem = new InlineItem( (__ref1)->loc, InlineItem::GotoExpr ); (__ref2)->inlineItem->children = (__ref3)->inlineList; #line 6329 "rlparse.cpp" } break; case 214: { Parser_Lel_inline_item *__ref0 = (Parser_Lel_inline_item*)&redLel->user.inline_item; Token *__ref1 = (Token*)&rhs[0]->user.token; #line 1295 "rlparse.kl" (__ref0)->inlineItem = new InlineItem( (__ref1)->loc, new NameRef(nameRef), InlineItem::Next ); #line 6339 "rlparse.cpp" } break; case 215: { Parser_Lel_inline_item *__ref0 = (Parser_Lel_inline_item*)&redLel->user.inline_item; Token *__ref1 = (Token*)&rhs[0]->user.token; Parser_Lel_inline_item *__ref2 = (Parser_Lel_inline_item*)&redLel->user.inline_item; Parser_Lel_inline_list *__ref3 = (Parser_Lel_inline_list*)&rhs[2]->user.inline_list; #line 1299 "rlparse.kl" (__ref0)->inlineItem = new InlineItem( (__ref1)->loc, InlineItem::NextExpr ); (__ref2)->inlineItem->children = (__ref3)->inlineList; #line 6352 "rlparse.cpp" } break; case 216: { Parser_Lel_inline_item *__ref0 = (Parser_Lel_inline_item*)&redLel->user.inline_item; Token *__ref1 = (Token*)&rhs[0]->user.token; #line 1304 "rlparse.kl" (__ref0)->inlineItem = new InlineItem( (__ref1)->loc, new NameRef(nameRef), InlineItem::Call ); #line 6362 "rlparse.cpp" } break; case 217: { Parser_Lel_inline_item *__ref0 = (Parser_Lel_inline_item*)&redLel->user.inline_item; Token *__ref1 = (Token*)&rhs[0]->user.token; Parser_Lel_inline_item *__ref2 = (Parser_Lel_inline_item*)&redLel->user.inline_item; Parser_Lel_inline_list *__ref3 = (Parser_Lel_inline_list*)&rhs[2]->user.inline_list; #line 1308 "rlparse.kl" (__ref0)->inlineItem = new InlineItem( (__ref1)->loc, InlineItem::CallExpr ); (__ref2)->inlineItem->children = (__ref3)->inlineList; #line 6375 "rlparse.cpp" } break; case 218: { Parser_Lel_inline_item *__ref0 = (Parser_Lel_inline_item*)&redLel->user.inline_item; Token *__ref1 = (Token*)&rhs[0]->user.token; #line 1313 "rlparse.kl" (__ref0)->inlineItem = new InlineItem( (__ref1)->loc, InlineItem::Ret ); #line 6385 "rlparse.cpp" } break; case 219: { Parser_Lel_inline_item *__ref0 = (Parser_Lel_inline_item*)&redLel->user.inline_item; Token *__ref1 = (Token*)&rhs[0]->user.token; #line 1317 "rlparse.kl" (__ref0)->inlineItem = new InlineItem( (__ref1)->loc, InlineItem::Break ); #line 6395 "rlparse.cpp" } break; case 220: { Parser_Lel_inline_list *__ref0 = (Parser_Lel_inline_list*)&redLel->user.inline_list; Parser_Lel_inline_list *__ref1 = (Parser_Lel_inline_list*)&rhs[0]->user.inline_list; Parser_Lel_inline_list *__ref2 = (Parser_Lel_inline_list*)&redLel->user.inline_list; Parser_Lel_inline_item *__ref3 = (Parser_Lel_inline_item*)&rhs[1]->user.inline_item; #line 1325 "rlparse.kl" (__ref0)->inlineList = (__ref1)->inlineList; (__ref2)->inlineList->append( (__ref3)->inlineItem ); #line 6408 "rlparse.cpp" } break; case 221: { Parser_Lel_inline_list *__ref0 = (Parser_Lel_inline_list*)&redLel->user.inline_list; #line 1330 "rlparse.kl" /* Init the list used for this expr. */ (__ref0)->inlineList = new InlineList; #line 6418 "rlparse.cpp" } break; case 222: { Parser_Lel_inline_item *__ref0 = (Parser_Lel_inline_item*)&redLel->user.inline_item; Parser_Lel_token_type *__ref1 = (Parser_Lel_token_type*)&rhs[0]->user.token_type; Parser_Lel_token_type *__ref2 = (Parser_Lel_token_type*)&rhs[0]->user.token_type; #line 1339 "rlparse.kl" /* Return a text segment. */ (__ref0)->inlineItem = new InlineItem( (__ref1)->token.loc, (__ref2)->token.data, InlineItem::Text ); #line 6430 "rlparse.cpp" } break; case 223: { Parser_Lel_inline_item *__ref0 = (Parser_Lel_inline_item*)&redLel->user.inline_item; Parser_Lel_token_type *__ref1 = (Parser_Lel_token_type*)&rhs[0]->user.token_type; Parser_Lel_token_type *__ref2 = (Parser_Lel_token_type*)&rhs[0]->user.token_type; #line 1345 "rlparse.kl" /* Return a text segment, must heap alloc the text. */ (__ref0)->inlineItem = new InlineItem( (__ref1)->token.loc, (__ref2)->token.data, InlineItem::Text ); #line 6442 "rlparse.cpp" } break; case 224: { Parser_Lel_inline_item *__ref0 = (Parser_Lel_inline_item*)&redLel->user.inline_item; Parser_Lel_inline_item *__ref1 = (Parser_Lel_inline_item*)&rhs[0]->user.inline_item; #line 1351 "rlparse.kl" /* Pass the inline item up. */ (__ref0)->inlineItem = (__ref1)->inlineItem; #line 6453 "rlparse.cpp" } break; case 237: { Parser_Lel_inline_item *__ref0 = (Parser_Lel_inline_item*)&redLel->user.inline_item; Token *__ref1 = (Token*)&rhs[0]->user.token; #line 1381 "rlparse.kl" (__ref0)->inlineItem = new InlineItem( (__ref1)->loc, InlineItem::PChar ); #line 6463 "rlparse.cpp" } break; case 238: { Parser_Lel_inline_item *__ref0 = (Parser_Lel_inline_item*)&redLel->user.inline_item; Token *__ref1 = (Token*)&rhs[0]->user.token; #line 1386 "rlparse.kl" (__ref0)->inlineItem = new InlineItem( (__ref1)->loc, InlineItem::Char ); #line 6473 "rlparse.cpp" } break; case 239: { Parser_Lel_inline_item *__ref0 = (Parser_Lel_inline_item*)&redLel->user.inline_item; Token *__ref1 = (Token*)&rhs[0]->user.token; #line 1391 "rlparse.kl" (__ref0)->inlineItem = new InlineItem( (__ref1)->loc, InlineItem::Curs ); #line 6483 "rlparse.cpp" } break; case 240: { Parser_Lel_inline_item *__ref0 = (Parser_Lel_inline_item*)&redLel->user.inline_item; Token *__ref1 = (Token*)&rhs[0]->user.token; #line 1396 "rlparse.kl" (__ref0)->inlineItem = new InlineItem( (__ref1)->loc, InlineItem::Targs ); #line 6493 "rlparse.cpp" } break; case 241: { Parser_Lel_inline_item *__ref0 = (Parser_Lel_inline_item*)&redLel->user.inline_item; Token *__ref1 = (Token*)&rhs[0]->user.token; #line 1401 "rlparse.kl" (__ref0)->inlineItem = new InlineItem( (__ref1)->loc, new NameRef(nameRef), InlineItem::Entry ); #line 6504 "rlparse.cpp" } break; case 243: { #line 1412 "rlparse.kl" nameRef.empty(); #line 6512 "rlparse.cpp" } break; case 245: { #line 1422 "rlparse.kl" /* Insert an initial null pointer val to indicate the existence of the * initial name seperator. */ nameRef.setAs( 0 ); #line 6522 "rlparse.cpp" } break; case 246: { #line 1428 "rlparse.kl" nameRef.empty(); #line 6530 "rlparse.cpp" } break; case 247: { Token *__ref0 = (Token*)&rhs[2]->user.token; #line 1435 "rlparse.kl" nameRef.append( (__ref0)->data ); #line 6539 "rlparse.cpp" } break; case 248: { Token *__ref0 = (Token*)&rhs[0]->user.token; #line 1440 "rlparse.kl" nameRef.append( (__ref0)->data ); #line 6548 "rlparse.cpp" } break; } } if ( lel->child != 0 ) { struct Parser_LangEl *first = lel->child; struct Parser_LangEl *child = lel->child; lel->child = 0; while ( 1 ) { if ( child->type < 226 ) { } else { } numNodes -= 1; if ( child->next == 0 ) break; child = child->next; } child->next = pool; pool = first; } } commit_base: if ( sp > 0 ) { sp -= 1; if ( lel->retry == 0 ) { lel = lel->prev; goto commit_reverse; } else { lel->retry = 0; lel = lel->prev; goto commit_upwards; } } lel->retry = 0; lastFinal = lel; numRetry = 0; } if ( *action & 0x2 ) { int reduction = *action >> 2; struct Parser_LangEl *redLel; if ( input != 0 ) input->causeReduce += 1; if ( pool == 0 ) { if ( freshPos == 8128 ) { struct Parser_Block* newBlock = (struct Parser_Block*) malloc( sizeof(struct Parser_Block) ); newBlock->next = block; block = newBlock; freshEl = newBlock->data; #ifdef KELBT_LOG_ACTIONS cerr << "allocating 8128 LangEls" << endl; #endif freshPos = 0; } redLel = freshEl + freshPos++; } else { redLel = pool; pool = pool->next; } numNodes += 1; redLel->type = Parser_prodLhsIds[reduction]; redLel->reduction = reduction; redLel->child = 0; redLel->next = 0; redLel->retry = (lel->retry << 16); redLel->causeReduce = 0; lel->retry &= 0xffff0000; rhsLen = Parser_prodLengths[reduction]; if ( rhsLen > 0 ) { int r; for ( r = rhsLen-1; r > 0; r-- ) { rhs[r] = stackTop; stackTop = stackTop->next; } rhs[0] = stackTop; stackTop = stackTop->next; rhs[0]->next = 0; } switch ( reduction ) { case 225: { Parser_Lel_token_type *__ref0 = (Parser_Lel_token_type*)&redLel->user.token_type; Token *__ref1 = (Token*)&rhs[0]->user.token; #line 1358 "rlparse.kl" (__ref0)->token = *(__ref1); #line 6643 "rlparse.cpp" } break; case 226: { Parser_Lel_token_type *__ref0 = (Parser_Lel_token_type*)&redLel->user.token_type; Token *__ref1 = (Token*)&rhs[0]->user.token; #line 1359 "rlparse.kl" (__ref0)->token = *(__ref1); #line 6651 "rlparse.cpp" } break; case 227: { Parser_Lel_token_type *__ref0 = (Parser_Lel_token_type*)&redLel->user.token_type; Token *__ref1 = (Token*)&rhs[0]->user.token; #line 1360 "rlparse.kl" (__ref0)->token = *(__ref1); #line 6659 "rlparse.cpp" } break; case 228: { Parser_Lel_token_type *__ref0 = (Parser_Lel_token_type*)&redLel->user.token_type; Token *__ref1 = (Token*)&rhs[0]->user.token; #line 1361 "rlparse.kl" (__ref0)->token = *(__ref1); #line 6667 "rlparse.cpp" } break; case 229: { Parser_Lel_token_type *__ref0 = (Parser_Lel_token_type*)&redLel->user.token_type; Token *__ref1 = (Token*)&rhs[0]->user.token; #line 1362 "rlparse.kl" (__ref0)->token = *(__ref1); #line 6675 "rlparse.cpp" } break; case 230: { Parser_Lel_token_type *__ref0 = (Parser_Lel_token_type*)&redLel->user.token_type; Token *__ref1 = (Token*)&rhs[0]->user.token; #line 1363 "rlparse.kl" (__ref0)->token = *(__ref1); #line 6683 "rlparse.cpp" } break; case 231: { Parser_Lel_token_type *__ref0 = (Parser_Lel_token_type*)&redLel->user.token_type; Token *__ref1 = (Token*)&rhs[0]->user.token; #line 1364 "rlparse.kl" (__ref0)->token = *(__ref1); #line 6691 "rlparse.cpp" } break; case 232: { Parser_Lel_token_type *__ref0 = (Parser_Lel_token_type*)&redLel->user.token_type; Token *__ref1 = (Token*)&rhs[0]->user.token; #line 1371 "rlparse.kl" (__ref0)->token = *(__ref1); #line 6699 "rlparse.cpp" } break; case 233: { Parser_Lel_token_type *__ref0 = (Parser_Lel_token_type*)&redLel->user.token_type; Token *__ref1 = (Token*)&rhs[0]->user.token; #line 1372 "rlparse.kl" (__ref0)->token = *(__ref1); #line 6707 "rlparse.cpp" } break; case 234: { Parser_Lel_token_type *__ref0 = (Parser_Lel_token_type*)&redLel->user.token_type; Token *__ref1 = (Token*)&rhs[0]->user.token; #line 1373 "rlparse.kl" (__ref0)->token = *(__ref1); #line 6715 "rlparse.cpp" } break; case 235: { Parser_Lel_token_type *__ref0 = (Parser_Lel_token_type*)&redLel->user.token_type; Token *__ref1 = (Token*)&rhs[0]->user.token; #line 1374 "rlparse.kl" (__ref0)->token = *(__ref1); #line 6723 "rlparse.cpp" } break; case 236: { Parser_Lel_token_type *__ref0 = (Parser_Lel_token_type*)&redLel->user.token_type; Token *__ref1 = (Token*)&rhs[0]->user.token; #line 1375 "rlparse.kl" (__ref0)->token = *(__ref1); #line 6731 "rlparse.cpp" } break; } #ifdef KELBT_LOG_ACTIONS cerr << "reduced: " << Parser_prodNames[reduction] << " rhsLen: " << rhsLen; #endif if ( action[1] == 0 ) redLel->retry = 0; else { redLel->retry += 0x10000; numRetry += 1; #ifdef KELBT_LOG_ACTIONS cerr << " retry: " << redLel; #endif } #ifdef KELBT_LOG_ACTIONS cerr << endl; #endif if ( rhsLen == 0 ) { redLel->file = lel->file; redLel->line = lel->line; targState = curs; } else { redLel->child = rhs[rhsLen-1]; redLel->file = rhs[0]->file; redLel->line = rhs[0]->line; targState = rhs[0]->state; } if ( induceReject ) { #ifdef KELBT_LOG_ACTIONS cerr << "error induced during reduction of " << Parser_lelNames[redLel->type] << endl; #endif redLel->state = curs; redLel->next = stackTop; stackTop = redLel; curs = targState; goto parseError; } else { redLel->next = input; input = redLel; } } curs = targState; goto again; parseError: #ifdef KELBT_LOG_BACKTRACK cerr << "hit error" << endl; #endif if ( numRetry > 0 ) { struct Parser_LangEl *redLel; if ( input != 0 ) { redLel = input; goto have_undo_element; } while ( 1 ) { redLel = stackTop; if ( stackTop->type < 226 ) { #ifdef KELBT_LOG_BACKTRACK cerr << "backing up over terminal: " << Parser_lelNames[stackTop->type] << endl; #endif stackTop = stackTop->next; redLel->next = input; input = redLel; } else { #ifdef KELBT_LOG_BACKTRACK cerr << "backing up over non-terminal: " << Parser_lelNames[stackTop->type] << endl; #endif stackTop = stackTop->next; struct Parser_LangEl *first = redLel->child; if ( first == 0 ) rhsLen = 0; else { rhsLen = 1; while ( first->next != 0 ) { first = first->next; rhsLen += 1; } first->next = stackTop; stackTop = redLel->child; struct Parser_LangEl *rhsEl = stackTop; int p = rhsLen; while ( p > 0 ) { rhs[--p] = rhsEl; rhsEl = rhsEl->next; } } redLel->next = pool; pool = redLel; numNodes -= 1; if ( input != 0 ) input->causeReduce -= 1; } have_undo_element: if ( redLel->retry == 0 ) { if ( input != 0 && input->causeReduce == 0 ) { #ifdef KELBT_LOG_BACKTRACK cerr << "pushing back: " << Parser_lelNames[input->type] << endl; #endif input->next = queue; queue = input; input = 0; } } else { #ifdef KELBT_LOG_BACKTRACK cerr << "found retry targ: " << redLel << endl; #endif numRetry -= 1; #ifdef KELBT_LOG_BACKTRACK cerr << "found retry: " << redLel << endl; #endif if ( redLel->retry & 0x0000ffff ) curs = input->state; else { input->retry = redLel->retry >> 16; if ( stackTop->state < 0 ) curs = Parser_startState; else { curs = Parser_targs[(int)Parser_indicies[Parser_offsets[stackTop->state] + (stackTop->type - Parser_keys[stackTop->state<<1])]]; } } goto again; } } } curs = -1; errCount += 1; _out: {} #line 1459 "rlparse.kl" return errCount == 0 ? 0 : -1; } void Parser::tryMachineDef( InputLoc &loc, char *name, MachineDef *machineDef, bool isInstance ) { GraphDictEl *newEl = pd->graphDict.insert( name ); if ( newEl != 0 ) { /* New element in the dict, all good. */ newEl->value = new VarDef( name, machineDef ); newEl->isInstance = isInstance; newEl->loc = loc; newEl->value->isExport = exportContext[exportContext.length()-1]; /* It it is an instance, put on the instance list. */ if ( isInstance ) pd->instanceList.append( newEl ); } else { // Recover by ignoring the duplicate. error(loc) << "fsm \"" << name << "\" previously defined" << endl; } } ostream &Parser::parse_error( int tokId, Token &token ) { /* Maintain the error count. */ gblErrorCount += 1; cerr << token.loc << ": "; cerr << "at token "; if ( tokId < 128 ) cerr << "\"" << Parser_lelNames[tokId] << "\""; else cerr << Parser_lelNames[tokId]; if ( token.data != 0 ) cerr << " with data \"" << token.data << "\""; cerr << ": "; return cerr; } int Parser::token( InputLoc &loc, int tokId, char *tokstart, int toklen ) { Token token; token.data = tokstart; token.length = toklen; token.loc = loc; int res = parseLangEl( tokId, &token ); if ( res < 0 ) { parse_error(tokId, token) << "parse error" << endl; exit(1); } return res; } ragel-6.8/ragel/gofflat.cpp0000664000175000017500000002143012106050031012610 00000000000000/* * Copyright 2004-2006 Adrian Thurston * 2004 Erich Ocean * 2005 Alan West */ /* This file is part of Ragel. * * Ragel is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Ragel is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Ragel; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "ragel.h" #include "gofflat.h" #include "redfsm.h" #include "gendata.h" using std::endl; std::ostream &GoFFlatCodeGen::TO_STATE_ACTION( RedStateAp *state ) { int act = 0; if ( state->toStateAction != 0 ) act = state->toStateAction->actListId+1; out << act; return out; } std::ostream &GoFFlatCodeGen::FROM_STATE_ACTION( RedStateAp *state ) { int act = 0; if ( state->fromStateAction != 0 ) act = state->fromStateAction->actListId+1; out << act; return out; } std::ostream &GoFFlatCodeGen::EOF_ACTION( RedStateAp *state ) { int act = 0; if ( state->eofAction != 0 ) act = state->eofAction->actListId+1; out << act; return out; } /* Write out the function for a transition. */ std::ostream &GoFFlatCodeGen::TRANS_ACTION( RedTransAp *trans ) { int action = 0; if ( trans->action != 0 ) action = trans->action->actListId+1; out << action; return out; } /* Write out the function switch. This switch is keyed on the values * of the func index. */ std::ostream &GoFFlatCodeGen::TO_STATE_ACTION_SWITCH( int level ) { /* Loop the actions. */ for ( GenActionTableMap::Iter redAct = redFsm->actionMap; redAct.lte(); redAct++ ) { if ( redAct->numToStateRefs > 0 ) { /* Write the entry label. */ out << TABS(level) << "case " << redAct->actListId+1 << ":" << endl; /* Write each action in the list of action items. */ for ( GenActionTable::Iter item = redAct->key; item.lte(); item++ ) ACTION( out, item->value, 0, false, false ); } } genLineDirective( out ); return out; } /* Write out the function switch. This switch is keyed on the values * of the func index. */ std::ostream &GoFFlatCodeGen::FROM_STATE_ACTION_SWITCH( int level ) { /* Loop the actions. */ for ( GenActionTableMap::Iter redAct = redFsm->actionMap; redAct.lte(); redAct++ ) { if ( redAct->numFromStateRefs > 0 ) { /* Write the entry label. */ out << TABS(level) << "case " << redAct->actListId+1 << ":" << endl; /* Write each action in the list of action items. */ for ( GenActionTable::Iter item = redAct->key; item.lte(); item++ ) ACTION( out, item->value, 0, false, false ); } } genLineDirective( out ); return out; } std::ostream &GoFFlatCodeGen::EOF_ACTION_SWITCH( int level ) { /* Loop the actions. */ for ( GenActionTableMap::Iter redAct = redFsm->actionMap; redAct.lte(); redAct++ ) { if ( redAct->numEofRefs > 0 ) { /* Write the entry label. */ out << TABS(level) << "case " << redAct->actListId+1 << ":" << endl; /* Write each action in the list of action items. */ for ( GenActionTable::Iter item = redAct->key; item.lte(); item++ ) ACTION( out, item->value, 0, true, false ); } } genLineDirective( out ); return out; } /* Write out the function switch. This switch is keyed on the values * of the func index. */ std::ostream &GoFFlatCodeGen::ACTION_SWITCH( int level ) { /* Loop the actions. */ for ( GenActionTableMap::Iter redAct = redFsm->actionMap; redAct.lte(); redAct++ ) { if ( redAct->numTransRefs > 0 ) { /* Write the entry label. */ out << TABS(level) << "case " << redAct->actListId+1 << ":" << endl; /* Write each action in the list of action items. */ for ( GenActionTable::Iter item = redAct->key; item.lte(); item++ ) ACTION( out, item->value, 0, false, false ); } } genLineDirective( out ); return out; } void GoFFlatCodeGen::writeData() { if ( redFsm->anyConditions() ) { OPEN_ARRAY( WIDE_ALPH_TYPE(), CK() ); COND_KEYS(); CLOSE_ARRAY() << endl; OPEN_ARRAY( ARRAY_TYPE(redFsm->maxCondSpan), CSP() ); COND_KEY_SPANS(); CLOSE_ARRAY() << endl; OPEN_ARRAY( ARRAY_TYPE(redFsm->maxCond), C() ); CONDS(); CLOSE_ARRAY() << endl; OPEN_ARRAY( ARRAY_TYPE(redFsm->maxCondIndexOffset), CO() ); COND_INDEX_OFFSET(); CLOSE_ARRAY() << endl; } OPEN_ARRAY( WIDE_ALPH_TYPE(), K() ); KEYS(); CLOSE_ARRAY() << endl; OPEN_ARRAY( ARRAY_TYPE(redFsm->maxSpan), SP() ); KEY_SPANS(); CLOSE_ARRAY() << endl; OPEN_ARRAY( ARRAY_TYPE(redFsm->maxFlatIndexOffset), IO() ); FLAT_INDEX_OFFSET(); CLOSE_ARRAY() << endl; OPEN_ARRAY( ARRAY_TYPE(redFsm->maxIndex), I() ); INDICIES(); CLOSE_ARRAY() << endl; OPEN_ARRAY( ARRAY_TYPE(redFsm->maxState), TT() ); TRANS_TARGS(); CLOSE_ARRAY() << endl; if ( redFsm->anyActions() ) { OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActListId), TA() ); TRANS_ACTIONS(); CLOSE_ARRAY() << endl; } if ( redFsm->anyToStateActions() ) { OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActionLoc), TSA() ); TO_STATE_ACTIONS(); CLOSE_ARRAY() << endl; } if ( redFsm->anyFromStateActions() ) { OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActionLoc), FSA() ); FROM_STATE_ACTIONS(); CLOSE_ARRAY() << endl; } if ( redFsm->anyEofActions() ) { OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActListId), EA() ); EOF_ACTIONS(); CLOSE_ARRAY() << endl; } if ( redFsm->anyEofTrans() ) { OPEN_ARRAY( ARRAY_TYPE(redFsm->maxIndexOffset+1), ET() ); EOF_TRANS(); CLOSE_ARRAY() << endl; } STATE_IDS(); } void GoFFlatCodeGen::writeExec() { testEofUsed = false; outLabelUsed = false; out << " {" << endl << " var _slen " << INT() << endl; if ( redFsm->anyRegCurStateRef() ) out << " var _ps " << INT() << endl; out << " var _trans " << INT() << endl; if ( redFsm->anyConditions() ) out << " var _cond " << INT() << endl; out << " var _keys " << INT() << endl << " var _inds " << INT() << endl; if ( redFsm->anyConditions() ) { out << " var _conds " << INT() << endl << " var _widec " << WIDE_ALPH_TYPE() << endl; } if ( !noEnd ) { testEofUsed = true; out << " if " << P() << " == " << PE() << " {" << endl << " goto _test_eof" << endl << " }" << endl; } if ( redFsm->errState != 0 ) { outLabelUsed = true; out << " if " << vCS() << " == " << redFsm->errState->id << " {" << endl << " goto _out" << endl << " }" << endl; } out << "_resume:" << endl; if ( redFsm->anyFromStateActions() ) { out << " switch " << FSA() << "[" << vCS() << "] {" << endl; FROM_STATE_ACTION_SWITCH(1); out << " }" << endl << endl; } if ( redFsm->anyConditions() ) COND_TRANSLATE(); LOCATE_TRANS(); if ( redFsm->anyEofTrans() ) out << "_eof_trans:" << endl; if ( redFsm->anyRegCurStateRef() ) out << " _ps = " << vCS() << endl; out << " " << vCS() << " = " << CAST(INT(), TT() + "[_trans]") << endl << endl; if ( redFsm->anyRegActions() ) { out << " if " << TA() << "[_trans] == 0 {" << endl << " goto _again" << endl << " }" << endl << endl << " switch " << TA() << "[_trans] {" << endl; ACTION_SWITCH(1); out << " }" << endl << endl; } if ( redFsm->anyRegActions() || redFsm->anyActionGotos() || redFsm->anyActionCalls() || redFsm->anyActionRets() ) out << "_again:" << endl; if ( redFsm->anyToStateActions() ) { out << " switch " << TSA() << "[" << vCS() << "] {" << endl; TO_STATE_ACTION_SWITCH(1); out << " }" << endl << endl; } if ( redFsm->errState != 0 ) { outLabelUsed = true; out << " if " << vCS() << " == " << redFsm->errState->id << " {" << endl << " goto _out" << endl << " }" << endl; } if ( !noEnd ) { out << " if " << P() << "++; " << P() << " != " << PE() << " {" " goto _resume" << endl << " }" << endl; } else { out << " " << P() << "++" << endl << " goto _resume" << endl; } if ( testEofUsed ) out << " _test_eof: {}" << endl; if ( redFsm->anyEofTrans() || redFsm->anyEofActions() ) { out << " if " << P() << " == " << vEOF() << " {" << endl; if ( redFsm->anyEofTrans() ) { out << " if " << ET() << "[" << vCS() << "] > 0 {" << endl << " _trans = " << CAST(INT(), ET() + "[" + vCS() + "] - 1") << endl << " goto _eof_trans" << endl << " }" << endl; } if ( redFsm->anyEofActions() ) { out << " switch " << EA() << "[" << vCS() << "] {" << endl; EOF_ACTION_SWITCH(2); out << " }" << endl; } out << " }" << endl << endl; } if ( outLabelUsed ) out << " _out: {}" << endl; out << " }" << endl; } ragel-6.8/ragel/gendata.h0000664000175000017500000001250412106050031012240 00000000000000/* * Copyright 2005-2007 Adrian Thurston */ /* This file is part of Ragel. * * Ragel is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Ragel is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Ragel; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef _GENDATA_H #define _GENDATA_H #include #include "config.h" #include "redfsm.h" #include "common.h" using std::ostream; extern bool generateDot; struct NameInst; typedef DList GenActionList; typedef unsigned long ulong; extern int gblErrorCount; struct CodeGenData; typedef AvlMap CodeGenMap; typedef AvlMapEl CodeGenMapEl; void cdLineDirective( ostream &out, const char *fileName, int line ); void javaLineDirective( ostream &out, const char *fileName, int line ); void goLineDirective( ostream &out, const char *fileName, int line ); void rubyLineDirective( ostream &out, const char *fileName, int line ); void csharpLineDirective( ostream &out, const char *fileName, int line ); void ocamlLineDirective( ostream &out, const char *fileName, int line ); void genLineDirective( ostream &out ); void lineDirective( ostream &out, const char *fileName, int line ); string itoa( int i ); /*********************************/ struct CodeGenData { /* * The interface to the code generator. */ virtual void finishRagelDef() {} /* These are invoked by the corresponding write statements. */ virtual void writeData() {}; virtual void writeInit() {}; virtual void writeExec() {}; virtual void writeExports() {}; virtual void writeStart() {}; virtual void writeFirstFinal() {}; virtual void writeError() {}; /* This can also be overwridden to modify the processing of write * statements. */ virtual void writeStatement( InputLoc &loc, int nargs, char **args ); /********************/ CodeGenData( ostream &out ); virtual ~CodeGenData() {} /* * Collecting the machine. */ const char *sourceFileName; const char *fsmName; ostream &out; RedFsmAp *redFsm; GenAction *allActions; RedAction *allActionTables; Condition *allConditions; GenCondSpace *allCondSpaces; RedStateAp *allStates; NameInst **nameIndex; int startState; int errState; GenActionList actionList; ConditionList conditionList; CondSpaceList condSpaceList; GenInlineList *getKeyExpr; GenInlineList *accessExpr; GenInlineList *prePushExpr; GenInlineList *postPopExpr; /* Overriding variables. */ GenInlineList *pExpr; GenInlineList *peExpr; GenInlineList *eofExpr; GenInlineList *csExpr; GenInlineList *topExpr; GenInlineList *stackExpr; GenInlineList *actExpr; GenInlineList *tokstartExpr; GenInlineList *tokendExpr; GenInlineList *dataExpr; KeyOps thisKeyOps; bool wantComplete; EntryIdVect entryPointIds; EntryNameVect entryPointNames; bool hasLongestMatch; ExportList exportList; /* Write options. */ bool noEnd; bool noPrefix; bool noFinal; bool noError; bool noCS; void createMachine(); void initActionList( unsigned long length ); void newAction( int anum, const char *name, const InputLoc &loc, GenInlineList *inlineList ); void initActionTableList( unsigned long length ); void initStateList( unsigned long length ); void setStartState( unsigned long startState ); void setErrorState( unsigned long errState ); void addEntryPoint( char *name, unsigned long entryState ); void setId( int snum, int id ); void setFinal( int snum ); void initTransList( int snum, unsigned long length ); void newTrans( int snum, int tnum, Key lowKey, Key highKey, long targ, long act ); void finishTransList( int snum ); void setStateActions( int snum, long toStateAction, long fromStateAction, long eofAction ); void setEofTrans( int snum, long targ, long eofAction ); void setForcedErrorState() { redFsm->forcedErrorState = true; } void initCondSpaceList( ulong length ); void condSpaceItem( int cnum, long condActionId ); void newCondSpace( int cnum, int condSpaceId, Key baseKey ); void initStateCondList( int snum, ulong length ); void addStateCond( int snum, Key lowKey, Key highKey, long condNum ); GenCondSpace *findCondSpace( Key lowKey, Key highKey ); Condition *findCondition( Key key ); bool setAlphType( const char *data ); void resolveTargetStates( GenInlineList *inlineList ); Key findMaxKey(); /* Gather various info on the machine. */ void analyzeActionList( RedAction *redAct, GenInlineList *inlineList ); void analyzeAction( GenAction *act, GenInlineList *inlineList ); void findFinalActionRefs(); void analyzeMachine(); void closeMachine(); void setValueLimits(); void assignActionIds(); ostream &source_warning( const InputLoc &loc ); ostream &source_error( const InputLoc &loc ); void write_option_error( InputLoc &loc, char *arg ); }; CodeGenData *makeCodeGen( const char *sourceFileName, const char *fsmName, ostream &out ); #endif ragel-6.8/ragel/rlparse.kh0000664000175000017500000000775512106050031012474 00000000000000/* * Copyright 2001-2007 Adrian Thurston */ /* This file is part of Ragel. * * Ragel is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Ragel is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Ragel; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef _RLPARSE_H #define _RLPARSE_H #include #include "avltree.h" #include "parsedata.h" /* Import scanner tokens. */ #define IMP_Word 128 #define IMP_Literal 129 #define IMP_UInt 130 #define IMP_Define 131 /* This is used for tracking the include files/machine pairs. */ struct IncludeHistoryItem { IncludeHistoryItem( const char *fileName, const char *sectionName ) : fileName(fileName), sectionName(sectionName) {} const char *fileName; const char *sectionName; }; typedef Vector IncludeHistory; struct Parser { %%{ parser Parser; # General tokens. token TK_Word, TK_Literal, TK_Number, TK_EndSection, TK_UInt, TK_Hex, TK_Word, TK_Literal, TK_DotDot, TK_ColonGt, TK_ColonGtGt, TK_LtColon, TK_Arrow, TK_DoubleArrow, TK_StarStar, TK_ColonEquals, TK_NameSep, TK_BarStar, TK_DashDash; # Conditions. token TK_StartCond, TK_AllCond, TK_LeavingCond; # State embedding actions. token TK_Middle; # Global error actions. token TK_StartGblError, TK_AllGblError, TK_FinalGblError, TK_NotFinalGblError, TK_NotStartGblError, TK_MiddleGblError; # Local error actions. token TK_StartLocalError, TK_AllLocalError, TK_FinalLocalError, TK_NotFinalLocalError, TK_NotStartLocalError, TK_MiddleLocalError; # EOF Action embedding. token TK_StartEOF, TK_AllEOF, TK_FinalEOF, TK_NotFinalEOF, TK_NotStartEOF, TK_MiddleEOF; # To State Actions. token TK_StartToState, TK_AllToState, TK_FinalToState, TK_NotFinalToState, TK_NotStartToState, TK_MiddleToState; # In State Actions. token TK_StartFromState, TK_AllFromState, TK_FinalFromState, TK_NotFinalFromState, TK_NotStartFromState, TK_MiddleFromState; # Regular expression tokens. */ token RE_Slash, RE_SqOpen, RE_SqOpenNeg, RE_SqClose, RE_Dot, RE_Star, RE_Dash, RE_Char; # Tokens specific to inline code. token IL_WhiteSpace, IL_Comment, IL_Literal, IL_Symbol; # Keywords. token KW_Machine, KW_Include, KW_Import, KW_Write, KW_Action, KW_AlphType, KW_Range, KW_GetKey, KW_Include, KW_Write, KW_Machine, KW_InWhen, KW_When, KW_OutWhen, KW_Eof, KW_Err, KW_Lerr, KW_To, KW_From, KW_Export, KW_PrePush, KW_PostPop, KW_Length; # Specials in code blocks. token KW_Break, KW_Exec, KW_Hold, KW_PChar, KW_Char, KW_Goto, KW_Call, KW_Ret, KW_CurState, KW_TargState, KW_Entry, KW_Next, KW_Exec, KW_Variable, KW_Access; }%% %% write instance_data; void init(); int parseLangEl( int type, const Token *token ); Parser( const char *fileName, char *sectionName, InputLoc §ionLoc ) : sectionName(sectionName) { pd = new ParseData( fileName, sectionName, sectionLoc ); exportContext.append( false ); includeHistory.append( IncludeHistoryItem( fileName, sectionName ) ); } int token( InputLoc &loc, int tokId, char *tokstart, int toklen ); void tryMachineDef( InputLoc &loc, char *name, MachineDef *machineDef, bool isInstance ); /* Report an error encountered by the parser. */ ostream &parse_error( int tokId, Token &token ); ParseData *pd; /* The name of the root section, this does not change during an include. */ char *sectionName; NameRef nameRef; NameRefList nameRefList; Vector exportContext; IncludeHistory includeHistory; Parser *prev, *next; }; %% write token_defs; #endif ragel-6.8/ragel/cdftable.h0000664000175000017500000000425012106050031012400 00000000000000/* * Copyright 2001-2006 Adrian Thurston * 2004 Erich Ocean * 2005 Alan West */ /* This file is part of Ragel. * * Ragel is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Ragel is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Ragel; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef _CDFTABLE_H #define _CDFTABLE_H #include #include "cdtable.h" /* Forwards. */ struct CodeGenData; /* * FTabCodeG\verb|e */ class FTabCodeGen : public TabCodeGen { protected: FTabCodeGen( ostream &out ) : FsmCodeGen(out), TabCodeGen(out) {} std::ostream &TO_STATE_ACTION_SWITCH(); std::ostream &FROM_STATE_ACTION_SWITCH(); std::ostream &EOF_ACTION_SWITCH(); std::ostream &ACTION_SWITCH(); virtual std::ostream &TO_STATE_ACTION( RedStateAp *state ); virtual std::ostream &FROM_STATE_ACTION( RedStateAp *state ); virtual std::ostream &EOF_ACTION( RedStateAp *state ); virtual std::ostream &TRANS_ACTION( RedTransAp *trans ); virtual void writeData(); virtual void writeExec(); virtual void calcIndexSize(); }; /* * CFTabCodeGen */ struct CFTabCodeGen : public FTabCodeGen, public CCodeGen { CFTabCodeGen( ostream &out ) : FsmCodeGen(out), FTabCodeGen(out), CCodeGen(out) {} }; /* * class DFTabCodeGen */ struct DFTabCodeGen : public FTabCodeGen, public DCodeGen { DFTabCodeGen( ostream &out ) : FsmCodeGen(out), FTabCodeGen(out), DCodeGen(out) {} }; /* * class D2FTabCodeGen */ struct D2FTabCodeGen : public FTabCodeGen, public D2CodeGen { D2FTabCodeGen( ostream &out ) : FsmCodeGen(out), FTabCodeGen(out), D2CodeGen(out) {} }; #endif ragel-6.8/ragel/rubyflat.cpp0000664000175000017500000005075112106050031013026 00000000000000/* * Copyright 2001-2007 Adrian Thurston * Copyright 2007 Victor Hugo Borja */ /* This file is part of Ragel. * * Ragel is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Ragel is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Ragel; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "rubyflat.h" #include "ragel.h" #include "redfsm.h" #include "gendata.h" using std::ostream; using std::string; std::ostream &RubyFlatCodeGen::TO_STATE_ACTION_SWITCH() { /* Walk the list of functions, printing the cases. */ for ( GenActionList::Iter act = actionList; act.lte(); act++ ) { /* Write out referenced actions. */ if ( act->numToStateRefs > 0 ) { /* Write the case label, the action and the case break */ out << "\twhen " << act->actionId << " then\n"; ACTION( out, act, 0, false ); } } genLineDirective( out ); return out; } std::ostream &RubyFlatCodeGen::FROM_STATE_ACTION_SWITCH() { /* Walk the list of functions, printing the cases. */ for ( GenActionList::Iter act = actionList; act.lte(); act++ ) { /* Write out referenced actions. */ if ( act->numFromStateRefs > 0 ) { /* Write the case label, the action and the case break */ out << "\twhen " << act->actionId << " then\n"; ACTION( out, act, 0, false ); } } genLineDirective( out ); return out; } std::ostream &RubyFlatCodeGen::EOF_ACTION_SWITCH() { /* Walk the list of functions, printing the cases. */ for ( GenActionList::Iter act = actionList; act.lte(); act++ ) { /* Write out referenced actions. */ if ( act->numEofRefs > 0 ) { /* Write the case label, the action and the case break */ out << "\twhen " << act->actionId << " then\n"; ACTION( out, act, 0, true ); } } genLineDirective( out ); return out; } std::ostream &RubyFlatCodeGen::ACTION_SWITCH() { /* Walk the list of functions, printing the cases. */ for ( GenActionList::Iter act = actionList; act.lte(); act++ ) { /* Write out referenced actions. */ if ( act->numTransRefs > 0 ) { /* Write the case label, the action and the case break */ out << "\twhen " << act->actionId << " then\n"; ACTION( out, act, 0, false ); } } genLineDirective( out ); return out; } std::ostream &RubyFlatCodeGen::KEYS() { START_ARRAY_LINE(); int totalTrans = 0; for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { /* Emit just low key and high key. */ ARRAY_ITEM( KEY( st->lowKey ), ++totalTrans, false ); ARRAY_ITEM( KEY( st->highKey ), ++totalTrans, false ); if ( ++totalTrans % IALL == 0 ) out << "\n\t"; } /* Output one last number so we don't have to figure out when the last * entry is and avoid writing a comma. */ ARRAY_ITEM( INT( 0 ), ++totalTrans, true ); END_ARRAY_LINE(); return out; } std::ostream &RubyFlatCodeGen::INDICIES() { int totalTrans = 0; START_ARRAY_LINE(); for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { if ( st->transList != 0 ) { /* Walk the singles. */ unsigned long long span = keyOps->span( st->lowKey, st->highKey ); for ( unsigned long long pos = 0; pos < span; pos++ ) { ARRAY_ITEM( KEY( st->transList[pos]->id ), ++totalTrans, false ); } } /* The state's default index goes next. */ if ( st->defTrans != 0 ) ARRAY_ITEM( KEY( st->defTrans->id ), ++totalTrans, false ); } /* Output one last number so we don't have to figure out when the last * entry is and avoid writing a comma. */ ARRAY_ITEM( INT( 0 ), ++totalTrans, true ); END_ARRAY_LINE(); return out; } std::ostream &RubyFlatCodeGen::FLAT_INDEX_OFFSET() { START_ARRAY_LINE(); int totalStateNum = 0, curIndOffset = 0; for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { /* Write the index offset. */ ARRAY_ITEM( INT( curIndOffset ), ++totalStateNum, st.last() ); /* Move the index offset ahead. */ if ( st->transList != 0 ) curIndOffset += keyOps->span( st->lowKey, st->highKey ); if ( st->defTrans != 0 ) curIndOffset += 1; } END_ARRAY_LINE(); return out; } std::ostream &RubyFlatCodeGen::KEY_SPANS() { START_ARRAY_LINE(); int totalStateNum = 0; for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { /* Write singles length. */ unsigned long long span = 0; if ( st->transList != 0 ) span = keyOps->span( st->lowKey, st->highKey ); ARRAY_ITEM( INT( span ), ++totalStateNum, st.last() ); } END_ARRAY_LINE(); return out; } std::ostream &RubyFlatCodeGen::TO_STATE_ACTIONS() { START_ARRAY_LINE(); int totalStateNum = 0; for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { /* Write any eof action. */ ARRAY_ITEM( INT( TO_STATE_ACTION(st) ), ++totalStateNum, st.last() ); } END_ARRAY_LINE(); return out; } std::ostream &RubyFlatCodeGen::FROM_STATE_ACTIONS() { START_ARRAY_LINE(); int totalStateNum = 0; for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { /* Write any eof action. */ ARRAY_ITEM( INT( FROM_STATE_ACTION(st) ), ++totalStateNum, st.last() ); } END_ARRAY_LINE(); return out; } std::ostream &RubyFlatCodeGen::EOF_ACTIONS() { START_ARRAY_LINE(); int totalStateNum = 0; for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { /* Write any eof action. */ ARRAY_ITEM( INT( EOF_ACTION(st) ), ++totalStateNum, st.last() ); } END_ARRAY_LINE(); return out; } std::ostream &RubyFlatCodeGen::EOF_TRANS() { START_ARRAY_LINE(); int totalStateNum = 0; for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { /* Write any eof action. */ long trans = 0; if ( st->eofTrans != 0 ) { assert( st->eofTrans->pos >= 0 ); trans = st->eofTrans->pos+1; } /* Write any eof action. */ ARRAY_ITEM( INT(trans), ++totalStateNum, st.last() ); } END_ARRAY_LINE(); return out; } std::ostream &RubyFlatCodeGen::TRANS_TARGS() { /* Transitions must be written ordered by their id. */ RedTransAp **transPtrs = new RedTransAp*[redFsm->transSet.length()]; for ( TransApSet::Iter trans = redFsm->transSet; trans.lte(); trans++ ) transPtrs[trans->id] = trans; /* Keep a count of the num of items in the array written. */ START_ARRAY_LINE(); int totalStates = 0; for ( int t = 0; t < redFsm->transSet.length(); t++ ) { /* Save the position. Needed for eofTargs. */ RedTransAp *trans = transPtrs[t]; trans->pos = t; /* Write out the target state. */ ARRAY_ITEM( INT( trans->targ->id ), ++totalStates, t >= redFsm->transSet.length()-1 ); } END_ARRAY_LINE(); delete[] transPtrs; return out; } std::ostream &RubyFlatCodeGen::TRANS_ACTIONS() { /* Transitions must be written ordered by their id. */ RedTransAp **transPtrs = new RedTransAp*[redFsm->transSet.length()]; for ( TransApSet::Iter trans = redFsm->transSet; trans.lte(); trans++ ) transPtrs[trans->id] = trans; /* Keep a count of the num of items in the array written. */ START_ARRAY_LINE(); int totalAct = 0; for ( int t = 0; t < redFsm->transSet.length(); t++ ) { /* Write the function for the transition. */ RedTransAp *trans = transPtrs[t]; ARRAY_ITEM( INT( TRANS_ACTION( trans ) ), ++totalAct, t >= redFsm->transSet.length()-1 ); } END_ARRAY_LINE(); delete[] transPtrs; return out; } void RubyFlatCodeGen::LOCATE_TRANS() { out << " _keys = " << vCS() << " << 1\n" " _inds = " << IO() << "[" << vCS() << "]\n" " _slen = " << SP() << "[" << vCS() << "]\n" " _trans = if ( _slen > 0 && \n" " " << K() << "[_keys] <= " << GET_WIDE_KEY() << " && \n" " " << GET_WIDE_KEY() << " <= " << K() << "[_keys + 1] \n" " ) then\n" " " << I() << "[ _inds + " << GET_WIDE_KEY() << " - " << K() << "[_keys] ] \n" " else \n" " " << I() << "[ _inds + _slen ]\n" " end\n" ""; } std::ostream &RubyFlatCodeGen::COND_INDEX_OFFSET() { START_ARRAY_LINE(); int totalStateNum = 0, curIndOffset = 0; for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { /* Write the index offset. */ ARRAY_ITEM( INT( curIndOffset ), ++totalStateNum, st.last() ); /* Move the index offset ahead. */ if ( st->condList != 0 ) curIndOffset += keyOps->span( st->condLowKey, st->condHighKey ); } END_ARRAY_LINE(); return out; } void RubyFlatCodeGen::COND_TRANSLATE() { out << " _widec = " << GET_KEY() << "\n" " _keys = " << vCS() << " << 1\n" " _conds = " << CO() << "[" << vCS() << "]\n" " _slen = " << CSP() << "[" << vCS() << "]\n" " _cond = if ( _slen > 0 && \n" " " << CK() << "[_keys] <= " << GET_WIDE_KEY() << " &&\n" " " << GET_WIDE_KEY() << " <= " << CK() << "[_keys + 1]\n" " ) then \n" " " << C() << "[ _conds + " << GET_WIDE_KEY() << " - " << CK() << "[_keys]" << " ]\n" " else\n" " 0\n" " end\n"; out << " case _cond \n"; for ( CondSpaceList::Iter csi = condSpaceList; csi.lte(); csi++ ) { GenCondSpace *condSpace = csi; out << " when " << condSpace->condSpaceId + 1 << " then\n"; out << TABS(2) << "_widec = " << "(" << KEY(condSpace->baseKey) << " + (" << GET_KEY() << " - " << KEY(keyOps->minKey) << "))\n"; for ( GenCondSet::Iter csi = condSpace->condSet; csi.lte(); csi++ ) { out << TABS(2) << "if ( "; CONDITION( out, *csi ); Size condValOffset = ((1 << csi.pos()) * keyOps->alphSize()); out << " ) then \n" << TABS(3) << " _widec += " << condValOffset << "\n" "end\n"; } } out << " end # _cond switch \n"; } std::ostream &RubyFlatCodeGen::CONDS() { int totalTrans = 0; START_ARRAY_LINE(); for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { if ( st->condList != 0 ) { /* Walk the singles. */ unsigned long long span = keyOps->span( st->condLowKey, st->condHighKey ); for ( unsigned long long pos = 0; pos < span; pos++ ) { if ( st->condList[pos] != 0 ) ARRAY_ITEM( INT( st->condList[pos]->condSpaceId + 1 ), ++totalTrans, false ); else ARRAY_ITEM( INT( 0 ), ++totalTrans, false ); } } } /* Output one last number so we don't have to figure out when the last * entry is and avoid writing a comma. */ ARRAY_ITEM( INT( 0 ), ++totalTrans, true ); END_ARRAY_LINE(); return out; } std::ostream &RubyFlatCodeGen::COND_KEYS() { START_ARRAY_LINE(); int totalTrans = 0; for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { /* Emit just cond low key and cond high key. */ ARRAY_ITEM( KEY( st->condLowKey ), ++totalTrans, false ); ARRAY_ITEM( KEY( st->condHighKey ), ++totalTrans, false ); } /* Output one last number so we don't have to figure out when the last * entry is and avoid writing a comma. */ ARRAY_ITEM( INT( 0 ), ++totalTrans, true ); END_ARRAY_LINE(); return out; } std::ostream &RubyFlatCodeGen::COND_KEY_SPANS() { START_ARRAY_LINE(); int totalStateNum = 0; for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { /* Write singles length. */ unsigned long long span = 0; if ( st->condList != 0 ) span = keyOps->span( st->condLowKey, st->condHighKey ); ARRAY_ITEM( INT( span ), ++totalStateNum, false ); } END_ARRAY_LINE(); return out; } void RubyFlatCodeGen::GOTO( ostream &out, int gotoDest, bool inFinish ) { out << " begin\n" " " << vCS() << " = " << gotoDest << "\n" " _trigger_goto = true\n" " _goto_level = _again\n" " break\n" " end\n"; } void RubyFlatCodeGen::CALL( ostream &out, int callDest, int targState, bool inFinish ) { if ( prePushExpr != 0 ) { out << "begin\n"; INLINE_LIST( out, prePushExpr, 0, false ); } out << " begin\n" " " << STACK() << "[" << TOP() << "] = " << vCS() << "\n" " " << TOP() << "+= 1\n" " " << vCS() << " = " << callDest << "\n" " _trigger_goto = true\n" " _goto_level = _again\n" " break\n" " end\n"; if ( prePushExpr != 0 ) out << "end\n"; } void RubyFlatCodeGen::CALL_EXPR(ostream &out, GenInlineItem *ilItem, int targState, bool inFinish ) { if ( prePushExpr != 0 ) { out << "begin\n"; INLINE_LIST( out, prePushExpr, 0, false ); } out << " begin\n" " " << STACK() << "[" << TOP() << "] = " << vCS() << "\n" " " << TOP() << " += 1\n" " " << vCS() << " = ("; INLINE_LIST( out, ilItem->children, targState, inFinish ); out << ")\n"; out << " _trigger_goto = true\n" " _goto_level = _again\n" " break\n" " end\n"; if ( prePushExpr != 0 ) out << "end\n"; } void RubyFlatCodeGen::RET( ostream &out, bool inFinish ) { out << " begin\n" " " << TOP() << " -= 1\n" " " << vCS() << " = " << STACK() << "[" << TOP() << "]\n"; if ( postPopExpr != 0 ) { out << "begin\n"; INLINE_LIST( out, postPopExpr, 0, false ); out << "end\n"; } out << " _trigger_goto = true\n" " _goto_level = _again\n" " break\n" " end\n"; } void RubyFlatCodeGen::NEXT( ostream &ret, int nextDest, bool inFinish ) { ret << vCS() << " = " << nextDest << ";"; } void RubyFlatCodeGen::GOTO_EXPR( ostream &out, GenInlineItem *ilItem, bool inFinish ) { out << " begin\n" " " << vCS() << " = ("; INLINE_LIST( out, ilItem->children, 0, inFinish ); out << ")\n"; out << " _trigger_goto = true\n" " _goto_level = _again\n" " break\n" " end\n"; } void RubyFlatCodeGen::NEXT_EXPR( ostream &ret, GenInlineItem *ilItem, bool inFinish ) { ret << vCS() << " = ("; INLINE_LIST( ret, ilItem->children, 0, inFinish ); ret << ");"; } void RubyFlatCodeGen::CURS( ostream &ret, bool inFinish ) { ret << "(_ps)"; } void RubyFlatCodeGen::TARGS( ostream &ret, bool inFinish, int targState ) { ret << "(" << vCS() << ")"; } void RubyFlatCodeGen::BREAK( ostream &out, int targState ) { out << " begin\n" " " << P() << " += 1\n" " _trigger_goto = true\n" " _goto_level = _out\n" " break\n" " end\n"; } int RubyFlatCodeGen::TO_STATE_ACTION( RedStateAp *state ) { int act = 0; if ( state->toStateAction != 0 ) act = state->toStateAction->location+1; return act; } int RubyFlatCodeGen::FROM_STATE_ACTION( RedStateAp *state ) { int act = 0; if ( state->fromStateAction != 0 ) act = state->fromStateAction->location+1; return act; } int RubyFlatCodeGen::EOF_ACTION( RedStateAp *state ) { int act = 0; if ( state->eofAction != 0 ) act = state->eofAction->location+1; return act; } int RubyFlatCodeGen::TRANS_ACTION( RedTransAp *trans ) { /* If there are actions, emit them. Otherwise emit zero. */ int act = 0; if ( trans->action != 0 ) act = trans->action->location+1; return act; } void RubyFlatCodeGen::writeData() { /* If there are any transtion functions then output the array. If there * are none, don't bother emitting an empty array that won't be used. */ if ( redFsm->anyActions() ) { OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActArrItem), A() ); ACTIONS_ARRAY(); CLOSE_ARRAY() << "\n"; } if ( redFsm->anyConditions() ) { OPEN_ARRAY( WIDE_ALPH_TYPE(), CK() ); COND_KEYS(); CLOSE_ARRAY() << "\n"; OPEN_ARRAY( ARRAY_TYPE(redFsm->maxCondSpan), CSP() ); COND_KEY_SPANS(); CLOSE_ARRAY() << "\n"; OPEN_ARRAY( ARRAY_TYPE(redFsm->maxCond), C() ); CONDS(); CLOSE_ARRAY() << "\n"; OPEN_ARRAY( ARRAY_TYPE(redFsm->maxCondIndexOffset), CO() ); COND_INDEX_OFFSET(); CLOSE_ARRAY() << "\n"; } OPEN_ARRAY( WIDE_ALPH_TYPE(), K() ); KEYS(); CLOSE_ARRAY() << "\n"; OPEN_ARRAY( ARRAY_TYPE(redFsm->maxSpan), SP() ); KEY_SPANS(); CLOSE_ARRAY() << "\n"; OPEN_ARRAY( ARRAY_TYPE(redFsm->maxFlatIndexOffset), IO() ); FLAT_INDEX_OFFSET(); CLOSE_ARRAY() << "\n"; OPEN_ARRAY( ARRAY_TYPE(redFsm->maxIndex), I() ); INDICIES(); CLOSE_ARRAY() << "\n"; OPEN_ARRAY( ARRAY_TYPE(redFsm->maxState), TT() ); TRANS_TARGS(); CLOSE_ARRAY() << "\n"; if ( redFsm->anyActions() ) { OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActionLoc), TA() ); TRANS_ACTIONS(); CLOSE_ARRAY() << "\n"; } if ( redFsm->anyToStateActions() ) { OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActionLoc), TSA() ); TO_STATE_ACTIONS(); CLOSE_ARRAY() << "\n"; } if ( redFsm->anyFromStateActions() ) { OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActionLoc), FSA() ); FROM_STATE_ACTIONS(); CLOSE_ARRAY() << "\n"; } if ( redFsm->anyEofActions() ) { OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActionLoc), EA() ); EOF_ACTIONS(); CLOSE_ARRAY() << "\n"; } if ( redFsm->anyEofTrans() ) { OPEN_ARRAY( ARRAY_TYPE(redFsm->maxIndexOffset+1), ET() ); EOF_TRANS(); CLOSE_ARRAY() << "\n"; } STATE_IDS(); } void RubyFlatCodeGen::writeExec() { out << "begin # ragel flat\n" " testEof = false\n" " _slen, _trans, _keys, _inds"; if ( redFsm->anyRegCurStateRef() ) out << ", _ps"; if ( redFsm->anyConditions() ) out << ", _cond, _conds, _widec"; if ( redFsm->anyToStateActions() || redFsm->anyRegActions() || redFsm->anyFromStateActions() ) out << ", _acts, _nacts"; out << " = nil\n"; out << " _goto_level = 0\n" " _resume = 10\n" " _eof_trans = 15\n" " _again = 20\n" " _test_eof = 30\n" " _out = 40\n"; out << " while true\n" " _trigger_goto = false\n" " if _goto_level <= 0\n"; if ( !noEnd ) { out << " if " << P() << " == " << PE() << "\n" " _goto_level = _test_eof\n" " next\n" " end\n"; } if ( redFsm->errState != 0 ) { out << " if " << vCS() << " == " << redFsm->errState->id << "\n" " _goto_level = _out\n" " next\n" " end\n"; } /* The resume label. */ out << " end\n" " if _goto_level <= _resume\n"; if ( redFsm->anyFromStateActions() ) { out << " _acts = " << FSA() << "[" << vCS() << "]\n" " _nacts = " << A() << "[_acts]\n" " _acts += 1\n" " while _nacts > 0\n" " _nacts -= 1\n" " _acts += 1\n" " case " << A() << "[_acts - 1]\n"; FROM_STATE_ACTION_SWITCH(); out << " end # from state action switch\n" " end\n" " if _trigger_goto\n" " next\n" " end\n"; } if ( redFsm->anyConditions() ) COND_TRANSLATE(); LOCATE_TRANS(); if ( redFsm->anyEofTrans() ) { out << " end\n" " if _goto_level <= _eof_trans\n"; } if ( redFsm->anyRegCurStateRef() ) out << " _ps = " << vCS() << "\n"; out << " " << vCS() << " = " << TT() << "[_trans]\n"; if ( redFsm->anyRegActions() ) { out << " if " << TA() << "[_trans] != 0\n" " _acts = " << TA() << "[_trans]\n" " _nacts = " << A() << "[_acts]\n" " _acts += 1\n" " while _nacts > 0\n" " _nacts -= 1\n" " _acts += 1\n" " case " << A() << "[_acts - 1]\n"; ACTION_SWITCH(); out << " end # action switch\n" " end\n" " end\n" " if _trigger_goto\n" " next\n" " end\n"; } /* The again label. */ out << " end\n" " if _goto_level <= _again\n"; if ( redFsm->anyToStateActions() ) { out << " _acts = " << TSA() << "[" << vCS() << "]\n" " _nacts = " << A() << "[_acts]\n" " _acts += 1\n" " while _nacts > 0\n" " _nacts -= 1\n" " _acts += 1\n" " case " << A() << "[_acts - 1]\n"; TO_STATE_ACTION_SWITCH() << " end # to state action switch\n" " end\n" " if _trigger_goto\n" " next\n" " end\n"; } if ( redFsm->errState != 0 ) { out << " if " << vCS() << " == " << redFsm->errState->id << "\n" " _goto_level = _out\n" " next\n" " end\n"; } out << " " << P() << " += 1\n"; if ( !noEnd ) { out << " if " << P() << " != " << PE() << "\n" " _goto_level = _resume\n" " next\n" " end\n"; } else { out << " _goto_level = _resume\n" " next\n"; } /* The test_eof label. */ out << " end\n" " if _goto_level <= _test_eof\n"; if ( redFsm->anyEofTrans() || redFsm->anyEofActions() ) { out << " if " << P() << " == " << vEOF() << "\n"; if ( redFsm->anyEofTrans() ) { out << " if " << ET() << "[" << vCS() << "] > 0\n" " _trans = " << ET() << "[" << vCS() << "] - 1;\n" " _goto_level = _eof_trans\n" " next;\n" " end\n"; } if ( redFsm->anyEofActions() ) { out << " begin\n" " __acts = " << EA() << "[" << vCS() << "]\n" " __nacts = " << A() << "[__acts]\n" << " __acts += 1\n" " while ( __nacts > 0 ) \n" " __nacts -= 1\n" " __acts += 1\n" " case ( "<< A() << "[__acts-1] ) \n"; EOF_ACTION_SWITCH() << " end\n" " end\n" " if _trigger_goto\n" " next\n" " end\n" " end\n"; } out << " end\n"; } out << " end\n" " if _goto_level <= _out\n" " break\n" " end\n"; /* The loop for faking goto. */ out << " end\n"; /* Wrapping the execute block. */ out << " end\n"; } /* * Local Variables: * mode: c++ * indent-tabs-mode: 1 * c-file-style: "bsd" * End: */ ragel-6.8/ragel/version.h0000664000175000017500000000006112106313356012331 00000000000000#define VERSION "6.8" #define PUBDATE "Feb 2013" ragel-6.8/ragel/fsmbase.cpp0000664000175000017500000004213412106050031012612 00000000000000/* * Copyright 2001-2007 Adrian Thurston */ /* This file is part of Ragel. * * Ragel is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Ragel is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Ragel; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #include "fsmgraph.h" /* Simple singly linked list append routine for the fill list. The new state * goes to the end of the list. */ void MergeData::fillListAppend( StateAp *state ) { state->alg.next = 0; if ( stfillHead == 0 ) { /* List is empty, state becomes head and tail. */ stfillHead = state; stfillTail = state; } else { /* List is not empty, state goes after last element. */ stfillTail->alg.next = state; stfillTail = state; } } /* Graph constructor. */ FsmAp::FsmAp() : /* No start state. */ startState(0), errState(0), /* Misfit accounting is a switch, turned on only at specific times. It * controls what happens when states have no way in from the outside * world.. */ misfitAccounting(false) { } /* Copy all graph data including transitions. */ FsmAp::FsmAp( const FsmAp &graph ) : /* Lists start empty. Will be filled by copy. */ stateList(), misfitList(), /* Copy in the entry points, * pointers will be resolved later. */ entryPoints(graph.entryPoints), startState(graph.startState), errState(0), /* Will be filled by copy. */ finStateSet(), /* Misfit accounting is only on during merging. */ misfitAccounting(false) { /* Create the states and record their map in the original state. */ StateList::Iter origState = graph.stateList; for ( ; origState.lte(); origState++ ) { /* Make the new state. */ StateAp *newState = new StateAp( *origState ); /* Add the state to the list. */ stateList.append( newState ); /* Set the mapsTo item of the old state. */ origState->alg.stateMap = newState; } /* Derefernce all the state maps. */ for ( StateList::Iter state = stateList; state.lte(); state++ ) { for ( TransList::Iter trans = state->outList; trans.lte(); trans++ ) { /* The points to the original in the src machine. The taget's duplicate * is in the statemap. */ StateAp *toState = trans->toState != 0 ? trans->toState->alg.stateMap : 0; /* Attach The transition to the duplicate. */ trans->toState = 0; attachTrans( state, toState, trans ); } /* Fix the eofTarg, if set. */ if ( state->eofTarget != 0 ) state->eofTarget = state->eofTarget->alg.stateMap; } /* Fix the state pointers in the entry points array. */ EntryMapEl *eel = entryPoints.data; for ( int e = 0; e < entryPoints.length(); e++, eel++ ) { /* Get the duplicate of the state. */ eel->value = eel->value->alg.stateMap; /* Foreign in transitions must be built up when duping machines so * increment it here. */ eel->value->foreignInTrans += 1; } /* Fix the start state pointer and the new start state's count of in * transiions. */ startState = startState->alg.stateMap; startState->foreignInTrans += 1; /* Build the final state set. */ StateSet::Iter st = graph.finStateSet; for ( ; st.lte(); st++ ) finStateSet.insert((*st)->alg.stateMap); } /* Deletes all transition data then deletes each state. */ FsmAp::~FsmAp() { /* Delete all the transitions. */ for ( StateList::Iter state = stateList; state.lte(); state++ ) { /* Iterate the out transitions, deleting them. */ state->outList.empty(); } /* Delete all the states. */ stateList.empty(); } /* Set a state final. The state has its isFinState set to true and the state * is added to the finStateSet. */ void FsmAp::setFinState( StateAp *state ) { /* Is it already a fin state. */ if ( state->stateBits & STB_ISFINAL ) return; state->stateBits |= STB_ISFINAL; finStateSet.insert( state ); } /* Set a state non-final. The has its isFinState flag set false and the state * is removed from the final state set. */ void FsmAp::unsetFinState( StateAp *state ) { /* Is it already a non-final state? */ if ( ! (state->stateBits & STB_ISFINAL) ) return; /* When a state looses its final state status it must relinquish all the * properties that are allowed only for final states. */ clearOutData( state ); state->stateBits &= ~ STB_ISFINAL; finStateSet.remove( state ); } /* Set and unset a state as the start state. */ void FsmAp::setStartState( StateAp *state ) { /* Sould change from unset to set. */ assert( startState == 0 ); startState = state; if ( misfitAccounting ) { /* If the number of foreign in transitions is about to go up to 1 then * take it off the misfit list and put it on the head list. */ if ( state->foreignInTrans == 0 ) stateList.append( misfitList.detach( state ) ); } /* Up the foreign in transitions to the state. */ state->foreignInTrans += 1; } void FsmAp::unsetStartState() { /* Should change from set to unset. */ assert( startState != 0 ); /* Decrement the entry's count of foreign entries. */ startState->foreignInTrans -= 1; if ( misfitAccounting ) { /* If the number of foreign in transitions just went down to 0 then take * it off the main list and put it on the misfit list. */ if ( startState->foreignInTrans == 0 ) misfitList.append( stateList.detach( startState ) ); } startState = 0; } /* Associate an id with a state. Makes the state a named entry point. Has no * effect if the entry point is already mapped to the state. */ void FsmAp::setEntry( int id, StateAp *state ) { /* Insert the id into the state. If the state is already labelled with id, * nothing to do. */ if ( state->entryIds.insert( id ) ) { /* Insert the entry and assert that it succeeds. */ entryPoints.insertMulti( id, state ); if ( misfitAccounting ) { /* If the number of foreign in transitions is about to go up to 1 then * take it off the misfit list and put it on the head list. */ if ( state->foreignInTrans == 0 ) stateList.append( misfitList.detach( state ) ); } /* Up the foreign in transitions to the state. */ state->foreignInTrans += 1; } } /* Remove the association of an id with a state. The state looses it's entry * point status. Assumes that the id is indeed mapped to state. */ void FsmAp::unsetEntry( int id, StateAp *state ) { /* Find the entry point in on id. */ EntryMapEl *enLow = 0, *enHigh = 0; entryPoints.findMulti( id, enLow, enHigh ); while ( enLow->value != state ) enLow += 1; /* Remove the record from the map. */ entryPoints.remove( enLow ); /* Remove the state's sense of the link. */ state->entryIds.remove( id ); state->foreignInTrans -= 1; if ( misfitAccounting ) { /* If the number of foreign in transitions just went down to 0 then take * it off the main list and put it on the misfit list. */ if ( state->foreignInTrans == 0 ) misfitList.append( stateList.detach( state ) ); } } /* Remove all association of an id with states. Assumes that the id is indeed * mapped to a state. */ void FsmAp::unsetEntry( int id ) { /* Find the entry point in on id. */ EntryMapEl *enLow = 0, *enHigh = 0; entryPoints.findMulti( id, enLow, enHigh ); for ( EntryMapEl *mel = enLow; mel <= enHigh; mel++ ) { /* Remove the state's sense of the link. */ mel->value->entryIds.remove( id ); mel->value->foreignInTrans -= 1; if ( misfitAccounting ) { /* If the number of foreign in transitions just went down to 0 * then take it off the main list and put it on the misfit list. */ if ( mel->value->foreignInTrans == 0 ) misfitList.append( stateList.detach( mel->value ) ); } } /* Remove the records from the entry points map. */ entryPoints.removeMulti( enLow, enHigh ); } void FsmAp::changeEntry( int id, StateAp *to, StateAp *from ) { /* Find the entry in the entry map. */ EntryMapEl *enLow = 0, *enHigh = 0; entryPoints.findMulti( id, enLow, enHigh ); while ( enLow->value != from ) enLow += 1; /* Change it to the new target. */ enLow->value = to; /* Remove from's sense of the link. */ from->entryIds.remove( id ); from->foreignInTrans -= 1; if ( misfitAccounting ) { /* If the number of foreign in transitions just went down to 0 then take * it off the main list and put it on the misfit list. */ if ( from->foreignInTrans == 0 ) misfitList.append( stateList.detach( from ) ); } /* Add to's sense of the link. */ if ( to->entryIds.insert( id ) != 0 ) { if ( misfitAccounting ) { /* If the number of foreign in transitions is about to go up to 1 then * take it off the misfit list and put it on the head list. */ if ( to->foreignInTrans == 0 ) stateList.append( misfitList.detach( to ) ); } /* Up the foreign in transitions to the state. */ to->foreignInTrans += 1; } } /* Clear all entry points from a machine. */ void FsmAp::unsetAllEntryPoints() { for ( EntryMap::Iter en = entryPoints; en.lte(); en++ ) { /* Kill all the state's entry points at once. */ if ( en->value->entryIds.length() > 0 ) { en->value->foreignInTrans -= en->value->entryIds.length(); if ( misfitAccounting ) { /* If the number of foreign in transitions just went down to 0 * then take it off the main list and put it on the misfit * list. */ if ( en->value->foreignInTrans == 0 ) misfitList.append( stateList.detach( en->value ) ); } /* Clear the set of ids out all at once. */ en->value->entryIds.empty(); } } /* Now clear out the entry map all at once. */ entryPoints.empty(); } /* Assigning an epsilon transition into final states. */ void FsmAp::epsilonTrans( int id ) { for ( StateSet::Iter fs = finStateSet; fs.lte(); fs++ ) (*fs)->epsilonTrans.append( id ); } /* Mark all states reachable from state. Traverses transitions forward. Used * for removing states that have no path into them. */ void FsmAp::markReachableFromHere( StateAp *state ) { /* Base case: return; */ if ( state->stateBits & STB_ISMARKED ) return; /* Set this state as processed. We are going to visit all states that this * state has a transition to. */ state->stateBits |= STB_ISMARKED; /* Recurse on all out transitions. */ for ( TransList::Iter trans = state->outList; trans.lte(); trans++ ) { if ( trans->toState != 0 ) markReachableFromHere( trans->toState ); } } void FsmAp::markReachableFromHereStopFinal( StateAp *state ) { /* Base case: return; */ if ( state->stateBits & STB_ISMARKED ) return; /* Set this state as processed. We are going to visit all states that this * state has a transition to. */ state->stateBits |= STB_ISMARKED; /* Recurse on all out transitions. */ for ( TransList::Iter trans = state->outList; trans.lte(); trans++ ) { StateAp *toState = trans->toState; if ( toState != 0 && !toState->isFinState() ) markReachableFromHereStopFinal( toState ); } } /* Mark all states reachable from state. Traverse transitions backwards. Used * for removing dead end paths in graphs. */ void FsmAp::markReachableFromHereReverse( StateAp *state ) { /* Base case: return; */ if ( state->stateBits & STB_ISMARKED ) return; /* Set this state as processed. We are going to visit all states with * transitions into this state. */ state->stateBits |= STB_ISMARKED; /* Recurse on all items in transitions. */ for ( TransInList::Iter trans = state->inList; trans.lte(); trans++ ) markReachableFromHereReverse( trans->fromState ); } /* Determine if there are any entry points into a start state other than the * start state. Setting starting transitions requires that the start state be * isolated. In most cases a start state will already be isolated. */ bool FsmAp::isStartStateIsolated() { /* If there are any in transitions then the state is not isolated. */ if ( startState->inList.head != 0 ) return false; /* If there are any entry points then isolated. */ if ( startState->entryIds.length() > 0 ) return false; return true; } /* Bring in other's entry points. Assumes others states are going to be * copied into this machine. */ void FsmAp::copyInEntryPoints( FsmAp *other ) { /* Use insert multi because names are not unique. */ for ( EntryMap::Iter en = other->entryPoints; en.lte(); en++ ) entryPoints.insertMulti( en->key, en->value ); } void FsmAp::unsetAllFinStates() { for ( StateSet::Iter st = finStateSet; st.lte(); st++ ) (*st)->stateBits &= ~ STB_ISFINAL; finStateSet.empty(); } void FsmAp::setFinBits( int finStateBits ) { for ( int s = 0; s < finStateSet.length(); s++ ) finStateSet.data[s]->stateBits |= finStateBits; } /* Tests the integrity of the transition lists and the fromStates. */ void FsmAp::verifyIntegrity() { for ( StateList::Iter state = stateList; state.lte(); state++ ) { /* Walk the out transitions and assert fromState is correct. */ for ( TransList::Iter trans = state->outList; trans.lte(); trans++ ) assert( trans->fromState == state ); /* Walk the inlist and assert toState is correct. */ for ( TransInList::Iter trans = state->inList; trans.lte(); trans++ ) assert( trans->toState == state ); } } void FsmAp::verifyReachability() { /* Mark all the states that can be reached * through the set of entry points. */ markReachableFromHere( startState ); for ( EntryMap::Iter en = entryPoints; en.lte(); en++ ) markReachableFromHere( en->value ); /* Check that everything got marked. */ for ( StateList::Iter st = stateList; st.lte(); st++ ) { /* Assert it got marked and then clear the mark. */ assert( st->stateBits & STB_ISMARKED ); st->stateBits &= ~ STB_ISMARKED; } } void FsmAp::verifyNoDeadEndStates() { /* Mark all states that have paths to the final states. */ for ( StateSet::Iter pst = finStateSet; pst.lte(); pst++ ) markReachableFromHereReverse( *pst ); /* Start state gets honorary marking. Must be done AFTER recursive call. */ startState->stateBits |= STB_ISMARKED; /* Make sure everything got marked. */ for ( StateList::Iter st = stateList; st.lte(); st++ ) { /* Assert the state got marked and unmark it. */ assert( st->stateBits & STB_ISMARKED ); st->stateBits &= ~ STB_ISMARKED; } } void FsmAp::depthFirstOrdering( StateAp *state ) { /* Nothing to do if the state is already on the list. */ if ( state->stateBits & STB_ONLIST ) return; /* Doing depth first, put state on the list. */ state->stateBits |= STB_ONLIST; stateList.append( state ); /* Recurse on everything ranges. */ for ( TransList::Iter tel = state->outList; tel.lte(); tel++ ) { if ( tel->toState != 0 ) depthFirstOrdering( tel->toState ); } } /* Ordering states by transition connections. */ void FsmAp::depthFirstOrdering() { /* Init on state list flags. */ for ( StateList::Iter st = stateList; st.lte(); st++ ) st->stateBits &= ~STB_ONLIST; /* Clear out the state list, we will rebuild it. */ int stateListLen = stateList.length(); stateList.abandon(); /* Add back to the state list from the start state and all other entry * points. */ if ( errState != 0 ) depthFirstOrdering( errState ); depthFirstOrdering( startState ); for ( EntryMap::Iter en = entryPoints; en.lte(); en++ ) depthFirstOrdering( en->value ); /* Make sure we put everything back on. */ assert( stateListLen == stateList.length() ); } /* Stable sort the states by final state status. */ void FsmAp::sortStatesByFinal() { /* Move forward through the list and throw final states onto the end. */ StateAp *state = 0; StateAp *next = stateList.head; StateAp *last = stateList.tail; while ( state != last ) { /* Move forward and load up the next. */ state = next; next = state->next; /* Throw to the end? */ if ( state->isFinState() ) { stateList.detach( state ); stateList.append( state ); } } } void FsmAp::setStateNumbers( int base ) { for ( StateList::Iter state = stateList; state.lte(); state++ ) state->alg.stateNum = base++; } bool FsmAp::checkErrTrans( StateAp *state, TransAp *trans ) { /* Might go directly to error state. */ if ( trans->toState == 0 ) return true; if ( trans->prev == 0 ) { /* If this is the first transition. */ if ( keyOps->minKey < trans->lowKey ) return true; } else { /* Not the first transition. Compare against the prev. */ TransAp *prev = trans->prev; Key nextKey = prev->highKey; nextKey.increment(); if ( nextKey < trans->lowKey ) return true; } return false; } bool FsmAp::checkErrTransFinish( StateAp *state ) { /* Check if there are any ranges already. */ if ( state->outList.length() == 0 ) return true; else { /* Get the last and check for a gap on the end. */ TransAp *last = state->outList.tail; if ( last->highKey < keyOps->maxKey ) return true; } return 0; } bool FsmAp::hasErrorTrans() { bool result; for ( StateList::Iter st = stateList; st.lte(); st++ ) { for ( TransList::Iter tr = st->outList; tr.lte(); tr++ ) { result = checkErrTrans( st, tr ); if ( result ) return true; } result = checkErrTransFinish( st ); if ( result ) return true; } return false; } ragel-6.8/ragel/mltable.cpp0000664000175000017500000007142412106050031012616 00000000000000/* * Copyright 2001-2006 Adrian Thurston * 2004 Erich Ocean * 2005 Alan West */ /* This file is part of Ragel. * * Ragel is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Ragel is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Ragel; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "ragel.h" #include "mltable.h" #include "redfsm.h" #include "gendata.h" /* Determine if we should use indicies or not. */ void OCamlTabCodeGen::calcIndexSize() { int sizeWithInds = 0, sizeWithoutInds = 0; /* Calculate cost of using with indicies. */ for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { int totalIndex = st->outSingle.length() + st->outRange.length() + (st->defTrans == 0 ? 0 : 1); sizeWithInds += arrayTypeSize(redFsm->maxIndex) * totalIndex; } sizeWithInds += arrayTypeSize(redFsm->maxState) * redFsm->transSet.length(); if ( redFsm->anyActions() ) sizeWithInds += arrayTypeSize(redFsm->maxActionLoc) * redFsm->transSet.length(); /* Calculate the cost of not using indicies. */ for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { int totalIndex = st->outSingle.length() + st->outRange.length() + (st->defTrans == 0 ? 0 : 1); sizeWithoutInds += arrayTypeSize(redFsm->maxState) * totalIndex; if ( redFsm->anyActions() ) sizeWithoutInds += arrayTypeSize(redFsm->maxActionLoc) * totalIndex; } /* If using indicies reduces the size, use them. */ useIndicies = sizeWithInds < sizeWithoutInds; } std::ostream &OCamlTabCodeGen::TO_STATE_ACTION( RedStateAp *state ) { int act = 0; if ( state->toStateAction != 0 ) act = state->toStateAction->location+1; out << act; return out; } std::ostream &OCamlTabCodeGen::FROM_STATE_ACTION( RedStateAp *state ) { int act = 0; if ( state->fromStateAction != 0 ) act = state->fromStateAction->location+1; out << act; return out; } std::ostream &OCamlTabCodeGen::EOF_ACTION( RedStateAp *state ) { int act = 0; if ( state->eofAction != 0 ) act = state->eofAction->location+1; out << act; return out; } std::ostream &OCamlTabCodeGen::TRANS_ACTION( RedTransAp *trans ) { /* If there are actions, emit them. Otherwise emit zero. */ int act = 0; if ( trans->action != 0 ) act = trans->action->location+1; out << act; return out; } std::ostream &OCamlTabCodeGen::TO_STATE_ACTION_SWITCH() { /* Walk the list of functions, printing the cases. */ for ( GenActionList::Iter act = actionList; act.lte(); act++ ) { /* Write out referenced actions. */ if ( act->numToStateRefs > 0 ) { /* Write the case label, the action and the case break. */ out << "\t| " << act->actionId << " ->\n"; ACTION( out, act, 0, false ); } } genLineDirective( out ); return out; } std::ostream &OCamlTabCodeGen::FROM_STATE_ACTION_SWITCH() { /* Walk the list of functions, printing the cases. */ for ( GenActionList::Iter act = actionList; act.lte(); act++ ) { /* Write out referenced actions. */ if ( act->numFromStateRefs > 0 ) { /* Write the case label, the action and the case break. */ out << "\t| " << act->actionId << " ->\n"; ACTION( out, act, 0, false ); } } genLineDirective( out ); return out; } std::ostream &OCamlTabCodeGen::EOF_ACTION_SWITCH() { /* Walk the list of functions, printing the cases. */ for ( GenActionList::Iter act = actionList; act.lte(); act++ ) { /* Write out referenced actions. */ if ( act->numEofRefs > 0 ) { /* Write the case label, the action and the case break. */ out << "\t| " << act->actionId << " ->\n"; ACTION( out, act, 0, true ); } } genLineDirective( out ); return out; } std::ostream &OCamlTabCodeGen::ACTION_SWITCH() { /* Walk the list of functions, printing the cases. */ for ( GenActionList::Iter act = actionList; act.lte(); act++ ) { /* Write out referenced actions. */ if ( act->numTransRefs > 0 ) { /* Write the case label, the action and the case break. */ out << "\t| " << act->actionId << " -> \n"; ACTION( out, act, 0, false ); } } genLineDirective( out ); return out; } std::ostream &OCamlTabCodeGen::COND_OFFSETS() { out << "\t"; int totalStateNum = 0, curKeyOffset = 0; for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { /* Write the key offset. */ out << curKeyOffset; if ( !st.last() ) { out << ARR_SEP(); if ( ++totalStateNum % IALL == 0 ) out << "\n\t"; } /* Move the key offset ahead. */ curKeyOffset += st->stateCondList.length(); } out << "\n"; return out; } std::ostream &OCamlTabCodeGen::KEY_OFFSETS() { out << "\t"; int totalStateNum = 0, curKeyOffset = 0; for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { /* Write the key offset. */ out << curKeyOffset; if ( !st.last() ) { out << ARR_SEP(); if ( ++totalStateNum % IALL == 0 ) out << "\n\t"; } /* Move the key offset ahead. */ curKeyOffset += st->outSingle.length() + st->outRange.length()*2; } out << "\n"; return out; } std::ostream &OCamlTabCodeGen::INDEX_OFFSETS() { out << "\t"; int totalStateNum = 0, curIndOffset = 0; for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { /* Write the index offset. */ out << curIndOffset; if ( !st.last() ) { out << ARR_SEP(); if ( ++totalStateNum % IALL == 0 ) out << "\n\t"; } /* Move the index offset ahead. */ curIndOffset += st->outSingle.length() + st->outRange.length(); if ( st->defTrans != 0 ) curIndOffset += 1; } out << "\n"; return out; } std::ostream &OCamlTabCodeGen::COND_LENS() { out << "\t"; int totalStateNum = 0; for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { /* Write singles length. */ out << st->stateCondList.length(); if ( !st.last() ) { out << ARR_SEP(); if ( ++totalStateNum % IALL == 0 ) out << "\n\t"; } } out << "\n"; return out; } std::ostream &OCamlTabCodeGen::SINGLE_LENS() { out << "\t"; int totalStateNum = 0; for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { /* Write singles length. */ out << st->outSingle.length(); if ( !st.last() ) { out << ARR_SEP(); if ( ++totalStateNum % IALL == 0 ) out << "\n\t"; } } out << "\n"; return out; } std::ostream &OCamlTabCodeGen::RANGE_LENS() { out << "\t"; int totalStateNum = 0; for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { /* Emit length of range index. */ out << st->outRange.length(); if ( !st.last() ) { out << ARR_SEP(); if ( ++totalStateNum % IALL == 0 ) out << "\n\t"; } } out << "\n"; return out; } std::ostream &OCamlTabCodeGen::TO_STATE_ACTIONS() { out << "\t"; int totalStateNum = 0; for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { /* Write any eof action. */ TO_STATE_ACTION(st); if ( !st.last() ) { out << ARR_SEP(); if ( ++totalStateNum % IALL == 0 ) out << "\n\t"; } } out << "\n"; return out; } std::ostream &OCamlTabCodeGen::FROM_STATE_ACTIONS() { out << "\t"; int totalStateNum = 0; for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { /* Write any eof action. */ FROM_STATE_ACTION(st); if ( !st.last() ) { out << ARR_SEP(); if ( ++totalStateNum % IALL == 0 ) out << "\n\t"; } } out << "\n"; return out; } std::ostream &OCamlTabCodeGen::EOF_ACTIONS() { out << "\t"; int totalStateNum = 0; for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { /* Write any eof action. */ EOF_ACTION(st); if ( !st.last() ) { out << ARR_SEP(); if ( ++totalStateNum % IALL == 0 ) out << "\n\t"; } } out << "\n"; return out; } std::ostream &OCamlTabCodeGen::EOF_TRANS() { out << "\t"; int totalStateNum = 0; for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { /* Write any eof action. */ long trans = 0; if ( st->eofTrans != 0 ) { assert( st->eofTrans->pos >= 0 ); trans = st->eofTrans->pos+1; } out << trans; if ( !st.last() ) { out << ARR_SEP(); if ( ++totalStateNum % IALL == 0 ) out << "\n\t"; } } out << "\n"; return out; } std::ostream &OCamlTabCodeGen::COND_KEYS() { out << '\t'; int totalTrans = 0; for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { /* Loop the state's transitions. */ for ( GenStateCondList::Iter sc = st->stateCondList; sc.lte(); sc++ ) { /* Lower key. */ out << ALPHA_KEY( sc->lowKey ) << ARR_SEP(); if ( ++totalTrans % IALL == 0 ) out << "\n\t"; /* Upper key. */ out << ALPHA_KEY( sc->highKey ) << ARR_SEP(); if ( ++totalTrans % IALL == 0 ) out << "\n\t"; } } /* Output one last number so we don't have to figure out when the last * entry is and avoid writing a comma. */ out << 0 << "\n"; return out; } std::ostream &OCamlTabCodeGen::COND_SPACES() { out << '\t'; int totalTrans = 0; for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { /* Loop the state's transitions. */ for ( GenStateCondList::Iter sc = st->stateCondList; sc.lte(); sc++ ) { /* Cond Space id. */ out << sc->condSpace->condSpaceId << ARR_SEP(); if ( ++totalTrans % IALL == 0 ) out << "\n\t"; } } /* Output one last number so we don't have to figure out when the last * entry is and avoid writing a comma. */ out << 0 << "\n"; return out; } std::ostream &OCamlTabCodeGen::KEYS() { out << '\t'; int totalTrans = 0; for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { /* Loop the singles. */ for ( RedTransList::Iter stel = st->outSingle; stel.lte(); stel++ ) { out << ALPHA_KEY( stel->lowKey ) << ARR_SEP(); if ( ++totalTrans % IALL == 0 ) out << "\n\t"; } /* Loop the state's transitions. */ for ( RedTransList::Iter rtel = st->outRange; rtel.lte(); rtel++ ) { /* Lower key. */ out << ALPHA_KEY( rtel->lowKey ) << ARR_SEP(); if ( ++totalTrans % IALL == 0 ) out << "\n\t"; /* Upper key. */ out << ALPHA_KEY( rtel->highKey ) << ARR_SEP(); if ( ++totalTrans % IALL == 0 ) out << "\n\t"; } } /* Output one last number so we don't have to figure out when the last * entry is and avoid writing a comma. */ out << 0 << "\n"; return out; } std::ostream &OCamlTabCodeGen::INDICIES() { int totalTrans = 0; out << '\t'; for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { /* Walk the singles. */ for ( RedTransList::Iter stel = st->outSingle; stel.lte(); stel++ ) { out << stel->value->id << ARR_SEP(); if ( ++totalTrans % IALL == 0 ) out << "\n\t"; } /* Walk the ranges. */ for ( RedTransList::Iter rtel = st->outRange; rtel.lte(); rtel++ ) { out << rtel->value->id << ARR_SEP(); if ( ++totalTrans % IALL == 0 ) out << "\n\t"; } /* The state's default index goes next. */ if ( st->defTrans != 0 ) { out << st->defTrans->id << ARR_SEP(); if ( ++totalTrans % IALL == 0 ) out << "\n\t"; } } /* Output one last number so we don't have to figure out when the last * entry is and avoid writing a comma. */ out << 0 << "\n"; return out; } std::ostream &OCamlTabCodeGen::TRANS_TARGS() { int totalTrans = 0; out << '\t'; for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { /* Walk the singles. */ for ( RedTransList::Iter stel = st->outSingle; stel.lte(); stel++ ) { RedTransAp *trans = stel->value; out << trans->targ->id << ARR_SEP(); if ( ++totalTrans % IALL == 0 ) out << "\n\t"; } /* Walk the ranges. */ for ( RedTransList::Iter rtel = st->outRange; rtel.lte(); rtel++ ) { RedTransAp *trans = rtel->value; out << trans->targ->id << ARR_SEP(); if ( ++totalTrans % IALL == 0 ) out << "\n\t"; } /* The state's default target state. */ if ( st->defTrans != 0 ) { RedTransAp *trans = st->defTrans; out << trans->targ->id << ARR_SEP(); if ( ++totalTrans % IALL == 0 ) out << "\n\t"; } } for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { if ( st->eofTrans != 0 ) { RedTransAp *trans = st->eofTrans; trans->pos = totalTrans; out << trans->targ->id << ARR_SEP(); if ( ++totalTrans % IALL == 0 ) out << "\n\t"; } } /* Output one last number so we don't have to figure out when the last * entry is and avoid writing a comma. */ out << 0 << "\n"; return out; } std::ostream &OCamlTabCodeGen::TRANS_ACTIONS() { int totalTrans = 0; out << '\t'; for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { /* Walk the singles. */ for ( RedTransList::Iter stel = st->outSingle; stel.lte(); stel++ ) { RedTransAp *trans = stel->value; TRANS_ACTION( trans ) << ARR_SEP(); if ( ++totalTrans % IALL == 0 ) out << "\n\t"; } /* Walk the ranges. */ for ( RedTransList::Iter rtel = st->outRange; rtel.lte(); rtel++ ) { RedTransAp *trans = rtel->value; TRANS_ACTION( trans ) << ARR_SEP(); if ( ++totalTrans % IALL == 0 ) out << "\n\t"; } /* The state's default index goes next. */ if ( st->defTrans != 0 ) { RedTransAp *trans = st->defTrans; TRANS_ACTION( trans ) << ARR_SEP(); if ( ++totalTrans % IALL == 0 ) out << "\n\t"; } } for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { if ( st->eofTrans != 0 ) { RedTransAp *trans = st->eofTrans; TRANS_ACTION( trans ) << ARR_SEP(); if ( ++totalTrans % IALL == 0 ) out << "\n\t"; } } /* Output one last number so we don't have to figure out when the last * entry is and avoid writing a comma. */ out << 0 << "\n"; return out; } std::ostream &OCamlTabCodeGen::TRANS_TARGS_WI() { /* Transitions must be written ordered by their id. */ RedTransAp **transPtrs = new RedTransAp*[redFsm->transSet.length()]; for ( TransApSet::Iter trans = redFsm->transSet; trans.lte(); trans++ ) transPtrs[trans->id] = trans; /* Keep a count of the num of items in the array written. */ out << '\t'; int totalStates = 0; for ( int t = 0; t < redFsm->transSet.length(); t++ ) { /* Record the position, need this for eofTrans. */ RedTransAp *trans = transPtrs[t]; trans->pos = t; /* Write out the target state. */ out << trans->targ->id; if ( t < redFsm->transSet.length()-1 ) { out << ARR_SEP(); if ( ++totalStates % IALL == 0 ) out << "\n\t"; } } out << "\n"; delete[] transPtrs; return out; } std::ostream &OCamlTabCodeGen::TRANS_ACTIONS_WI() { /* Transitions must be written ordered by their id. */ RedTransAp **transPtrs = new RedTransAp*[redFsm->transSet.length()]; for ( TransApSet::Iter trans = redFsm->transSet; trans.lte(); trans++ ) transPtrs[trans->id] = trans; /* Keep a count of the num of items in the array written. */ out << '\t'; int totalAct = 0; for ( int t = 0; t < redFsm->transSet.length(); t++ ) { /* Write the function for the transition. */ RedTransAp *trans = transPtrs[t]; TRANS_ACTION( trans ); if ( t < redFsm->transSet.length()-1 ) { out << ARR_SEP(); if ( ++totalAct % IALL == 0 ) out << "\n\t"; } } out << "\n"; delete[] transPtrs; return out; } void OCamlTabCodeGen::GOTO( ostream &ret, int gotoDest, bool inFinish ) { ret << "begin " << vCS() << " <- " << gotoDest << "; " << CTRL_FLOW() << "raise Goto_again end"; } void OCamlTabCodeGen::GOTO_EXPR( ostream &ret, GenInlineItem *ilItem, bool inFinish ) { ret << "begin " << vCS() << " <- ("; INLINE_LIST( ret, ilItem->children, 0, inFinish ); ret << "); " << CTRL_FLOW() << "raise Goto_again end"; } void OCamlTabCodeGen::CURS( ostream &ret, bool inFinish ) { ret << "(_ps)"; } void OCamlTabCodeGen::TARGS( ostream &ret, bool inFinish, int targState ) { ret << "(" << vCS() << ")"; } void OCamlTabCodeGen::NEXT( ostream &ret, int nextDest, bool inFinish ) { ret << vCS() << " <- " << nextDest << ";"; } void OCamlTabCodeGen::NEXT_EXPR( ostream &ret, GenInlineItem *ilItem, bool inFinish ) { ret << vCS() << " <- ("; INLINE_LIST( ret, ilItem->children, 0, inFinish ); ret << ");"; } void OCamlTabCodeGen::CALL( ostream &ret, int callDest, int targState, bool inFinish ) { if ( prePushExpr != 0 ) { ret << "begin "; INLINE_LIST( ret, prePushExpr, 0, false ); } ret << "begin " << AT( STACK(), POST_INCR(TOP()) ) << " <- " << vCS() << "; "; ret << vCS() << " <- " << callDest << "; " << CTRL_FLOW() << "raise Goto_again end "; if ( prePushExpr != 0 ) ret << "end"; } void OCamlTabCodeGen::CALL_EXPR( ostream &ret, GenInlineItem *ilItem, int targState, bool inFinish ) { if ( prePushExpr != 0 ) { ret << "begin "; INLINE_LIST( ret, prePushExpr, 0, false ); } ret << "begin " << AT(STACK(), POST_INCR(TOP()) ) << " <- " << vCS() << "; " << vCS() << " <- ("; INLINE_LIST( ret, ilItem->children, targState, inFinish ); ret << "); " << CTRL_FLOW() << "raise Goto_again end "; if ( prePushExpr != 0 ) ret << "end"; } void OCamlTabCodeGen::RET( ostream &ret, bool inFinish ) { ret << "begin " << vCS() << " <- " << AT(STACK(), PRE_DECR(TOP()) ) << "; "; if ( postPopExpr != 0 ) { ret << "begin "; INLINE_LIST( ret, postPopExpr, 0, false ); ret << "end "; } ret << CTRL_FLOW() << "raise Goto_again end"; } void OCamlTabCodeGen::BREAK( ostream &ret, int targState ) { outLabelUsed = true; ret << "begin " << P() << " <- " << P() << " + 1; " << CTRL_FLOW() << "raise Goto_out end"; } void OCamlTabCodeGen::writeData() { /* If there are any transtion functions then output the array. If there * are none, don't bother emitting an empty array that won't be used. */ if ( redFsm->anyActions() ) { OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActArrItem), A() ); ACTIONS_ARRAY(); CLOSE_ARRAY() << "\n"; } if ( redFsm->anyConditions() ) { OPEN_ARRAY( ARRAY_TYPE(redFsm->maxCondOffset), CO() ); COND_OFFSETS(); CLOSE_ARRAY() << "\n"; OPEN_ARRAY( ARRAY_TYPE(redFsm->maxCondLen), CL() ); COND_LENS(); CLOSE_ARRAY() << "\n"; OPEN_ARRAY( WIDE_ALPH_TYPE(), CK() ); COND_KEYS(); CLOSE_ARRAY() << "\n"; OPEN_ARRAY( ARRAY_TYPE(redFsm->maxCondSpaceId), C() ); COND_SPACES(); CLOSE_ARRAY() << "\n"; } OPEN_ARRAY( ARRAY_TYPE(redFsm->maxKeyOffset), KO() ); KEY_OFFSETS(); CLOSE_ARRAY() << "\n"; OPEN_ARRAY( WIDE_ALPH_TYPE(), K() ); KEYS(); CLOSE_ARRAY() << "\n"; OPEN_ARRAY( ARRAY_TYPE(redFsm->maxSingleLen), SL() ); SINGLE_LENS(); CLOSE_ARRAY() << "\n"; OPEN_ARRAY( ARRAY_TYPE(redFsm->maxRangeLen), RL() ); RANGE_LENS(); CLOSE_ARRAY() << "\n"; OPEN_ARRAY( ARRAY_TYPE(redFsm->maxIndexOffset), IO() ); INDEX_OFFSETS(); CLOSE_ARRAY() << "\n"; if ( useIndicies ) { OPEN_ARRAY( ARRAY_TYPE(redFsm->maxIndex), I() ); INDICIES(); CLOSE_ARRAY() << "\n"; OPEN_ARRAY( ARRAY_TYPE(redFsm->maxState), TT() ); TRANS_TARGS_WI(); CLOSE_ARRAY() << "\n"; if ( redFsm->anyActions() ) { OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActionLoc), TA() ); TRANS_ACTIONS_WI(); CLOSE_ARRAY() << "\n"; } } else { OPEN_ARRAY( ARRAY_TYPE(redFsm->maxState), TT() ); TRANS_TARGS(); CLOSE_ARRAY() << "\n"; if ( redFsm->anyActions() ) { OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActionLoc), TA() ); TRANS_ACTIONS(); CLOSE_ARRAY() << "\n"; } } if ( redFsm->anyToStateActions() ) { OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActionLoc), TSA() ); TO_STATE_ACTIONS(); CLOSE_ARRAY() << "\n"; } if ( redFsm->anyFromStateActions() ) { OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActionLoc), FSA() ); FROM_STATE_ACTIONS(); CLOSE_ARRAY() << "\n"; } if ( redFsm->anyEofActions() ) { OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActionLoc), EA() ); EOF_ACTIONS(); CLOSE_ARRAY() << "\n"; } if ( redFsm->anyEofTrans() ) { OPEN_ARRAY( ARRAY_TYPE(redFsm->maxIndexOffset+1), ET() ); EOF_TRANS(); CLOSE_ARRAY() << "\n"; } STATE_IDS(); out << "type state = { mutable keys : int; mutable trans : int; mutable acts : int; mutable nacts : int; }" << TOP_SEP(); out << "exception Goto_match" << TOP_SEP(); out << "exception Goto_again" << TOP_SEP(); out << "exception Goto_eof_trans" << TOP_SEP(); } void OCamlTabCodeGen::LOCATE_TRANS() { out << " state.keys <- " << AT( KO(), vCS() ) << ";\n" " state.trans <- " << CAST(transType) << AT( IO(), vCS() ) << ";\n" "\n" " let klen = " << AT( SL(), vCS() ) << " in\n" " if klen > 0 then begin\n" " let lower : " << signedKeysType << " ref = ref state.keys in\n" " let upper : " << signedKeysType << " ref = ref " << CAST(signedKeysType) << "(state.keys + klen - 1) in\n" " while !upper >= !lower do\n" " let mid = " << CAST(signedKeysType) << " (!lower + ((!upper - !lower) / 2)) in\n" " if " << GET_WIDE_KEY() << " < " << AT( K(), "mid" ) << " then\n" " upper := " << CAST(signedKeysType) << " (mid - 1)\n" " else if " << GET_WIDE_KEY() << " > " << AT( K(), "mid" ) << " then\n" " lower := " << CAST(signedKeysType) << " (mid + 1)\n" " else begin\n" " state.trans <- state.trans + " << CAST(transType) << " (mid - state.keys);\n" " raise Goto_match;\n" " end\n" " done;\n" " state.keys <- state.keys + " << CAST(keysType) << " klen;\n" " state.trans <- state.trans + " << CAST(transType) << " klen;\n" " end;\n" "\n" " let klen = " << AT( RL(), vCS() ) << " in\n" " if klen > 0 then begin\n" " let lower : " << signedKeysType << " ref = ref state.keys in\n" " let upper : " << signedKeysType << " ref = ref " << CAST(signedKeysType) << "(state.keys + (klen * 2) - 2) in\n" " while !upper >= !lower do\n" " let mid = " << CAST(signedKeysType) << " (!lower + (((!upper - !lower) / 2) land (lnot 1))) in\n" " if " << GET_WIDE_KEY() << " < " << AT( K() , "mid" ) << " then\n" " upper := " << CAST(signedKeysType) << " (mid - 2)\n" " else if " << GET_WIDE_KEY() << " > " << AT( K(), "mid+1" ) << " then\n" " lower := " << CAST(signedKeysType) << " (mid + 2)\n" " else begin\n" " state.trans <- state.trans + " << CAST(transType) << "((mid - state.keys) / 2);\n" " raise Goto_match;\n" " end\n" " done;\n" " state.trans <- state.trans + " << CAST(transType) << " klen;\n" " end;\n" "\n"; } void OCamlTabCodeGen::COND_TRANSLATE() { out << " _widec = " << GET_KEY() << ";\n" " _klen = " << CL() << "[" << vCS() << "];\n" " _keys = " << CAST(keysType) << " ("<< CO() << "[" << vCS() << "]*2);\n" " if ( _klen > 0 ) {\n" " " << signedKeysType << " _lower = _keys;\n" " " << signedKeysType << " _mid;\n" " " << signedKeysType << " _upper = " << CAST(signedKeysType) << " (_keys + (_klen<<1) - 2);\n" " while (true) {\n" " if ( _upper < _lower )\n" " break;\n" "\n" " _mid = " << CAST(signedKeysType) << " (_lower + (((_upper-_lower) >> 1) & ~1));\n" " if ( " << GET_WIDE_KEY() << " < " << CK() << "[_mid] )\n" " _upper = " << CAST(signedKeysType) << " (_mid - 2);\n" " else if ( " << GET_WIDE_KEY() << " > " << CK() << "[_mid+1] )\n" " _lower = " << CAST(signedKeysType) << " (_mid + 2);\n" " else {\n" " switch ( " << C() << "[" << CO() << "[" << vCS() << "]" " + ((_mid - _keys)>>1)] ) {\n"; for ( CondSpaceList::Iter csi = condSpaceList; csi.lte(); csi++ ) { GenCondSpace *condSpace = csi; out << " case " << condSpace->condSpaceId << ": {\n"; out << TABS(2) << "_widec = " << CAST(WIDE_ALPH_TYPE()) << "(" << KEY(condSpace->baseKey) << " + (" << GET_KEY() << " - " << KEY(keyOps->minKey) << "));\n"; for ( GenCondSet::Iter csi = condSpace->condSet; csi.lte(); csi++ ) { out << TABS(2) << "if ( "; CONDITION( out, *csi ); Size condValOffset = ((1 << csi.pos()) * keyOps->alphSize()); out << " ) _widec += " << condValOffset << ";\n"; } out << " break;\n" " }\n"; } SWITCH_DEFAULT(); out << " }\n" " break;\n" " }\n" " }\n" " }\n" "\n"; } void OCamlTabCodeGen::writeExec() { testEofUsed = false; outLabelUsed = false; initVarTypes(); out << " begin\n"; // " " << klenType << " _klen"; // if ( redFsm->anyRegCurStateRef() ) // out << ", _ps"; /* out << " " << transType << " _trans;\n"; if ( redFsm->anyConditions() ) out << " " << WIDE_ALPH_TYPE() << " _widec;\n"; if ( redFsm->anyToStateActions() || redFsm->anyRegActions() || redFsm->anyFromStateActions() ) { out << " int _acts;\n" " int _nacts;\n"; } out << " " << keysType << " _keys;\n" "\n"; // " " << PTR_CONST() << WIDE_ALPH_TYPE() << POINTER() << "_keys;\n" */ out << " let state = { keys = 0; trans = 0; acts = 0; nacts = 0; } in\n" " let rec do_start () =\n"; if ( !noEnd ) { testEofUsed = true; out << " if " << P() << " = " << PE() << " then\n" " do_test_eof ()\n" "\telse\n"; } if ( redFsm->errState != 0 ) { outLabelUsed = true; out << " if " << vCS() << " = " << redFsm->errState->id << " then\n" " do_out ()\n" "\telse\n"; } out << "\tdo_resume ()\n"; out << "and do_resume () =\n"; if ( redFsm->anyFromStateActions() ) { out << " state.acts <- " << AT( FSA(), vCS() ) << ";\n" " state.nacts <- " << AT( A(), POST_INCR("state.acts") ) << ";\n" " while " << POST_DECR("state.nacts") << " > 0 do\n" " begin match " << AT( A(), POST_INCR("state.acts") ) << " with\n"; FROM_STATE_ACTION_SWITCH(); SWITCH_DEFAULT() << " end\n" " done;\n" "\n"; } if ( redFsm->anyConditions() ) COND_TRANSLATE(); out << "\tbegin try\n"; LOCATE_TRANS(); out << "\twith Goto_match -> () end;\n"; out << "\tdo_match ()\n"; out << "and do_match () =\n"; if ( useIndicies ) out << " state.trans <- " << CAST(transType) << AT( I(), "state.trans" ) << ";\n"; out << "\tdo_eof_trans ()\n"; // if ( redFsm->anyEofTrans() ) out << "and do_eof_trans () =\n"; if ( redFsm->anyRegCurStateRef() ) out << " let ps = " << vCS() << " in\n"; out << " " << vCS() << " <- " << AT( TT() ,"state.trans" ) << ";\n" "\n"; if ( redFsm->anyRegActions() ) { out << "\tbegin try\n" " match " << AT( TA(), "state.trans" ) << " with\n" "\t| 0 -> raise Goto_again\n" "\t| _ ->\n" " state.acts <- " << AT( TA(), "state.trans" ) << ";\n" " state.nacts <- " << AT( A(), POST_INCR("state.acts") ) << ";\n" " while " << POST_DECR("state.nacts") << " > 0 do\n" " begin match " << AT( A(), POST_INCR("state.acts") ) << " with\n"; ACTION_SWITCH(); SWITCH_DEFAULT() << " end;\n" " done\n" "\twith Goto_again -> () end;\n"; } out << "\tdo_again ()\n"; // if ( redFsm->anyRegActions() || redFsm->anyActionGotos() || // redFsm->anyActionCalls() || redFsm->anyActionRets() ) out << "\tand do_again () =\n"; if ( redFsm->anyToStateActions() ) { out << " state.acts <- " << AT( TSA(), vCS() ) << ";\n" " state.nacts <- " << AT( A(), POST_INCR("state.acts") ) << ";\n" " while " << POST_DECR("state.nacts") << " > 0 do\n" " begin match " << AT( A(), POST_INCR("state.acts") ) << " with\n"; TO_STATE_ACTION_SWITCH(); SWITCH_DEFAULT() << " end\n" " done;\n" "\n"; } if ( redFsm->errState != 0 ) { outLabelUsed = true; out << " match " << vCS() << " with\n" "\t| " << redFsm->errState->id << " -> do_out ()\n" "\t| _ ->\n"; } out << "\t" << P() << " <- " << P() << " + 1;\n"; if ( !noEnd ) { out << " if " << P() << " <> " << PE() << " then\n" " do_resume ()\n" "\telse do_test_eof ()\n"; } else { out << " do_resume ()\n"; } // if ( testEofUsed ) out << "and do_test_eof () =\n"; if ( redFsm->anyEofTrans() || redFsm->anyEofActions() ) { out << " if " << P() << " = " << vEOF() << " then\n" " begin try\n"; if ( redFsm->anyEofTrans() ) { out << " if " << AT( ET(), vCS() ) << " > 0 then\n" " begin\n" " state.trans <- " << CAST(transType) << "(" << AT( ET(), vCS() ) << " - 1);\n" " raise Goto_eof_trans;\n" " end\n"; } if ( redFsm->anyEofActions() ) { out << " let __acts = ref " << AT( EA(), vCS() ) << " in\n" " let __nacts = ref " << AT( A(), "!__acts" ) << " in\n" " incr __acts;\n" " while !__nacts > 0 do\n" " decr __nacts;\n" " begin match " << AT( A(), POST_INCR("__acts.contents") ) << " with\n"; EOF_ACTION_SWITCH(); SWITCH_DEFAULT() << " end;\n" " done\n"; } out << " with Goto_again -> do_again ()\n" " | Goto_eof_trans -> do_eof_trans () end\n" "\n"; } else { out << "\t()\n"; } if ( outLabelUsed ) out << " and do_out () = ()\n"; out << "\tin do_start ()\n"; out << " end;\n"; } void OCamlTabCodeGen::initVarTypes() { int klenMax = MAX(MAX(redFsm->maxCondLen, redFsm->maxRangeLen), redFsm->maxSingleLen); int keysMax = MAX(MAX(redFsm->maxKeyOffset, klenMax), redFsm->maxCondOffset); int transMax = MAX(MAX(redFsm->maxIndex+1, redFsm->maxIndexOffset), keysMax); transMax = MAX(transMax, klenMax); transType = ARRAY_TYPE(transMax); klenType = ARRAY_TYPE(klenMax); keysType = ARRAY_TYPE(keysMax); signedKeysType = ARRAY_TYPE(keysMax, true); } ragel-6.8/ragel/rbxgoto.h0000664000175000017500000000607612106050031012330 00000000000000/* * Copyright 2007 Victor Hugo Borja * 2006-2007 Adrian Thurston */ /* This file is part of Ragel. * * Ragel is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Ragel is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Ragel; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef _RBX_GOTOCODEGEN_H #define _RBX_GOTOCODEGEN_H #include #include #include "rubycodegen.h" using std::string; class RbxGotoCodeGen : public RubyCodeGen { public: RbxGotoCodeGen( ostream &out ) : RubyCodeGen(out) {} virtual ~RbxGotoCodeGen() {} std::ostream &TO_STATE_ACTION_SWITCH(); std::ostream &FROM_STATE_ACTION_SWITCH(); std::ostream &EOF_ACTION_SWITCH(); std::ostream &ACTION_SWITCH(); std::ostream &STATE_GOTOS(); std::ostream &TRANSITIONS(); std::ostream &EXEC_FUNCS(); std::ostream &FINISH_CASES(); void GOTO( ostream &ret, int gotoDest, bool inFinish ); void CALL( ostream &ret, int callDest, int targState, bool inFinish ); void NEXT( ostream &ret, int nextDest, bool inFinish ); void GOTO_EXPR( ostream &ret, GenInlineItem *ilItem, bool inFinish ); void NEXT_EXPR( ostream &ret, GenInlineItem *ilItem, bool inFinish ); void CALL_EXPR( ostream &ret, GenInlineItem *ilItem, int targState, bool inFinish ); void CURS( ostream &ret, bool inFinish ); void TARGS( ostream &ret, bool inFinish, int targState ); void RET( ostream &ret, bool inFinish ); void BREAK( ostream &ret, int targState ); int TO_STATE_ACTION( RedStateAp *state ); int FROM_STATE_ACTION( RedStateAp *state ); int EOF_ACTION( RedStateAp *state ); void COND_TRANSLATE( GenStateCond *stateCond, int level ); void emitCondBSearch( RedStateAp *state, int level, int low, int high ); void STATE_CONDS( RedStateAp *state, bool genDefault ); virtual std::ostream &TRANS_GOTO( RedTransAp *trans, int level ); void emitSingleSwitch( RedStateAp *state ); void emitRangeBSearch( RedStateAp *state, int level, int low, int high ); /* Called from STATE_GOTOS just before writing the gotos */ virtual void GOTO_HEADER( RedStateAp *state ); virtual void STATE_GOTO_ERROR(); virtual void writeData(); virtual void writeEOF(); virtual void writeExec(); std::ostream &TO_STATE_ACTIONS(); std::ostream &FROM_STATE_ACTIONS(); std::ostream &EOF_ACTIONS(); private: ostream &rbxGoto(ostream &out, string label); ostream &rbxLabel(ostream &out, string label); }; /* * Local Variables: * mode: c++ * indent-tabs-mode: 1 * c-file-style: "bsd" * End: */ #endif ragel-6.8/ragel/redfsm.h0000664000175000017500000003023312106050031012114 00000000000000/* * Copyright 2001-2006 Adrian Thurston */ /* This file is part of Ragel. * * Ragel is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Ragel is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Ragel; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef _REDFSM_H #define _REDFSM_H #include #include #include #include "config.h" #include "common.h" #include "vector.h" #include "dlist.h" #include "compare.h" #include "bstmap.h" #include "bstset.h" #include "avlmap.h" #include "avltree.h" #include "avlbasic.h" #include "mergesort.h" #include "sbstmap.h" #include "sbstset.h" #include "sbsttable.h" #define TRANS_ERR_TRANS 0 #define STATE_ERR_STATE 0 #define FUNC_NO_FUNC 0 using std::string; struct RedStateAp; struct GenInlineList; struct GenAction; /* * Inline code tree */ struct GenInlineItem { enum Type { Text, Goto, Call, Next, GotoExpr, CallExpr, NextExpr, Ret, PChar, Char, Hold, Exec, Curs, Targs, Entry, LmSwitch, LmSetActId, LmSetTokEnd, LmGetTokEnd, LmInitTokStart, LmInitAct, LmSetTokStart, SubAction, Break }; GenInlineItem( const InputLoc &loc, Type type ) : loc(loc), data(0), targId(0), targState(0), lmId(0), children(0), offset(0), type(type) { } InputLoc loc; char *data; int targId; RedStateAp *targState; int lmId; GenInlineList *children; int offset; Type type; GenInlineItem *prev, *next; }; /* Normally this would be atypedef, but that would entail including DList from * ptreetypes, which should be just typedef forwards. */ struct GenInlineList : public DList { }; /* Element in list of actions. Contains the string for the code to exectute. */ struct GenAction : public DListEl { GenAction( ) : name(0), inlineList(0), actionId(0), numTransRefs(0), numToStateRefs(0), numFromStateRefs(0), numEofRefs(0) { } /* Data collected during parse. */ InputLoc loc; const char *name; GenInlineList *inlineList; int actionId; string nameOrLoc(); /* Number of references in the final machine. */ int numRefs() { return numTransRefs + numToStateRefs + numFromStateRefs + numEofRefs; } int numTransRefs; int numToStateRefs; int numFromStateRefs; int numEofRefs; }; /* Forwards. */ struct RedStateAp; struct StateAp; /* Transistion GenAction Element. */ typedef SBstMapEl< int, GenAction* > GenActionTableEl; /* Transition GenAction Table. */ struct GenActionTable : public SBstMap< int, GenAction*, CmpOrd > { void setAction( int ordering, GenAction *action ); void setActions( int *orderings, GenAction **actions, int nActs ); void setActions( const GenActionTable &other ); }; /* Compare of a whole action table element (key & value). */ struct CmpGenActionTableEl { static int compare( const GenActionTableEl &action1, const GenActionTableEl &action2 ) { if ( action1.key < action2.key ) return -1; else if ( action1.key > action2.key ) return 1; else if ( action1.value < action2.value ) return -1; else if ( action1.value > action2.value ) return 1; return 0; } }; /* Compare for GenActionTable. */ typedef CmpSTable< GenActionTableEl, CmpGenActionTableEl > CmpGenActionTable; /* Set of states. */ typedef BstSet RedStateSet; typedef BstSet IntSet; /* Reduced action. */ struct RedAction : public AvlTreeEl { RedAction( ) : key(), eofRefs(0), numTransRefs(0), numToStateRefs(0), numFromStateRefs(0), numEofRefs(0), bAnyNextStmt(false), bAnyCurStateRef(false), bAnyBreakStmt(false) { } const GenActionTable &getKey() { return key; } GenActionTable key; int actListId; int location; IntSet *eofRefs; /* Number of references in the final machine. */ int numRefs() { return numTransRefs + numToStateRefs + numFromStateRefs + numEofRefs; } int numTransRefs; int numToStateRefs; int numFromStateRefs; int numEofRefs; bool anyNextStmt() { return bAnyNextStmt; } bool anyCurStateRef() { return bAnyCurStateRef; } bool anyBreakStmt() { return bAnyBreakStmt; } bool bAnyNextStmt; bool bAnyCurStateRef; bool bAnyBreakStmt; }; typedef AvlTree GenActionTableMap; /* Reduced transition. */ struct RedTransAp : public AvlTreeEl { RedTransAp( RedStateAp *targ, RedAction *action, int id ) : targ(targ), action(action), id(id), pos(-1), labelNeeded(true) { } RedStateAp *targ; RedAction *action; int id; int pos; bool partitionBoundary; bool labelNeeded; }; /* Compare of transitions for the final reduction of transitions. Comparison * is on target and the pointer to the shared action table. It is assumed that * when this is used the action tables have been reduced. */ struct CmpRedTransAp { static int compare( const RedTransAp &t1, const RedTransAp &t2 ) { if ( t1.targ < t2.targ ) return -1; else if ( t1.targ > t2.targ ) return 1; else if ( t1.action < t2.action ) return -1; else if ( t1.action > t2.action ) return 1; else return 0; } }; typedef AvlBasic TransApSet; /* Element in out range. */ struct RedTransEl { /* Constructors. */ RedTransEl( Key lowKey, Key highKey, RedTransAp *value ) : lowKey(lowKey), highKey(highKey), value(value) { } Key lowKey, highKey; RedTransAp *value; }; typedef Vector RedTransList; typedef Vector RedStateVect; typedef BstMapEl RedSpanMapEl; typedef BstMap RedSpanMap; /* Compare used by span map sort. Reverse sorts by the span. */ struct CmpRedSpanMapEl { static int compare( const RedSpanMapEl &smel1, const RedSpanMapEl &smel2 ) { if ( smel1.value > smel2.value ) return -1; else if ( smel1.value < smel2.value ) return 1; else return 0; } }; /* Sorting state-span map entries by span. */ typedef MergeSort RedSpanMapSort; /* Set of entry ids that go into this state. */ typedef Vector EntryIdVect; typedef Vector EntryNameVect; typedef Vector< GenAction* > GenCondSet; struct Condition { Condition( ) : key(0), baseKey(0) {} Key key; Key baseKey; GenCondSet condSet; Condition *next, *prev; }; typedef DList ConditionList; struct GenCondSpace { Key baseKey; GenCondSet condSet; int condSpaceId; GenCondSpace *next, *prev; }; typedef DList CondSpaceList; struct GenStateCond { Key lowKey; Key highKey; GenCondSpace *condSpace; GenStateCond *prev, *next; }; typedef DList GenStateCondList; typedef Vector StateCondVect; /* Reduced state. */ struct RedStateAp { RedStateAp() : defTrans(0), condList(0), transList(0), isFinal(false), labelNeeded(false), outNeeded(false), onStateList(false), toStateAction(0), fromStateAction(0), eofAction(0), eofTrans(0), id(0), bAnyRegCurStateRef(false), partitionBoundary(false), inTrans(0), numInTrans(0) { } /* Transitions out. */ RedTransList outSingle; RedTransList outRange; RedTransAp *defTrans; /* For flat conditions. */ Key condLowKey, condHighKey; GenCondSpace **condList; /* For flat keys. */ Key lowKey, highKey; RedTransAp **transList; /* The list of states that transitions from this state go to. */ RedStateVect targStates; bool isFinal; bool labelNeeded; bool outNeeded; bool onStateList; RedAction *toStateAction; RedAction *fromStateAction; RedAction *eofAction; RedTransAp *eofTrans; int id; GenStateCondList stateCondList; StateCondVect stateCondVect; /* Pointers for the list of states. */ RedStateAp *prev, *next; bool anyRegCurStateRef() { return bAnyRegCurStateRef; } bool bAnyRegCurStateRef; int partition; bool partitionBoundary; RedTransAp **inTrans; int numInTrans; }; /* List of states. */ typedef DList RedStateList; /* Set of reduced transitons. Comparison is by pointer. */ typedef BstSet< RedTransAp*, CmpOrd > RedTransSet; /* Next version of the fsm machine. */ struct RedFsmAp { RedFsmAp(); bool forcedErrorState; int nextActionId; int nextTransId; /* Next State Id doubles as the total number of state ids. */ int nextStateId; TransApSet transSet; GenActionTableMap actionMap; RedStateList stateList; RedStateSet entryPoints; RedStateAp *startState; RedStateAp *errState; RedTransAp *errTrans; RedTransAp *errActionTrans; RedStateAp *firstFinState; int numFinStates; int nParts; bool bAnyToStateActions; bool bAnyFromStateActions; bool bAnyRegActions; bool bAnyEofActions; bool bAnyEofTrans; bool bAnyActionGotos; bool bAnyActionCalls; bool bAnyActionRets; bool bAnyRegActionRets; bool bAnyRegActionByValControl; bool bAnyRegNextStmt; bool bAnyRegCurStateRef; bool bAnyRegBreak; bool bAnyConditions; int maxState; int maxSingleLen; int maxRangeLen; int maxKeyOffset; int maxIndexOffset; int maxIndex; int maxActListId; int maxActionLoc; int maxActArrItem; unsigned long long maxSpan; unsigned long long maxCondSpan; int maxFlatIndexOffset; Key maxKey; int maxCondOffset; int maxCondLen; int maxCondSpaceId; int maxCondIndexOffset; int maxCond; bool anyActions(); bool anyToStateActions() { return bAnyToStateActions; } bool anyFromStateActions() { return bAnyFromStateActions; } bool anyRegActions() { return bAnyRegActions; } bool anyEofActions() { return bAnyEofActions; } bool anyEofTrans() { return bAnyEofTrans; } bool anyActionGotos() { return bAnyActionGotos; } bool anyActionCalls() { return bAnyActionCalls; } bool anyActionRets() { return bAnyActionRets; } bool anyRegActionRets() { return bAnyRegActionRets; } bool anyRegActionByValControl() { return bAnyRegActionByValControl; } bool anyRegNextStmt() { return bAnyRegNextStmt; } bool anyRegCurStateRef() { return bAnyRegCurStateRef; } bool anyRegBreak() { return bAnyRegBreak; } bool anyConditions() { return bAnyConditions; } /* Is is it possible to extend a range by bumping ranges that span only * one character to the singles array. */ bool canExtend( const RedTransList &list, int pos ); /* Pick single transitions from the ranges. */ void moveTransToSingle( RedStateAp *state ); void chooseSingle(); void makeFlat(); /* Move a selected transition from ranges to default. */ void moveToDefault( RedTransAp *defTrans, RedStateAp *state ); /* Pick a default transition by largest span. */ RedTransAp *chooseDefaultSpan( RedStateAp *state ); void chooseDefaultSpan(); /* Pick a default transition by most number of ranges. */ RedTransAp *chooseDefaultNumRanges( RedStateAp *state ); void chooseDefaultNumRanges(); /* Pick a default transition tailored towards goto driven machine. */ RedTransAp *chooseDefaultGoto( RedStateAp *state ); void chooseDefaultGoto(); /* Ordering states by transition connections. */ void optimizeStateOrdering( RedStateAp *state ); void optimizeStateOrdering(); /* Ordering states by transition connections. */ void depthFirstOrdering( RedStateAp *state ); void depthFirstOrdering(); /* Set state ids. */ void sequentialStateIds(); void sortStateIdsByFinal(); /* Arrange states in by final id. This is a stable sort. */ void sortStatesByFinal(); /* Sorting states by id. */ void sortByStateId(); /* Locating the first final state. This is the final state with the lowest * id. */ void findFirstFinState(); void assignActionLocs(); RedTransAp *getErrorTrans(); RedStateAp *getErrorState(); /* Is every char in the alphabet covered? */ bool alphabetCovered( RedTransList &outRange ); RedTransAp *allocateTrans( RedStateAp *targState, RedAction *actionTable ); void partitionFsm( int nParts ); void setInTrans(); }; #endif ragel-6.8/ragel/goipgoto.cpp0000664000175000017500000003123612106050031013022 00000000000000/* * Copyright 2001-2006 Adrian Thurston * 2004 Erich Ocean * 2005 Alan West */ /* This file is part of Ragel. * * Ragel is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Ragel is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Ragel; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "ragel.h" #include "goipgoto.h" #include "redfsm.h" #include "gendata.h" #include "bstmap.h" using std::endl; bool GoIpGotoCodeGen::useAgainLabel() { return redFsm->anyRegActionRets() || redFsm->anyRegActionByValControl() || redFsm->anyRegNextStmt(); } void GoIpGotoCodeGen::GOTO( ostream &ret, int gotoDest, bool inFinish ) { ret << "{" << "goto st" << gotoDest << " }"; } void GoIpGotoCodeGen::CALL( ostream &ret, int callDest, int targState, bool inFinish ) { if ( prePushExpr != 0 ) { ret << "{"; INLINE_LIST( ret, prePushExpr, 0, false, false ); } ret << "{" << STACK() << "[" << TOP() << "] = " << targState << "; " << TOP() << "++; " << "goto st" << callDest << " }"; if ( prePushExpr != 0 ) ret << "}"; } void GoIpGotoCodeGen::CALL_EXPR( ostream &ret, GenInlineItem *ilItem, int targState, bool inFinish ) { if ( prePushExpr != 0 ) { ret << "{"; INLINE_LIST( ret, prePushExpr, 0, false, false ); } ret << "{" << STACK() << "[" << TOP() << "] = " << targState << "; " << TOP() << "++; " << vCS() << " = ("; INLINE_LIST( ret, ilItem->children, 0, inFinish, false ); ret << "); " << "goto _again }"; if ( prePushExpr != 0 ) ret << "}"; } void GoIpGotoCodeGen::RET( ostream &ret, bool inFinish ) { ret << "{" << TOP() << "--; " << vCS() << " = " << STACK() << "[" << TOP() << "];"; if ( postPopExpr != 0 ) { ret << "{"; INLINE_LIST( ret, postPopExpr, 0, false, false ); ret << "}"; } ret << "goto _again }"; } void GoIpGotoCodeGen::GOTO_EXPR( ostream &ret, GenInlineItem *ilItem, bool inFinish ) { ret << "{" << vCS() << " = ("; INLINE_LIST( ret, ilItem->children, 0, inFinish, false ); ret << "); " << "goto _again }"; } void GoIpGotoCodeGen::NEXT( ostream &ret, int nextDest, bool inFinish ) { ret << vCS() << " = " << nextDest << ";"; } void GoIpGotoCodeGen::NEXT_EXPR( ostream &ret, GenInlineItem *ilItem, bool inFinish ) { ret << vCS() << " = ("; INLINE_LIST( ret, ilItem->children, 0, inFinish, false ); ret << ");"; } void GoIpGotoCodeGen::CURS( ostream &ret, bool inFinish ) { ret << "(_ps)"; } void GoIpGotoCodeGen::TARGS( ostream &ret, bool inFinish, int targState ) { ret << targState; } void GoIpGotoCodeGen::BREAK( ostream &ret, int targState, bool csForced ) { outLabelUsed = true; ret << "{" << P() << "++; "; if ( !csForced ) ret << vCS() << " = " << targState << "; "; ret << "goto _out }"; } bool GoIpGotoCodeGen::IN_TRANS_ACTIONS( RedStateAp *state ) { bool anyWritten = false; /* Emit any transitions that have actions and that go to this state. */ for ( int it = 0; it < state->numInTrans; it++ ) { RedTransAp *trans = state->inTrans[it]; if ( trans->action != 0 && trans->labelNeeded ) { /* Remember that we wrote an action so we know to write the * line directive for going back to the output. */ anyWritten = true; /* Write the label for the transition so it can be jumped to. */ out << "tr" << trans->id << ":" << endl; /* If the action contains a next, then we must preload the current * state since the action may or may not set it. */ if ( trans->action->anyNextStmt() ) out << " " << vCS() << " = " << trans->targ->id << endl; /* Write each action in the list. */ for ( GenActionTable::Iter item = trans->action->key; item.lte(); item++ ) { ACTION( out, item->value, trans->targ->id, false, trans->action->anyNextStmt() ); } /* If the action contains a next then we need to reload, otherwise * jump directly to the target state. */ if ( trans->action->anyNextStmt() ) out << " goto _again" << endl; else out << " goto st" << trans->targ->id << endl; } } return anyWritten; } std::ostream &GoIpGotoCodeGen::STATE_GOTOS_SWITCH( int level ) { for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { out << TABS(level) << "case " << st->id << ":" << endl; out << TABS(level + 1) << "goto st_case_" << st->id << endl; } return out; } /* Called from GotoCodeGen::STATE_GOTOS just before writing the gotos for each * state. */ void GoIpGotoCodeGen::GOTO_HEADER( RedStateAp *state, int level ) { bool anyWritten = IN_TRANS_ACTIONS( state ); if ( state->labelNeeded ) out << TABS(level) << "st" << state->id << ":" << endl; if ( state->toStateAction != 0 ) { /* Remember that we wrote an action. Write every action in the list. */ anyWritten = true; for ( GenActionTable::Iter item = state->toStateAction->key; item.lte(); item++ ) { ACTION( out, item->value, state->id, false, state->toStateAction->anyNextStmt() ); } } /* Advance and test buffer pos. */ if ( state->labelNeeded ) { if ( !noEnd ) { out << TABS(level + 1) << "if " << P() << "++; " << P() << " == " << PE() << " {" << endl << TABS(level + 2) << "goto _test_eof" << state->id << endl << TABS(level + 1) << "}" << endl; } else { out << TABS(level + 1) << P() << "++" << endl; } } /* Give the state a label. */ out << TABS(level) << "st_case_" << state->id << ":" << endl; if ( state->fromStateAction != 0 ) { /* Remember that we wrote an action. Write every action in the list. */ anyWritten = true; for ( GenActionTable::Iter item = state->fromStateAction->key; item.lte(); item++ ) { ACTION( out, item->value, state->id, false, state->fromStateAction->anyNextStmt() ); } } if ( anyWritten ) genLineDirective( out ); /* Record the prev state if necessary. */ if ( state->anyRegCurStateRef() ) out << TABS(level + 1) << "_ps = " << state->id << endl; } void GoIpGotoCodeGen::STATE_GOTO_ERROR( int level ) { /* In the error state we need to emit some stuff that usually goes into * the header. */ RedStateAp *state = redFsm->errState; bool anyWritten = IN_TRANS_ACTIONS( state ); /* No case label needed since we don't switch on the error state. */ if ( anyWritten ) genLineDirective( out ); out << "st_case_" << state->id << ":" << endl; if ( state->labelNeeded ) out << TABS(level) << "st" << state->id << ":" << endl; /* Break out here. */ outLabelUsed = true; out << TABS(level + 1) << vCS() << " = " << state->id << endl; out << TABS(level + 1) << "goto _out" << endl; } /* Emit the goto to take for a given transition. */ std::ostream &GoIpGotoCodeGen::TRANS_GOTO( RedTransAp *trans, int level ) { if ( trans->action != 0 ) { /* Go to the transition which will go to the state. */ out << TABS(level) << "goto tr" << trans->id; } else { /* Go directly to the target state. */ out << TABS(level) << "goto st" << trans->targ->id; } return out; } int GoIpGotoCodeGen::TRANS_NR( RedTransAp *trans ) { if ( trans->action != 0 ) { /* Go to the transition which will go to the state. */ return trans->id + redFsm->stateList.length(); } else { /* Go directly to the target state. */ return trans->targ->id; } } std::ostream &GoIpGotoCodeGen::EXIT_STATES() { for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { if ( st->outNeeded ) { testEofUsed = true; out << " _test_eof" << st->id << ": " << vCS() << " = " << st->id << "; goto _test_eof" << endl; } } return out; } std::ostream &GoIpGotoCodeGen::AGAIN_CASES( int level ) { for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { out << TABS(level) << "case " << st->id << ":" << endl << TABS(level + 1) << "goto st" << st->id << endl; } return out; } std::ostream &GoIpGotoCodeGen::FINISH_CASES( int level ) { bool anyWritten = false; for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { if ( st->eofAction != 0 ) { if ( st->eofAction->eofRefs == 0 ) st->eofAction->eofRefs = new IntSet; st->eofAction->eofRefs->insert( st->id ); } } for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { if ( st->eofTrans != 0 ) out << TABS(level) << "case " << st->id << ":" << endl << TABS(level + 1) << "goto tr" << st->eofTrans->id << endl; } for ( GenActionTableMap::Iter act = redFsm->actionMap; act.lte(); act++ ) { if ( act->eofRefs != 0 ) { out << TABS(level) << "case "; for ( IntSet::Iter pst = *act->eofRefs; pst.lte(); pst++ ) { out << *pst; if ( !pst.last() ) out << ", "; } out << ":" << endl; /* Remember that we wrote a trans so we know to write the * line directive for going back to the output. */ anyWritten = true; /* Write each action in the eof action list. */ for ( GenActionTable::Iter item = act->key; item.lte(); item++ ) ACTION( out, item->value, STATE_ERR_STATE, true, false ); } } if ( anyWritten ) genLineDirective( out ); return out; } void GoIpGotoCodeGen::setLabelsNeeded( GenInlineList *inlineList ) { for ( GenInlineList::Iter item = *inlineList; item.lte(); item++ ) { switch ( item->type ) { case GenInlineItem::Goto: case GenInlineItem::Call: { /* Mark the target as needing a label. */ item->targState->labelNeeded = true; break; } default: break; } if ( item->children != 0 ) setLabelsNeeded( item->children ); } } /* Set up labelNeeded flag for each state. */ void GoIpGotoCodeGen::setLabelsNeeded() { /* If we use the _again label, then we the _again switch, which uses all * labels. */ if ( useAgainLabel() ) { for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) st->labelNeeded = true; } else { /* Do not use all labels by default, init all labelNeeded vars to false. */ for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) st->labelNeeded = false; /* Walk all transitions and set only those that have targs. */ for ( TransApSet::Iter trans = redFsm->transSet; trans.lte(); trans++ ) { /* If there is no action with a next statement, then the label will be * needed. */ if ( trans->action == 0 || !trans->action->anyNextStmt() ) trans->targ->labelNeeded = true; /* Need labels for states that have goto or calls in action code * invoked on characters (ie, not from out action code). */ if ( trans->action != 0 ) { /* Loop the actions. */ for ( GenActionTable::Iter act = trans->action->key; act.lte(); act++ ) { /* Get the action and walk it's tree. */ setLabelsNeeded( act->value->inlineList ); } } } } if ( !noEnd ) { for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { if ( st != redFsm->errState ) st->outNeeded = st->labelNeeded; } } } void GoIpGotoCodeGen::writeData() { STATE_IDS(); } void GoIpGotoCodeGen::writeExec() { /* Must set labels immediately before writing because we may depend on the * noend write option. */ setLabelsNeeded(); testEofUsed = false; outLabelUsed = false; out << " {" << endl; if ( redFsm->anyRegCurStateRef() ) out << " var _ps " << INT() << " = 0" << endl; if ( redFsm->anyConditions() ) out << " var _widec " << WIDE_ALPH_TYPE() << endl; if ( !noEnd ) { testEofUsed = true; out << " if " << P() << " == " << PE() << " {" << endl << " goto _test_eof" << endl << " }" << endl; } if ( useAgainLabel() ) { out << " goto _resume" << endl << endl << "_again:" << endl << " switch " << vCS() << " {" << endl; AGAIN_CASES(1) << " }" << endl << endl; if ( !noEnd ) { testEofUsed = true; out << " if " << P() << "++; " << P() << " == " << PE() << " {" << endl << " goto _test_eof" << endl << " }" << endl; } else { out << " " << P() << "++" << endl; } out << "_resume:" << endl; } out << " switch " << vCS() << " {" << endl; STATE_GOTOS_SWITCH(1); out << " }" << endl; out << " goto st_out" << endl; STATE_GOTOS(1); out << " st_out:" << endl; EXIT_STATES() << endl; if ( testEofUsed ) out << " _test_eof: {}" << endl; if ( redFsm->anyEofTrans() || redFsm->anyEofActions() ) { out << " if " << P() << " == " << vEOF() << " {" << endl << " switch " << vCS() << " {" << endl; FINISH_CASES(2); out << " }" << endl << " }" << endl << endl; } if ( outLabelUsed ) out << " _out: {}" << endl; out << " }" << endl; } ragel-6.8/ragel/fsmgraph.cpp0000664000175000017500000013121412106050031012777 00000000000000/* * Copyright 2001, 2002, 2006 Adrian Thurston */ /* This file is part of Ragel. * * Ragel is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Ragel is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Ragel; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #include "fsmgraph.h" #include "mergesort.h" #include "parsedata.h" using std::cerr; using std::endl; /* Make a new state. The new state will be put on the graph's * list of state. The new state can be created final or non final. */ StateAp *FsmAp::addState() { /* Make the new state to return. */ StateAp *state = new StateAp(); if ( misfitAccounting ) { /* Create the new state on the misfit list. All states are created * with no foreign in transitions. */ misfitList.append( state ); } else { /* Create the new state. */ stateList.append( state ); } return state; } /* Construct an FSM that is the concatenation of an array of characters. A new * machine will be made that has len+1 states with one transition between each * state for each integer in str. IsSigned determines if the integers are to * be considered as signed or unsigned ints. */ void FsmAp::concatFsm( Key *str, int len ) { /* Make the first state and set it as the start state. */ StateAp *last = addState(); setStartState( last ); /* Attach subsequent states. */ for ( int i = 0; i < len; i++ ) { StateAp *newState = addState(); attachNewTrans( last, newState, str[i], str[i] ); last = newState; } /* Make the last state the final state. */ setFinState( last ); } /* Case insensitive version of concatFsm. */ void FsmAp::concatFsmCI( Key *str, int len ) { /* Make the first state and set it as the start state. */ StateAp *last = addState(); setStartState( last ); /* Attach subsequent states. */ for ( int i = 0; i < len; i++ ) { StateAp *newState = addState(); KeySet keySet; if ( str[i].isLower() ) keySet.insert( str[i].toUpper() ); if ( str[i].isUpper() ) keySet.insert( str[i].toLower() ); keySet.insert( str[i] ); for ( int i = 0; i < keySet.length(); i++ ) attachNewTrans( last, newState, keySet[i], keySet[i] ); last = newState; } /* Make the last state the final state. */ setFinState( last ); } /* Construct a machine that matches one character. A new machine will be made * that has two states with a single transition between the states. IsSigned * determines if the integers are to be considered as signed or unsigned ints. */ void FsmAp::concatFsm( Key chr ) { /* Two states first start, second final. */ setStartState( addState() ); StateAp *end = addState(); setFinState( end ); /* Attach on the character. */ attachNewTrans( startState, end, chr, chr ); } /* Construct a machine that matches any character in set. A new machine will * be made that has two states and len transitions between the them. The set * should be ordered correctly accroding to KeyOps and should not contain * any duplicates. */ void FsmAp::orFsm( Key *set, int len ) { /* Two states first start, second final. */ setStartState( addState() ); StateAp *end = addState(); setFinState( end ); for ( int i = 1; i < len; i++ ) assert( set[i-1] < set[i] ); /* Attach on all the integers in the given string of ints. */ for ( int i = 0; i < len; i++ ) attachNewTrans( startState, end, set[i], set[i] ); } /* Construct a machine that matches a range of characters. A new machine will * be made with two states and a range transition between them. The range will * match any characters from low to high inclusive. Low should be less than or * equal to high otherwise undefined behaviour results. IsSigned determines * if the integers are to be considered as signed or unsigned ints. */ void FsmAp::rangeFsm( Key low, Key high ) { /* Two states first start, second final. */ setStartState( addState() ); StateAp *end = addState(); setFinState( end ); /* Attach using the range of characters. */ attachNewTrans( startState, end, low, high ); } /* Construct a machine that a repeated range of characters. */ void FsmAp::rangeStarFsm( Key low, Key high) { /* One state which is final and is the start state. */ setStartState( addState() ); setFinState( startState ); /* Attach start to start using range of characters. */ attachNewTrans( startState, startState, low, high ); } /* Construct a machine that matches the empty string. A new machine will be * made with only one state. The new state will be both a start and final * state. IsSigned determines if the machine has a signed or unsigned * alphabet. Fsm operations must be done on machines with the same alphabet * signedness. */ void FsmAp::lambdaFsm( ) { /* Give it one state with no transitions making it * the start state and final state. */ setStartState( addState() ); setFinState( startState ); } /* Construct a machine that matches nothing at all. A new machine will be * made with only one state. It will not be final. */ void FsmAp::emptyFsm( ) { /* Give it one state with no transitions making it * the start state and final state. */ setStartState( addState() ); } void FsmAp::transferOutData( StateAp *destState, StateAp *srcState ) { for ( TransList::Iter trans = destState->outList; trans.lte(); trans++ ) { if ( trans->toState != 0 ) { /* Get the actions data from the outActionTable. */ trans->actionTable.setActions( srcState->outActionTable ); /* Get the priorities from the outPriorTable. */ trans->priorTable.setPriors( srcState->outPriorTable ); } } } /* Kleene star operator. Makes this machine the kleene star of itself. Any * transitions made going out of the machine and back into itself will be * notified that they are leaving transitions by having the leavingFromState * callback invoked. */ void FsmAp::starOp( ) { /* For the merging process. */ MergeData md; /* Turn on misfit accounting to possibly catch the old start state. */ setMisfitAccounting( true ); /* Create the new new start state. It will be set final after the merging * of the final states with the start state is complete. */ StateAp *prevStartState = startState; unsetStartState(); setStartState( addState() ); /* Merge the new start state with the old one to isolate it. */ mergeStates( md, startState, prevStartState ); /* Merge the start state into all final states. Except the start state on * the first pass. If the start state is set final we will be doubling up * its transitions, which will get transfered to any final states that * follow it in the final state set. This will be determined by the order * of items in the final state set. To prevent this we just merge with the * start on a second pass. */ for ( StateSet::Iter st = finStateSet; st.lte(); st++ ) { if ( *st != startState ) mergeStatesLeaving( md, *st, startState ); } /* Now it is safe to merge the start state with itself (provided it * is set final). */ if ( startState->isFinState() ) mergeStatesLeaving( md, startState, startState ); /* Now ensure the new start state is a final state. */ setFinState( startState ); /* Fill in any states that were newed up as combinations of others. */ fillInStates( md ); /* Remove the misfits and turn off misfit accounting. */ removeMisfits(); setMisfitAccounting( false ); } void FsmAp::repeatOp( int times ) { /* Must be 1 and up. 0 produces null machine and requires deleting this. */ assert( times > 0 ); /* A repeat of one does absolutely nothing. */ if ( times == 1 ) return; /* Make a machine to make copies from. */ FsmAp *copyFrom = new FsmAp( *this ); /* Concatentate duplicates onto the end up until before the last. */ for ( int i = 1; i < times-1; i++ ) { FsmAp *dup = new FsmAp( *copyFrom ); doConcat( dup, 0, false ); } /* Now use the copyFrom on the end. */ doConcat( copyFrom, 0, false ); } void FsmAp::optionalRepeatOp( int times ) { /* Must be 1 and up. 0 produces null machine and requires deleting this. */ assert( times > 0 ); /* A repeat of one optional merely allows zero string. */ if ( times == 1 ) { setFinState( startState ); return; } /* Make a machine to make copies from. */ FsmAp *copyFrom = new FsmAp( *this ); /* The state set used in the from end of the concatentation. Starts with * the initial final state set, then after each concatenation, gets set to * the the final states that come from the the duplicate. */ StateSet lastFinSet( finStateSet ); /* Set the initial state to zero to allow zero copies. */ setFinState( startState ); /* Concatentate duplicates onto the end up until before the last. */ for ( int i = 1; i < times-1; i++ ) { /* Make a duplicate for concating and set the fin bits to graph 2 so we * can pick out it's final states after the optional style concat. */ FsmAp *dup = new FsmAp( *copyFrom ); dup->setFinBits( STB_GRAPH2 ); doConcat( dup, &lastFinSet, true ); /* Clear the last final state set and make the new one by taking only * the final states that come from graph 2.*/ lastFinSet.empty(); for ( int i = 0; i < finStateSet.length(); i++ ) { /* If the state came from graph 2, add it to the last set and clear * the bits. */ StateAp *fs = finStateSet[i]; if ( fs->stateBits & STB_GRAPH2 ) { lastFinSet.insert( fs ); fs->stateBits &= ~STB_GRAPH2; } } } /* Now use the copyFrom on the end, no bits set, no bits to clear. */ doConcat( copyFrom, &lastFinSet, true ); } /* Fsm concatentation worker. Supports treating the concatentation as optional, * which essentially leaves the final states of machine one as final. */ void FsmAp::doConcat( FsmAp *other, StateSet *fromStates, bool optional ) { /* For the merging process. */ StateSet finStateSetCopy, startStateSet; MergeData md; /* Turn on misfit accounting for both graphs. */ setMisfitAccounting( true ); other->setMisfitAccounting( true ); /* Get the other's start state. */ StateAp *otherStartState = other->startState; /* Unset other's start state before bringing in the entry points. */ other->unsetStartState(); /* Bring in the rest of other's entry points. */ copyInEntryPoints( other ); other->entryPoints.empty(); /* Bring in other's states into our state lists. */ stateList.append( other->stateList ); misfitList.append( other->misfitList ); /* If from states is not set, then get a copy of our final state set before * we clobber it and use it instead. */ if ( fromStates == 0 ) { finStateSetCopy = finStateSet; fromStates = &finStateSetCopy; } /* Unset all of our final states and get the final states from other. */ if ( !optional ) unsetAllFinStates(); finStateSet.insert( other->finStateSet ); /* Since other's lists are empty, we can delete the fsm without * affecting any states. */ delete other; /* Merge our former final states with the start state of other. */ for ( int i = 0; i < fromStates->length(); i++ ) { StateAp *state = fromStates->data[i]; /* Merge the former final state with other's start state. */ mergeStatesLeaving( md, state, otherStartState ); /* If the former final state was not reset final then we must clear * the state's out trans data. If it got reset final then it gets to * keep its out trans data. This must be done before fillInStates gets * called to prevent the data from being sourced. */ if ( ! state->isFinState() ) clearOutData( state ); } /* Fill in any new states made from merging. */ fillInStates( md ); /* Remove the misfits and turn off misfit accounting. */ removeMisfits(); setMisfitAccounting( false ); } /* Concatenates other to the end of this machine. Other is deleted. Any * transitions made leaving this machine and entering into other are notified * that they are leaving transitions by having the leavingFromState callback * invoked. */ void FsmAp::concatOp( FsmAp *other ) { /* Assert same signedness and return graph concatenation op. */ doConcat( other, 0, false ); } void FsmAp::doOr( FsmAp *other ) { /* For the merging process. */ MergeData md; /* Build a state set consisting of both start states */ StateSet startStateSet; startStateSet.insert( startState ); startStateSet.insert( other->startState ); /* Both of the original start states loose their start state status. */ unsetStartState(); other->unsetStartState(); /* Bring in the rest of other's entry points. */ copyInEntryPoints( other ); other->entryPoints.empty(); /* Merge the lists. This will move all the states from other * into this. No states will be deleted. */ stateList.append( other->stateList ); misfitList.append( other->misfitList ); /* Move the final set data from other into this. */ finStateSet.insert(other->finStateSet); other->finStateSet.empty(); /* Since other's list is empty, we can delete the fsm without * affecting any states. */ delete other; /* Create a new start state. */ setStartState( addState() ); /* Merge the start states. */ mergeStates( md, startState, startStateSet.data, startStateSet.length() ); /* Fill in any new states made from merging. */ fillInStates( md ); } /* Unions other with this machine. Other is deleted. */ void FsmAp::unionOp( FsmAp *other ) { /* Turn on misfit accounting for both graphs. */ setMisfitAccounting( true ); other->setMisfitAccounting( true ); /* Call Worker routine. */ doOr( other ); /* Remove the misfits and turn off misfit accounting. */ removeMisfits(); setMisfitAccounting( false ); } /* Intersects other with this machine. Other is deleted. */ void FsmAp::intersectOp( FsmAp *other ) { /* Turn on misfit accounting for both graphs. */ setMisfitAccounting( true ); other->setMisfitAccounting( true ); /* Set the fin bits on this and other to want each other. */ setFinBits( STB_GRAPH1 ); other->setFinBits( STB_GRAPH2 ); /* Call worker Or routine. */ doOr( other ); /* Unset any final states that are no longer to * be final due to final bits. */ unsetIncompleteFinals(); /* Remove the misfits and turn off misfit accounting. */ removeMisfits(); setMisfitAccounting( false ); /* Remove states that have no path to a final state. */ removeDeadEndStates(); } /* Set subtracts other machine from this machine. Other is deleted. */ void FsmAp::subtractOp( FsmAp *other ) { /* Turn on misfit accounting for both graphs. */ setMisfitAccounting( true ); other->setMisfitAccounting( true ); /* Set the fin bits of other to be killers. */ other->setFinBits( STB_GRAPH1 ); /* Call worker Or routine. */ doOr( other ); /* Unset any final states that are no longer to * be final due to final bits. */ unsetKilledFinals(); /* Remove the misfits and turn off misfit accounting. */ removeMisfits(); setMisfitAccounting( false ); /* Remove states that have no path to a final state. */ removeDeadEndStates(); } bool FsmAp::inEptVect( EptVect *eptVect, StateAp *state ) { if ( eptVect != 0 ) { /* Vect is there, walk it looking for state. */ for ( int i = 0; i < eptVect->length(); i++ ) { if ( eptVect->data[i].targ == state ) return true; } } return false; } /* Fill epsilon vectors in a root state from a given starting point. Epmploys * a depth first search through the graph of epsilon transitions. */ void FsmAp::epsilonFillEptVectFrom( StateAp *root, StateAp *from, bool parentLeaving ) { /* Walk the epsilon transitions out of the state. */ for ( EpsilonTrans::Iter ep = from->epsilonTrans; ep.lte(); ep++ ) { /* Find the entry point, if the it does not resove, ignore it. */ EntryMapEl *enLow, *enHigh; if ( entryPoints.findMulti( *ep, enLow, enHigh ) ) { /* Loop the targets. */ for ( EntryMapEl *en = enLow; en <= enHigh; en++ ) { /* Do not add the root or states already in eptVect. */ StateAp *targ = en->value; if ( targ != from && !inEptVect(root->eptVect, targ) ) { /* Maybe need to create the eptVect. */ if ( root->eptVect == 0 ) root->eptVect = new EptVect(); /* If moving to a different graph or if any parent is * leaving then we are leaving. */ bool leaving = parentLeaving || root->owningGraph != targ->owningGraph; /* All ok, add the target epsilon and recurse. */ root->eptVect->append( EptVectEl(targ, leaving) ); epsilonFillEptVectFrom( root, targ, leaving ); } } } } } void FsmAp::shadowReadWriteStates( MergeData &md ) { /* Init isolatedShadow algorithm data. */ for ( StateList::Iter st = stateList; st.lte(); st++ ) st->isolatedShadow = 0; /* Any states that may be both read from and written to must * be shadowed. */ for ( StateList::Iter st = stateList; st.lte(); st++ ) { /* Find such states by looping through stateVect lists, which give us * the states that will be read from. May cause us to visit the states * that we are interested in more than once. */ if ( st->eptVect != 0 ) { /* For all states that will be read from. */ for ( EptVect::Iter ept = *st->eptVect; ept.lte(); ept++ ) { /* Check for read and write to the same state. */ StateAp *targ = ept->targ; if ( targ->eptVect != 0 ) { /* State is to be written to, if the shadow is not already * there, create it. */ if ( targ->isolatedShadow == 0 ) { StateAp *shadow = addState(); mergeStates( md, shadow, targ ); targ->isolatedShadow = shadow; } /* Write shadow into the state vector so that it is the * state that the epsilon transition will read from. */ ept->targ = targ->isolatedShadow; } } } } } void FsmAp::resolveEpsilonTrans( MergeData &md ) { /* Walk the state list and invoke recursive worker on each state. */ for ( StateList::Iter st = stateList; st.lte(); st++ ) epsilonFillEptVectFrom( st, st, false ); /* Prevent reading from and writing to of the same state. */ shadowReadWriteStates( md ); /* For all states that have epsilon transitions out, draw the transitions, * clear the epsilon transitions. */ for ( StateList::Iter st = stateList; st.lte(); st++ ) { /* If there is a state vector, then create the pre-merge state. */ if ( st->eptVect != 0 ) { /* Merge all the epsilon targets into the state. */ for ( EptVect::Iter ept = *st->eptVect; ept.lte(); ept++ ) { if ( ept->leaving ) mergeStatesLeaving( md, st, ept->targ ); else mergeStates( md, st, ept->targ ); } /* Clean up the target list. */ delete st->eptVect; st->eptVect = 0; } /* Clear the epsilon transitions vector. */ st->epsilonTrans.empty(); } } void FsmAp::epsilonOp() { /* For merging process. */ MergeData md; setMisfitAccounting( true ); for ( StateList::Iter st = stateList; st.lte(); st++ ) st->owningGraph = 0; /* Perform merges. */ resolveEpsilonTrans( md ); /* Epsilons can caused merges which leave behind unreachable states. */ fillInStates( md ); /* Remove the misfits and turn off misfit accounting. */ removeMisfits(); setMisfitAccounting( false ); } /* Make a new maching by joining together a bunch of machines without making * any transitions between them. A negative finalId results in there being no * final id. */ void FsmAp::joinOp( int startId, int finalId, FsmAp **others, int numOthers ) { /* For the merging process. */ MergeData md; /* Set the owning machines. Start at one. Zero is reserved for the start * and final states. */ for ( StateList::Iter st = stateList; st.lte(); st++ ) st->owningGraph = 1; for ( int m = 0; m < numOthers; m++ ) { for ( StateList::Iter st = others[m]->stateList; st.lte(); st++ ) st->owningGraph = 2+m; } /* All machines loose start state status. */ unsetStartState(); for ( int m = 0; m < numOthers; m++ ) others[m]->unsetStartState(); /* Bring the other machines into this. */ for ( int m = 0; m < numOthers; m++ ) { /* Bring in the rest of other's entry points. */ copyInEntryPoints( others[m] ); others[m]->entryPoints.empty(); /* Merge the lists. This will move all the states from other into * this. No states will be deleted. */ stateList.append( others[m]->stateList ); assert( others[m]->misfitList.length() == 0 ); /* Move the final set data from other into this. */ finStateSet.insert( others[m]->finStateSet ); others[m]->finStateSet.empty(); /* Since other's list is empty, we can delete the fsm without * affecting any states. */ delete others[m]; } /* Look up the start entry point. */ EntryMapEl *enLow = 0, *enHigh = 0; bool findRes = entryPoints.findMulti( startId, enLow, enHigh ); if ( ! findRes ) { /* No start state. Set a default one and proceed with the join. Note * that the result of the join will be a very uninteresting machine. */ setStartState( addState() ); } else { /* There is at least one start state, create a state that will become * the new start state. */ StateAp *newStart = addState(); setStartState( newStart ); /* The start state is in an owning machine class all it's own. */ newStart->owningGraph = 0; /* Create the set of states to merge from. */ StateSet stateSet; for ( EntryMapEl *en = enLow; en <= enHigh; en++ ) stateSet.insert( en->value ); /* Merge in the set of start states into the new start state. */ mergeStates( md, newStart, stateSet.data, stateSet.length() ); } /* Take a copy of the final state set, before unsetting them all. This * will allow us to call clearOutData on the states that don't get * final state status back back. */ StateSet finStateSetCopy = finStateSet; /* Now all final states are unset. */ unsetAllFinStates(); if ( finalId >= 0 ) { /* Create the implicit final state. */ StateAp *finState = addState(); setFinState( finState ); /* Assign an entry into the final state on the final state entry id. Note * that there may already be an entry on this id. That's ok. Also set the * final state owning machine id. It's in a class all it's own. */ setEntry( finalId, finState ); finState->owningGraph = 0; } /* Hand over to workers for resolving epsilon trans. This will merge states * with the targets of their epsilon transitions. */ resolveEpsilonTrans( md ); /* Invoke the relinquish final callback on any states that did not get * final state status back. */ for ( StateSet::Iter st = finStateSetCopy; st.lte(); st++ ) { if ( !((*st)->stateBits & STB_ISFINAL) ) clearOutData( *st ); } /* Fill in any new states made from merging. */ fillInStates( md ); /* Joining can be messy. Instead of having misfit accounting on (which is * tricky here) do a full cleaning. */ removeUnreachableStates(); } void FsmAp::globOp( FsmAp **others, int numOthers ) { /* All other machines loose start states status. */ for ( int m = 0; m < numOthers; m++ ) others[m]->unsetStartState(); /* Bring the other machines into this. */ for ( int m = 0; m < numOthers; m++ ) { /* Bring in the rest of other's entry points. */ copyInEntryPoints( others[m] ); others[m]->entryPoints.empty(); /* Merge the lists. This will move all the states from other into * this. No states will be deleted. */ stateList.append( others[m]->stateList ); assert( others[m]->misfitList.length() == 0 ); /* Move the final set data from other into this. */ finStateSet.insert( others[m]->finStateSet ); others[m]->finStateSet.empty(); /* Since other's list is empty, we can delete the fsm without * affecting any states. */ delete others[m]; } } void FsmAp::deterministicEntry() { /* For the merging process. */ MergeData md; /* States may loose their entry points, turn on misfit accounting. */ setMisfitAccounting( true ); /* Get a copy of the entry map then clear all the entry points. As we * iterate the old entry map finding duplicates we will add the entry * points for the new states that we create. */ EntryMap prevEntry = entryPoints; unsetAllEntryPoints(); for ( int enId = 0; enId < prevEntry.length(); ) { /* Count the number of states on this entry key. */ int highId = enId; while ( highId < prevEntry.length() && prevEntry[enId].key == prevEntry[highId].key ) highId += 1; int numIds = highId - enId; if ( numIds == 1 ) { /* Only a single entry point, just set the entry. */ setEntry( prevEntry[enId].key, prevEntry[enId].value ); } else { /* Multiple entry points, need to create a new state and merge in * all the targets of entry points. */ StateAp *newEntry = addState(); for ( int en = enId; en < highId; en++ ) mergeStates( md, newEntry, prevEntry[en].value ); /* Add the new state as the single entry point. */ setEntry( prevEntry[enId].key, newEntry ); } enId += numIds; } /* The old start state may be unreachable. Remove the misfits and turn off * misfit accounting. */ removeMisfits(); setMisfitAccounting( false ); } /* Unset any final states that are no longer to be final due to final bits. */ void FsmAp::unsetKilledFinals() { /* Duplicate the final state set before we begin modifying it. */ StateSet fin( finStateSet ); for ( int s = 0; s < fin.length(); s++ ) { /* Check for killing bit. */ StateAp *state = fin.data[s]; if ( state->stateBits & STB_GRAPH1 ) { /* One final state is a killer, set to non-final. */ unsetFinState( state ); } /* Clear all killing bits. Non final states should never have had those * state bits set in the first place. */ state->stateBits &= ~STB_GRAPH1; } } /* Unset any final states that are no longer to be final due to final bits. */ void FsmAp::unsetIncompleteFinals() { /* Duplicate the final state set before we begin modifying it. */ StateSet fin( finStateSet ); for ( int s = 0; s < fin.length(); s++ ) { /* Check for one set but not the other. */ StateAp *state = fin.data[s]; if ( state->stateBits & STB_BOTH && (state->stateBits & STB_BOTH) != STB_BOTH ) { /* One state wants the other but it is not there. */ unsetFinState( state ); } /* Clear wanting bits. Non final states should never have had those * state bits set in the first place. */ state->stateBits &= ~STB_BOTH; } } /* Ensure that the start state is free of entry points (aside from the fact * that it is the start state). If the start state has entry points then Make a * new start state by merging with the old one. Useful before modifying start * transitions. If the existing start state has any entry points other than the * start state entry then modifying its transitions changes more than the start * transitions. So isolate the start state by separating it out such that it * only has start stateness as it's entry point. */ void FsmAp::isolateStartState( ) { /* For the merging process. */ MergeData md; /* Bail out if the start state is already isolated. */ if ( isStartStateIsolated() ) return; /* Turn on misfit accounting to possibly catch the old start state. */ setMisfitAccounting( true ); /* This will be the new start state. The existing start * state is merged with it. */ StateAp *prevStartState = startState; unsetStartState(); setStartState( addState() ); /* Merge the new start state with the old one to isolate it. */ mergeStates( md, startState, prevStartState ); /* Stfil and stateDict will be empty because the merging of the old start * state into the new one will not have any conflicting transitions. */ assert( md.stateDict.treeSize == 0 ); assert( md.stfillHead == 0 ); /* The old start state may be unreachable. Remove the misfits and turn off * misfit accounting. */ removeMisfits(); setMisfitAccounting( false ); } #ifdef LOG_CONDS void logCondSpace( CondSpace *condSpace ) { if ( condSpace == 0 ) cerr << ""; else { for ( CondSet::Iter csi = condSpace->condSet.last(); csi.gtb(); csi-- ) { if ( ! csi.last() ) cerr << ','; (*csi)->actionName( cerr ); } } } void logNewExpansion( Expansion *exp ) { cerr << "created expansion:" << endl; cerr << " range: " << exp->lowKey.getVal() << " .. " << exp->highKey.getVal() << endl; cerr << " fromCondSpace: "; logCondSpace( exp->fromCondSpace ); cerr << endl; cerr << " fromVals: " << exp->fromVals << endl; cerr << " toCondSpace: "; logCondSpace( exp->toCondSpace ); cerr << endl; cerr << " toValsList: "; for ( LongVect::Iter to = exp->toValsList; to.lte(); to++ ) cerr << " " << *to; cerr << endl; } #endif void FsmAp::findTransExpansions( ExpansionList &expansionList, StateAp *destState, StateAp *srcState ) { PairIter transCond( destState->outList.head, srcState->stateCondList.head ); for ( ; !transCond.end(); transCond++ ) { if ( transCond.userState == RangeOverlap ) { Expansion *expansion = new Expansion( transCond.s1Tel.lowKey, transCond.s1Tel.highKey ); expansion->fromTrans = new TransAp(*transCond.s1Tel.trans); expansion->fromTrans->fromState = 0; expansion->fromTrans->toState = transCond.s1Tel.trans->toState; expansion->fromCondSpace = 0; expansion->fromVals = 0; CondSpace *srcCS = transCond.s2Tel.trans->condSpace; expansion->toCondSpace = srcCS; long numTargVals = (1 << srcCS->condSet.length()); for ( long targVals = 0; targVals < numTargVals; targVals++ ) expansion->toValsList.append( targVals ); #ifdef LOG_CONDS logNewExpansion( expansion ); #endif expansionList.append( expansion ); } } } void FsmAp::findCondExpInTrans( ExpansionList &expansionList, StateAp *state, Key lowKey, Key highKey, CondSpace *fromCondSpace, CondSpace *toCondSpace, long fromVals, LongVect &toValsList ) { /* Make condition-space low and high keys for searching. */ TransAp searchTrans; searchTrans.lowKey = fromCondSpace->baseKey + fromVals * keyOps->alphSize() + (lowKey - keyOps->minKey); searchTrans.highKey = fromCondSpace->baseKey + fromVals * keyOps->alphSize() + (highKey - keyOps->minKey); searchTrans.prev = searchTrans.next = 0; PairIter pairIter( state->outList.head, &searchTrans ); for ( ; !pairIter.end(); pairIter++ ) { if ( pairIter.userState == RangeOverlap ) { /* Need to make character-space low and high keys from the range * overlap for the expansion object. */ Key expLowKey = pairIter.s1Tel.lowKey - fromCondSpace->baseKey - fromVals * keyOps->alphSize() + keyOps->minKey; Key expHighKey = pairIter.s1Tel.highKey - fromCondSpace->baseKey - fromVals * keyOps->alphSize() + keyOps->minKey; Expansion *expansion = new Expansion( expLowKey, expHighKey ); expansion->fromTrans = new TransAp(*pairIter.s1Tel.trans); expansion->fromTrans->fromState = 0; expansion->fromTrans->toState = pairIter.s1Tel.trans->toState; expansion->fromCondSpace = fromCondSpace; expansion->fromVals = fromVals; expansion->toCondSpace = toCondSpace; expansion->toValsList = toValsList; expansionList.append( expansion ); #ifdef LOG_CONDS logNewExpansion( expansion ); #endif } } } void FsmAp::findCondExpansions( ExpansionList &expansionList, StateAp *destState, StateAp *srcState ) { PairIter condCond( destState->stateCondList.head, srcState->stateCondList.head ); for ( ; !condCond.end(); condCond++ ) { if ( condCond.userState == RangeOverlap ) { /* Loop over all existing condVals . */ CondSet &destCS = condCond.s1Tel.trans->condSpace->condSet; long destLen = destCS.length(); /* Find the items in src cond set that are not in dest * cond set. These are the items that we must expand. */ CondSet srcOnlyCS = condCond.s2Tel.trans->condSpace->condSet; for ( CondSet::Iter dcsi = destCS; dcsi.lte(); dcsi++ ) srcOnlyCS.remove( *dcsi ); long srcOnlyLen = srcOnlyCS.length(); if ( srcOnlyCS.length() > 0 ) { #ifdef LOG_CONDS cerr << "there are " << srcOnlyCS.length() << " item(s) that are " "only in the srcCS" << endl; #endif CondSet mergedCS = destCS; mergedCS.insert( condCond.s2Tel.trans->condSpace->condSet ); CondSpace *fromCondSpace = addCondSpace( destCS ); CondSpace *toCondSpace = addCondSpace( mergedCS ); /* Loop all values in the dest space. */ for ( long destVals = 0; destVals < (1 << destLen); destVals++ ) { long basicVals = 0; for ( CondSet::Iter csi = destCS; csi.lte(); csi++ ) { if ( destVals & (1 << csi.pos()) ) { Action **cim = mergedCS.find( *csi ); long bitPos = (cim - mergedCS.data); basicVals |= 1 << bitPos; } } /* Loop all new values. */ LongVect expandToVals; for ( long soVals = 0; soVals < (1 << srcOnlyLen); soVals++ ) { long targVals = basicVals; for ( CondSet::Iter csi = srcOnlyCS; csi.lte(); csi++ ) { if ( soVals & (1 << csi.pos()) ) { Action **cim = mergedCS.find( *csi ); long bitPos = (cim - mergedCS.data); targVals |= 1 << bitPos; } } expandToVals.append( targVals ); } findCondExpInTrans( expansionList, destState, condCond.s1Tel.lowKey, condCond.s1Tel.highKey, fromCondSpace, toCondSpace, destVals, expandToVals ); } } } } } void FsmAp::doExpand( MergeData &md, StateAp *destState, ExpansionList &expList1 ) { for ( ExpansionList::Iter exp = expList1; exp.lte(); exp++ ) { for ( LongVect::Iter to = exp->toValsList; to.lte(); to++ ) { long targVals = *to; /* We will use the copy of the transition that was made when the * expansion was created. It will get used multiple times. Each * time we must set up the keys, everything else is constant and * and already prepared. */ TransAp *srcTrans = exp->fromTrans; srcTrans->lowKey = exp->toCondSpace->baseKey + targVals * keyOps->alphSize() + (exp->lowKey - keyOps->minKey); srcTrans->highKey = exp->toCondSpace->baseKey + targVals * keyOps->alphSize() + (exp->highKey - keyOps->minKey); TransList srcList; srcList.append( srcTrans ); outTransCopy( md, destState, srcList.head ); srcList.abandon(); } } } void FsmAp::doRemove( MergeData &md, StateAp *destState, ExpansionList &expList1 ) { for ( ExpansionList::Iter exp = expList1; exp.lte(); exp++ ) { Removal removal; if ( exp->fromCondSpace == 0 ) { removal.lowKey = exp->lowKey; removal.highKey = exp->highKey; } else { removal.lowKey = exp->fromCondSpace->baseKey + exp->fromVals * keyOps->alphSize() + (exp->lowKey - keyOps->minKey); removal.highKey = exp->fromCondSpace->baseKey + exp->fromVals * keyOps->alphSize() + (exp->highKey - keyOps->minKey); } removal.next = 0; TransList destList; PairIter pairIter( destState->outList.head, &removal ); for ( ; !pairIter.end(); pairIter++ ) { switch ( pairIter.userState ) { case RangeInS1: { TransAp *destTrans = pairIter.s1Tel.trans; destTrans->lowKey = pairIter.s1Tel.lowKey; destTrans->highKey = pairIter.s1Tel.highKey; destList.append( destTrans ); break; } case RangeInS2: break; case RangeOverlap: { TransAp *trans = pairIter.s1Tel.trans; detachTrans( trans->fromState, trans->toState, trans ); delete trans; break; } case BreakS1: { pairIter.s1Tel.trans = dupTrans( destState, pairIter.s1Tel.trans ); break; } case BreakS2: break; } } destState->outList.transfer( destList ); } } void FsmAp::mergeStateConds( StateAp *destState, StateAp *srcState ) { StateCondList destList; PairIter pairIter( destState->stateCondList.head, srcState->stateCondList.head ); for ( ; !pairIter.end(); pairIter++ ) { switch ( pairIter.userState ) { case RangeInS1: { StateCond *destCond = pairIter.s1Tel.trans; destCond->lowKey = pairIter.s1Tel.lowKey; destCond->highKey = pairIter.s1Tel.highKey; destList.append( destCond ); break; } case RangeInS2: { StateCond *newCond = new StateCond( *pairIter.s2Tel.trans ); newCond->lowKey = pairIter.s2Tel.lowKey; newCond->highKey = pairIter.s2Tel.highKey; destList.append( newCond ); break; } case RangeOverlap: { StateCond *destCond = pairIter.s1Tel.trans; StateCond *srcCond = pairIter.s2Tel.trans; CondSet mergedCondSet; mergedCondSet.insert( destCond->condSpace->condSet ); mergedCondSet.insert( srcCond->condSpace->condSet ); destCond->condSpace = addCondSpace( mergedCondSet ); destCond->lowKey = pairIter.s1Tel.lowKey; destCond->highKey = pairIter.s1Tel.highKey; destList.append( destCond ); break; } case BreakS1: pairIter.s1Tel.trans = new StateCond( *pairIter.s1Tel.trans ); break; case BreakS2: break; } } destState->stateCondList.transfer( destList ); } /* A state merge which represents the drawing in of leaving transitions. If * there is any out data then we duplicate the source state, transfer the out * data, then merge in the state. The new state will be reaped because it will * not be given any in transitions. */ void FsmAp::mergeStatesLeaving( MergeData &md, StateAp *destState, StateAp *srcState ) { if ( !hasOutData( destState ) ) mergeStates( md, destState, srcState ); else { StateAp *ssMutable = addState(); mergeStates( md, ssMutable, srcState ); transferOutData( ssMutable, destState ); for ( OutCondSet::Iter cond = destState->outCondSet; cond.lte(); cond++ ) embedCondition( md, ssMutable, cond->action, cond->sense ); mergeStates( md, destState, ssMutable ); } } void FsmAp::mergeStates( MergeData &md, StateAp *destState, StateAp **srcStates, int numSrc ) { for ( int s = 0; s < numSrc; s++ ) mergeStates( md, destState, srcStates[s] ); } void FsmAp::mergeStates( MergeData &md, StateAp *destState, StateAp *srcState ) { ExpansionList expList1; ExpansionList expList2; findTransExpansions( expList1, destState, srcState ); findCondExpansions( expList1, destState, srcState ); findTransExpansions( expList2, srcState, destState ); findCondExpansions( expList2, srcState, destState ); mergeStateConds( destState, srcState ); outTransCopy( md, destState, srcState->outList.head ); doExpand( md, destState, expList1 ); doExpand( md, destState, expList2 ); doRemove( md, destState, expList1 ); doRemove( md, destState, expList2 ); expList1.empty(); expList2.empty(); /* Get its bits and final state status. */ destState->stateBits |= ( srcState->stateBits & ~STB_ISFINAL ); if ( srcState->isFinState() ) setFinState( destState ); /* Draw in any properties of srcState into destState. */ if ( srcState == destState ) { /* Duplicate the list to protect against write to source. The * priorities sets are not copied in because that would have no * effect. */ destState->epsilonTrans.append( EpsilonTrans( srcState->epsilonTrans ) ); /* Get all actions, duplicating to protect against write to source. */ destState->toStateActionTable.setActions( ActionTable( srcState->toStateActionTable ) ); destState->fromStateActionTable.setActions( ActionTable( srcState->fromStateActionTable ) ); destState->outActionTable.setActions( ActionTable( srcState->outActionTable ) ); destState->outCondSet.insert( OutCondSet( srcState->outCondSet ) ); destState->errActionTable.setActions( ErrActionTable( srcState->errActionTable ) ); destState->eofActionTable.setActions( ActionTable( srcState->eofActionTable ) ); } else { /* Get the epsilons, out priorities. */ destState->epsilonTrans.append( srcState->epsilonTrans ); destState->outPriorTable.setPriors( srcState->outPriorTable ); /* Get all actions. */ destState->toStateActionTable.setActions( srcState->toStateActionTable ); destState->fromStateActionTable.setActions( srcState->fromStateActionTable ); destState->outActionTable.setActions( srcState->outActionTable ); destState->outCondSet.insert( srcState->outCondSet ); destState->errActionTable.setActions( srcState->errActionTable ); destState->eofActionTable.setActions( srcState->eofActionTable ); } } void FsmAp::fillInStates( MergeData &md ) { /* Merge any states that are awaiting merging. This will likey cause * other states to be added to the stfil list. */ StateAp *state = md.stfillHead; while ( state != 0 ) { StateSet *stateSet = &state->stateDictEl->stateSet; mergeStates( md, state, stateSet->data, stateSet->length() ); state = state->alg.next; } /* Delete the state sets of all states that are on the fill list. */ state = md.stfillHead; while ( state != 0 ) { /* Delete and reset the state set. */ delete state->stateDictEl; state->stateDictEl = 0; /* Next state in the stfill list. */ state = state->alg.next; } /* StateDict will still have its ptrs/size set but all of it's element * will be deleted so we don't need to clean it up. */ } void FsmAp::findEmbedExpansions( ExpansionList &expansionList, StateAp *destState, Action *condAction, bool sense ) { StateCondList destList; PairIter transCond( destState->outList.head, destState->stateCondList.head ); for ( ; !transCond.end(); transCond++ ) { switch ( transCond.userState ) { case RangeInS1: { if ( transCond.s1Tel.lowKey <= keyOps->maxKey ) { assert( transCond.s1Tel.highKey <= keyOps->maxKey ); /* Make a new state cond. */ StateCond *newStateCond = new StateCond( transCond.s1Tel.lowKey, transCond.s1Tel.highKey ); newStateCond->condSpace = addCondSpace( CondSet( condAction ) ); destList.append( newStateCond ); /* Create the expansion. */ Expansion *expansion = new Expansion( transCond.s1Tel.lowKey, transCond.s1Tel.highKey ); expansion->fromTrans = new TransAp(*transCond.s1Tel.trans); expansion->fromTrans->fromState = 0; expansion->fromTrans->toState = transCond.s1Tel.trans->toState; expansion->fromCondSpace = 0; expansion->fromVals = 0; expansion->toCondSpace = newStateCond->condSpace; expansion->toValsList.append( sense?1:0 ); #ifdef LOG_CONDS logNewExpansion( expansion ); #endif expansionList.append( expansion ); } break; } case RangeInS2: { /* Enhance state cond and find the expansion. */ StateCond *stateCond = transCond.s2Tel.trans; stateCond->lowKey = transCond.s2Tel.lowKey; stateCond->highKey = transCond.s2Tel.highKey; CondSet &destCS = stateCond->condSpace->condSet; long destLen = destCS.length(); CondSpace *fromCondSpace = stateCond->condSpace; CondSet mergedCS = destCS; mergedCS.insert( condAction ); CondSpace *toCondSpace = addCondSpace( mergedCS ); stateCond->condSpace = toCondSpace; destList.append( stateCond ); /* Loop all values in the dest space. */ for ( long destVals = 0; destVals < (1 << destLen); destVals++ ) { long basicVals = 0; for ( CondSet::Iter csi = destCS; csi.lte(); csi++ ) { if ( destVals & (1 << csi.pos()) ) { Action **cim = mergedCS.find( *csi ); long bitPos = (cim - mergedCS.data); basicVals |= 1 << bitPos; } } long targVals = basicVals; Action **cim = mergedCS.find( condAction ); long bitPos = (cim - mergedCS.data); targVals |= (sense?1:0) << bitPos; LongVect expandToVals( targVals ); findCondExpInTrans( expansionList, destState, transCond.s2Tel.lowKey, transCond.s2Tel.highKey, fromCondSpace, toCondSpace, destVals, expandToVals ); } break; } case RangeOverlap: case BreakS1: case BreakS2: assert( false ); break; } } destState->stateCondList.transfer( destList ); } void FsmAp::embedCondition( StateAp *state, Action *condAction, bool sense ) { MergeData md; ExpansionList expList; /* Turn on misfit accounting to possibly catch the old start state. */ setMisfitAccounting( true ); /* Worker. */ embedCondition( md, state, condAction, sense ); /* Fill in any states that were newed up as combinations of others. */ fillInStates( md ); /* Remove the misfits and turn off misfit accounting. */ removeMisfits(); setMisfitAccounting( false ); } void FsmAp::embedCondition( MergeData &md, StateAp *state, Action *condAction, bool sense ) { ExpansionList expList; findEmbedExpansions( expList, state, condAction, sense ); doExpand( md, state, expList ); doRemove( md, state, expList ); expList.empty(); } /* Check if a machine defines a single character. This is useful in validating * ranges and machines to export. */ bool FsmAp::checkSingleCharMachine() { /* Must have two states. */ if ( stateList.length() != 2 ) return false; /* The start state cannot be final. */ if ( startState->isFinState() ) return false; /* There should be only one final state. */ if ( finStateSet.length() != 1 ) return false; /* The final state cannot have any transitions out. */ if ( finStateSet[0]->outList.length() != 0 ) return false; /* The start state should have only one transition out. */ if ( startState->outList.length() != 1 ) return false; /* The singe transition out of the start state should not be a range. */ TransAp *startTrans = startState->outList.head; if ( startTrans->lowKey != startTrans->highKey ) return false; return true; } ragel-6.8/ragel/csipgoto.cpp0000664000175000017500000002667012106050031013030 00000000000000/* * Copyright 2001-2006 Adrian Thurston * 2004 Erich Ocean * 2005 Alan West */ /* This file is part of Ragel. * * Ragel is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Ragel is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Ragel; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "ragel.h" #include "csipgoto.h" #include "redfsm.h" #include "gendata.h" #include "bstmap.h" bool CSharpIpGotoCodeGen::useAgainLabel() { return redFsm->anyRegActionRets() || redFsm->anyRegActionByValControl() || redFsm->anyRegNextStmt(); } void CSharpIpGotoCodeGen::GOTO( ostream &ret, int gotoDest, bool inFinish ) { ret << "{" << CTRL_FLOW() << "goto st" << gotoDest << ";}"; } void CSharpIpGotoCodeGen::CALL( ostream &ret, int callDest, int targState, bool inFinish ) { if ( prePushExpr != 0 ) { ret << "{"; INLINE_LIST( ret, prePushExpr, 0, false ); } ret << "{" << STACK() << "[" << TOP() << "++] = " << targState << "; " << CTRL_FLOW() << "goto st" << callDest << ";}"; if ( prePushExpr != 0 ) ret << "}"; } void CSharpIpGotoCodeGen::CALL_EXPR( ostream &ret, GenInlineItem *ilItem, int targState, bool inFinish ) { if ( prePushExpr != 0 ) { ret << "{"; INLINE_LIST( ret, prePushExpr, 0, false ); } ret << "{" << STACK() << "[" << TOP() << "++] = " << targState << "; " << vCS() << " = ("; INLINE_LIST( ret, ilItem->children, 0, inFinish ); ret << "); " << CTRL_FLOW() << "goto _again;}"; if ( prePushExpr != 0 ) ret << "}"; } void CSharpIpGotoCodeGen::RET( ostream &ret, bool inFinish ) { ret << "{" << vCS() << " = " << STACK() << "[--" << TOP() << "];"; if ( postPopExpr != 0 ) { ret << "{"; INLINE_LIST( ret, postPopExpr, 0, false ); ret << "}"; } ret << CTRL_FLOW() << "goto _again;}"; } void CSharpIpGotoCodeGen::GOTO_EXPR( ostream &ret, GenInlineItem *ilItem, bool inFinish ) { ret << "{" << vCS() << " = ("; INLINE_LIST( ret, ilItem->children, 0, inFinish ); ret << "); " << CTRL_FLOW() << "goto _again;}"; } void CSharpIpGotoCodeGen::NEXT( ostream &ret, int nextDest, bool inFinish ) { ret << vCS() << " = " << nextDest << ";"; } void CSharpIpGotoCodeGen::NEXT_EXPR( ostream &ret, GenInlineItem *ilItem, bool inFinish ) { ret << vCS() << " = ("; INLINE_LIST( ret, ilItem->children, 0, inFinish ); ret << ");"; } void CSharpIpGotoCodeGen::CURS( ostream &ret, bool inFinish ) { ret << "(_ps)"; } void CSharpIpGotoCodeGen::TARGS( ostream &ret, bool inFinish, int targState ) { ret << targState; } void CSharpIpGotoCodeGen::BREAK( ostream &ret, int targState ) { /* FIXME: If this code generator is made active then BREAK generation * needs to check csForced. */ outLabelUsed = true; ret << "{" << P() << "++; " << vCS() << " = " << targState << "; " << CTRL_FLOW() << "goto _out;}"; } bool CSharpIpGotoCodeGen::IN_TRANS_ACTIONS( RedStateAp *state ) { bool anyWritten = false; /* Emit any transitions that have actions and that go to this state. */ for ( int it = 0; it < state->numInTrans; it++ ) { RedTransAp *trans = state->inTrans[it]; if ( trans->action != 0 && trans->labelNeeded ) { /* Remember that we wrote an action so we know to write the * line directive for going back to the output. */ anyWritten = true; /* Write the label for the transition so it can be jumped to. */ out << "tr" << trans->id << ":\n"; /* If the action contains a next, then we must preload the current * state since the action may or may not set it. */ if ( trans->action->anyNextStmt() ) out << " " << vCS() << " = " << trans->targ->id << ";\n"; /* Write each action in the list. */ for ( GenActionTable::Iter item = trans->action->key; item.lte(); item++ ) ACTION( out, item->value, trans->targ->id, false ); /* If the action contains a next then we need to reload, otherwise * jump directly to the target state. */ if ( trans->action->anyNextStmt() ) out << "\tgoto _again;\n"; else out << "\tgoto st" << trans->targ->id << ";\n"; } } return anyWritten; } /* Called from GotoCodeGen::STATE_GOTOS just before writing the gotos for each * state. */ void CSharpIpGotoCodeGen::GOTO_HEADER( RedStateAp *state ) { bool anyWritten = IN_TRANS_ACTIONS( state ); if ( state->labelNeeded ) out << "st" << state->id << ":\n"; if ( state->toStateAction != 0 ) { /* Remember that we wrote an action. Write every action in the list. */ anyWritten = true; for ( GenActionTable::Iter item = state->toStateAction->key; item.lte(); item++ ) ACTION( out, item->value, state->id, false ); } /* Advance and test buffer pos. */ if ( state->labelNeeded ) { if ( !noEnd ) { out << " if ( ++" << P() << " == " << PE() << " )\n" " goto _test_eof" << state->id << ";\n"; } else { out << " " << P() << " += 1;\n"; } } /* Give the state a switch case. */ out << "case " << state->id << ":\n"; if ( state->fromStateAction != 0 ) { /* Remember that we wrote an action. Write every action in the list. */ anyWritten = true; for ( GenActionTable::Iter item = state->fromStateAction->key; item.lte(); item++ ) ACTION( out, item->value, state->id, false ); } if ( anyWritten ) genLineDirective( out ); /* Record the prev state if necessary. */ if ( state->anyRegCurStateRef() ) out << " _ps = " << state->id << ";\n"; } void CSharpIpGotoCodeGen::STATE_GOTO_ERROR() { /* In the error state we need to emit some stuff that usually goes into * the header. */ RedStateAp *state = redFsm->errState; bool anyWritten = IN_TRANS_ACTIONS( state ); /* No case label needed since we don't switch on the error state. */ if ( anyWritten ) genLineDirective( out ); if ( state->labelNeeded ) out << "st" << state->id << ":\n"; /* Break out here. */ outLabelUsed = true; out << vCS() << " = " << state->id << ";\n"; out << " goto _out;\n"; } /* Emit the goto to take for a given transition. */ std::ostream &CSharpIpGotoCodeGen::TRANS_GOTO( RedTransAp *trans, int level ) { if ( trans->action != 0 ) { /* Go to the transition which will go to the state. */ out << TABS(level) << "goto tr" << trans->id << ";"; } else { /* Go directly to the target state. */ out << TABS(level) << "goto st" << trans->targ->id << ";"; } return out; } std::ostream &CSharpIpGotoCodeGen::EXIT_STATES() { for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { if ( st->outNeeded ) { testEofUsed = true; out << " _test_eof" << st->id << ": " << vCS() << " = " << st->id << "; goto _test_eof; \n"; } } return out; } std::ostream &CSharpIpGotoCodeGen::AGAIN_CASES() { for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { out << " case " << st->id << ": goto st" << st->id << ";\n"; } return out; } std::ostream &CSharpIpGotoCodeGen::FINISH_CASES() { bool anyWritten = false; for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { if ( st->eofAction != 0 ) { if ( st->eofAction->eofRefs == 0 ) st->eofAction->eofRefs = new IntSet; st->eofAction->eofRefs->insert( st->id ); } } for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { if ( st->eofTrans != 0 ) out << " case " << st->id << ": goto tr" << st->eofTrans->id << ";\n"; } for ( GenActionTableMap::Iter act = redFsm->actionMap; act.lte(); act++ ) { if ( act->eofRefs != 0 ) { for ( IntSet::Iter pst = *act->eofRefs; pst.lte(); pst++ ) out << " case " << *pst << ": \n"; /* Remember that we wrote a trans so we know to write the * line directive for going back to the output. */ anyWritten = true; /* Write each action in the eof action list. */ for ( GenActionTable::Iter item = act->key; item.lte(); item++ ) ACTION( out, item->value, STATE_ERR_STATE, true ); out << "\tbreak;\n"; } } if ( anyWritten ) genLineDirective( out ); return out; } void CSharpIpGotoCodeGen::setLabelsNeeded( GenInlineList *inlineList ) { for ( GenInlineList::Iter item = *inlineList; item.lte(); item++ ) { switch ( item->type ) { case GenInlineItem::Goto: case GenInlineItem::Call: { /* Mark the target as needing a label. */ item->targState->labelNeeded = true; break; } default: break; } if ( item->children != 0 ) setLabelsNeeded( item->children ); } } /* Set up labelNeeded flag for each state. */ void CSharpIpGotoCodeGen::setLabelsNeeded() { /* If we use the _again label, then we the _again switch, which uses all * labels. */ if ( useAgainLabel() ) { for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) st->labelNeeded = true; } else { /* Do not use all labels by default, init all labelNeeded vars to false. */ for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) st->labelNeeded = false; /* Walk all transitions and set only those that have targs. */ for ( TransApSet::Iter trans = redFsm->transSet; trans.lte(); trans++ ) { /* If there is no action with a next statement, then the label will be * needed. */ if ( trans->action == 0 || !trans->action->anyNextStmt() ) trans->targ->labelNeeded = true; /* Need labels for states that have goto or calls in action code * invoked on characters (ie, not from out action code). */ if ( trans->action != 0 ) { /* Loop the actions. */ for ( GenActionTable::Iter act = trans->action->key; act.lte(); act++ ) { /* Get the action and walk it's tree. */ setLabelsNeeded( act->value->inlineList ); } } } } if ( !noEnd ) { for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { if ( st != redFsm->errState ) st->outNeeded = st->labelNeeded; } } } void CSharpIpGotoCodeGen::writeData() { STATE_IDS(); } void CSharpIpGotoCodeGen::writeExec() { /* Must set labels immediately before writing because we may depend on the * noend write option. */ setLabelsNeeded(); testEofUsed = false; outLabelUsed = false; out << " {\n"; if ( redFsm->anyRegCurStateRef() ) out << " int _ps = 0;\n"; if ( redFsm->anyConditions() ) out << " " << WIDE_ALPH_TYPE() << " _widec;\n"; if ( !noEnd ) { testEofUsed = true; out << " if ( " << P() << " == " << PE() << " )\n" " goto _test_eof;\n"; } if ( useAgainLabel() ) { out << " goto _resume;\n" "\n" "_again:\n" " switch ( " << vCS() << " ) {\n"; AGAIN_CASES() << " default: break;\n" " }\n" "\n"; if ( !noEnd ) { testEofUsed = true; out << " if ( ++" << P() << " == " << PE() << " )\n" " goto _test_eof;\n"; } else { out << " " << P() << " += 1;\n"; } out << "_resume:\n"; } out << " switch ( " << vCS() << " )\n {\n"; STATE_GOTOS(); SWITCH_DEFAULT() << " }\n"; EXIT_STATES() << "\n"; if ( testEofUsed ) out << " _test_eof: {}\n"; if ( redFsm->anyEofTrans() || redFsm->anyEofActions() ) { out << " if ( " << P() << " == " << vEOF() << " )\n" " {\n" " switch ( " << vCS() << " ) {\n"; FINISH_CASES(); SWITCH_DEFAULT() << " }\n" " }\n" "\n"; } if ( outLabelUsed ) out << " _out: {}\n"; out << " }\n"; } ragel-6.8/ragel/goftable.cpp0000664000175000017500000002455512106050031012764 00000000000000/* * Copyright 2001-2006 Adrian Thurston * 2004 Erich Ocean * 2005 Alan West */ /* This file is part of Ragel. * * Ragel is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Ragel is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Ragel; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "ragel.h" #include "goftable.h" #include "redfsm.h" #include "gendata.h" using std::endl; /* Determine if we should use indicies or not. */ void GoFTabCodeGen::calcIndexSize() { int sizeWithInds = 0, sizeWithoutInds = 0; /* Calculate cost of using with indicies. */ for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { int totalIndex = st->outSingle.length() + st->outRange.length() + (st->defTrans == 0 ? 0 : 1); sizeWithInds += arrayTypeSize(redFsm->maxIndex) * totalIndex; } sizeWithInds += arrayTypeSize(redFsm->maxState) * redFsm->transSet.length(); if ( redFsm->anyActions() ) sizeWithInds += arrayTypeSize(redFsm->maxActListId) * redFsm->transSet.length(); /* Calculate the cost of not using indicies. */ for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { int totalIndex = st->outSingle.length() + st->outRange.length() + (st->defTrans == 0 ? 0 : 1); sizeWithoutInds += arrayTypeSize(redFsm->maxState) * totalIndex; if ( redFsm->anyActions() ) sizeWithoutInds += arrayTypeSize(redFsm->maxActListId) * totalIndex; } /* If using indicies reduces the size, use them. */ useIndicies = sizeWithInds < sizeWithoutInds; } std::ostream &GoFTabCodeGen::TO_STATE_ACTION( RedStateAp *state ) { int act = 0; if ( state->toStateAction != 0 ) act = state->toStateAction->actListId+1; out << act; return out; } std::ostream &GoFTabCodeGen::FROM_STATE_ACTION( RedStateAp *state ) { int act = 0; if ( state->fromStateAction != 0 ) act = state->fromStateAction->actListId+1; out << act; return out; } std::ostream &GoFTabCodeGen::EOF_ACTION( RedStateAp *state ) { int act = 0; if ( state->eofAction != 0 ) act = state->eofAction->actListId+1; out << act; return out; } /* Write out the function for a transition. */ std::ostream &GoFTabCodeGen::TRANS_ACTION( RedTransAp *trans ) { int action = 0; if ( trans->action != 0 ) action = trans->action->actListId+1; out << action; return out; } /* Write out the function switch. This switch is keyed on the values * of the func index. */ std::ostream &GoFTabCodeGen::TO_STATE_ACTION_SWITCH( int level ) { /* Loop the actions. */ for ( GenActionTableMap::Iter redAct = redFsm->actionMap; redAct.lte(); redAct++ ) { if ( redAct->numToStateRefs > 0 ) { /* Write the entry label. */ out << TABS(level) << "case " << redAct->actListId+1 << ":" << endl; /* Write each action in the list of action items. */ for ( GenActionTable::Iter item = redAct->key; item.lte(); item++ ) ACTION( out, item->value, 0, false, false ); out << endl; } } genLineDirective( out ); return out; } /* Write out the function switch. This switch is keyed on the values * of the func index. */ std::ostream &GoFTabCodeGen::FROM_STATE_ACTION_SWITCH( int level ) { /* Loop the actions. */ for ( GenActionTableMap::Iter redAct = redFsm->actionMap; redAct.lte(); redAct++ ) { if ( redAct->numFromStateRefs > 0 ) { /* Write the entry label. */ out << TABS(level) << "case " << redAct->actListId+1 << ":" << endl; /* Write each action in the list of action items. */ for ( GenActionTable::Iter item = redAct->key; item.lte(); item++ ) ACTION( out, item->value, 0, false, false ); out << endl; } } genLineDirective( out ); return out; } std::ostream &GoFTabCodeGen::EOF_ACTION_SWITCH( int level ) { /* Loop the actions. */ for ( GenActionTableMap::Iter redAct = redFsm->actionMap; redAct.lte(); redAct++ ) { if ( redAct->numEofRefs > 0 ) { /* Write the entry label. */ out << TABS(level) << "case " << redAct->actListId+1 << ":" << endl; /* Write each action in the list of action items. */ for ( GenActionTable::Iter item = redAct->key; item.lte(); item++ ) ACTION( out, item->value, 0, true, false ); out << endl; } } genLineDirective( out ); return out; } /* Write out the function switch. This switch is keyed on the values * of the func index. */ std::ostream &GoFTabCodeGen::ACTION_SWITCH( int level ) { /* Loop the actions. */ for ( GenActionTableMap::Iter redAct = redFsm->actionMap; redAct.lte(); redAct++ ) { if ( redAct->numTransRefs > 0 ) { /* Write the entry label. */ out << TABS(level) << "case " << redAct->actListId+1 << ":" << endl; /* Write each action in the list of action items. */ for ( GenActionTable::Iter item = redAct->key; item.lte(); item++ ) ACTION( out, item->value, 0, false, false ); out << endl; } } genLineDirective( out ); return out; } void GoFTabCodeGen::writeData() { if ( redFsm->anyConditions() ) { OPEN_ARRAY( ARRAY_TYPE(redFsm->maxCondOffset), CO() ); COND_OFFSETS(); CLOSE_ARRAY() << endl; OPEN_ARRAY( ARRAY_TYPE(redFsm->maxCondLen), CL() ); COND_LENS(); CLOSE_ARRAY() << endl; OPEN_ARRAY( WIDE_ALPH_TYPE(), CK() ); COND_KEYS(); CLOSE_ARRAY() << endl; OPEN_ARRAY( ARRAY_TYPE(redFsm->maxCondSpaceId), C() ); COND_SPACES(); CLOSE_ARRAY() << endl; } OPEN_ARRAY( ARRAY_TYPE(redFsm->maxKeyOffset), KO() ); KEY_OFFSETS(); CLOSE_ARRAY() << endl; OPEN_ARRAY( WIDE_ALPH_TYPE(), K() ); KEYS(); CLOSE_ARRAY() << endl; OPEN_ARRAY( ARRAY_TYPE(redFsm->maxSingleLen), SL() ); SINGLE_LENS(); CLOSE_ARRAY() << endl; OPEN_ARRAY( ARRAY_TYPE(redFsm->maxRangeLen), RL() ); RANGE_LENS(); CLOSE_ARRAY() << endl; OPEN_ARRAY( ARRAY_TYPE(redFsm->maxIndexOffset), IO() ); INDEX_OFFSETS(); CLOSE_ARRAY() << endl; if ( useIndicies ) { OPEN_ARRAY( ARRAY_TYPE(redFsm->maxIndex), I() ); INDICIES(); CLOSE_ARRAY() << endl; OPEN_ARRAY( ARRAY_TYPE(redFsm->maxState), TT() ); TRANS_TARGS_WI(); CLOSE_ARRAY() << endl; if ( redFsm->anyActions() ) { OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActListId), TA() ); TRANS_ACTIONS_WI(); CLOSE_ARRAY() << endl; } } else { OPEN_ARRAY( ARRAY_TYPE(redFsm->maxState), TT() ); TRANS_TARGS(); CLOSE_ARRAY() << endl; if ( redFsm->anyActions() ) { OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActListId), TA() ); TRANS_ACTIONS(); CLOSE_ARRAY() << endl; } } if ( redFsm->anyToStateActions() ) { OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActionLoc), TSA() ); TO_STATE_ACTIONS(); CLOSE_ARRAY() << endl; } if ( redFsm->anyFromStateActions() ) { OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActionLoc), FSA() ); FROM_STATE_ACTIONS(); CLOSE_ARRAY() << endl; } if ( redFsm->anyEofActions() ) { OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActListId), EA() ); EOF_ACTIONS(); CLOSE_ARRAY() << endl; } if ( redFsm->anyEofTrans() ) { OPEN_ARRAY( ARRAY_TYPE(redFsm->maxIndexOffset+1), ET() ); EOF_TRANS(); CLOSE_ARRAY() << endl; } STATE_IDS(); } void GoFTabCodeGen::writeExec() { testEofUsed = false; outLabelUsed = false; out << " {" << endl << " var _klen " << INT() << endl; if ( redFsm->anyRegCurStateRef() ) out << " var _ps " << INT() << endl; out << " var _keys " << INT() << endl << " var _trans " << INT() << endl; if ( redFsm->anyConditions() ) out << " var _widec " << WIDE_ALPH_TYPE() << endl; out << endl; if ( !noEnd ) { testEofUsed = true; out << " if " << P() << " == " << PE() << " {" << endl << " goto _test_eof" << endl << " }" << endl; } if ( redFsm->errState != 0 ) { outLabelUsed = true; out << " if " << vCS() << " == " << redFsm->errState->id << " {" << endl << " goto _out" << endl << " }" << endl; } out << "_resume:" << endl; if ( redFsm->anyFromStateActions() ) { out << " switch " << FSA() << "[" << vCS() << "] {" << endl; FROM_STATE_ACTION_SWITCH(1); out << " }" << endl << endl; } if ( redFsm->anyConditions() ) COND_TRANSLATE(); LOCATE_TRANS(); out << "_match:" << endl; if ( useIndicies ) out << " _trans = " << CAST(INT(), I() + "[_trans]") << endl; if ( redFsm->anyEofTrans() ) out << "_eof_trans:" << endl; if ( redFsm->anyRegCurStateRef() ) out << " _ps = " << vCS() << endl; out << " " << vCS() << " = " << CAST(INT(), TT() + "[_trans]") << endl << endl; if ( redFsm->anyRegActions() ) { out << " if " << TA() << "[_trans] == 0 {" << endl << " goto _again" << endl << " }" << endl << endl << " switch " << TA() << "[_trans] {" << endl; ACTION_SWITCH(1); out << " }" << endl << endl; } if ( redFsm->anyRegActions() || redFsm->anyActionGotos() || redFsm->anyActionCalls() || redFsm->anyActionRets() ) out << "_again:" << endl; if ( redFsm->anyToStateActions() ) { out << " switch " << TSA() << "[" << vCS() << "] {" << endl; TO_STATE_ACTION_SWITCH(1); out << " }" << endl << endl; } if ( redFsm->errState != 0 ) { outLabelUsed = true; out << " if " << vCS() << " == " << redFsm->errState->id << " {" << endl << " goto _out" << endl << " }" << endl; } if ( !noEnd ) { out << " if " << P() << "++; " << P() << " != " << PE() << " {" << endl << " goto _resume" << endl << " }" << endl; } else { out << " " << P() << "++" << endl << " goto _resume" << endl; } if ( testEofUsed ) out << " _test_eof: {}" << endl; if ( redFsm->anyEofTrans() || redFsm->anyEofActions() ) { out << " if " << P() << " == " << vEOF() << " {" << endl; if ( redFsm->anyEofTrans() ) { out << " if " << ET() << "[" << vCS() << "] > 0 {" << endl << " _trans = " << CAST(INT(), ET() + "[" + vCS() + "] - 1") << endl << " goto _eof_trans" << endl << " }" << endl; } if ( redFsm->anyEofActions() ) { out << " switch " << EA() << "[" << vCS() << "] {" << endl; EOF_ACTION_SWITCH(2); out << " }" << endl; } out << " }" << endl << endl; } if ( outLabelUsed ) out << " _out: {}" << endl; out << " }" << endl; } ragel-6.8/ragel/cdipgoto.cpp0000664000175000017500000002667012106050031013011 00000000000000/* * Copyright 2001-2006 Adrian Thurston * 2004 Erich Ocean * 2005 Alan West */ /* This file is part of Ragel. * * Ragel is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Ragel is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Ragel; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "ragel.h" #include "cdipgoto.h" #include "redfsm.h" #include "gendata.h" #include "bstmap.h" bool IpGotoCodeGen::useAgainLabel() { return redFsm->anyRegActionRets() || redFsm->anyRegActionByValControl() || redFsm->anyRegNextStmt(); } void IpGotoCodeGen::GOTO( ostream &ret, int gotoDest, bool inFinish ) { ret << "{" << CTRL_FLOW() << "goto st" << gotoDest << ";}"; } void IpGotoCodeGen::CALL( ostream &ret, int callDest, int targState, bool inFinish ) { if ( prePushExpr != 0 ) { ret << "{"; INLINE_LIST( ret, prePushExpr, 0, false, false ); } ret << "{" << STACK() << "[" << TOP() << "++] = " << targState << "; " << CTRL_FLOW() << "goto st" << callDest << ";}"; if ( prePushExpr != 0 ) ret << "}"; } void IpGotoCodeGen::CALL_EXPR( ostream &ret, GenInlineItem *ilItem, int targState, bool inFinish ) { if ( prePushExpr != 0 ) { ret << "{"; INLINE_LIST( ret, prePushExpr, 0, false, false ); } ret << "{" << STACK() << "[" << TOP() << "++] = " << targState << "; " << vCS() << " = ("; INLINE_LIST( ret, ilItem->children, 0, inFinish, false ); ret << "); " << CTRL_FLOW() << "goto _again;}"; if ( prePushExpr != 0 ) ret << "}"; } void IpGotoCodeGen::RET( ostream &ret, bool inFinish ) { ret << "{" << vCS() << " = " << STACK() << "[--" << TOP() << "];"; if ( postPopExpr != 0 ) { ret << "{"; INLINE_LIST( ret, postPopExpr, 0, false, false ); ret << "}"; } ret << CTRL_FLOW() << "goto _again;}"; } void IpGotoCodeGen::GOTO_EXPR( ostream &ret, GenInlineItem *ilItem, bool inFinish ) { ret << "{" << vCS() << " = ("; INLINE_LIST( ret, ilItem->children, 0, inFinish, false ); ret << "); " << CTRL_FLOW() << "goto _again;}"; } void IpGotoCodeGen::NEXT( ostream &ret, int nextDest, bool inFinish ) { ret << vCS() << " = " << nextDest << ";"; } void IpGotoCodeGen::NEXT_EXPR( ostream &ret, GenInlineItem *ilItem, bool inFinish ) { ret << vCS() << " = ("; INLINE_LIST( ret, ilItem->children, 0, inFinish, false ); ret << ");"; } void IpGotoCodeGen::CURS( ostream &ret, bool inFinish ) { ret << "(_ps)"; } void IpGotoCodeGen::TARGS( ostream &ret, bool inFinish, int targState ) { ret << targState; } void IpGotoCodeGen::BREAK( ostream &ret, int targState, bool csForced ) { outLabelUsed = true; ret << "{" << P() << "++; "; if ( !csForced ) ret << vCS() << " = " << targState << "; "; ret << CTRL_FLOW() << "goto _out;}"; } bool IpGotoCodeGen::IN_TRANS_ACTIONS( RedStateAp *state ) { bool anyWritten = false; /* Emit any transitions that have actions and that go to this state. */ for ( int it = 0; it < state->numInTrans; it++ ) { RedTransAp *trans = state->inTrans[it]; if ( trans->action != 0 && trans->labelNeeded ) { /* Remember that we wrote an action so we know to write the * line directive for going back to the output. */ anyWritten = true; /* Write the label for the transition so it can be jumped to. */ out << "tr" << trans->id << ":\n"; /* If the action contains a next, then we must preload the current * state since the action may or may not set it. */ if ( trans->action->anyNextStmt() ) out << " " << vCS() << " = " << trans->targ->id << ";\n"; /* Write each action in the list. */ for ( GenActionTable::Iter item = trans->action->key; item.lte(); item++ ) { ACTION( out, item->value, trans->targ->id, false, trans->action->anyNextStmt() ); } /* If the action contains a next then we need to reload, otherwise * jump directly to the target state. */ if ( trans->action->anyNextStmt() ) out << "\tgoto _again;\n"; else out << "\tgoto st" << trans->targ->id << ";\n"; } } return anyWritten; } /* Called from GotoCodeGen::STATE_GOTOS just before writing the gotos for each * state. */ void IpGotoCodeGen::GOTO_HEADER( RedStateAp *state ) { bool anyWritten = IN_TRANS_ACTIONS( state ); if ( state->labelNeeded ) out << "st" << state->id << ":\n"; if ( state->toStateAction != 0 ) { /* Remember that we wrote an action. Write every action in the list. */ anyWritten = true; for ( GenActionTable::Iter item = state->toStateAction->key; item.lte(); item++ ) { ACTION( out, item->value, state->id, false, state->toStateAction->anyNextStmt() ); } } /* Advance and test buffer pos. */ if ( state->labelNeeded ) { if ( !noEnd ) { out << " if ( ++" << P() << " == " << PE() << " )\n" " goto _test_eof" << state->id << ";\n"; } else { out << " " << P() << " += 1;\n"; } } /* Give the state a switch case. */ out << "case " << state->id << ":\n"; if ( state->fromStateAction != 0 ) { /* Remember that we wrote an action. Write every action in the list. */ anyWritten = true; for ( GenActionTable::Iter item = state->fromStateAction->key; item.lte(); item++ ) { ACTION( out, item->value, state->id, false, state->fromStateAction->anyNextStmt() ); } } if ( anyWritten ) genLineDirective( out ); /* Record the prev state if necessary. */ if ( state->anyRegCurStateRef() ) out << " _ps = " << state->id << ";\n"; } void IpGotoCodeGen::STATE_GOTO_ERROR() { /* In the error state we need to emit some stuff that usually goes into * the header. */ RedStateAp *state = redFsm->errState; bool anyWritten = IN_TRANS_ACTIONS( state ); /* No case label needed since we don't switch on the error state. */ if ( anyWritten ) genLineDirective( out ); if ( state->labelNeeded ) out << "st" << state->id << ":\n"; /* Break out here. */ outLabelUsed = true; out << vCS() << " = " << state->id << ";\n"; out << " goto _out;\n"; } /* Emit the goto to take for a given transition. */ std::ostream &IpGotoCodeGen::TRANS_GOTO( RedTransAp *trans, int level ) { if ( trans->action != 0 ) { /* Go to the transition which will go to the state. */ out << TABS(level) << "goto tr" << trans->id << ";"; } else { /* Go directly to the target state. */ out << TABS(level) << "goto st" << trans->targ->id << ";"; } return out; } std::ostream &IpGotoCodeGen::EXIT_STATES() { for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { if ( st->outNeeded ) { testEofUsed = true; out << " _test_eof" << st->id << ": " << vCS() << " = " << st->id << "; goto _test_eof; \n"; } } return out; } std::ostream &IpGotoCodeGen::AGAIN_CASES() { for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { out << " case " << st->id << ": goto st" << st->id << ";\n"; } return out; } std::ostream &IpGotoCodeGen::FINISH_CASES() { bool anyWritten = false; for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { if ( st->eofAction != 0 ) { if ( st->eofAction->eofRefs == 0 ) st->eofAction->eofRefs = new IntSet; st->eofAction->eofRefs->insert( st->id ); } } for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { if ( st->eofTrans != 0 ) out << " case " << st->id << ": goto tr" << st->eofTrans->id << ";\n"; } for ( GenActionTableMap::Iter act = redFsm->actionMap; act.lte(); act++ ) { if ( act->eofRefs != 0 ) { for ( IntSet::Iter pst = *act->eofRefs; pst.lte(); pst++ ) out << " case " << *pst << ": \n"; /* Remember that we wrote a trans so we know to write the * line directive for going back to the output. */ anyWritten = true; /* Write each action in the eof action list. */ for ( GenActionTable::Iter item = act->key; item.lte(); item++ ) ACTION( out, item->value, STATE_ERR_STATE, true, false ); out << "\tbreak;\n"; } } if ( anyWritten ) genLineDirective( out ); return out; } void IpGotoCodeGen::setLabelsNeeded( GenInlineList *inlineList ) { for ( GenInlineList::Iter item = *inlineList; item.lte(); item++ ) { switch ( item->type ) { case GenInlineItem::Goto: case GenInlineItem::Call: { /* Mark the target as needing a label. */ item->targState->labelNeeded = true; break; } default: break; } if ( item->children != 0 ) setLabelsNeeded( item->children ); } } /* Set up labelNeeded flag for each state. */ void IpGotoCodeGen::setLabelsNeeded() { /* If we use the _again label, then we the _again switch, which uses all * labels. */ if ( useAgainLabel() ) { for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) st->labelNeeded = true; } else { /* Do not use all labels by default, init all labelNeeded vars to false. */ for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) st->labelNeeded = false; /* Walk all transitions and set only those that have targs. */ for ( TransApSet::Iter trans = redFsm->transSet; trans.lte(); trans++ ) { /* If there is no action with a next statement, then the label will be * needed. */ if ( trans->action == 0 || !trans->action->anyNextStmt() ) trans->targ->labelNeeded = true; /* Need labels for states that have goto or calls in action code * invoked on characters (ie, not from out action code). */ if ( trans->action != 0 ) { /* Loop the actions. */ for ( GenActionTable::Iter act = trans->action->key; act.lte(); act++ ) { /* Get the action and walk it's tree. */ setLabelsNeeded( act->value->inlineList ); } } } } if ( !noEnd ) { for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { if ( st != redFsm->errState ) st->outNeeded = st->labelNeeded; } } } void IpGotoCodeGen::writeData() { STATE_IDS(); } void IpGotoCodeGen::writeExec() { /* Must set labels immediately before writing because we may depend on the * noend write option. */ setLabelsNeeded(); testEofUsed = false; outLabelUsed = false; out << " {\n"; if ( redFsm->anyRegCurStateRef() ) out << " int _ps = 0;\n"; if ( redFsm->anyConditions() ) out << " " << WIDE_ALPH_TYPE() << " _widec;\n"; if ( !noEnd ) { testEofUsed = true; out << " if ( " << P() << " == " << PE() << " )\n" " goto _test_eof;\n"; } if ( useAgainLabel() ) { out << " goto _resume;\n" "\n" "_again:\n" " switch ( " << vCS() << " ) {\n"; AGAIN_CASES() << " default: break;\n" " }\n" "\n"; if ( !noEnd ) { testEofUsed = true; out << " if ( ++" << P() << " == " << PE() << " )\n" " goto _test_eof;\n"; } else { out << " " << P() << " += 1;\n"; } out << "_resume:\n"; } out << " switch ( " << vCS() << " )\n {\n"; STATE_GOTOS(); SWITCH_DEFAULT() << " }\n"; EXIT_STATES() << "\n"; if ( testEofUsed ) out << " _test_eof: {}\n"; if ( redFsm->anyEofTrans() || redFsm->anyEofActions() ) { out << " if ( " << P() << " == " << vEOF() << " )\n" " {\n" " switch ( " << vCS() << " ) {\n"; FINISH_CASES(); SWITCH_DEFAULT() << " }\n" " }\n" "\n"; } if ( outLabelUsed ) out << " _out: {}\n"; out << " }\n"; } ragel-6.8/ragel/cstable.h0000664000175000017500000000606512106050031012257 00000000000000/* * Copyright 2001-2006 Adrian Thurston * 2004 Erich Ocean * 2005 Alan West */ /* This file is part of Ragel. * * Ragel is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Ragel is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Ragel; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef _TABCODEGEN_H #define _TABCODEGEN_H #include #include "cscodegen.h" /* Forwards. */ struct CodeGenData; struct NameInst; struct RedTransAp; struct RedStateAp; /* * TabCodeGen */ class CSharpTabCodeGen : virtual public CSharpFsmCodeGen, public CSharpCodeGen { public: CSharpTabCodeGen( ostream &out ) : CSharpFsmCodeGen(out), CSharpCodeGen(out) {} virtual ~CSharpTabCodeGen() { } virtual void writeData(); virtual void writeExec(); protected: std::ostream &TO_STATE_ACTION_SWITCH(); std::ostream &FROM_STATE_ACTION_SWITCH(); std::ostream &EOF_ACTION_SWITCH(); std::ostream &ACTION_SWITCH(); std::ostream &COND_KEYS(); std::ostream &COND_SPACES(); std::ostream &KEYS(); std::ostream &INDICIES(); std::ostream &COND_OFFSETS(); std::ostream &KEY_OFFSETS(); std::ostream &INDEX_OFFSETS(); std::ostream &COND_LENS(); std::ostream &SINGLE_LENS(); std::ostream &RANGE_LENS(); std::ostream &TO_STATE_ACTIONS(); std::ostream &FROM_STATE_ACTIONS(); std::ostream &EOF_ACTIONS(); std::ostream &EOF_TRANS(); std::ostream &TRANS_TARGS(); std::ostream &TRANS_ACTIONS(); std::ostream &TRANS_TARGS_WI(); std::ostream &TRANS_ACTIONS_WI(); void LOCATE_TRANS(); void COND_TRANSLATE(); void GOTO( ostream &ret, int gotoDest, bool inFinish ); void CALL( ostream &ret, int callDest, int targState, bool inFinish ); void NEXT( ostream &ret, int nextDest, bool inFinish ); void GOTO_EXPR( ostream &ret, GenInlineItem *ilItem, bool inFinish ); void NEXT_EXPR( ostream &ret, GenInlineItem *ilItem, bool inFinish ); void CALL_EXPR( ostream &ret, GenInlineItem *ilItem, int targState, bool inFinish ); void CURS( ostream &ret, bool inFinish ); void TARGS( ostream &ret, bool inFinish, int targState ); void RET( ostream &ret, bool inFinish ); void BREAK( ostream &ret, int targState ); virtual std::ostream &TO_STATE_ACTION( RedStateAp *state ); virtual std::ostream &FROM_STATE_ACTION( RedStateAp *state ); virtual std::ostream &EOF_ACTION( RedStateAp *state ); virtual std::ostream &TRANS_ACTION( RedTransAp *trans ); virtual void calcIndexSize(); void initVarTypes(); string klenType; string keysType; string signedKeysType; string transType; }; #endif ragel-6.8/ragel/goftable.h0000664000175000017500000000325712106050031012425 00000000000000/* * Copyright 2001-2006 Adrian Thurston * 2004 Erich Ocean * 2005 Alan West */ /* This file is part of Ragel. * * Ragel is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Ragel is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Ragel; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef _GOFTABLE_H #define _GOFTABLE_H #include #include "gotable.h" /* Forwards. */ struct CodeGenData; /* * GoFTabCode */ class GoFTabCodeGen : public GoTabCodeGen { public: GoFTabCodeGen( ostream &out ) : GoTabCodeGen(out) {} protected: std::ostream &TO_STATE_ACTION_SWITCH( int level ); std::ostream &FROM_STATE_ACTION_SWITCH( int level ); std::ostream &EOF_ACTION_SWITCH( int level ); std::ostream &ACTION_SWITCH( int level ); virtual std::ostream &TO_STATE_ACTION( RedStateAp *state ); virtual std::ostream &FROM_STATE_ACTION( RedStateAp *state ); virtual std::ostream &EOF_ACTION( RedStateAp *state ); virtual std::ostream &TRANS_ACTION( RedTransAp *trans ); virtual void writeData(); virtual void writeExec(); virtual void calcIndexSize(); }; #endif ragel-6.8/ragel/buffer.h0000664000175000017500000000254612106050031012113 00000000000000/* * Copyright 2003 Adrian Thurston */ /* This file is part of Ragel. * * Ragel is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Ragel is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Ragel; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef _BUFFER_H #define _BUFFER_H #define BUFFER_INITIAL_SIZE 4096 /* An automatically grown buffer for collecting tokens. Always reuses space; * never down resizes. */ struct Buffer { Buffer() { data = (char*) malloc( BUFFER_INITIAL_SIZE ); allocated = BUFFER_INITIAL_SIZE; length = 0; } ~Buffer() { free(data); } void append( char p ) { if ( length == allocated ) { allocated *= 2; data = (char*) realloc( data, allocated ); } data[length++] = p; } void clear() { length = 0; } char *data; int allocated; int length; }; #endif ragel-6.8/ragel/cdfgoto.cpp0000664000175000017500000001543212106050031012620 00000000000000/* * Copyright 2001-2006 Adrian Thurston * 2004 Erich Ocean * 2005 Alan West */ /* This file is part of Ragel. * * Ragel is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Ragel is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Ragel; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "ragel.h" #include "cdfgoto.h" #include "redfsm.h" #include "gendata.h" #include "bstmap.h" std::ostream &FGotoCodeGen::EXEC_ACTIONS() { /* Loop the actions. */ for ( GenActionTableMap::Iter redAct = redFsm->actionMap; redAct.lte(); redAct++ ) { if ( redAct->numTransRefs > 0 ) { /* We are at the start of a glob, write the case. */ out << "f" << redAct->actListId << ":\n"; /* Write each action in the list of action items. */ for ( GenActionTable::Iter item = redAct->key; item.lte(); item++ ) ACTION( out, item->value, 0, false, false ); out << "\tgoto _again;\n"; } } return out; } /* Write out the function switch. This switch is keyed on the values * of the func index. */ std::ostream &FGotoCodeGen::TO_STATE_ACTION_SWITCH() { /* Loop the actions. */ for ( GenActionTableMap::Iter redAct = redFsm->actionMap; redAct.lte(); redAct++ ) { if ( redAct->numToStateRefs > 0 ) { /* Write the entry label. */ out << "\tcase " << redAct->actListId+1 << ":\n"; /* Write each action in the list of action items. */ for ( GenActionTable::Iter item = redAct->key; item.lte(); item++ ) ACTION( out, item->value, 0, false, false ); out << "\tbreak;\n"; } } genLineDirective( out ); return out; } /* Write out the function switch. This switch is keyed on the values * of the func index. */ std::ostream &FGotoCodeGen::FROM_STATE_ACTION_SWITCH() { /* Loop the actions. */ for ( GenActionTableMap::Iter redAct = redFsm->actionMap; redAct.lte(); redAct++ ) { if ( redAct->numFromStateRefs > 0 ) { /* Write the entry label. */ out << "\tcase " << redAct->actListId+1 << ":\n"; /* Write each action in the list of action items. */ for ( GenActionTable::Iter item = redAct->key; item.lte(); item++ ) ACTION( out, item->value, 0, false, false ); out << "\tbreak;\n"; } } genLineDirective( out ); return out; } std::ostream &FGotoCodeGen::EOF_ACTION_SWITCH() { /* Loop the actions. */ for ( GenActionTableMap::Iter redAct = redFsm->actionMap; redAct.lte(); redAct++ ) { if ( redAct->numEofRefs > 0 ) { /* Write the entry label. */ out << "\tcase " << redAct->actListId+1 << ":\n"; /* Write each action in the list of action items. */ for ( GenActionTable::Iter item = redAct->key; item.lte(); item++ ) ACTION( out, item->value, 0, true, false ); out << "\tbreak;\n"; } } genLineDirective( out ); return out; } std::ostream &FGotoCodeGen::FINISH_CASES() { for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { /* States that are final and have an out action need a case. */ if ( st->eofAction != 0 ) { /* Write the case label. */ out << "\t\tcase " << st->id << ": "; /* Jump to the func. */ out << "goto f" << st->eofAction->actListId << ";\n"; } } return out; } unsigned int FGotoCodeGen::TO_STATE_ACTION( RedStateAp *state ) { int act = 0; if ( state->toStateAction != 0 ) act = state->toStateAction->actListId+1; return act; } unsigned int FGotoCodeGen::FROM_STATE_ACTION( RedStateAp *state ) { int act = 0; if ( state->fromStateAction != 0 ) act = state->fromStateAction->actListId+1; return act; } unsigned int FGotoCodeGen::EOF_ACTION( RedStateAp *state ) { int act = 0; if ( state->eofAction != 0 ) act = state->eofAction->actListId+1; return act; } void FGotoCodeGen::writeData() { if ( redFsm->anyToStateActions() ) { OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActionLoc), TSA() ); TO_STATE_ACTIONS(); CLOSE_ARRAY() << "\n"; } if ( redFsm->anyFromStateActions() ) { OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActionLoc), FSA() ); FROM_STATE_ACTIONS(); CLOSE_ARRAY() << "\n"; } if ( redFsm->anyEofActions() ) { OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActionLoc), EA() ); EOF_ACTIONS(); CLOSE_ARRAY() << "\n"; } STATE_IDS(); } void FGotoCodeGen::writeExec() { testEofUsed = false; outLabelUsed = false; out << " {\n"; if ( redFsm->anyRegCurStateRef() ) out << " int _ps = 0;\n"; if ( redFsm->anyConditions() ) out << " " << WIDE_ALPH_TYPE() << " _widec;\n"; if ( !noEnd ) { testEofUsed = true; out << " if ( " << P() << " == " << PE() << " )\n" " goto _test_eof;\n"; } if ( redFsm->errState != 0 ) { outLabelUsed = true; out << " if ( " << vCS() << " == " << redFsm->errState->id << " )\n" " goto _out;\n"; } out << "_resume:\n"; if ( redFsm->anyFromStateActions() ) { out << " switch ( " << FSA() << "[" << vCS() << "] ) {\n"; FROM_STATE_ACTION_SWITCH(); SWITCH_DEFAULT() << " }\n" "\n"; } out << " switch ( " << vCS() << " ) {\n"; STATE_GOTOS(); SWITCH_DEFAULT() << " }\n" "\n"; TRANSITIONS() << "\n"; if ( redFsm->anyRegActions() ) EXEC_ACTIONS() << "\n"; out << "_again:\n"; if ( redFsm->anyToStateActions() ) { out << " switch ( " << TSA() << "[" << vCS() << "] ) {\n"; TO_STATE_ACTION_SWITCH(); SWITCH_DEFAULT() << " }\n" "\n"; } if ( redFsm->errState != 0 ) { outLabelUsed = true; out << " if ( " << vCS() << " == " << redFsm->errState->id << " )\n" " goto _out;\n"; } if ( !noEnd ) { out << " if ( ++" << P() << " != " << PE() << " )\n" " goto _resume;\n"; } else { out << " " << P() << " += 1;\n" " goto _resume;\n"; } if ( testEofUsed ) out << " _test_eof: {}\n"; if ( redFsm->anyEofTrans() || redFsm->anyEofActions() ) { out << " if ( " << P() << " == " << vEOF() << " )\n" " {\n"; if ( redFsm->anyEofTrans() ) { out << " switch ( " << vCS() << " ) {\n"; for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { if ( st->eofTrans != 0 ) out << " case " << st->id << ": goto tr" << st->eofTrans->id << ";\n"; } SWITCH_DEFAULT() << " }\n"; } if ( redFsm->anyEofActions() ) { out << " switch ( " << EA() << "[" << vCS() << "] ) {\n"; EOF_ACTION_SWITCH(); SWITCH_DEFAULT() << " }\n"; } out << " }\n" "\n"; } if ( outLabelUsed ) out << " _out: {}\n"; out << " }\n"; } ragel-6.8/ragel/pcheck.h0000664000175000017500000000300112106050031012062 00000000000000/* * Copyright 2001, 2002 Adrian Thurston */ /* This file is part of Ragel. * * Ragel is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Ragel is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Ragel; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef _PCHECK_H #define _PCHECK_H class ParamCheck { public: ParamCheck( const char *paramSpec, int argc, const char **argv); bool check(); const char *paramArg; /* The argument to the parameter. */ char parameter; /* The parameter matched. */ enum { match, invalid, noparam } state; const char *argOffset; /* If we are reading params inside an * arg this points to the offset. */ const char *curArg; /* Pointer to the current arg. */ int iCurArg; /* Index to the current arg. */ private: const char *paramSpec; /* Parameter spec supplied by the coder. */ int argc; /* Arguement data from the command line. */ const char **argv; }; #endif ragel-6.8/ragel/mlftable.h0000664000175000017500000000322312106050031012421 00000000000000/* * Copyright 2001-2006 Adrian Thurston * 2004 Erich Ocean * 2005 Alan West */ /* This file is part of Ragel. * * Ragel is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Ragel is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Ragel; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef _MLFTABLE_H #define _MLFTABLE_H #include #include "mltable.h" /* Forwards. */ //struct CodeGenData; /* * OCamlFTabCodeGen */ class OCamlFTabCodeGen : public OCamlTabCodeGen { public: OCamlFTabCodeGen( ostream &out ) : OCamlTabCodeGen(out) {} private: std::ostream &TO_STATE_ACTION_SWITCH(); std::ostream &FROM_STATE_ACTION_SWITCH(); std::ostream &EOF_ACTION_SWITCH(); std::ostream &ACTION_SWITCH(); virtual std::ostream &TO_STATE_ACTION( RedStateAp *state ); virtual std::ostream &FROM_STATE_ACTION( RedStateAp *state ); virtual std::ostream &EOF_ACTION( RedStateAp *state ); virtual std::ostream &TRANS_ACTION( RedTransAp *trans ); virtual void writeData(); virtual void writeExec(); virtual void calcIndexSize(); }; #endif ragel-6.8/ragel/csftable.cpp0000664000175000017500000002403012106050031012750 00000000000000/* * Copyright 2001-2006 Adrian Thurston * 2004 Erich Ocean * 2005 Alan West */ /* This file is part of Ragel. * * Ragel is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Ragel is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Ragel; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "ragel.h" #include "csftable.h" #include "redfsm.h" #include "gendata.h" /* Determine if we should use indicies or not. */ void CSharpFTabCodeGen::calcIndexSize() { int sizeWithInds = 0, sizeWithoutInds = 0; /* Calculate cost of using with indicies. */ for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { int totalIndex = st->outSingle.length() + st->outRange.length() + (st->defTrans == 0 ? 0 : 1); sizeWithInds += arrayTypeSize(redFsm->maxIndex) * totalIndex; } sizeWithInds += arrayTypeSize(redFsm->maxState) * redFsm->transSet.length(); if ( redFsm->anyActions() ) sizeWithInds += arrayTypeSize(redFsm->maxActListId) * redFsm->transSet.length(); /* Calculate the cost of not using indicies. */ for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { int totalIndex = st->outSingle.length() + st->outRange.length() + (st->defTrans == 0 ? 0 : 1); sizeWithoutInds += arrayTypeSize(redFsm->maxState) * totalIndex; if ( redFsm->anyActions() ) sizeWithoutInds += arrayTypeSize(redFsm->maxActListId) * totalIndex; } /* If using indicies reduces the size, use them. */ useIndicies = sizeWithInds < sizeWithoutInds; } std::ostream &CSharpFTabCodeGen::TO_STATE_ACTION( RedStateAp *state ) { int act = 0; if ( state->toStateAction != 0 ) act = state->toStateAction->actListId+1; out << act; return out; } std::ostream &CSharpFTabCodeGen::FROM_STATE_ACTION( RedStateAp *state ) { int act = 0; if ( state->fromStateAction != 0 ) act = state->fromStateAction->actListId+1; out << act; return out; } std::ostream &CSharpFTabCodeGen::EOF_ACTION( RedStateAp *state ) { int act = 0; if ( state->eofAction != 0 ) act = state->eofAction->actListId+1; out << act; return out; } /* Write out the function for a transition. */ std::ostream &CSharpFTabCodeGen::TRANS_ACTION( RedTransAp *trans ) { int action = 0; if ( trans->action != 0 ) action = trans->action->actListId+1; out << action; return out; } /* Write out the function switch. This switch is keyed on the values * of the func index. */ std::ostream &CSharpFTabCodeGen::TO_STATE_ACTION_SWITCH() { /* Loop the actions. */ for ( GenActionTableMap::Iter redAct = redFsm->actionMap; redAct.lte(); redAct++ ) { if ( redAct->numToStateRefs > 0 ) { /* Write the entry label. */ out << "\tcase " << redAct->actListId+1 << ":\n"; /* Write each action in the list of action items. */ for ( GenActionTable::Iter item = redAct->key; item.lte(); item++ ) ACTION( out, item->value, 0, false ); out << "\tbreak;\n"; } } genLineDirective( out ); return out; } /* Write out the function switch. This switch is keyed on the values * of the func index. */ std::ostream &CSharpFTabCodeGen::FROM_STATE_ACTION_SWITCH() { /* Loop the actions. */ for ( GenActionTableMap::Iter redAct = redFsm->actionMap; redAct.lte(); redAct++ ) { if ( redAct->numFromStateRefs > 0 ) { /* Write the entry label. */ out << "\tcase " << redAct->actListId+1 << ":\n"; /* Write each action in the list of action items. */ for ( GenActionTable::Iter item = redAct->key; item.lte(); item++ ) ACTION( out, item->value, 0, false ); out << "\tbreak;\n"; } } genLineDirective( out ); return out; } std::ostream &CSharpFTabCodeGen::EOF_ACTION_SWITCH() { /* Loop the actions. */ for ( GenActionTableMap::Iter redAct = redFsm->actionMap; redAct.lte(); redAct++ ) { if ( redAct->numEofRefs > 0 ) { /* Write the entry label. */ out << "\tcase " << redAct->actListId+1 << ":\n"; /* Write each action in the list of action items. */ for ( GenActionTable::Iter item = redAct->key; item.lte(); item++ ) ACTION( out, item->value, 0, true ); out << "\tbreak;\n"; } } genLineDirective( out ); return out; } /* Write out the function switch. This switch is keyed on the values * of the func index. */ std::ostream &CSharpFTabCodeGen::ACTION_SWITCH() { /* Loop the actions. */ for ( GenActionTableMap::Iter redAct = redFsm->actionMap; redAct.lte(); redAct++ ) { if ( redAct->numTransRefs > 0 ) { /* Write the entry label. */ out << "\tcase " << redAct->actListId+1 << ":\n"; /* Write each action in the list of action items. */ for ( GenActionTable::Iter item = redAct->key; item.lte(); item++ ) ACTION( out, item->value, 0, false ); out << "\tbreak;\n"; } } genLineDirective( out ); return out; } void CSharpFTabCodeGen::writeData() { if ( redFsm->anyConditions() ) { OPEN_ARRAY( ARRAY_TYPE(redFsm->maxCondOffset), CO() ); COND_OFFSETS(); CLOSE_ARRAY() << "\n"; OPEN_ARRAY( ARRAY_TYPE(redFsm->maxCondLen), CL() ); COND_LENS(); CLOSE_ARRAY() << "\n"; OPEN_ARRAY( WIDE_ALPH_TYPE(), CK() ); COND_KEYS(); CLOSE_ARRAY() << "\n"; OPEN_ARRAY( ARRAY_TYPE(redFsm->maxCondSpaceId), C() ); COND_SPACES(); CLOSE_ARRAY() << "\n"; } OPEN_ARRAY( ARRAY_TYPE(redFsm->maxKeyOffset), KO() ); KEY_OFFSETS(); CLOSE_ARRAY() << "\n"; OPEN_ARRAY( WIDE_ALPH_TYPE(), K() ); KEYS(); CLOSE_ARRAY() << "\n"; OPEN_ARRAY( ARRAY_TYPE(redFsm->maxSingleLen), SL() ); SINGLE_LENS(); CLOSE_ARRAY() << "\n"; OPEN_ARRAY( ARRAY_TYPE(redFsm->maxRangeLen), RL() ); RANGE_LENS(); CLOSE_ARRAY() << "\n"; OPEN_ARRAY( ARRAY_TYPE(redFsm->maxIndexOffset), IO() ); INDEX_OFFSETS(); CLOSE_ARRAY() << "\n"; if ( useIndicies ) { OPEN_ARRAY( ARRAY_TYPE(redFsm->maxIndex), I() ); INDICIES(); CLOSE_ARRAY() << "\n"; OPEN_ARRAY( ARRAY_TYPE(redFsm->maxState), TT() ); TRANS_TARGS_WI(); CLOSE_ARRAY() << "\n"; if ( redFsm->anyActions() ) { OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActListId), TA() ); TRANS_ACTIONS_WI(); CLOSE_ARRAY() << "\n"; } } else { OPEN_ARRAY( ARRAY_TYPE(redFsm->maxState), TT() ); TRANS_TARGS(); CLOSE_ARRAY() << "\n"; if ( redFsm->anyActions() ) { OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActListId), TA() ); TRANS_ACTIONS(); CLOSE_ARRAY() << "\n"; } } if ( redFsm->anyToStateActions() ) { OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActionLoc), TSA() ); TO_STATE_ACTIONS(); CLOSE_ARRAY() << "\n"; } if ( redFsm->anyFromStateActions() ) { OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActionLoc), FSA() ); FROM_STATE_ACTIONS(); CLOSE_ARRAY() << "\n"; } if ( redFsm->anyEofActions() ) { OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActListId), EA() ); EOF_ACTIONS(); CLOSE_ARRAY() << "\n"; } if ( redFsm->anyEofTrans() ) { OPEN_ARRAY( ARRAY_TYPE(redFsm->maxIndexOffset+1), ET() ); EOF_TRANS(); CLOSE_ARRAY() << "\n"; } STATE_IDS(); } void CSharpFTabCodeGen::writeExec() { testEofUsed = false; outLabelUsed = false; initVarTypes(); out << " {\n" " " << klenType << " _klen"; if ( redFsm->anyRegCurStateRef() ) out << ", _ps"; out << ";\n" " " << keysType << " _keys;\n" " " << transType << " _trans;\n"; if ( redFsm->anyConditions() ) out << " " << WIDE_ALPH_TYPE() << " _widec;\n"; out << "\n"; if ( !noEnd ) { testEofUsed = true; out << " if ( " << P() << " == " << PE() << " )\n" " goto _test_eof;\n"; } if ( redFsm->errState != 0 ) { outLabelUsed = true; out << " if ( " << vCS() << " == " << redFsm->errState->id << " )\n" " goto _out;\n"; } out << "_resume:\n"; if ( redFsm->anyFromStateActions() ) { out << " switch ( " << FSA() << "[" << vCS() << "] ) {\n"; FROM_STATE_ACTION_SWITCH(); SWITCH_DEFAULT() << " }\n" "\n"; } if ( redFsm->anyConditions() ) COND_TRANSLATE(); LOCATE_TRANS(); out << "_match:\n"; if ( useIndicies ) out << " _trans = " << CAST(transType) << I() << "[_trans];\n"; if ( redFsm->anyEofTrans() ) out << "_eof_trans:\n"; if ( redFsm->anyRegCurStateRef() ) out << " _ps = " << vCS() << ";\n"; out << " " << vCS() << " = " << TT() << "[_trans];\n" "\n"; if ( redFsm->anyRegActions() ) { out << " if ( " << TA() << "[_trans] == 0 )\n" " goto _again;\n" "\n" " switch ( " << TA() << "[_trans] ) {\n"; ACTION_SWITCH(); SWITCH_DEFAULT() << " }\n" "\n"; } if ( redFsm->anyRegActions() || redFsm->anyActionGotos() || redFsm->anyActionCalls() || redFsm->anyActionRets() ) out << "_again:\n"; if ( redFsm->anyToStateActions() ) { out << " switch ( " << TSA() << "[" << vCS() << "] ) {\n"; TO_STATE_ACTION_SWITCH(); SWITCH_DEFAULT() << " }\n" "\n"; } if ( redFsm->errState != 0 ) { outLabelUsed = true; out << " if ( " << vCS() << " == " << redFsm->errState->id << " )\n" " goto _out;\n"; } if ( !noEnd ) { out << " if ( ++" << P() << " != " << PE() << " )\n" " goto _resume;\n"; } else { out << " " << P() << " += 1;\n" " goto _resume;\n"; } if ( testEofUsed ) out << " _test_eof: {}\n"; if ( redFsm->anyEofTrans() || redFsm->anyEofActions() ) { out << " if ( " << P() << " == " << vEOF() << " )\n" " {\n"; if ( redFsm->anyEofTrans() ) { out << " if ( " << ET() << "[" << vCS() << "] > 0 ) {\n" " _trans = " << CAST(transType) << " (" << ET() << "[" << vCS() << "] - 1);\n" " goto _eof_trans;\n" " }\n"; } if ( redFsm->anyEofActions() ) { out << " switch ( " << EA() << "[" << vCS() << "] ) {\n"; EOF_ACTION_SWITCH(); SWITCH_DEFAULT() << " }\n"; } out << " }\n" "\n"; } if ( outLabelUsed ) out << " _out: {}\n"; out << " }\n"; } ragel-6.8/ragel/rubyflat.h0000664000175000017500000000533612106050031012472 00000000000000/* * 2007 Victor Hugo Borja * Copyright 2001-2007 Adrian Thurston */ /* This file is part of Ragel. * * Ragel is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Ragel is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Ragel; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef _RUBY_FLATCODEGEN_H #define _RUBY_FLATCODEGEN_H #include #include "rubycodegen.h" using std::string; using std::ostream; /* * FlatCodeGen */ class RubyFlatCodeGen : public RubyCodeGen { public: RubyFlatCodeGen( ostream &out ) : RubyCodeGen(out) {}; virtual ~RubyFlatCodeGen() {} protected: std::ostream &TO_STATE_ACTION_SWITCH(); std::ostream &FROM_STATE_ACTION_SWITCH(); std::ostream &EOF_ACTION_SWITCH(); std::ostream &ACTION_SWITCH(); std::ostream &KEYS(); std::ostream &INDICIES(); std::ostream &FLAT_INDEX_OFFSET(); std::ostream &KEY_SPANS(); std::ostream &TO_STATE_ACTIONS(); std::ostream &FROM_STATE_ACTIONS(); std::ostream &EOF_ACTIONS(); std::ostream &EOF_TRANS(); std::ostream &TRANS_TARGS(); std::ostream &TRANS_ACTIONS(); void LOCATE_TRANS(); std::ostream &COND_INDEX_OFFSET(); void COND_TRANSLATE(); std::ostream &CONDS(); std::ostream &COND_KEYS(); std::ostream &COND_KEY_SPANS(); void GOTO( ostream &ret, int gotoDest, bool inFinish ); void CALL( ostream &ret, int callDest, int targState, bool inFinish ); void NEXT( ostream &ret, int nextDest, bool inFinish ); void GOTO_EXPR( ostream &ret, GenInlineItem *ilItem, bool inFinish ); void NEXT_EXPR( ostream &ret, GenInlineItem *ilItem, bool inFinish ); void CALL_EXPR( ostream &ret, GenInlineItem *ilItem, int targState, bool inFinish ); void CURS( ostream &ret, bool inFinish ); void TARGS( ostream &ret, bool inFinish, int targState ); void RET( ostream &ret, bool inFinish ); void BREAK( ostream &ret, int targState ); virtual int TO_STATE_ACTION( RedStateAp *state ); virtual int FROM_STATE_ACTION( RedStateAp *state ); virtual int EOF_ACTION( RedStateAp *state ); virtual int TRANS_ACTION( RedTransAp *trans ); virtual void writeData(); virtual void writeExec(); }; #endif /* * Local Variables: * mode: c++ * indent-tabs-mode: 1 * c-file-style: "bsd" * End: */ ragel-6.8/ragel/gotable.cpp0000664000175000017500000006164712106050031012621 00000000000000/* * Copyright 2001-2006 Adrian Thurston * 2004 Erich Ocean * 2005 Alan West */ /* This file is part of Ragel. * * Ragel is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Ragel is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Ragel; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include "ragel.h" #include "gotable.h" #include "redfsm.h" #include "gendata.h" using std::endl; /* Determine if we should use indicies or not. */ void GoTabCodeGen::calcIndexSize() { int sizeWithInds = 0, sizeWithoutInds = 0; /* Calculate cost of using with indicies. */ for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { int totalIndex = st->outSingle.length() + st->outRange.length() + (st->defTrans == 0 ? 0 : 1); sizeWithInds += arrayTypeSize(redFsm->maxIndex) * totalIndex; } sizeWithInds += arrayTypeSize(redFsm->maxState) * redFsm->transSet.length(); if ( redFsm->anyActions() ) sizeWithInds += arrayTypeSize(redFsm->maxActionLoc) * redFsm->transSet.length(); /* Calculate the cost of not using indicies. */ for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { int totalIndex = st->outSingle.length() + st->outRange.length() + (st->defTrans == 0 ? 0 : 1); sizeWithoutInds += arrayTypeSize(redFsm->maxState) * totalIndex; if ( redFsm->anyActions() ) sizeWithoutInds += arrayTypeSize(redFsm->maxActionLoc) * totalIndex; } /* If using indicies reduces the size, use them. */ useIndicies = sizeWithInds < sizeWithoutInds; } std::ostream &GoTabCodeGen::TO_STATE_ACTION( RedStateAp *state ) { int act = 0; if ( state->toStateAction != 0 ) act = state->toStateAction->location+1; out << act; return out; } std::ostream &GoTabCodeGen::FROM_STATE_ACTION( RedStateAp *state ) { int act = 0; if ( state->fromStateAction != 0 ) act = state->fromStateAction->location+1; out << act; return out; } std::ostream &GoTabCodeGen::EOF_ACTION( RedStateAp *state ) { int act = 0; if ( state->eofAction != 0 ) act = state->eofAction->location+1; out << act; return out; } std::ostream &GoTabCodeGen::TRANS_ACTION( RedTransAp *trans ) { /* If there are actions, emit them. Otherwise emit zero. */ int act = 0; if ( trans->action != 0 ) act = trans->action->location+1; out << act; return out; } std::ostream &GoTabCodeGen::TO_STATE_ACTION_SWITCH( int level ) { /* Walk the list of functions, printing the cases. */ for ( GenActionList::Iter act = actionList; act.lte(); act++ ) { /* Write out referenced actions. */ if ( act->numToStateRefs > 0 ) { /* Write the case label, the action and the case break. */ out << TABS(level) << "case " << act->actionId << ":" << endl; ACTION( out, act, 0, false, false ); } } genLineDirective( out ); return out; } std::ostream &GoTabCodeGen::FROM_STATE_ACTION_SWITCH( int level ) { /* Walk the list of functions, printing the cases. */ for ( GenActionList::Iter act = actionList; act.lte(); act++ ) { /* Write out referenced actions. */ if ( act->numFromStateRefs > 0 ) { /* Write the case label, the action and the case break. */ out << TABS(level) << "case " << act->actionId << ":" << endl; ACTION( out, act, 0, false, false ); } } genLineDirective( out ); return out; } std::ostream &GoTabCodeGen::EOF_ACTION_SWITCH( int level ) { /* Walk the list of functions, printing the cases. */ for ( GenActionList::Iter act = actionList; act.lte(); act++ ) { /* Write out referenced actions. */ if ( act->numEofRefs > 0 ) { /* Write the case label, the action and the case break. */ out << TABS(level) << "case " << act->actionId << ":" << endl; ACTION( out, act, 0, true, false ); } } genLineDirective(out); return out; } std::ostream &GoTabCodeGen::ACTION_SWITCH( int level ) { /* Walk the list of functions, printing the cases. */ for ( GenActionList::Iter act = actionList; act.lte(); act++ ) { /* Write out referenced actions. */ if ( act->numTransRefs > 0 ) { /* Write the case label, the action and the case break. */ out << TABS(level) << "case " << act->actionId << ":" << endl; ACTION( out, act, 0, false, false ); } } genLineDirective(out); return out; } std::ostream &GoTabCodeGen::COND_OFFSETS() { out << " "; int totalStateNum = 0, curKeyOffset = 0; for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { /* Write the key offset. */ out << curKeyOffset; out << ", "; if ( !st.last() ) { if ( ++totalStateNum % IALL == 0 ) out << endl << " "; } /* Move the key offset ahead. */ curKeyOffset += st->stateCondList.length(); } out << endl; return out; } std::ostream &GoTabCodeGen::KEY_OFFSETS() { out << " "; int totalStateNum = 0, curKeyOffset = 0; for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { /* Write the key offset. */ out << curKeyOffset; out << ", "; if ( !st.last() ) { if ( ++totalStateNum % IALL == 0 ) out << endl << " "; } /* Move the key offset ahead. */ curKeyOffset += st->outSingle.length() + st->outRange.length()*2; } out << endl; return out; } std::ostream &GoTabCodeGen::INDEX_OFFSETS() { out << " "; int totalStateNum = 0, curIndOffset = 0; for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { /* Write the index offset. */ out << curIndOffset; out << ", "; if ( !st.last() ) { if ( ++totalStateNum % IALL == 0 ) out << endl << " "; } /* Move the index offset ahead. */ curIndOffset += st->outSingle.length() + st->outRange.length(); if ( st->defTrans != 0 ) curIndOffset += 1; } out << endl; return out; } std::ostream &GoTabCodeGen::COND_LENS() { out << " "; int totalStateNum = 0; for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { /* Write singles length. */ out << st->stateCondList.length(); out << ", "; if ( !st.last() ) { if ( ++totalStateNum % IALL == 0 ) out << endl << " "; } } out << endl; return out; } std::ostream &GoTabCodeGen::SINGLE_LENS() { out << " "; int totalStateNum = 0; for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { /* Write singles length. */ out << st->outSingle.length(); out << ", "; if ( !st.last() ) { if ( ++totalStateNum % IALL == 0 ) out << endl << " "; } } out << endl; return out; } std::ostream &GoTabCodeGen::RANGE_LENS() { out << " "; int totalStateNum = 0; for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { /* Emit length of range index. */ out << st->outRange.length(); out << ", "; if ( !st.last() ) { if ( ++totalStateNum % IALL == 0 ) out << endl << " "; } } out << endl; return out; } std::ostream &GoTabCodeGen::TO_STATE_ACTIONS() { out << " "; int totalStateNum = 0; for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { /* Write any eof action. */ TO_STATE_ACTION(st); out << ", "; if ( !st.last() ) { if ( ++totalStateNum % IALL == 0 ) out << endl << " "; } } out << endl; return out; } std::ostream &GoTabCodeGen::FROM_STATE_ACTIONS() { out << " "; int totalStateNum = 0; for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { /* Write any eof action. */ FROM_STATE_ACTION(st); out << ", "; if ( !st.last() ) { if ( ++totalStateNum % IALL == 0 ) out << endl << " "; } } out << endl; return out; } std::ostream &GoTabCodeGen::EOF_ACTIONS() { out << " "; int totalStateNum = 0; for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { /* Write any eof action. */ EOF_ACTION(st); out << ", "; if ( !st.last() ) { if ( ++totalStateNum % IALL == 0 ) out << endl << " "; } } out << endl; return out; } std::ostream &GoTabCodeGen::EOF_TRANS() { out << " "; int totalStateNum = 0; for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { /* Write any eof action. */ long trans = 0; if ( st->eofTrans != 0 ) { assert( st->eofTrans->pos >= 0 ); trans = st->eofTrans->pos+1; } out << trans; out << ", "; if ( !st.last() ) { if ( ++totalStateNum % IALL == 0 ) out << endl << " "; } } out << endl; return out; } std::ostream &GoTabCodeGen::COND_KEYS() { out << " "; int totalTrans = 0; for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { /* Loop the state's transitions. */ for ( GenStateCondList::Iter sc = st->stateCondList; sc.lte(); sc++ ) { /* Lower key. */ out << KEY( sc->lowKey ) << ", "; if ( ++totalTrans % IALL == 0 ) out << endl << " "; /* Upper key. */ out << KEY( sc->highKey ) << ", "; if ( ++totalTrans % IALL == 0 ) out << endl << " "; } } out << endl; return out; } std::ostream &GoTabCodeGen::COND_SPACES() { out << " "; int totalTrans = 0; for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { /* Loop the state's transitions. */ for ( GenStateCondList::Iter sc = st->stateCondList; sc.lte(); sc++ ) { /* Cond Space id. */ out << sc->condSpace->condSpaceId << ", "; if ( ++totalTrans % IALL == 0 ) out << endl << " "; } } out << endl; return out; } std::ostream &GoTabCodeGen::KEYS() { out << " "; int totalTrans = 0; for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { /* Loop the singles. */ for ( RedTransList::Iter stel = st->outSingle; stel.lte(); stel++ ) { out << KEY( stel->lowKey ) << ", "; if ( ++totalTrans % IALL == 0 ) out << endl << " "; } /* Loop the state's transitions. */ for ( RedTransList::Iter rtel = st->outRange; rtel.lte(); rtel++ ) { /* Lower key. */ out << KEY( rtel->lowKey ) << ", "; if ( ++totalTrans % IALL == 0 ) out << endl << " "; /* Upper key. */ out << KEY( rtel->highKey ) << ", "; if ( ++totalTrans % IALL == 0 ) out << endl << " "; } } out << endl; return out; } std::ostream &GoTabCodeGen::INDICIES() { out << " "; int totalTrans = 0; for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { /* Walk the singles. */ for ( RedTransList::Iter stel = st->outSingle; stel.lte(); stel++ ) { out << stel->value->id << ", "; if ( ++totalTrans % IALL == 0 ) out << endl << " "; } /* Walk the ranges. */ for ( RedTransList::Iter rtel = st->outRange; rtel.lte(); rtel++ ) { out << rtel->value->id << ", "; if ( ++totalTrans % IALL == 0 ) out << endl << " "; } /* The state's default index goes next. */ if ( st->defTrans != 0 ) { out << st->defTrans->id << ", "; if ( ++totalTrans % IALL == 0 ) out << endl << " "; } } out << endl; return out; } std::ostream &GoTabCodeGen::TRANS_TARGS() { out << " "; int totalTrans = 0; for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { /* Walk the singles. */ for ( RedTransList::Iter stel = st->outSingle; stel.lte(); stel++ ) { RedTransAp *trans = stel->value; out << trans->targ->id << ", "; if ( ++totalTrans % IALL == 0 ) out << endl << " "; } /* Walk the ranges. */ for ( RedTransList::Iter rtel = st->outRange; rtel.lte(); rtel++ ) { RedTransAp *trans = rtel->value; out << trans->targ->id << ", "; if ( ++totalTrans % IALL == 0 ) out << endl << " "; } /* The state's default target state. */ if ( st->defTrans != 0 ) { RedTransAp *trans = st->defTrans; out << trans->targ->id << ", "; if ( ++totalTrans % IALL == 0 ) out << endl << " "; } } /* Add any eof transitions that have not yet been written out above. */ for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { if ( st->eofTrans != 0 ) { RedTransAp *trans = st->eofTrans; trans->pos = totalTrans; out << trans->targ->id << ", "; if ( ++totalTrans % IALL == 0 ) out << endl << " "; } } out << endl; return out; } std::ostream &GoTabCodeGen::TRANS_ACTIONS() { out << " "; int totalTrans = 0; for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { /* Walk the singles. */ for ( RedTransList::Iter stel = st->outSingle; stel.lte(); stel++ ) { RedTransAp *trans = stel->value; TRANS_ACTION( trans ) << ", "; if ( ++totalTrans % IALL == 0 ) out << endl << " "; } /* Walk the ranges. */ for ( RedTransList::Iter rtel = st->outRange; rtel.lte(); rtel++ ) { RedTransAp *trans = rtel->value; TRANS_ACTION( trans ) << ", "; if ( ++totalTrans % IALL == 0 ) out << endl << " "; } /* The state's default index goes next. */ if ( st->defTrans != 0 ) { RedTransAp *trans = st->defTrans; TRANS_ACTION( trans ) << ", "; if ( ++totalTrans % IALL == 0 ) out << endl << " "; } } /* Add any eof transitions that have not yet been written out above. */ for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { if ( st->eofTrans != 0 ) { RedTransAp *trans = st->eofTrans; TRANS_ACTION( trans ) << ", "; if ( ++totalTrans % IALL == 0 ) out << endl << " "; } } out << endl; return out; } std::ostream &GoTabCodeGen::TRANS_TARGS_WI() { /* Transitions must be written ordered by their id. */ RedTransAp **transPtrs = new RedTransAp*[redFsm->transSet.length()]; for ( TransApSet::Iter trans = redFsm->transSet; trans.lte(); trans++ ) transPtrs[trans->id] = trans; /* Keep a count of the num of items in the array written. */ out << " "; int totalStates = 0; for ( int t = 0; t < redFsm->transSet.length(); t++ ) { /* Record the position, need this for eofTrans. */ RedTransAp *trans = transPtrs[t]; trans->pos = t; /* Write out the target state. */ out << trans->targ->id << ", "; if ( t < redFsm->transSet.length()-1 ) { if ( ++totalStates % IALL == 0 ) out << endl << " "; } } out << endl; delete[] transPtrs; return out; } std::ostream &GoTabCodeGen::TRANS_ACTIONS_WI() { /* Transitions must be written ordered by their id. */ RedTransAp **transPtrs = new RedTransAp*[redFsm->transSet.length()]; for ( TransApSet::Iter trans = redFsm->transSet; trans.lte(); trans++ ) transPtrs[trans->id] = trans; /* Keep a count of the num of items in the array written. */ out << " "; int totalAct = 0; for ( int t = 0; t < redFsm->transSet.length(); t++ ) { /* Write the function for the transition. */ RedTransAp *trans = transPtrs[t]; TRANS_ACTION( trans ); out << ", "; if ( t < redFsm->transSet.length()-1 ) { if ( ++totalAct % IALL == 0 ) out << endl << " "; } } out << endl; delete[] transPtrs; return out; } void GoTabCodeGen::writeData() { /* If there are any transtion functions then output the array. If there * are none, don't bother emitting an empty array that won't be used. */ if ( redFsm->anyActions() ) { OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActArrItem), A() ); ACTIONS_ARRAY(); CLOSE_ARRAY() << endl; } if ( redFsm->anyConditions() ) { OPEN_ARRAY( ARRAY_TYPE(redFsm->maxCondOffset), CO() ); COND_OFFSETS(); CLOSE_ARRAY() << endl; OPEN_ARRAY( ARRAY_TYPE(redFsm->maxCondLen), CL() ); COND_LENS(); CLOSE_ARRAY() << endl; OPEN_ARRAY( WIDE_ALPH_TYPE(), CK() ); COND_KEYS(); CLOSE_ARRAY() << endl; OPEN_ARRAY( ARRAY_TYPE(redFsm->maxCondSpaceId), C() ); COND_SPACES(); CLOSE_ARRAY() << endl; } OPEN_ARRAY( ARRAY_TYPE(redFsm->maxKeyOffset), KO() ); KEY_OFFSETS(); CLOSE_ARRAY() << endl; OPEN_ARRAY( WIDE_ALPH_TYPE(), K() ); KEYS(); CLOSE_ARRAY() << endl; OPEN_ARRAY( ARRAY_TYPE(redFsm->maxSingleLen), SL() ); SINGLE_LENS(); CLOSE_ARRAY() << endl; OPEN_ARRAY( ARRAY_TYPE(redFsm->maxRangeLen), RL() ); RANGE_LENS(); CLOSE_ARRAY() << endl; OPEN_ARRAY( ARRAY_TYPE(redFsm->maxIndexOffset), IO() ); INDEX_OFFSETS(); CLOSE_ARRAY() << endl; if ( useIndicies ) { OPEN_ARRAY( ARRAY_TYPE(redFsm->maxIndex), I() ); INDICIES(); CLOSE_ARRAY() << endl; OPEN_ARRAY( ARRAY_TYPE(redFsm->maxState), TT() ); TRANS_TARGS_WI(); CLOSE_ARRAY() << endl; if ( redFsm->anyActions() ) { OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActionLoc), TA() ); TRANS_ACTIONS_WI(); CLOSE_ARRAY() << endl; } } else { OPEN_ARRAY( ARRAY_TYPE(redFsm->maxState), TT() ); TRANS_TARGS(); CLOSE_ARRAY() << endl; if ( redFsm->anyActions() ) { OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActionLoc), TA() ); TRANS_ACTIONS(); CLOSE_ARRAY() << endl; } } if ( redFsm->anyToStateActions() ) { OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActionLoc), TSA() ); TO_STATE_ACTIONS(); CLOSE_ARRAY() << endl; } if ( redFsm->anyFromStateActions() ) { OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActionLoc), FSA() ); FROM_STATE_ACTIONS(); CLOSE_ARRAY() << endl; } if ( redFsm->anyEofActions() ) { OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActionLoc), EA() ); EOF_ACTIONS(); CLOSE_ARRAY() << endl; } if ( redFsm->anyEofTrans() ) { OPEN_ARRAY( ARRAY_TYPE(redFsm->maxIndexOffset+1), ET() ); EOF_TRANS(); CLOSE_ARRAY() << endl; } STATE_IDS(); } void GoTabCodeGen::LOCATE_TRANS() { out << " _keys = " << CAST(INT(), KO() + "[" + vCS() + "]") << endl << " _trans = " << CAST(INT(), IO() + "[" + vCS() + "]") << endl << endl << " _klen = " << CAST(INT(), SL() + "[" + vCS() + "]") << endl << " if _klen > 0 {" << endl << " _lower := " << CAST(INT(), "_keys") << endl << " var _mid " << INT() << endl << " _upper := " << CAST(INT(), "_keys + _klen - 1") << endl << " for {" << endl << " if _upper < _lower {" << endl << " break" << endl << " }" << endl << endl << " _mid = _lower + ((_upper - _lower) >> 1)" << endl << " switch {" << endl << " case " << GET_WIDE_KEY() << " < " << K() << "[_mid]" << ":" << endl << " _upper = _mid - 1" << endl << " case " << GET_WIDE_KEY() << " > " << K() << "[_mid]" << ":" << endl << " _lower = _mid + 1" << endl << " default:" << endl << " _trans += " << CAST(INT(), "_mid - " + CAST(INT(), "_keys")) << endl << " goto _match" << endl << " }" << endl << " }" << endl << " _keys += _klen" << endl << " _trans += _klen" << endl << " }" << endl << endl << " _klen = " << CAST(INT(), RL() + "[" + vCS() + "]") << endl << " if _klen > 0 {" << endl << " _lower := " << CAST(INT(), "_keys") << endl << " var _mid " << INT() << endl << " _upper := " << CAST(INT(), "_keys + (_klen << 1) - 2") << endl << " for {" << endl << " if _upper < _lower {" << endl << " break" << endl << " }" << endl << endl << " _mid = _lower + (((_upper - _lower) >> 1) & ^1)" << endl << " switch {" << endl << " case " << GET_WIDE_KEY() << " < " << K() << "[_mid]" << ":" << endl << " _upper = _mid - 2" << endl << " case " << GET_WIDE_KEY() << " > " << K() << "[_mid + 1]" << ":" << endl << " _lower = _mid + 2" << endl << " default:" << endl << " _trans += " << CAST(INT(), "(_mid - " + CAST(INT(), "_keys") + ") >> 1") << endl << " goto _match" << endl << " }" << endl << " }" << endl << " _trans += _klen" << endl << " }" << endl << endl; } void GoTabCodeGen::COND_TRANSLATE() { out << " _widec = " << CAST(WIDE_ALPH_TYPE(), GET_KEY()) << endl << " _klen = " << CAST(INT(), CL() + "[" + vCS() + "]") << endl << " _keys = " << CAST(INT(), CO() + "[" + vCS() + "] * 2") << endl << " if _klen > 0 {" << endl << " _lower := " << CAST(INT(), "_keys") << endl << " var _mid " << INT() << endl << " _upper := " << CAST(INT(), "_keys + (_klen << 1) - 2") << endl << " COND_LOOP:" << endl << " for {" << endl << " if _upper < _lower {" << endl << " break" << endl << " }" << endl << endl << " _mid = _lower + (((_upper - _lower) >> 1) & ^1)" << endl << " switch {" << endl << " case " << GET_WIDE_KEY() << " < " << CAST(WIDE_ALPH_TYPE(), CK() + "[_mid]") << ":" << endl << " _upper = _mid - 2" << endl << " case " << GET_WIDE_KEY() << " > " << CAST(WIDE_ALPH_TYPE(), CK() + "[_mid + 1]") << ":" << endl << " _lower = _mid + 2" << endl << " default:" << endl << " switch " << C() << "[" << CAST(INT(), CO() + "[" + vCS() + "]") << " + ((_mid - _keys)>>1)] {" << endl; for ( CondSpaceList::Iter csi = condSpaceList; csi.lte(); csi++ ) { GenCondSpace *condSpace = csi; out << TABS(4) << "case " << condSpace->condSpaceId << ":" << endl; out << TABS(5) << "_widec = " << KEY(condSpace->baseKey) << " + (" << CAST(WIDE_ALPH_TYPE(), GET_KEY()) << " - " << KEY(keyOps->minKey) << ")" << endl; for ( GenCondSet::Iter csi = condSpace->condSet; csi.lte(); csi++ ) { out << TABS(5) << "if "; CONDITION( out, *csi ); Size condValOffset = ((1 << csi.pos()) * keyOps->alphSize()); out << " {" << endl << TABS(6) << "_widec += " << condValOffset << endl << TABS(5) << "}" << endl; } } out << " }" << endl << " break COND_LOOP" << endl << " }" << endl << " }" << endl << " }" << endl << endl; } void GoTabCodeGen::writeExec() { testEofUsed = false; outLabelUsed = false; out << " {" << endl << " var _klen " << INT() << endl; if ( redFsm->anyRegCurStateRef() ) out << " var _ps " << INT() << endl; out << " var _trans " << INT() << endl; if ( redFsm->anyConditions() ) out << " var _widec " << WIDE_ALPH_TYPE() << endl; if ( redFsm->anyToStateActions() || redFsm->anyRegActions() || redFsm->anyFromStateActions() ) { out << " var _acts " << INT() << endl << " var _nacts " << UINT() << endl; } out << " var _keys " << INT() << endl; if ( !noEnd ) { testEofUsed = true; out << " if " << P() << " == " << PE() << " {" << endl << " goto _test_eof" << endl << " }" << endl; } if ( redFsm->errState != 0 ) { outLabelUsed = true; out << " if " << vCS() << " == " << redFsm->errState->id << " {" << endl << " goto _out" << endl << " }" << endl; } out << "_resume:" << endl; if ( redFsm->anyFromStateActions() ) { out << " _acts = " << CAST(INT(), FSA() + "[" + vCS() + "]") << endl << " _nacts = " << CAST(UINT(), A() + "[_acts]") << "; _acts++" << endl << " for ; _nacts > 0; _nacts-- {" << endl << " _acts++" << endl << " switch " << A() << "[_acts - 1]" << " {" << endl; FROM_STATE_ACTION_SWITCH(2); out << " }" << endl << " }" << endl << endl; } if ( redFsm->anyConditions() ) COND_TRANSLATE(); LOCATE_TRANS(); out << "_match:" << endl; if ( useIndicies ) out << " _trans = " << CAST(INT(), I() + "[_trans]") << endl; if ( redFsm->anyEofTrans() ) out << "_eof_trans:" << endl; if ( redFsm->anyRegCurStateRef() ) out << " _ps = " << vCS() << endl; out << " " << vCS() << " = " << CAST(INT(), TT() + "[_trans]") << endl << endl; if ( redFsm->anyRegActions() ) { out << " if " << TA() << "[_trans] == 0 {" << endl << " goto _again" << endl << " }" << endl << endl << " _acts = " << CAST(INT(), TA() + "[_trans]") << endl << " _nacts = " << CAST(UINT(), A() + "[_acts]") << "; _acts++" << endl << " for ; _nacts > 0; _nacts-- {" << endl << " _acts++" << endl << " switch " << A() << "[_acts-1]" << " {" << endl; ACTION_SWITCH(2); out << " }" << endl << " }" << endl << endl; } if ( redFsm->anyRegActions() || redFsm->anyActionGotos() || redFsm->anyActionCalls() || redFsm->anyActionRets() ) out << "_again:" << endl; if ( redFsm->anyToStateActions() ) { out << " _acts = " << CAST(INT(), TSA() + "[" + vCS() + "]") << endl << " _nacts = " << CAST(UINT(), A() + "[_acts]") << "; _acts++" << endl << " for ; _nacts > 0; _nacts-- {" << endl << " _acts++" << endl << " switch " << A() << "[_acts-1] {" << endl; TO_STATE_ACTION_SWITCH(2); out << " }" << endl << " }" << endl << endl; } if ( redFsm->errState != 0 ) { outLabelUsed = true; out << " if " << vCS() << " == " << redFsm->errState->id << " {" << endl << " goto _out" << endl << " }" << endl; } if ( !noEnd ) { out << " " << P() << "++" << endl << " if " << P() << " != " << PE() << " {" << endl << " goto _resume" << endl << " }" << endl; } else { out << " " << P() << "++" << endl << " goto _resume" << endl; } if ( testEofUsed ) out << " _test_eof: {}" << endl; if ( redFsm->anyEofTrans() || redFsm->anyEofActions() ) { out << " if " << P() << " == " << vEOF() << " {" << endl; if ( redFsm->anyEofTrans() ) { out << " if " << ET() << "[" << vCS() << "] > 0 {" << endl << " _trans = " << CAST(INT(), ET() + "[" + vCS() + "] - 1") << endl << " goto _eof_trans" << endl << " }" << endl; } if ( redFsm->anyEofActions() ) { out << " __acts := " << EA() << "[" << vCS() << "]" << endl << " __nacts := " << CAST(UINT(), A() + "[__acts]") << "; __acts++" << endl << " for ; __nacts > 0; __nacts-- {" << endl << " __acts++" << endl << " switch " << A() << "[__acts-1] {" << endl; EOF_ACTION_SWITCH(3); out << " }" << endl << " }" << endl; } out << " }" << endl << endl; } if ( outLabelUsed ) out << " _out: {}" << endl; out << " }" << endl; } ragel-6.8/ragel/cdftable.cpp0000664000175000017500000002370412106050031012740 00000000000000/* * Copyright 2001-2006 Adrian Thurston * 2004 Erich Ocean * 2005 Alan West */ /* This file is part of Ragel. * * Ragel is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Ragel is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Ragel; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "ragel.h" #include "cdftable.h" #include "redfsm.h" #include "gendata.h" /* Determine if we should use indicies or not. */ void FTabCodeGen::calcIndexSize() { int sizeWithInds = 0, sizeWithoutInds = 0; /* Calculate cost of using with indicies. */ for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { int totalIndex = st->outSingle.length() + st->outRange.length() + (st->defTrans == 0 ? 0 : 1); sizeWithInds += arrayTypeSize(redFsm->maxIndex) * totalIndex; } sizeWithInds += arrayTypeSize(redFsm->maxState) * redFsm->transSet.length(); if ( redFsm->anyActions() ) sizeWithInds += arrayTypeSize(redFsm->maxActListId) * redFsm->transSet.length(); /* Calculate the cost of not using indicies. */ for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { int totalIndex = st->outSingle.length() + st->outRange.length() + (st->defTrans == 0 ? 0 : 1); sizeWithoutInds += arrayTypeSize(redFsm->maxState) * totalIndex; if ( redFsm->anyActions() ) sizeWithoutInds += arrayTypeSize(redFsm->maxActListId) * totalIndex; } /* If using indicies reduces the size, use them. */ useIndicies = sizeWithInds < sizeWithoutInds; } std::ostream &FTabCodeGen::TO_STATE_ACTION( RedStateAp *state ) { int act = 0; if ( state->toStateAction != 0 ) act = state->toStateAction->actListId+1; out << act; return out; } std::ostream &FTabCodeGen::FROM_STATE_ACTION( RedStateAp *state ) { int act = 0; if ( state->fromStateAction != 0 ) act = state->fromStateAction->actListId+1; out << act; return out; } std::ostream &FTabCodeGen::EOF_ACTION( RedStateAp *state ) { int act = 0; if ( state->eofAction != 0 ) act = state->eofAction->actListId+1; out << act; return out; } /* Write out the function for a transition. */ std::ostream &FTabCodeGen::TRANS_ACTION( RedTransAp *trans ) { int action = 0; if ( trans->action != 0 ) action = trans->action->actListId+1; out << action; return out; } /* Write out the function switch. This switch is keyed on the values * of the func index. */ std::ostream &FTabCodeGen::TO_STATE_ACTION_SWITCH() { /* Loop the actions. */ for ( GenActionTableMap::Iter redAct = redFsm->actionMap; redAct.lte(); redAct++ ) { if ( redAct->numToStateRefs > 0 ) { /* Write the entry label. */ out << "\tcase " << redAct->actListId+1 << ":\n"; /* Write each action in the list of action items. */ for ( GenActionTable::Iter item = redAct->key; item.lte(); item++ ) ACTION( out, item->value, 0, false, false ); out << "\tbreak;\n"; } } genLineDirective( out ); return out; } /* Write out the function switch. This switch is keyed on the values * of the func index. */ std::ostream &FTabCodeGen::FROM_STATE_ACTION_SWITCH() { /* Loop the actions. */ for ( GenActionTableMap::Iter redAct = redFsm->actionMap; redAct.lte(); redAct++ ) { if ( redAct->numFromStateRefs > 0 ) { /* Write the entry label. */ out << "\tcase " << redAct->actListId+1 << ":\n"; /* Write each action in the list of action items. */ for ( GenActionTable::Iter item = redAct->key; item.lte(); item++ ) ACTION( out, item->value, 0, false, false ); out << "\tbreak;\n"; } } genLineDirective( out ); return out; } std::ostream &FTabCodeGen::EOF_ACTION_SWITCH() { /* Loop the actions. */ for ( GenActionTableMap::Iter redAct = redFsm->actionMap; redAct.lte(); redAct++ ) { if ( redAct->numEofRefs > 0 ) { /* Write the entry label. */ out << "\tcase " << redAct->actListId+1 << ":\n"; /* Write each action in the list of action items. */ for ( GenActionTable::Iter item = redAct->key; item.lte(); item++ ) ACTION( out, item->value, 0, true, false ); out << "\tbreak;\n"; } } genLineDirective( out ); return out; } /* Write out the function switch. This switch is keyed on the values * of the func index. */ std::ostream &FTabCodeGen::ACTION_SWITCH() { /* Loop the actions. */ for ( GenActionTableMap::Iter redAct = redFsm->actionMap; redAct.lte(); redAct++ ) { if ( redAct->numTransRefs > 0 ) { /* Write the entry label. */ out << "\tcase " << redAct->actListId+1 << ":\n"; /* Write each action in the list of action items. */ for ( GenActionTable::Iter item = redAct->key; item.lte(); item++ ) ACTION( out, item->value, 0, false, false ); out << "\tbreak;\n"; } } genLineDirective( out ); return out; } void FTabCodeGen::writeData() { if ( redFsm->anyConditions() ) { OPEN_ARRAY( ARRAY_TYPE(redFsm->maxCondOffset), CO() ); COND_OFFSETS(); CLOSE_ARRAY() << "\n"; OPEN_ARRAY( ARRAY_TYPE(redFsm->maxCondLen), CL() ); COND_LENS(); CLOSE_ARRAY() << "\n"; OPEN_ARRAY( WIDE_ALPH_TYPE(), CK() ); COND_KEYS(); CLOSE_ARRAY() << "\n"; OPEN_ARRAY( ARRAY_TYPE(redFsm->maxCondSpaceId), C() ); COND_SPACES(); CLOSE_ARRAY() << "\n"; } OPEN_ARRAY( ARRAY_TYPE(redFsm->maxKeyOffset), KO() ); KEY_OFFSETS(); CLOSE_ARRAY() << "\n"; OPEN_ARRAY( WIDE_ALPH_TYPE(), K() ); KEYS(); CLOSE_ARRAY() << "\n"; OPEN_ARRAY( ARRAY_TYPE(redFsm->maxSingleLen), SL() ); SINGLE_LENS(); CLOSE_ARRAY() << "\n"; OPEN_ARRAY( ARRAY_TYPE(redFsm->maxRangeLen), RL() ); RANGE_LENS(); CLOSE_ARRAY() << "\n"; OPEN_ARRAY( ARRAY_TYPE(redFsm->maxIndexOffset), IO() ); INDEX_OFFSETS(); CLOSE_ARRAY() << "\n"; if ( useIndicies ) { OPEN_ARRAY( ARRAY_TYPE(redFsm->maxIndex), I() ); INDICIES(); CLOSE_ARRAY() << "\n"; OPEN_ARRAY( ARRAY_TYPE(redFsm->maxState), TT() ); TRANS_TARGS_WI(); CLOSE_ARRAY() << "\n"; if ( redFsm->anyActions() ) { OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActListId), TA() ); TRANS_ACTIONS_WI(); CLOSE_ARRAY() << "\n"; } } else { OPEN_ARRAY( ARRAY_TYPE(redFsm->maxState), TT() ); TRANS_TARGS(); CLOSE_ARRAY() << "\n"; if ( redFsm->anyActions() ) { OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActListId), TA() ); TRANS_ACTIONS(); CLOSE_ARRAY() << "\n"; } } if ( redFsm->anyToStateActions() ) { OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActionLoc), TSA() ); TO_STATE_ACTIONS(); CLOSE_ARRAY() << "\n"; } if ( redFsm->anyFromStateActions() ) { OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActionLoc), FSA() ); FROM_STATE_ACTIONS(); CLOSE_ARRAY() << "\n"; } if ( redFsm->anyEofActions() ) { OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActListId), EA() ); EOF_ACTIONS(); CLOSE_ARRAY() << "\n"; } if ( redFsm->anyEofTrans() ) { OPEN_ARRAY( ARRAY_TYPE(redFsm->maxIndexOffset+1), ET() ); EOF_TRANS(); CLOSE_ARRAY() << "\n"; } STATE_IDS(); } void FTabCodeGen::writeExec() { testEofUsed = false; outLabelUsed = false; out << " {\n" " int _klen"; if ( redFsm->anyRegCurStateRef() ) out << ", _ps"; out << ";\n" " " << PTR_CONST() << WIDE_ALPH_TYPE() << PTR_CONST_END() << POINTER() << "_keys;\n" " int _trans;\n"; if ( redFsm->anyConditions() ) out << " " << WIDE_ALPH_TYPE() << " _widec;\n"; out << "\n"; if ( !noEnd ) { testEofUsed = true; out << " if ( " << P() << " == " << PE() << " )\n" " goto _test_eof;\n"; } if ( redFsm->errState != 0 ) { outLabelUsed = true; out << " if ( " << vCS() << " == " << redFsm->errState->id << " )\n" " goto _out;\n"; } out << "_resume:\n"; if ( redFsm->anyFromStateActions() ) { out << " switch ( " << FSA() << "[" << vCS() << "] ) {\n"; FROM_STATE_ACTION_SWITCH(); SWITCH_DEFAULT() << " }\n" "\n"; } if ( redFsm->anyConditions() ) COND_TRANSLATE(); LOCATE_TRANS(); out << "_match:\n"; if ( useIndicies ) out << " _trans = " << I() << "[_trans];\n"; if ( redFsm->anyEofTrans() ) out << "_eof_trans:\n"; if ( redFsm->anyRegCurStateRef() ) out << " _ps = " << vCS() << ";\n"; out << " " << vCS() << " = " << TT() << "[_trans];\n" "\n"; if ( redFsm->anyRegActions() ) { out << " if ( " << TA() << "[_trans] == 0 )\n" " goto _again;\n" "\n" " switch ( " << TA() << "[_trans] ) {\n"; ACTION_SWITCH(); SWITCH_DEFAULT() << " }\n" "\n"; } if ( redFsm->anyRegActions() || redFsm->anyActionGotos() || redFsm->anyActionCalls() || redFsm->anyActionRets() ) out << "_again:\n"; if ( redFsm->anyToStateActions() ) { out << " switch ( " << TSA() << "[" << vCS() << "] ) {\n"; TO_STATE_ACTION_SWITCH(); SWITCH_DEFAULT() << " }\n" "\n"; } if ( redFsm->errState != 0 ) { outLabelUsed = true; out << " if ( " << vCS() << " == " << redFsm->errState->id << " )\n" " goto _out;\n"; } if ( !noEnd ) { out << " if ( ++" << P() << " != " << PE() << " )\n" " goto _resume;\n"; } else { out << " " << P() << " += 1;\n" " goto _resume;\n"; } if ( testEofUsed ) out << " _test_eof: {}\n"; if ( redFsm->anyEofTrans() || redFsm->anyEofActions() ) { out << " if ( " << P() << " == " << vEOF() << " )\n" " {\n"; if ( redFsm->anyEofTrans() ) { out << " if ( " << ET() << "[" << vCS() << "] > 0 ) {\n" " _trans = " << ET() << "[" << vCS() << "] - 1;\n" " goto _eof_trans;\n" " }\n"; } if ( redFsm->anyEofActions() ) { out << " switch ( " << EA() << "[" << vCS() << "] ) {\n"; EOF_ACTION_SWITCH(); SWITCH_DEFAULT() << " }\n"; } out << " }\n" "\n"; } if ( outLabelUsed ) out << " _out: {}\n"; out << " }\n"; } ragel-6.8/ragel/mlfflat.h0000664000175000017500000000316612106050031012266 00000000000000/* * Copyright 2004-2006 Adrian Thurston * 2004 Erich Ocean * 2005 Alan West */ /* This file is part of Ragel. * * Ragel is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Ragel is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Ragel; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef _MLFFLAT_H #define _MLFFLAT_H #include #include "mlflat.h" /* Forwards. */ //struct CodeGenData; /* * OCamlFFlatCodeGen */ class OCamlFFlatCodeGen : public OCamlFlatCodeGen { public: OCamlFFlatCodeGen( ostream &out ) : OCamlFlatCodeGen(out) {} private: std::ostream &TO_STATE_ACTION_SWITCH(); std::ostream &FROM_STATE_ACTION_SWITCH(); std::ostream &EOF_ACTION_SWITCH(); std::ostream &ACTION_SWITCH(); virtual std::ostream &TO_STATE_ACTION( RedStateAp *state ); virtual std::ostream &FROM_STATE_ACTION( RedStateAp *state ); virtual std::ostream &EOF_ACTION( RedStateAp *state ); virtual std::ostream &TRANS_ACTION( RedTransAp *trans ); virtual void writeData(); virtual void writeExec(); }; #endif ragel-6.8/ragel/ragel.h0000664000175000017500000000507012106050031011727 00000000000000/* * Copyright 2001-2007 Adrian Thurston */ /* This file is part of Ragel. * * Ragel is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Ragel is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Ragel; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef _RAGEL_H #define _RAGEL_H #include #include #include #include #include "vector.h" #include "config.h" #include "common.h" #define PROGNAME "ragel" /* Target output style. */ enum CodeStyle { GenTables, GenFTables, GenFlat, GenFFlat, GenGoto, GenFGoto, GenIpGoto, GenSplit }; /* To what degree are machine minimized. */ enum MinimizeLevel { MinimizeApprox, MinimizeStable, MinimizePartition1, MinimizePartition2 }; enum MinimizeOpt { MinimizeNone, MinimizeEnd, MinimizeMostOps, MinimizeEveryOp }; /* Target implementation */ enum RubyImplEnum { MRI, Rubinius }; /* Options. */ extern MinimizeLevel minimizeLevel; extern MinimizeOpt minimizeOpt; extern const char *machineSpec, *machineName; extern bool printStatistics; extern bool wantDupsRemoved; extern bool generateDot; extern bool generateXML; extern RubyImplEnum rubyImpl; /* Error reporting format. */ enum ErrorFormat { ErrorFormatGNU, ErrorFormatMSVC, }; extern ErrorFormat errorFormat; extern int gblErrorCount; extern char mainMachine[]; InputLoc makeInputLoc( const char *fileName, int line = 0, int col = 0 ); std::ostream &operator<<( std::ostream &out, const InputLoc &loc ); /* Error reporting. */ std::ostream &error(); std::ostream &error( const InputLoc &loc ); std::ostream &warning( const InputLoc &loc ); struct XmlParser; void xmlEscapeHost( std::ostream &out, char *data, long len ); extern CodeStyle codeStyle; /* IO filenames and stream. */ extern bool displayPrintables; extern int gblErrorCount; /* Options. */ extern int numSplitPartitions; extern bool noLineDirectives; std::ostream &error(); /* Target language and output style. */ extern CodeStyle codeStyle; extern int numSplitPartitions; extern bool noLineDirectives; #endif ragel-6.8/ragel/csfflat.h0000664000175000017500000000322012106050031012252 00000000000000/* * Copyright 2004-2006 Adrian Thurston * 2004 Erich Ocean * 2005 Alan West */ /* This file is part of Ragel. * * Ragel is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Ragel is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Ragel; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef _CSFFLAT_H #define _CSFFLAT_H #include #include "csflat.h" /* Forwards. */ struct CodeGenData; /* * CSharpFFlatCodeGen */ class CSharpFFlatCodeGen : public CSharpFlatCodeGen { public: CSharpFFlatCodeGen( ostream &out ) : CSharpFsmCodeGen(out), CSharpFlatCodeGen(out) {} private: std::ostream &TO_STATE_ACTION_SWITCH(); std::ostream &FROM_STATE_ACTION_SWITCH(); std::ostream &EOF_ACTION_SWITCH(); std::ostream &ACTION_SWITCH(); virtual std::ostream &TO_STATE_ACTION( RedStateAp *state ); virtual std::ostream &FROM_STATE_ACTION( RedStateAp *state ); virtual std::ostream &EOF_ACTION( RedStateAp *state ); virtual std::ostream &TRANS_ACTION( RedTransAp *trans ); virtual void writeData(); virtual void writeExec(); }; #endif ragel-6.8/ragel/xmlcodegen.h0000664000175000017500000001156312106050031012766 00000000000000/* * Copyright 2005-2007 Adrian Thurston */ /* This file is part of Ragel. * * Ragel is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Ragel is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Ragel; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef _XMLCODEGEN_H #define _XMLCODEGEN_H #include #include "avltree.h" #include "fsmgraph.h" #include "parsedata.h" #include "redfsm.h" /* Forwards. */ struct TransAp; struct FsmAp; struct ParseData; struct GenInlineList; struct CodeGenData; struct RedActionTable : public AvlTreeEl { RedActionTable( const ActionTable &key ) : key(key), id(0) { } const ActionTable &getKey() { return key; } ActionTable key; int id; }; typedef AvlTree ActionTableMap; struct NextRedTrans { Key lowKey, highKey; TransAp *trans; TransAp *next; void load() { if ( trans != 0 ) { next = trans->next; lowKey = trans->lowKey; highKey = trans->highKey; } } NextRedTrans( TransAp *t ) { trans = t; load(); } void increment() { trans = next; load(); } }; struct GenBase { GenBase( char *fsmName, ParseData *pd, FsmAp *fsm ); void appendTrans( TransListVect &outList, Key lowKey, Key highKey, TransAp *trans ); void reduceActionTables(); char *fsmName; ParseData *pd; FsmAp *fsm; ActionTableMap actionTableMap; int nextActionTableId; }; class XMLCodeGen : protected GenBase { public: XMLCodeGen( char *fsmName, ParseData *pd, FsmAp *fsm, std::ostream &out ); void writeXML( ); private: void writeStateActions( StateAp *state ); void writeStateList(); void writeStateConditions( StateAp *state ); void writeKey( Key key ); void writeText( InlineItem *item ); void writeGoto( InlineItem *item ); void writeGotoExpr( InlineItem *item ); void writeCall( InlineItem *item ); void writeCallExpr( InlineItem *item ); void writeNext( InlineItem *item ); void writeNextExpr( InlineItem *item ); void writeEntry( InlineItem *item ); void writeLmOnLast( InlineItem *item ); void writeLmOnNext( InlineItem *item ); void writeLmOnLagBehind( InlineItem *item ); void writeExports(); bool writeNameInst( NameInst *nameInst ); void writeEntryPoints(); void writeConditions(); void writeInlineList( InlineList *inlineList ); void writeActionList(); void writeActionTableList(); void reduceTrans( TransAp *trans ); void writeTransList( StateAp *state ); void writeEofTrans( StateAp *state ); void writeTrans( Key lowKey, Key highKey, TransAp *defTrans ); void writeAction( Action *action ); void writeLmSwitch( InlineItem *item ); void writeMachine(); void writeActionExec( InlineItem *item ); std::ostream &out; }; class BackendGen : protected GenBase { public: BackendGen( char *fsmName, ParseData *pd, FsmAp *fsm, CodeGenData *cgd ); void makeBackend( ); private: void makeGenInlineList( GenInlineList *outList, InlineList *inList ); void makeKey( GenInlineList *outList, Key key ); void makeText( GenInlineList *outList, InlineItem *item ); void makeLmOnLast( GenInlineList *outList, InlineItem *item ); void makeLmOnNext( GenInlineList *outList, InlineItem *item ); void makeLmOnLagBehind( GenInlineList *outList, InlineItem *item ); void makeActionExec( GenInlineList *outList, InlineItem *item ); void makeLmSwitch( GenInlineList *outList, InlineItem *item ); void makeSetTokend( GenInlineList *outList, long offset ); void makeSetAct( GenInlineList *outList, long lmId ); void makeSubList( GenInlineList *outList, InlineList *inlineList, GenInlineItem::Type type ); void makeTargetItem( GenInlineList *outList, NameInst *nameTarg, GenInlineItem::Type type ); void makeExecGetTokend( GenInlineList *outList ); void makeExports(); void makeMachine(); void makeActionList(); void makeAction( Action *action ); void makeActionTableList(); void makeConditions(); void makeEntryPoints(); bool makeNameInst( std::string &out, NameInst *nameInst ); void makeStateList(); void makeStateActions( StateAp *state ); void makeEofTrans( StateAp *state ); void makeStateConditions( StateAp *state ); void makeTransList( StateAp *state ); void makeTrans( Key lowKey, Key highKey, TransAp *trans ); void close_ragel_def(); CodeGenData *cgd; /* Collected during parsing. */ int curAction; int curActionTable; int curTrans; int curState; int curCondSpace; int curStateCond; }; #endif ragel-6.8/ragel/mltable.h0000664000175000017500000000601512106050031012255 00000000000000/* * Copyright 2001-2006 Adrian Thurston * 2004 Erich Ocean * 2005 Alan West */ /* This file is part of Ragel. * * Ragel is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Ragel is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Ragel; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef _OCAMLTABCODEGEN_H #define _OCAMLTABCODEGEN_H #include #include "mlcodegen.h" /* Forwards. */ /* struct CodeGenData; struct NameInst; struct RedTransAp; struct RedStateAp; */ /* * OCamlTabCodeGen */ class OCamlTabCodeGen : public OCamlCodeGen { public: OCamlTabCodeGen( ostream &out ) : OCamlCodeGen(out) {} virtual ~OCamlTabCodeGen() { } virtual void writeData(); virtual void writeExec(); protected: std::ostream &TO_STATE_ACTION_SWITCH(); std::ostream &FROM_STATE_ACTION_SWITCH(); std::ostream &EOF_ACTION_SWITCH(); std::ostream &ACTION_SWITCH(); std::ostream &COND_KEYS(); std::ostream &COND_SPACES(); std::ostream &KEYS(); std::ostream &INDICIES(); std::ostream &COND_OFFSETS(); std::ostream &KEY_OFFSETS(); std::ostream &INDEX_OFFSETS(); std::ostream &COND_LENS(); std::ostream &SINGLE_LENS(); std::ostream &RANGE_LENS(); std::ostream &TO_STATE_ACTIONS(); std::ostream &FROM_STATE_ACTIONS(); std::ostream &EOF_ACTIONS(); std::ostream &EOF_TRANS(); std::ostream &TRANS_TARGS(); std::ostream &TRANS_ACTIONS(); std::ostream &TRANS_TARGS_WI(); std::ostream &TRANS_ACTIONS_WI(); void LOCATE_TRANS(); void COND_TRANSLATE(); void GOTO( ostream &ret, int gotoDest, bool inFinish ); void CALL( ostream &ret, int callDest, int targState, bool inFinish ); void NEXT( ostream &ret, int nextDest, bool inFinish ); void GOTO_EXPR( ostream &ret, GenInlineItem *ilItem, bool inFinish ); void NEXT_EXPR( ostream &ret, GenInlineItem *ilItem, bool inFinish ); void CALL_EXPR( ostream &ret, GenInlineItem *ilItem, int targState, bool inFinish ); void CURS( ostream &ret, bool inFinish ); void TARGS( ostream &ret, bool inFinish, int targState ); void RET( ostream &ret, bool inFinish ); void BREAK( ostream &ret, int targState ); virtual std::ostream &TO_STATE_ACTION( RedStateAp *state ); virtual std::ostream &FROM_STATE_ACTION( RedStateAp *state ); virtual std::ostream &EOF_ACTION( RedStateAp *state ); virtual std::ostream &TRANS_ACTION( RedTransAp *trans ); virtual void calcIndexSize(); void initVarTypes(); string klenType; string keysType; string signedKeysType; string transType; }; #endif ragel-6.8/ragel/cstable.cpp0000664000175000017500000006651612106050031012621 00000000000000/* * Copyright 2001-2006 Adrian Thurston * 2004 Erich Ocean * 2005 Alan West */ /* This file is part of Ragel. * * Ragel is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Ragel is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Ragel; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "ragel.h" #include "cstable.h" #include "redfsm.h" #include "gendata.h" /* Determine if we should use indicies or not. */ void CSharpTabCodeGen::calcIndexSize() { int sizeWithInds = 0, sizeWithoutInds = 0; /* Calculate cost of using with indicies. */ for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { int totalIndex = st->outSingle.length() + st->outRange.length() + (st->defTrans == 0 ? 0 : 1); sizeWithInds += arrayTypeSize(redFsm->maxIndex) * totalIndex; } sizeWithInds += arrayTypeSize(redFsm->maxState) * redFsm->transSet.length(); if ( redFsm->anyActions() ) sizeWithInds += arrayTypeSize(redFsm->maxActionLoc) * redFsm->transSet.length(); /* Calculate the cost of not using indicies. */ for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { int totalIndex = st->outSingle.length() + st->outRange.length() + (st->defTrans == 0 ? 0 : 1); sizeWithoutInds += arrayTypeSize(redFsm->maxState) * totalIndex; if ( redFsm->anyActions() ) sizeWithoutInds += arrayTypeSize(redFsm->maxActionLoc) * totalIndex; } /* If using indicies reduces the size, use them. */ useIndicies = sizeWithInds < sizeWithoutInds; } std::ostream &CSharpTabCodeGen::TO_STATE_ACTION( RedStateAp *state ) { int act = 0; if ( state->toStateAction != 0 ) act = state->toStateAction->location+1; out << act; return out; } std::ostream &CSharpTabCodeGen::FROM_STATE_ACTION( RedStateAp *state ) { int act = 0; if ( state->fromStateAction != 0 ) act = state->fromStateAction->location+1; out << act; return out; } std::ostream &CSharpTabCodeGen::EOF_ACTION( RedStateAp *state ) { int act = 0; if ( state->eofAction != 0 ) act = state->eofAction->location+1; out << act; return out; } std::ostream &CSharpTabCodeGen::TRANS_ACTION( RedTransAp *trans ) { /* If there are actions, emit them. Otherwise emit zero. */ int act = 0; if ( trans->action != 0 ) act = trans->action->location+1; out << act; return out; } std::ostream &CSharpTabCodeGen::TO_STATE_ACTION_SWITCH() { /* Walk the list of functions, printing the cases. */ for ( GenActionList::Iter act = actionList; act.lte(); act++ ) { /* Write out referenced actions. */ if ( act->numToStateRefs > 0 ) { /* Write the case label, the action and the case break. */ out << "\tcase " << act->actionId << ":\n"; ACTION( out, act, 0, false ); out << "\tbreak;\n"; } } genLineDirective( out ); return out; } std::ostream &CSharpTabCodeGen::FROM_STATE_ACTION_SWITCH() { /* Walk the list of functions, printing the cases. */ for ( GenActionList::Iter act = actionList; act.lte(); act++ ) { /* Write out referenced actions. */ if ( act->numFromStateRefs > 0 ) { /* Write the case label, the action and the case break. */ out << "\tcase " << act->actionId << ":\n"; ACTION( out, act, 0, false ); out << "\tbreak;\n"; } } genLineDirective( out ); return out; } std::ostream &CSharpTabCodeGen::EOF_ACTION_SWITCH() { /* Walk the list of functions, printing the cases. */ for ( GenActionList::Iter act = actionList; act.lte(); act++ ) { /* Write out referenced actions. */ if ( act->numEofRefs > 0 ) { /* Write the case label, the action and the case break. */ out << "\tcase " << act->actionId << ":\n"; ACTION( out, act, 0, true ); out << "\tbreak;\n"; } } genLineDirective( out ); return out; } std::ostream &CSharpTabCodeGen::ACTION_SWITCH() { /* Walk the list of functions, printing the cases. */ for ( GenActionList::Iter act = actionList; act.lte(); act++ ) { /* Write out referenced actions. */ if ( act->numTransRefs > 0 ) { /* Write the case label, the action and the case break. */ out << "\tcase " << act->actionId << ":\n"; ACTION( out, act, 0, false ); out << "\tbreak;\n"; } } genLineDirective( out ); return out; } std::ostream &CSharpTabCodeGen::COND_OFFSETS() { out << "\t"; int totalStateNum = 0, curKeyOffset = 0; for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { /* Write the key offset. */ out << curKeyOffset; if ( !st.last() ) { out << ", "; if ( ++totalStateNum % IALL == 0 ) out << "\n\t"; } /* Move the key offset ahead. */ curKeyOffset += st->stateCondList.length(); } out << "\n"; return out; } std::ostream &CSharpTabCodeGen::KEY_OFFSETS() { out << "\t"; int totalStateNum = 0, curKeyOffset = 0; for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { /* Write the key offset. */ out << curKeyOffset; if ( !st.last() ) { out << ", "; if ( ++totalStateNum % IALL == 0 ) out << "\n\t"; } /* Move the key offset ahead. */ curKeyOffset += st->outSingle.length() + st->outRange.length()*2; } out << "\n"; return out; } std::ostream &CSharpTabCodeGen::INDEX_OFFSETS() { out << "\t"; int totalStateNum = 0, curIndOffset = 0; for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { /* Write the index offset. */ out << curIndOffset; if ( !st.last() ) { out << ", "; if ( ++totalStateNum % IALL == 0 ) out << "\n\t"; } /* Move the index offset ahead. */ curIndOffset += st->outSingle.length() + st->outRange.length(); if ( st->defTrans != 0 ) curIndOffset += 1; } out << "\n"; return out; } std::ostream &CSharpTabCodeGen::COND_LENS() { out << "\t"; int totalStateNum = 0; for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { /* Write singles length. */ out << st->stateCondList.length(); if ( !st.last() ) { out << ", "; if ( ++totalStateNum % IALL == 0 ) out << "\n\t"; } } out << "\n"; return out; } std::ostream &CSharpTabCodeGen::SINGLE_LENS() { out << "\t"; int totalStateNum = 0; for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { /* Write singles length. */ out << st->outSingle.length(); if ( !st.last() ) { out << ", "; if ( ++totalStateNum % IALL == 0 ) out << "\n\t"; } } out << "\n"; return out; } std::ostream &CSharpTabCodeGen::RANGE_LENS() { out << "\t"; int totalStateNum = 0; for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { /* Emit length of range index. */ out << st->outRange.length(); if ( !st.last() ) { out << ", "; if ( ++totalStateNum % IALL == 0 ) out << "\n\t"; } } out << "\n"; return out; } std::ostream &CSharpTabCodeGen::TO_STATE_ACTIONS() { out << "\t"; int totalStateNum = 0; for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { /* Write any eof action. */ TO_STATE_ACTION(st); if ( !st.last() ) { out << ", "; if ( ++totalStateNum % IALL == 0 ) out << "\n\t"; } } out << "\n"; return out; } std::ostream &CSharpTabCodeGen::FROM_STATE_ACTIONS() { out << "\t"; int totalStateNum = 0; for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { /* Write any eof action. */ FROM_STATE_ACTION(st); if ( !st.last() ) { out << ", "; if ( ++totalStateNum % IALL == 0 ) out << "\n\t"; } } out << "\n"; return out; } std::ostream &CSharpTabCodeGen::EOF_ACTIONS() { out << "\t"; int totalStateNum = 0; for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { /* Write any eof action. */ EOF_ACTION(st); if ( !st.last() ) { out << ", "; if ( ++totalStateNum % IALL == 0 ) out << "\n\t"; } } out << "\n"; return out; } std::ostream &CSharpTabCodeGen::EOF_TRANS() { out << "\t"; int totalStateNum = 0; for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { /* Write any eof action. */ long trans = 0; if ( st->eofTrans != 0 ) { assert( st->eofTrans->pos >= 0 ); trans = st->eofTrans->pos+1; } out << trans; if ( !st.last() ) { out << ", "; if ( ++totalStateNum % IALL == 0 ) out << "\n\t"; } } out << "\n"; return out; } std::ostream &CSharpTabCodeGen::COND_KEYS() { out << '\t'; int totalTrans = 0; for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { /* Loop the state's transitions. */ for ( GenStateCondList::Iter sc = st->stateCondList; sc.lte(); sc++ ) { /* Lower key. */ out << ALPHA_KEY( sc->lowKey ) << ", "; if ( ++totalTrans % IALL == 0 ) out << "\n\t"; /* Upper key. */ out << ALPHA_KEY( sc->highKey ) << ", "; if ( ++totalTrans % IALL == 0 ) out << "\n\t"; } } /* Output one last number so we don't have to figure out when the last * entry is and avoid writing a comma. */ if ( keyOps->alphType->isChar ) out << "(char) " << 0 << "\n"; else out << 0 << "\n"; return out; } std::ostream &CSharpTabCodeGen::COND_SPACES() { out << '\t'; int totalTrans = 0; for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { /* Loop the state's transitions. */ for ( GenStateCondList::Iter sc = st->stateCondList; sc.lte(); sc++ ) { /* Cond Space id. */ out << sc->condSpace->condSpaceId << ", "; if ( ++totalTrans % IALL == 0 ) out << "\n\t"; } } /* Output one last number so we don't have to figure out when the last * entry is and avoid writing a comma. */ out << 0 << "\n"; return out; } std::ostream &CSharpTabCodeGen::KEYS() { out << '\t'; int totalTrans = 0; for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { /* Loop the singles. */ for ( RedTransList::Iter stel = st->outSingle; stel.lte(); stel++ ) { out << ALPHA_KEY( stel->lowKey ) << ", "; if ( ++totalTrans % IALL == 0 ) out << "\n\t"; } /* Loop the state's transitions. */ for ( RedTransList::Iter rtel = st->outRange; rtel.lte(); rtel++ ) { /* Lower key. */ out << ALPHA_KEY( rtel->lowKey ) << ", "; if ( ++totalTrans % IALL == 0 ) out << "\n\t"; /* Upper key. */ out << ALPHA_KEY( rtel->highKey ) << ", "; if ( ++totalTrans % IALL == 0 ) out << "\n\t"; } } /* Output one last number so we don't have to figure out when the last * entry is and avoid writing a comma. */ if ( keyOps->alphType->isChar ) out << "(char) " << 0 << "\n"; else out << 0 << "\n"; return out; } std::ostream &CSharpTabCodeGen::INDICIES() { int totalTrans = 0; out << '\t'; for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { /* Walk the singles. */ for ( RedTransList::Iter stel = st->outSingle; stel.lte(); stel++ ) { out << stel->value->id << ", "; if ( ++totalTrans % IALL == 0 ) out << "\n\t"; } /* Walk the ranges. */ for ( RedTransList::Iter rtel = st->outRange; rtel.lte(); rtel++ ) { out << rtel->value->id << ", "; if ( ++totalTrans % IALL == 0 ) out << "\n\t"; } /* The state's default index goes next. */ if ( st->defTrans != 0 ) { out << st->defTrans->id << ", "; if ( ++totalTrans % IALL == 0 ) out << "\n\t"; } } /* Output one last number so we don't have to figure out when the last * entry is and avoid writing a comma. */ out << 0 << "\n"; return out; } std::ostream &CSharpTabCodeGen::TRANS_TARGS() { int totalTrans = 0; out << '\t'; for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { /* Walk the singles. */ for ( RedTransList::Iter stel = st->outSingle; stel.lte(); stel++ ) { RedTransAp *trans = stel->value; out << trans->targ->id << ", "; if ( ++totalTrans % IALL == 0 ) out << "\n\t"; } /* Walk the ranges. */ for ( RedTransList::Iter rtel = st->outRange; rtel.lte(); rtel++ ) { RedTransAp *trans = rtel->value; out << trans->targ->id << ", "; if ( ++totalTrans % IALL == 0 ) out << "\n\t"; } /* The state's default target state. */ if ( st->defTrans != 0 ) { RedTransAp *trans = st->defTrans; out << trans->targ->id << ", "; if ( ++totalTrans % IALL == 0 ) out << "\n\t"; } } for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { if ( st->eofTrans != 0 ) { RedTransAp *trans = st->eofTrans; trans->pos = totalTrans; out << trans->targ->id << ", "; if ( ++totalTrans % IALL == 0 ) out << "\n\t"; } } /* Output one last number so we don't have to figure out when the last * entry is and avoid writing a comma. */ out << 0 << "\n"; return out; } std::ostream &CSharpTabCodeGen::TRANS_ACTIONS() { int totalTrans = 0; out << '\t'; for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { /* Walk the singles. */ for ( RedTransList::Iter stel = st->outSingle; stel.lte(); stel++ ) { RedTransAp *trans = stel->value; TRANS_ACTION( trans ) << ", "; if ( ++totalTrans % IALL == 0 ) out << "\n\t"; } /* Walk the ranges. */ for ( RedTransList::Iter rtel = st->outRange; rtel.lte(); rtel++ ) { RedTransAp *trans = rtel->value; TRANS_ACTION( trans ) << ", "; if ( ++totalTrans % IALL == 0 ) out << "\n\t"; } /* The state's default index goes next. */ if ( st->defTrans != 0 ) { RedTransAp *trans = st->defTrans; TRANS_ACTION( trans ) << ", "; if ( ++totalTrans % IALL == 0 ) out << "\n\t"; } } for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { if ( st->eofTrans != 0 ) { RedTransAp *trans = st->eofTrans; TRANS_ACTION( trans ) << ", "; if ( ++totalTrans % IALL == 0 ) out << "\n\t"; } } /* Output one last number so we don't have to figure out when the last * entry is and avoid writing a comma. */ out << 0 << "\n"; return out; } std::ostream &CSharpTabCodeGen::TRANS_TARGS_WI() { /* Transitions must be written ordered by their id. */ RedTransAp **transPtrs = new RedTransAp*[redFsm->transSet.length()]; for ( TransApSet::Iter trans = redFsm->transSet; trans.lte(); trans++ ) transPtrs[trans->id] = trans; /* Keep a count of the num of items in the array written. */ out << '\t'; int totalStates = 0; for ( int t = 0; t < redFsm->transSet.length(); t++ ) { /* Record the position, need this for eofTrans. */ RedTransAp *trans = transPtrs[t]; trans->pos = t; /* Write out the target state. */ out << trans->targ->id; if ( t < redFsm->transSet.length()-1 ) { out << ", "; if ( ++totalStates % IALL == 0 ) out << "\n\t"; } } out << "\n"; delete[] transPtrs; return out; } std::ostream &CSharpTabCodeGen::TRANS_ACTIONS_WI() { /* Transitions must be written ordered by their id. */ RedTransAp **transPtrs = new RedTransAp*[redFsm->transSet.length()]; for ( TransApSet::Iter trans = redFsm->transSet; trans.lte(); trans++ ) transPtrs[trans->id] = trans; /* Keep a count of the num of items in the array written. */ out << '\t'; int totalAct = 0; for ( int t = 0; t < redFsm->transSet.length(); t++ ) { /* Write the function for the transition. */ RedTransAp *trans = transPtrs[t]; TRANS_ACTION( trans ); if ( t < redFsm->transSet.length()-1 ) { out << ", "; if ( ++totalAct % IALL == 0 ) out << "\n\t"; } } out << "\n"; delete[] transPtrs; return out; } void CSharpTabCodeGen::GOTO( ostream &ret, int gotoDest, bool inFinish ) { ret << "{" << vCS() << " = " << gotoDest << "; " << CTRL_FLOW() << "goto _again;}"; } void CSharpTabCodeGen::GOTO_EXPR( ostream &ret, GenInlineItem *ilItem, bool inFinish ) { ret << "{" << vCS() << " = ("; INLINE_LIST( ret, ilItem->children, 0, inFinish ); ret << "); " << CTRL_FLOW() << "goto _again;}"; } void CSharpTabCodeGen::CURS( ostream &ret, bool inFinish ) { ret << "(_ps)"; } void CSharpTabCodeGen::TARGS( ostream &ret, bool inFinish, int targState ) { ret << "(" << vCS() << ")"; } void CSharpTabCodeGen::NEXT( ostream &ret, int nextDest, bool inFinish ) { ret << vCS() << " = " << nextDest << ";"; } void CSharpTabCodeGen::NEXT_EXPR( ostream &ret, GenInlineItem *ilItem, bool inFinish ) { ret << vCS() << " = ("; INLINE_LIST( ret, ilItem->children, 0, inFinish ); ret << ");"; } void CSharpTabCodeGen::CALL( ostream &ret, int callDest, int targState, bool inFinish ) { if ( prePushExpr != 0 ) { ret << "{"; INLINE_LIST( ret, prePushExpr, 0, false ); } ret << "{" << STACK() << "[" << TOP() << "++] = " << vCS() << "; " << vCS() << " = " << callDest << "; " << CTRL_FLOW() << "goto _again;}"; if ( prePushExpr != 0 ) ret << "}"; } void CSharpTabCodeGen::CALL_EXPR( ostream &ret, GenInlineItem *ilItem, int targState, bool inFinish ) { if ( prePushExpr != 0 ) { ret << "{"; INLINE_LIST( ret, prePushExpr, 0, false ); } ret << "{" << STACK() << "[" << TOP() << "++] = " << vCS() << "; " << vCS() << " = ("; INLINE_LIST( ret, ilItem->children, targState, inFinish ); ret << "); " << CTRL_FLOW() << "goto _again;}"; if ( prePushExpr != 0 ) ret << "}"; } void CSharpTabCodeGen::RET( ostream &ret, bool inFinish ) { ret << "{" << vCS() << " = " << STACK() << "[--" << TOP() << "]; "; if ( postPopExpr != 0 ) { ret << "{"; INLINE_LIST( ret, postPopExpr, 0, false ); ret << "}"; } ret << CTRL_FLOW() << "goto _again;}"; } void CSharpTabCodeGen::BREAK( ostream &ret, int targState ) { outLabelUsed = true; ret << "{" << P() << "++; " << CTRL_FLOW() << "goto _out; }"; } void CSharpTabCodeGen::writeData() { /* If there are any transtion functions then output the array. If there * are none, don't bother emitting an empty array that won't be used. */ if ( redFsm->anyActions() ) { OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActArrItem), A() ); ACTIONS_ARRAY(); CLOSE_ARRAY() << "\n"; } if ( redFsm->anyConditions() ) { OPEN_ARRAY( ARRAY_TYPE(redFsm->maxCondOffset), CO() ); COND_OFFSETS(); CLOSE_ARRAY() << "\n"; OPEN_ARRAY( ARRAY_TYPE(redFsm->maxCondLen), CL() ); COND_LENS(); CLOSE_ARRAY() << "\n"; OPEN_ARRAY( WIDE_ALPH_TYPE(), CK() ); COND_KEYS(); CLOSE_ARRAY() << "\n"; OPEN_ARRAY( ARRAY_TYPE(redFsm->maxCondSpaceId), C() ); COND_SPACES(); CLOSE_ARRAY() << "\n"; } OPEN_ARRAY( ARRAY_TYPE(redFsm->maxKeyOffset), KO() ); KEY_OFFSETS(); CLOSE_ARRAY() << "\n"; OPEN_ARRAY( WIDE_ALPH_TYPE(), K() ); KEYS(); CLOSE_ARRAY() << "\n"; OPEN_ARRAY( ARRAY_TYPE(redFsm->maxSingleLen), SL() ); SINGLE_LENS(); CLOSE_ARRAY() << "\n"; OPEN_ARRAY( ARRAY_TYPE(redFsm->maxRangeLen), RL() ); RANGE_LENS(); CLOSE_ARRAY() << "\n"; OPEN_ARRAY( ARRAY_TYPE(redFsm->maxIndexOffset), IO() ); INDEX_OFFSETS(); CLOSE_ARRAY() << "\n"; if ( useIndicies ) { OPEN_ARRAY( ARRAY_TYPE(redFsm->maxIndex), I() ); INDICIES(); CLOSE_ARRAY() << "\n"; OPEN_ARRAY( ARRAY_TYPE(redFsm->maxState), TT() ); TRANS_TARGS_WI(); CLOSE_ARRAY() << "\n"; if ( redFsm->anyActions() ) { OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActionLoc), TA() ); TRANS_ACTIONS_WI(); CLOSE_ARRAY() << "\n"; } } else { OPEN_ARRAY( ARRAY_TYPE(redFsm->maxState), TT() ); TRANS_TARGS(); CLOSE_ARRAY() << "\n"; if ( redFsm->anyActions() ) { OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActionLoc), TA() ); TRANS_ACTIONS(); CLOSE_ARRAY() << "\n"; } } if ( redFsm->anyToStateActions() ) { OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActionLoc), TSA() ); TO_STATE_ACTIONS(); CLOSE_ARRAY() << "\n"; } if ( redFsm->anyFromStateActions() ) { OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActionLoc), FSA() ); FROM_STATE_ACTIONS(); CLOSE_ARRAY() << "\n"; } if ( redFsm->anyEofActions() ) { OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActionLoc), EA() ); EOF_ACTIONS(); CLOSE_ARRAY() << "\n"; } if ( redFsm->anyEofTrans() ) { OPEN_ARRAY( ARRAY_TYPE(redFsm->maxIndexOffset+1), ET() ); EOF_TRANS(); CLOSE_ARRAY() << "\n"; } STATE_IDS(); } void CSharpTabCodeGen::LOCATE_TRANS() { out << " _keys = " << KO() + "[" + vCS() + "]" << ";\n" " _trans = " << CAST(transType) << IO() << "[" << vCS() << "];\n" "\n" " _klen = " << SL() << "[" << vCS() << "];\n" " if ( _klen > 0 ) {\n" " " << signedKeysType << " _lower = _keys;\n" " " << signedKeysType << " _mid;\n" " " << signedKeysType << " _upper = " << CAST(signedKeysType) << " (_keys + _klen - 1);\n" " while (true) {\n" " if ( _upper < _lower )\n" " break;\n" "\n" " _mid = " << CAST(signedKeysType) << " (_lower + ((_upper-_lower) >> 1));\n" " if ( " << GET_WIDE_KEY() << " < " << K() << "[_mid] )\n" " _upper = " << CAST(signedKeysType) << " (_mid - 1);\n" " else if ( " << GET_WIDE_KEY() << " > " << K() << "[_mid] )\n" " _lower = " << CAST(signedKeysType) << " (_mid + 1);\n" " else {\n" " _trans += " << CAST(transType) << " (_mid - _keys);\n" " goto _match;\n" " }\n" " }\n" " _keys += " << CAST(keysType) << " _klen;\n" " _trans += " << CAST(transType) << " _klen;\n" " }\n" "\n" " _klen = " << RL() << "[" << vCS() << "];\n" " if ( _klen > 0 ) {\n" " " << signedKeysType << " _lower = _keys;\n" " " << signedKeysType << " _mid;\n" " " << signedKeysType << " _upper = " << CAST(signedKeysType) << " (_keys + (_klen<<1) - 2);\n" " while (true) {\n" " if ( _upper < _lower )\n" " break;\n" "\n" " _mid = " << CAST(signedKeysType) << " (_lower + (((_upper-_lower) >> 1) & ~1));\n" " if ( " << GET_WIDE_KEY() << " < " << K() << "[_mid] )\n" " _upper = " << CAST(signedKeysType) << " (_mid - 2);\n" " else if ( " << GET_WIDE_KEY() << " > " << K() << "[_mid+1] )\n" " _lower = " << CAST(signedKeysType) << " (_mid + 2);\n" " else {\n" " _trans += " << CAST(transType) << "((_mid - _keys)>>1);\n" " goto _match;\n" " }\n" " }\n" " _trans += " << CAST(transType) << " _klen;\n" " }\n" "\n"; } void CSharpTabCodeGen::COND_TRANSLATE() { out << " _widec = " << GET_KEY() << ";\n" " _klen = " << CL() << "[" << vCS() << "];\n" " _keys = " << CAST(keysType) << " ("<< CO() << "[" << vCS() << "]*2);\n" " if ( _klen > 0 ) {\n" " " << signedKeysType << " _lower = _keys;\n" " " << signedKeysType << " _mid;\n" " " << signedKeysType << " _upper = " << CAST(signedKeysType) << " (_keys + (_klen<<1) - 2);\n" " while (true) {\n" " if ( _upper < _lower )\n" " break;\n" "\n" " _mid = " << CAST(signedKeysType) << " (_lower + (((_upper-_lower) >> 1) & ~1));\n" " if ( " << GET_WIDE_KEY() << " < " << CK() << "[_mid] )\n" " _upper = " << CAST(signedKeysType) << " (_mid - 2);\n" " else if ( " << GET_WIDE_KEY() << " > " << CK() << "[_mid+1] )\n" " _lower = " << CAST(signedKeysType) << " (_mid + 2);\n" " else {\n" " switch ( " << C() << "[" << CO() << "[" << vCS() << "]" " + ((_mid - _keys)>>1)] ) {\n"; for ( CondSpaceList::Iter csi = condSpaceList; csi.lte(); csi++ ) { GenCondSpace *condSpace = csi; out << " case " << condSpace->condSpaceId << ": {\n"; out << TABS(2) << "_widec = " << CAST(WIDE_ALPH_TYPE()) << "(" << KEY(condSpace->baseKey) << " + (" << GET_KEY() << " - " << KEY(keyOps->minKey) << "));\n"; for ( GenCondSet::Iter csi = condSpace->condSet; csi.lte(); csi++ ) { out << TABS(2) << "if ( "; CONDITION( out, *csi ); Size condValOffset = ((1 << csi.pos()) * keyOps->alphSize()); out << " ) _widec += " << condValOffset << ";\n"; } out << " break;\n" " }\n"; } SWITCH_DEFAULT(); out << " }\n" " break;\n" " }\n" " }\n" " }\n" "\n"; } void CSharpTabCodeGen::writeExec() { testEofUsed = false; outLabelUsed = false; initVarTypes(); out << " {\n" " " << klenType << " _klen"; if ( redFsm->anyRegCurStateRef() ) out << ", _ps"; out << ";\n" " " << transType << " _trans;\n"; if ( redFsm->anyConditions() ) out << " " << WIDE_ALPH_TYPE() << " _widec;\n"; if ( redFsm->anyToStateActions() || redFsm->anyRegActions() || redFsm->anyFromStateActions() ) { out << " int _acts;\n" " int _nacts;\n"; } out << " " << keysType << " _keys;\n" "\n"; // " " << PTR_CONST() << WIDE_ALPH_TYPE() << POINTER() << "_keys;\n" if ( !noEnd ) { testEofUsed = true; out << " if ( " << P() << " == " << PE() << " )\n" " goto _test_eof;\n"; } if ( redFsm->errState != 0 ) { outLabelUsed = true; out << " if ( " << vCS() << " == " << redFsm->errState->id << " )\n" " goto _out;\n"; } out << "_resume:\n"; if ( redFsm->anyFromStateActions() ) { out << " _acts = " << FSA() << "[" + vCS() + "]" << ";\n" " _nacts = " << A() << "[_acts++];\n" " while ( _nacts-- > 0 ) {\n" " switch ( " << A() << "[_acts++] ) {\n"; FROM_STATE_ACTION_SWITCH(); SWITCH_DEFAULT() << " }\n" " }\n" "\n"; } if ( redFsm->anyConditions() ) COND_TRANSLATE(); LOCATE_TRANS(); out << "_match:\n"; if ( useIndicies ) out << " _trans = " << CAST(transType) << I() << "[_trans];\n"; if ( redFsm->anyEofTrans() ) out << "_eof_trans:\n"; if ( redFsm->anyRegCurStateRef() ) out << " _ps = " << vCS() << ";\n"; out << " " << vCS() << " = " << TT() << "[_trans];\n" "\n"; if ( redFsm->anyRegActions() ) { out << " if ( " << TA() << "[_trans] == 0 )\n" " goto _again;\n" "\n" " _acts = " << TA() << "[_trans]" << ";\n" " _nacts = " << A() << "[_acts++];\n" " while ( _nacts-- > 0 )\n {\n" " switch ( " << A() << "[_acts++] )\n {\n"; ACTION_SWITCH(); SWITCH_DEFAULT() << " }\n" " }\n" "\n"; } if ( redFsm->anyRegActions() || redFsm->anyActionGotos() || redFsm->anyActionCalls() || redFsm->anyActionRets() ) out << "_again:\n"; if ( redFsm->anyToStateActions() ) { out << " _acts = " << TSA() << "[" << vCS() << "]" << ";\n" " _nacts = " << A() << "[_acts++];\n" " while ( _nacts-- > 0 ) {\n" " switch ( " << A() << "[_acts++] ) {\n"; TO_STATE_ACTION_SWITCH(); SWITCH_DEFAULT() << " }\n" " }\n" "\n"; } if ( redFsm->errState != 0 ) { outLabelUsed = true; out << " if ( " << vCS() << " == " << redFsm->errState->id << " )\n" " goto _out;\n"; } if ( !noEnd ) { out << " if ( ++" << P() << " != " << PE() << " )\n" " goto _resume;\n"; } else { out << " " << P() << " += 1;\n" " goto _resume;\n"; } if ( testEofUsed ) out << " _test_eof: {}\n"; if ( redFsm->anyEofTrans() || redFsm->anyEofActions() ) { out << " if ( " << P() << " == " << vEOF() << " )\n" " {\n"; if ( redFsm->anyEofTrans() ) { out << " if ( " << ET() << "[" << vCS() << "] > 0 ) {\n" " _trans = " << CAST(transType) << " (" << ET() << "[" << vCS() << "] - 1);\n" " goto _eof_trans;\n" " }\n"; } if ( redFsm->anyEofActions() ) { out << " int __acts = " << EA() << "[" << vCS() << "]" << ";\n" " int __nacts = " << A() << "[__acts++];\n" " while ( __nacts-- > 0 ) {\n" " switch ( " << A() << "[__acts++] ) {\n"; EOF_ACTION_SWITCH(); SWITCH_DEFAULT() << " }\n" " }\n"; } out << " }\n" "\n"; } if ( outLabelUsed ) out << " _out: {}\n"; out << " }\n"; } void CSharpTabCodeGen::initVarTypes() { int klenMax = MAX(MAX(redFsm->maxCondLen, redFsm->maxRangeLen), redFsm->maxSingleLen); int keysMax = MAX(MAX(redFsm->maxKeyOffset, klenMax), redFsm->maxCondOffset); int transMax = MAX(MAX(redFsm->maxIndex+1, redFsm->maxIndexOffset), keysMax); transMax = MAX(transMax, klenMax); transType = ARRAY_TYPE(transMax); klenType = ARRAY_TYPE(klenMax); keysType = ARRAY_TYPE(keysMax); signedKeysType = ARRAY_TYPE(keysMax, true); } ragel-6.8/ragel/rubyfflat.cpp0000664000175000017500000002452612106050031013175 00000000000000/* * 2007 Victor Hugo Borja * Copyright 2001-2007 Adrian Thurston */ /* This file is part of Ragel. * * Ragel is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Ragel is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Ragel; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "rubyfflat.h" void RubyFFlatCodeGen::GOTO( ostream &out, int gotoDest, bool inFinish ) { out << " begin\n" " " << vCS() << " = " << gotoDest << "\n" " _goto_level = _again\n" " next\n" " end\n"; } void RubyFFlatCodeGen::GOTO_EXPR( ostream &out, GenInlineItem *ilItem, bool inFinish ) { out << " begin\n" " " << vCS() << " = ("; INLINE_LIST( out, ilItem->children, 0, inFinish ); out << ")\n"; out << " _goto_level = _again\n" " next\n" " end\n"; } void RubyFFlatCodeGen::CALL( ostream &out, int callDest, int targState, bool inFinish ) { if ( prePushExpr != 0 ) { out << "begin\n"; INLINE_LIST( out, prePushExpr, 0, false ); } out << " begin\n" " " << STACK() << "[" << TOP() << "] = " << vCS() << "\n" " " << TOP() << "+= 1\n" " " << vCS() << " = " << callDest << "\n" " _goto_level = _again\n" " next\n" " end\n"; if ( prePushExpr != 0 ) out << "end\n"; } void RubyFFlatCodeGen::CALL_EXPR(ostream &out, GenInlineItem *ilItem, int targState, bool inFinish ) { if ( prePushExpr != 0 ) { out << "begin\n"; INLINE_LIST( out, prePushExpr, 0, false ); } out << " begin\n" " " << STACK() << "[" << TOP() << "] = " << vCS() << "\n" " " << TOP() << " += 1\n" " " << vCS() << " = ("; INLINE_LIST( out, ilItem->children, targState, inFinish ); out << ")\n"; out << " _goto_level = _again\n" " next\n" " end\n"; if ( prePushExpr != 0 ) out << "end\n"; } void RubyFFlatCodeGen::RET( ostream &out, bool inFinish ) { out << " begin\n" " " << TOP() << " -= 1\n" " " << vCS() << " = " << STACK() << "[" << TOP() << "]\n"; if ( postPopExpr != 0 ) { out << "begin\n"; INLINE_LIST( out, postPopExpr, 0, false ); out << "end\n"; } out << " _goto_level = _again\n" " next\n" " end\n"; } void RubyFFlatCodeGen::BREAK( ostream &out, int targState ) { out << " begin\n" " " << P() << " += 1\n" " _goto_level = _out\n" " next\n" " end\n"; } int RubyFFlatCodeGen::TO_STATE_ACTION( RedStateAp *state ) { int act = 0; if ( state->toStateAction != 0 ) act = state->toStateAction->actListId+1; return act; } int RubyFFlatCodeGen::FROM_STATE_ACTION( RedStateAp *state ) { int act = 0; if ( state->fromStateAction != 0 ) act = state->fromStateAction->actListId+1; return act; } int RubyFFlatCodeGen::EOF_ACTION( RedStateAp *state ) { int act = 0; if ( state->eofAction != 0 ) act = state->eofAction->actListId+1; return act; } /* Write out the function for a transition. */ int RubyFFlatCodeGen::TRANS_ACTION( RedTransAp *trans ) { int action = 0; if ( trans->action != 0 ) action = trans->action->actListId+1; return action; } /* Write out the function switch. This switch is keyed on the values * of the func index. */ std::ostream &RubyFFlatCodeGen::TO_STATE_ACTION_SWITCH() { /* Loop the actions. */ for ( GenActionTableMap::Iter redAct = redFsm->actionMap; redAct.lte(); redAct++ ) { if ( redAct->numToStateRefs > 0 ) { /* Write the entry label. */ out << "\twhen " << redAct->actListId+1 << " then\n"; /* Write each action in the list of action items. */ for ( GenActionTable::Iter item = redAct->key; item.lte(); item++ ) ACTION( out, item->value, 0, false ); } } genLineDirective( out ); return out; } /* Write out the function switch. This switch is keyed on the values * of the func index. */ std::ostream &RubyFFlatCodeGen::FROM_STATE_ACTION_SWITCH() { /* Loop the actions. */ for ( GenActionTableMap::Iter redAct = redFsm->actionMap; redAct.lte(); redAct++ ) { if ( redAct->numFromStateRefs > 0 ) { /* Write the entry label. */ out << "\twhen " << redAct->actListId+1 << " then\n"; /* Write each action in the list of action items. */ for ( GenActionTable::Iter item = redAct->key; item.lte(); item++ ) ACTION( out, item->value, 0, false ); } } genLineDirective( out ); return out; } std::ostream &RubyFFlatCodeGen::EOF_ACTION_SWITCH() { /* Loop the actions. */ for ( GenActionTableMap::Iter redAct = redFsm->actionMap; redAct.lte(); redAct++ ) { if ( redAct->numEofRefs > 0 ) { /* Write the entry label. */ out << "\twhen " << redAct->actListId+1 << " then\n"; /* Write each action in the list of action items. */ for ( GenActionTable::Iter item = redAct->key; item.lte(); item++ ) ACTION( out, item->value, 0, true ); } } genLineDirective( out ); return out; } /* Write out the function switch. This switch is keyed on the values * of the func index. */ std::ostream &RubyFFlatCodeGen::ACTION_SWITCH() { /* Loop the actions. */ for ( GenActionTableMap::Iter redAct = redFsm->actionMap; redAct.lte(); redAct++ ) { if ( redAct->numTransRefs > 0 ) { /* Write the entry label. */ out << "\twhen " << redAct->actListId+1 << " then\n"; /* Write each action in the list of action items. */ for ( GenActionTable::Iter item = redAct->key; item.lte(); item++ ) ACTION( out, item->value, 0, false ); } } genLineDirective( out ); return out; } void RubyFFlatCodeGen::writeData() { if ( redFsm->anyConditions() ) { OPEN_ARRAY( WIDE_ALPH_TYPE(), CK() ); COND_KEYS(); CLOSE_ARRAY() << "\n"; OPEN_ARRAY( ARRAY_TYPE(redFsm->maxCondSpan), CSP() ); COND_KEY_SPANS(); CLOSE_ARRAY() << "\n"; OPEN_ARRAY( ARRAY_TYPE(redFsm->maxCond), C() ); CONDS(); CLOSE_ARRAY() << "\n"; OPEN_ARRAY( ARRAY_TYPE(redFsm->maxCondIndexOffset), CO() ); COND_INDEX_OFFSET(); CLOSE_ARRAY() << "\n"; } OPEN_ARRAY( WIDE_ALPH_TYPE(), K() ); KEYS(); CLOSE_ARRAY() << "\n"; OPEN_ARRAY( ARRAY_TYPE(redFsm->maxSpan), SP() ); KEY_SPANS(); CLOSE_ARRAY() << "\n"; OPEN_ARRAY( ARRAY_TYPE(redFsm->maxFlatIndexOffset), IO() ); FLAT_INDEX_OFFSET(); CLOSE_ARRAY() << "\n"; OPEN_ARRAY( ARRAY_TYPE(redFsm->maxIndex), I() ); INDICIES(); CLOSE_ARRAY() << "\n"; OPEN_ARRAY( ARRAY_TYPE(redFsm->maxState), TT() ); TRANS_TARGS(); CLOSE_ARRAY() << "\n"; if ( redFsm->anyActions() ) { OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActListId), TA() ); TRANS_ACTIONS(); CLOSE_ARRAY() << "\n"; } if ( redFsm->anyToStateActions() ) { OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActionLoc), TSA() ); TO_STATE_ACTIONS(); CLOSE_ARRAY() << "\n"; } if ( redFsm->anyFromStateActions() ) { OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActionLoc), FSA() ); FROM_STATE_ACTIONS(); CLOSE_ARRAY() << "\n"; } if ( redFsm->anyEofActions() ) { OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActListId), EA() ); EOF_ACTIONS(); CLOSE_ARRAY() << "\n"; } if ( redFsm->anyEofTrans() ) { OPEN_ARRAY( ARRAY_TYPE(redFsm->maxIndexOffset+1), ET() ); EOF_TRANS(); CLOSE_ARRAY() << "\n"; } STATE_IDS(); } void RubyFFlatCodeGen::writeExec() { out << "begin\n" " testEof = false\n" " _slen, _trans, _keys, _inds"; if ( redFsm->anyRegCurStateRef() ) out << ", _ps"; if ( redFsm->anyConditions() ) out << ", _cond, _conds, _widec"; if ( redFsm->anyToStateActions() || redFsm->anyRegActions() || redFsm->anyFromStateActions() ) out << ", _acts, _nacts"; out << " = nil\n"; out << " _goto_level = 0\n" " _resume = 10\n" " _eof_trans = 15\n" " _again = 20\n" " _test_eof = 30\n" " _out = 40\n"; out << " while true\n" " if _goto_level <= 0\n"; if ( !noEnd ) { out << " if " << P() << " == " << PE() << "\n" " _goto_level = _test_eof\n" " next\n" " end\n"; } if ( redFsm->errState != 0 ) { out << " if " << vCS() << " == " << redFsm->errState->id << "\n" " _goto_level = _out\n" " next\n" " end\n"; } /* The resume label. */ out << " end\n" " if _goto_level <= _resume\n"; if ( redFsm->anyFromStateActions() ) { out << " case " << FSA() << "[" << vCS() << "] \n"; FROM_STATE_ACTION_SWITCH() << " end\n"; } if ( redFsm->anyConditions() ) COND_TRANSLATE(); LOCATE_TRANS(); if ( redFsm->anyEofTrans() ) { out << " end\n" " if _goto_level <= _eof_trans\n"; } if ( redFsm->anyRegCurStateRef() ) out << " _ps = " << vCS() << "\n"; out << " " << vCS() << " = " << TT() << "[_trans]\n"; if ( redFsm->anyRegActions() ) { /* break _again */ out << " if " << TA() << "[_trans] != 0\n" " case " << TA() << "[_trans]" << "\n"; ACTION_SWITCH() << " end\n" " end\n"; } /* The again label. */ out << " end\n" " if _goto_level <= _again\n"; if ( redFsm->anyToStateActions() ) { out << " case " << TSA() << "[" << vCS() << "] \n"; TO_STATE_ACTION_SWITCH() << " end\n" "\n"; } if ( redFsm->errState != 0 ) { out << " if " << vCS() << " == " << redFsm->errState->id << "\n" " _goto_level = _out\n" " next\n" " end\n"; } out << " " << P() << " += 1\n"; if ( !noEnd ) { out << " if " << P() << " != " << PE() << "\n" " _goto_level = _resume\n" " next\n" " end\n"; } else { out << " _goto_level = _resume\n" " next\n"; } /* The test eof label. */ out << " end\n" " if _goto_level <= _test_eof\n"; if ( redFsm->anyEofTrans() || redFsm->anyEofActions() ) { out << " if " << P() << " == " << vEOF() << "\n"; if ( redFsm->anyEofTrans() ) { out << " if " << ET() << "[" << vCS() << "] > 0\n" " _trans = " << ET() << "[" << vCS() << "] - 1;\n" " _goto_level = _eof_trans\n" " next;\n" " end\n"; } if ( redFsm->anyEofActions() ) { out << " case " << EA() << "[" << vCS() << "]\n"; EOF_ACTION_SWITCH() << " end\n"; } out << " end\n" "\n"; } out << " end\n" " if _goto_level <= _out\n" " break\n" " end\n" "end\n"; /* Wrapping the execute block. */ out << " end\n"; } /* * Local Variables: * mode: c++ * indent-tabs-mode: 1 * c-file-style: "bsd" * End: */ ragel-6.8/ragel/rubycodegen.h0000664000175000017500000001331012106050031013137 00000000000000/* * 2007 Victor Hugo Borja * Copyright 2001-2007 Adrian Thurston */ /* This file is part of Ragel. * * Ragel is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Ragel is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Ragel; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef _RUBY_CODEGEN_H #define _RUBY_CODEGEN_H #include "common.h" #include "gendata.h" /* Integer array line length. */ #define IALL 8 class RubyCodeGen : public CodeGenData { public: RubyCodeGen( ostream &out ) : CodeGenData(out) { } virtual ~RubyCodeGen() {} protected: ostream &START_ARRAY_LINE(); ostream &ARRAY_ITEM( string item, int count, bool last ); ostream &END_ARRAY_LINE(); string FSM_NAME(); string START_STATE_ID(); string ERROR_STATE(); string FIRST_FINAL_STATE(); void INLINE_LIST(ostream &ret, GenInlineList *inlineList, int targState, bool inFinish); string ACCESS(); void ACTION( ostream &ret, GenAction *action, int targState, bool inFinish ); string GET_KEY(); string GET_WIDE_KEY(); string GET_WIDE_KEY( RedStateAp *state ); string KEY( Key key ); string TABS( int level ); string INT( int i ); void CONDITION( ostream &ret, GenAction *condition ); string ALPH_TYPE(); string WIDE_ALPH_TYPE(); string ARRAY_TYPE( unsigned long maxVal ); ostream &ACTIONS_ARRAY(); void STATE_IDS(); string DATA_PREFIX(); string PM() { return "_" + DATA_PREFIX() + "partition_map"; } string C() { return "_" + DATA_PREFIX() + "cond_spaces"; } string CK() { return "_" + DATA_PREFIX() + "cond_keys"; } string K() { return "_" + DATA_PREFIX() + "trans_keys"; } string I() { return "_" + DATA_PREFIX() + "indicies"; } string CO() { return "_" + DATA_PREFIX() + "cond_offsets"; } string KO() { return "_" + DATA_PREFIX() + "key_offsets"; } string IO() { return "_" + DATA_PREFIX() + "index_offsets"; } string CL() { return "_" + DATA_PREFIX() + "cond_lengths"; } string SL() { return "_" + DATA_PREFIX() + "single_lengths"; } string RL() { return "_" + DATA_PREFIX() + "range_lengths"; } string A() { return "_" + DATA_PREFIX() + "actions"; } string TA() { return "_" + DATA_PREFIX() + "trans_actions"; } string TT() { return "_" + DATA_PREFIX() + "trans_targs"; } string TSA() { return "_" + DATA_PREFIX() + "to_state_actions"; } string FSA() { return "_" + DATA_PREFIX() + "from_state_actions"; } string EA() { return "_" + DATA_PREFIX() + "eof_actions"; } string ET() { return "_" + DATA_PREFIX() + "eof_trans"; } string SP() { return "_" + DATA_PREFIX() + "key_spans"; } string CSP() { return "_" + DATA_PREFIX() + "cond_key_spans"; } string START() { return DATA_PREFIX() + "start"; } string ERROR() { return DATA_PREFIX() + "error"; } string FIRST_FINAL() { return DATA_PREFIX() + "first_final"; } string CTXDATA() { return DATA_PREFIX() + "ctxdata"; } public: string NULL_ITEM(); ostream &OPEN_ARRAY( string type, string name ); ostream &CLOSE_ARRAY(); ostream &STATIC_VAR( string type, string name ); string ARR_OFF( string ptr, string offset ); string P(); string PE(); string vEOF(); string vCS(); string TOP(); string STACK(); string ACT(); string TOKSTART(); string TOKEND(); string DATA(); void finishRagelDef(); unsigned int arrayTypeSize( unsigned long maxVal ); protected: virtual void writeExports(); virtual void writeInit(); virtual void writeStart(); virtual void writeFirstFinal(); virtual void writeError(); /* Determine if we should use indicies. */ virtual void calcIndexSize(); virtual void BREAK( ostream &ret, int targState ) = 0; virtual void GOTO( ostream &ret, int gotoDest, bool inFinish ) = 0; virtual void GOTO_EXPR( ostream &ret, GenInlineItem *ilItem, bool inFinish ) = 0; virtual void CALL( ostream &ret, int callDest, int targState, bool inFinish ) = 0; virtual void CALL_EXPR( ostream &ret, GenInlineItem *ilItem, int targState, bool inFinish ) = 0; virtual void RET( ostream &ret, bool inFinish ) = 0; virtual void NEXT( ostream &ret, int nextDest, bool inFinish ) = 0; virtual void NEXT_EXPR( ostream &ret, GenInlineItem *ilItem, bool inFinish ) = 0; virtual int TO_STATE_ACTION( RedStateAp *state ) = 0; virtual int FROM_STATE_ACTION( RedStateAp *state ) = 0; virtual int EOF_ACTION( RedStateAp *state ) = 0; virtual int TRANS_ACTION( RedTransAp *trans ); void EXEC( ostream &ret, GenInlineItem *item, int targState, int inFinish ); void LM_SWITCH( ostream &ret, GenInlineItem *item, int targState, int inFinish ); void SET_ACT( ostream &ret, GenInlineItem *item ); void INIT_TOKSTART( ostream &ret, GenInlineItem *item ); void INIT_ACT( ostream &ret, GenInlineItem *item ); void SET_TOKSTART( ostream &ret, GenInlineItem *item ); void SET_TOKEND( ostream &ret, GenInlineItem *item ); void GET_TOKEND( ostream &ret, GenInlineItem *item ); void SUB_ACTION( ostream &ret, GenInlineItem *item, int targState, bool inFinish ); protected: ostream &source_warning(const InputLoc &loc); ostream &source_error(const InputLoc &loc); /* fields */ bool outLabelUsed; bool againLabelUsed; bool useIndicies; void genLineDirective( ostream &out ); }; /* * Local Variables: * mode: c++ * indent-tabs-mode: 1 * c-file-style: "bsd" * End: */ #endif ragel-6.8/ragel/mlftable.cpp0000664000175000017500000002554212106050031012764 00000000000000/* * Copyright 2001-2006 Adrian Thurston * 2004 Erich Ocean * 2005 Alan West */ /* This file is part of Ragel. * * Ragel is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Ragel is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Ragel; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "ragel.h" #include "mlftable.h" #include "redfsm.h" #include "gendata.h" /* Determine if we should use indicies or not. */ void OCamlFTabCodeGen::calcIndexSize() { int sizeWithInds = 0, sizeWithoutInds = 0; /* Calculate cost of using with indicies. */ for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { int totalIndex = st->outSingle.length() + st->outRange.length() + (st->defTrans == 0 ? 0 : 1); sizeWithInds += arrayTypeSize(redFsm->maxIndex) * totalIndex; } sizeWithInds += arrayTypeSize(redFsm->maxState) * redFsm->transSet.length(); if ( redFsm->anyActions() ) sizeWithInds += arrayTypeSize(redFsm->maxActListId) * redFsm->transSet.length(); /* Calculate the cost of not using indicies. */ for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { int totalIndex = st->outSingle.length() + st->outRange.length() + (st->defTrans == 0 ? 0 : 1); sizeWithoutInds += arrayTypeSize(redFsm->maxState) * totalIndex; if ( redFsm->anyActions() ) sizeWithoutInds += arrayTypeSize(redFsm->maxActListId) * totalIndex; } /* If using indicies reduces the size, use them. */ useIndicies = sizeWithInds < sizeWithoutInds; } std::ostream &OCamlFTabCodeGen::TO_STATE_ACTION( RedStateAp *state ) { int act = 0; if ( state->toStateAction != 0 ) act = state->toStateAction->actListId+1; out << act; return out; } std::ostream &OCamlFTabCodeGen::FROM_STATE_ACTION( RedStateAp *state ) { int act = 0; if ( state->fromStateAction != 0 ) act = state->fromStateAction->actListId+1; out << act; return out; } std::ostream &OCamlFTabCodeGen::EOF_ACTION( RedStateAp *state ) { int act = 0; if ( state->eofAction != 0 ) act = state->eofAction->actListId+1; out << act; return out; } /* Write out the function for a transition. */ std::ostream &OCamlFTabCodeGen::TRANS_ACTION( RedTransAp *trans ) { int action = 0; if ( trans->action != 0 ) action = trans->action->actListId+1; out << action; return out; } /* Write out the function switch. This switch is keyed on the values * of the func index. */ std::ostream &OCamlFTabCodeGen::TO_STATE_ACTION_SWITCH() { /* Loop the actions. */ for ( GenActionTableMap::Iter redAct = redFsm->actionMap; redAct.lte(); redAct++ ) { if ( redAct->numToStateRefs > 0 ) { /* Write the entry label. */ out << "\t| " << redAct->actListId+1 << " ->\n"; /* Write each action in the list of action items. */ for ( GenActionTable::Iter item = redAct->key; item.lte(); item++ ) ACTION( out, item->value, 0, false ); out << "\t()\n"; } } genLineDirective( out ); return out; } /* Write out the function switch. This switch is keyed on the values * of the func index. */ std::ostream &OCamlFTabCodeGen::FROM_STATE_ACTION_SWITCH() { /* Loop the actions. */ for ( GenActionTableMap::Iter redAct = redFsm->actionMap; redAct.lte(); redAct++ ) { if ( redAct->numFromStateRefs > 0 ) { /* Write the entry label. */ out << "\t| " << redAct->actListId+1 << " ->\n"; /* Write each action in the list of action items. */ for ( GenActionTable::Iter item = redAct->key; item.lte(); item++ ) ACTION( out, item->value, 0, false ); out << "\t()\n"; } } genLineDirective( out ); return out; } std::ostream &OCamlFTabCodeGen::EOF_ACTION_SWITCH() { /* Loop the actions. */ for ( GenActionTableMap::Iter redAct = redFsm->actionMap; redAct.lte(); redAct++ ) { if ( redAct->numEofRefs > 0 ) { /* Write the entry label. */ out << "\t| " << redAct->actListId+1 << " ->\n"; /* Write each action in the list of action items. */ for ( GenActionTable::Iter item = redAct->key; item.lte(); item++ ) ACTION( out, item->value, 0, true ); out << "\t()\n"; } } genLineDirective( out ); return out; } /* Write out the function switch. This switch is keyed on the values * of the func index. */ std::ostream &OCamlFTabCodeGen::ACTION_SWITCH() { /* Loop the actions. */ for ( GenActionTableMap::Iter redAct = redFsm->actionMap; redAct.lte(); redAct++ ) { if ( redAct->numTransRefs > 0 ) { /* Write the entry label. */ out << "\t| " << redAct->actListId+1 << " ->\n"; /* Write each action in the list of action items. */ for ( GenActionTable::Iter item = redAct->key; item.lte(); item++ ) ACTION( out, item->value, 0, false ); out << "\t()\n"; } } genLineDirective( out ); return out; } void OCamlFTabCodeGen::writeData() { if ( redFsm->anyConditions() ) { OPEN_ARRAY( ARRAY_TYPE(redFsm->maxCondOffset), CO() ); COND_OFFSETS(); CLOSE_ARRAY() << "\n"; OPEN_ARRAY( ARRAY_TYPE(redFsm->maxCondLen), CL() ); COND_LENS(); CLOSE_ARRAY() << "\n"; OPEN_ARRAY( WIDE_ALPH_TYPE(), CK() ); COND_KEYS(); CLOSE_ARRAY() << "\n"; OPEN_ARRAY( ARRAY_TYPE(redFsm->maxCondSpaceId), C() ); COND_SPACES(); CLOSE_ARRAY() << "\n"; } OPEN_ARRAY( ARRAY_TYPE(redFsm->maxKeyOffset), KO() ); KEY_OFFSETS(); CLOSE_ARRAY() << "\n"; OPEN_ARRAY( WIDE_ALPH_TYPE(), K() ); KEYS(); CLOSE_ARRAY() << "\n"; OPEN_ARRAY( ARRAY_TYPE(redFsm->maxSingleLen), SL() ); SINGLE_LENS(); CLOSE_ARRAY() << "\n"; OPEN_ARRAY( ARRAY_TYPE(redFsm->maxRangeLen), RL() ); RANGE_LENS(); CLOSE_ARRAY() << "\n"; OPEN_ARRAY( ARRAY_TYPE(redFsm->maxIndexOffset), IO() ); INDEX_OFFSETS(); CLOSE_ARRAY() << "\n"; if ( useIndicies ) { OPEN_ARRAY( ARRAY_TYPE(redFsm->maxIndex), I() ); INDICIES(); CLOSE_ARRAY() << "\n"; OPEN_ARRAY( ARRAY_TYPE(redFsm->maxState), TT() ); TRANS_TARGS_WI(); CLOSE_ARRAY() << "\n"; if ( redFsm->anyActions() ) { OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActListId), TA() ); TRANS_ACTIONS_WI(); CLOSE_ARRAY() << "\n"; } } else { OPEN_ARRAY( ARRAY_TYPE(redFsm->maxState), TT() ); TRANS_TARGS(); CLOSE_ARRAY() << "\n"; if ( redFsm->anyActions() ) { OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActListId), TA() ); TRANS_ACTIONS(); CLOSE_ARRAY() << "\n"; } } if ( redFsm->anyToStateActions() ) { OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActionLoc), TSA() ); TO_STATE_ACTIONS(); CLOSE_ARRAY() << "\n"; } if ( redFsm->anyFromStateActions() ) { OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActionLoc), FSA() ); FROM_STATE_ACTIONS(); CLOSE_ARRAY() << "\n"; } if ( redFsm->anyEofActions() ) { OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActListId), EA() ); EOF_ACTIONS(); CLOSE_ARRAY() << "\n"; } if ( redFsm->anyEofTrans() ) { OPEN_ARRAY( ARRAY_TYPE(redFsm->maxIndexOffset+1), ET() ); EOF_TRANS(); CLOSE_ARRAY() << "\n"; } STATE_IDS(); out << "type state = { mutable keys : int; mutable trans : int; }" << TOP_SEP(); out << "exception Goto_match" << TOP_SEP(); out << "exception Goto_again" << TOP_SEP(); out << "exception Goto_eof_trans" << TOP_SEP(); } void OCamlFTabCodeGen::writeExec() { testEofUsed = false; outLabelUsed = false; initVarTypes(); out << " begin\n"; // if ( redFsm->anyRegCurStateRef() ) // out << klenType ", _ps"; out << " let state = { keys = 0; trans = 0; } in\n" " let rec do_start () =\n"; // if ( redFsm->anyConditions() ) // out << " " << WIDE_ALPH_TYPE() << " _widec;\n"; if ( !noEnd ) { testEofUsed = true; out << " if " << P() << " = " << PE() << " then\n" " do_test_eof ()\n" "\telse\n"; } if ( redFsm->errState != 0 ) { outLabelUsed = true; out << " if " << vCS() << " = " << redFsm->errState->id << " then\n" " do_out ()\n" "\telse\n"; } out << "\tdo_resume ()\n"; out << "and do_resume () =\n"; if ( redFsm->anyFromStateActions() ) { out << " begin match " << AT( FSA(), vCS() ) << " with\n"; FROM_STATE_ACTION_SWITCH(); SWITCH_DEFAULT() << " end;\n" "\n"; } if ( redFsm->anyConditions() ) COND_TRANSLATE(); out << "\tbegin try\n"; LOCATE_TRANS(); out << "\twith Goto_match -> () end;\n"; out << "\tdo_match ()\n"; out << "and do_match () =\n"; if ( useIndicies ) out << " state.trans <- " << CAST(transType) << AT( I(), "state.trans" ) << ";\n"; out << "\tdo_eof_trans ()\n"; // if ( redFsm->anyEofTrans() ) out << "and do_eof_trans () =\n"; if ( redFsm->anyRegCurStateRef() ) out << " let ps = " << vCS() << " in\n"; out << " " << vCS() << " <- " << AT( TT() ,"state.trans" ) << ";\n" "\n"; if ( redFsm->anyRegActions() ) { out << " begin try if " << AT( TA() , "state.trans" ) << " = 0 then\n" " raise Goto_again;\n" "\n" " match " << AT( TA(), "state.trans" ) << " with\n"; ACTION_SWITCH(); SWITCH_DEFAULT() << " with Goto_again -> () end;\n" "\n"; } out << "\tdo_again ()\n"; // if ( redFsm->anyRegActions() || redFsm->anyActionGotos() || // redFsm->anyActionCalls() || redFsm->anyActionRets() ) out << "\tand do_again () =\n"; if ( redFsm->anyToStateActions() ) { out << " begin match " << AT( TSA(), vCS() ) << " with\n"; TO_STATE_ACTION_SWITCH(); SWITCH_DEFAULT() << " end;\n" "\n"; } if ( redFsm->errState != 0 ) { outLabelUsed = true; out << " match " << vCS() << " with\n" "\t| " << redFsm->errState->id << " -> do_out ()\n" "\t| _ ->\n"; } out << "\t" << P() << " <- " << P() << " + 1;\n"; if ( !noEnd ) { out << " if " << P() << " <> " << PE() << " then\n" " do_resume ()\n" "\telse do_test_eof ()\n"; } else { out << " do_resume ()\n"; } // if ( testEofUsed ) out << "and do_test_eof () =\n"; if ( redFsm->anyEofTrans() || redFsm->anyEofActions() ) { out << " if " << P() << " = " << vEOF() << " then\n" " begin try\n"; if ( redFsm->anyEofTrans() ) { out << " if " << AT( ET(), vCS() ) << " > 0 then\n" " begin\n" " state.trans <- " << CAST(transType) << "(" << AT( ET(), vCS() ) << " - 1);\n" " raise Goto_eof_trans;\n" " end;\n"; } if ( redFsm->anyEofActions() ) { out << " begin match " << AT( EA(), vCS() ) << " with\n"; EOF_ACTION_SWITCH(); SWITCH_DEFAULT() << " end\n"; } out << " with Goto_again -> do_again ()\n" " | Goto_eof_trans -> do_eof_trans () end\n" "\n"; } else { out << "\t()\n"; } if ( outLabelUsed ) out << " and do_out () = ()\n"; out << "\tin do_start ()\n"; out << " end;\n"; } ragel-6.8/ragel/gogoto.h0000664000175000017500000000475612106050031012145 00000000000000/* * Copyright 2001-2006 Adrian Thurston * 2004 Erich Ocean * 2005 Alan West */ /* This file is part of Ragel. * * Ragel is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Ragel is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Ragel; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef _GOGOTO_H #define _GOGOTO_H #include #include "gotablish.h" /* Forwards. */ struct CodeGenData; struct NameInst; struct RedTransAp; struct RedStateAp; struct GenStateCond; /* * Goto driven fsm. */ class GoGotoCodeGen : public GoTablishCodeGen { public: GoGotoCodeGen( ostream &out ) : GoTablishCodeGen(out) {} protected: std::ostream &TO_STATE_ACTION_SWITCH( int level ); std::ostream &FROM_STATE_ACTION_SWITCH( int level ); std::ostream &EOF_ACTION_SWITCH( int level ); std::ostream &ACTION_SWITCH( int level ); std::ostream &STATE_GOTOS( int level ); std::ostream &TRANSITIONS(); std::ostream &EXEC_FUNCS(); std::ostream &FINISH_CASES(); virtual unsigned int TO_STATE_ACTION( RedStateAp *state ); virtual unsigned int FROM_STATE_ACTION( RedStateAp *state ); virtual unsigned int EOF_ACTION( RedStateAp *state ); std::ostream &TO_STATE_ACTIONS(); std::ostream &FROM_STATE_ACTIONS(); std::ostream &EOF_ACTIONS(); void COND_TRANSLATE( GenStateCond *stateCond, int level ); void emitCondBSearch( RedStateAp *state, int level, int low, int high ); void STATE_CONDS( RedStateAp *state, bool genDefault ); virtual std::ostream &TRANS_GOTO( RedTransAp *trans, int level ); virtual int TRANS_NR( RedTransAp *trans ); void emitSingleSwitch( RedStateAp *state, int level ); void emitRangeBSearch( RedStateAp *state, int level, int low, int high ); /* Called from STATE_GOTOS just before writing the gotos */ virtual void GOTO_HEADER( RedStateAp *state, int level ); virtual void STATE_GOTO_ERROR( int level ); virtual void writeData(); virtual void writeExec(); }; #endif ragel-6.8/ragel/mlgoto.h0000664000175000017500000000573312106050031012144 00000000000000/* * Copyright 2001-2006 Adrian Thurston * 2004 Erich Ocean * 2005 Alan West */ /* This file is part of Ragel. * * Ragel is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Ragel is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Ragel; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef _MLGOTO_H #define _MLGOTO_H #include #include "mlcodegen.h" /* Forwards. */ //struct CodeGenData; //struct NameInst; //struct RedTransAp; //struct RedStateAp; //struct GenStateCond; /* * OCamlGotoCodeGen */ class OCamlGotoCodeGen : virtual public OCamlCodeGen { public: OCamlGotoCodeGen( ostream &out ) : OCamlCodeGen(out) {} std::ostream &TO_STATE_ACTION_SWITCH(); std::ostream &FROM_STATE_ACTION_SWITCH(); std::ostream &EOF_ACTION_SWITCH(); std::ostream &ACTION_SWITCH(); std::ostream &STATE_GOTOS(); std::ostream &TRANSITIONS(); std::ostream &EXEC_FUNCS(); std::ostream &FINISH_CASES(); void GOTO( ostream &ret, int gotoDest, bool inFinish ); void CALL( ostream &ret, int callDest, int targState, bool inFinish ); void NEXT( ostream &ret, int nextDest, bool inFinish ); void GOTO_EXPR( ostream &ret, GenInlineItem *ilItem, bool inFinish ); void NEXT_EXPR( ostream &ret, GenInlineItem *ilItem, bool inFinish ); void CALL_EXPR( ostream &ret, GenInlineItem *ilItem, int targState, bool inFinish ); void CURS( ostream &ret, bool inFinish ); void TARGS( ostream &ret, bool inFinish, int targState ); void RET( ostream &ret, bool inFinish ); void BREAK( ostream &ret, int targState ); virtual unsigned int TO_STATE_ACTION( RedStateAp *state ); virtual unsigned int FROM_STATE_ACTION( RedStateAp *state ); virtual unsigned int EOF_ACTION( RedStateAp *state ); std::ostream &TO_STATE_ACTIONS(); std::ostream &FROM_STATE_ACTIONS(); std::ostream &EOF_ACTIONS(); void COND_TRANSLATE( GenStateCond *stateCond, int level ); void emitCondBSearch( RedStateAp *state, int level, int low, int high ); void STATE_CONDS( RedStateAp *state, bool genDefault ); virtual std::ostream &TRANS_GOTO( RedTransAp *trans, int level ); void emitSingleSwitch( RedStateAp *state ); void emitRangeBSearch( RedStateAp *state, int level, int low, int high, RedTransAp* def ); /* Called from STATE_GOTOS just before writing the gotos */ virtual void GOTO_HEADER( RedStateAp *state ); virtual void STATE_GOTO_ERROR(); virtual void writeData(); virtual void writeExec(); }; #endif ragel-6.8/ragel/javacodegen.h0000664000175000017500000001463112106050031013106 00000000000000/* * Copyright 2006-2007 Adrian Thurston * 2007 Colin Fleming */ /* This file is part of Ragel. * * Ragel is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Ragel is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Ragel; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef _JAVACODEGEN_H #define _JAVACODEGEN_H #include #include #include #include "common.h" #include "gendata.h" using std::string; using std::ostream; /* * JavaTabCodeGen */ struct JavaTabCodeGen : public CodeGenData { JavaTabCodeGen( ostream &out ) : CodeGenData(out) {} std::ostream &TO_STATE_ACTION_SWITCH(); std::ostream &FROM_STATE_ACTION_SWITCH(); std::ostream &EOF_ACTION_SWITCH(); std::ostream &ACTION_SWITCH(); std::ostream &COND_KEYS(); std::ostream &COND_SPACES(); std::ostream &KEYS(); std::ostream &INDICIES(); std::ostream &COND_OFFSETS(); std::ostream &KEY_OFFSETS(); std::ostream &INDEX_OFFSETS(); std::ostream &COND_LENS(); std::ostream &SINGLE_LENS(); std::ostream &RANGE_LENS(); std::ostream &TO_STATE_ACTIONS(); std::ostream &FROM_STATE_ACTIONS(); std::ostream &EOF_ACTIONS(); std::ostream &EOF_TRANS(); std::ostream &TRANS_TARGS(); std::ostream &TRANS_ACTIONS(); std::ostream &TRANS_TARGS_WI(); std::ostream &TRANS_ACTIONS_WI(); void BREAK( ostream &ret, int targState ); void GOTO( ostream &ret, int gotoDest, bool inFinish ); void GOTO_EXPR( ostream &ret, GenInlineItem *ilItem, bool inFinish ); void CALL( ostream &ret, int callDest, int targState, bool inFinish ); void CALL_EXPR( ostream &ret, GenInlineItem *ilItem, int targState, bool inFinish ); void RET( ostream &ret, bool inFinish ); void COND_TRANSLATE(); void LOCATE_TRANS(); virtual void writeExec(); virtual void writeData(); virtual void writeInit(); virtual void writeExports(); virtual void writeStart(); virtual void writeFirstFinal(); virtual void writeError(); virtual void finishRagelDef(); void NEXT( ostream &ret, int nextDest, bool inFinish ); void NEXT_EXPR( ostream &ret, GenInlineItem *ilItem, bool inFinish ); int TO_STATE_ACTION( RedStateAp *state ); int FROM_STATE_ACTION( RedStateAp *state ); int EOF_ACTION( RedStateAp *state ); int TRANS_ACTION( RedTransAp *trans ); /* Determine if we should use indicies. */ void calcIndexSize(); private: string array_type; string array_name; int item_count; int div_count; public: virtual string NULL_ITEM(); virtual ostream &OPEN_ARRAY( string type, string name ); virtual ostream &ARRAY_ITEM( string item, bool last ); virtual ostream &CLOSE_ARRAY(); virtual ostream &STATIC_VAR( string type, string name ); virtual string ARR_OFF( string ptr, string offset ); virtual string CAST( string type ); virtual string GET_KEY(); virtual string CTRL_FLOW(); string FSM_NAME(); string START_STATE_ID(); ostream &ACTIONS_ARRAY(); string GET_WIDE_KEY(); string GET_WIDE_KEY( RedStateAp *state ); string TABS( int level ); string KEY( Key key ); string INT( int i ); void ACTION( ostream &ret, GenAction *action, int targState, bool inFinish ); void CONDITION( ostream &ret, GenAction *condition ); string ALPH_TYPE(); string WIDE_ALPH_TYPE(); string ARRAY_TYPE( unsigned long maxVal ); string ACCESS(); string P(); string PE(); string vEOF(); string vCS(); string STACK(); string TOP(); string TOKSTART(); string TOKEND(); string ACT(); string DATA(); string DATA_PREFIX(); string PM() { return "_" + DATA_PREFIX() + "partition_map"; } string C() { return "_" + DATA_PREFIX() + "cond_spaces"; } string CK() { return "_" + DATA_PREFIX() + "cond_keys"; } string K() { return "_" + DATA_PREFIX() + "trans_keys"; } string I() { return "_" + DATA_PREFIX() + "indicies"; } string CO() { return "_" + DATA_PREFIX() + "cond_offsets"; } string KO() { return "_" + DATA_PREFIX() + "key_offsets"; } string IO() { return "_" + DATA_PREFIX() + "index_offsets"; } string CL() { return "_" + DATA_PREFIX() + "cond_lengths"; } string SL() { return "_" + DATA_PREFIX() + "single_lengths"; } string RL() { return "_" + DATA_PREFIX() + "range_lengths"; } string A() { return "_" + DATA_PREFIX() + "actions"; } string TA() { return "_" + DATA_PREFIX() + "trans_actions"; } string TT() { return "_" + DATA_PREFIX() + "trans_targs"; } string TSA() { return "_" + DATA_PREFIX() + "to_state_actions"; } string FSA() { return "_" + DATA_PREFIX() + "from_state_actions"; } string EA() { return "_" + DATA_PREFIX() + "eof_actions"; } string ET() { return "_" + DATA_PREFIX() + "eof_trans"; } string SP() { return "_" + DATA_PREFIX() + "key_spans"; } string CSP() { return "_" + DATA_PREFIX() + "cond_key_spans"; } string START() { return DATA_PREFIX() + "start"; } string ERROR() { return DATA_PREFIX() + "error"; } string FIRST_FINAL() { return DATA_PREFIX() + "first_final"; } string CTXDATA() { return DATA_PREFIX() + "ctxdata"; } void INLINE_LIST( ostream &ret, GenInlineList *inlineList, int targState, bool inFinish ); void EXEC( ostream &ret, GenInlineItem *item, int targState, int inFinish ); void EXECTE( ostream &ret, GenInlineItem *item, int targState, int inFinish ); void LM_SWITCH( ostream &ret, GenInlineItem *item, int targState, int inFinish ); void SET_ACT( ostream &ret, GenInlineItem *item ); void INIT_TOKSTART( ostream &ret, GenInlineItem *item ); void INIT_ACT( ostream &ret, GenInlineItem *item ); void SET_TOKSTART( ostream &ret, GenInlineItem *item ); void SET_TOKEND( ostream &ret, GenInlineItem *item ); void GET_TOKEND( ostream &ret, GenInlineItem *item ); void SUB_ACTION( ostream &ret, GenInlineItem *item, int targState, bool inFinish ); string ERROR_STATE(); string FIRST_FINAL_STATE(); ostream &source_warning(const InputLoc &loc); ostream &source_error(const InputLoc &loc); unsigned int arrayTypeSize( unsigned long maxVal ); bool outLabelUsed; bool againLabelUsed; bool useIndicies; void genLineDirective( ostream &out ); }; #endif ragel-6.8/ragel/cdfflat.h0000664000175000017500000000421012106050031012233 00000000000000/* * Copyright 2004-2006 Adrian Thurston * 2004 Erich Ocean * 2005 Alan West */ /* This file is part of Ragel. * * Ragel is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Ragel is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Ragel; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef _CDFFLAT_H #define _CDFFLAT_H #include #include "cdflat.h" /* Forwards. */ struct CodeGenData; /* * FFlatCodeGen */ class FFlatCodeGen : public FlatCodeGen { protected: FFlatCodeGen( ostream &out ) : FsmCodeGen(out), FlatCodeGen(out) {} std::ostream &TO_STATE_ACTION_SWITCH(); std::ostream &FROM_STATE_ACTION_SWITCH(); std::ostream &EOF_ACTION_SWITCH(); std::ostream &ACTION_SWITCH(); virtual std::ostream &TO_STATE_ACTION( RedStateAp *state ); virtual std::ostream &FROM_STATE_ACTION( RedStateAp *state ); virtual std::ostream &EOF_ACTION( RedStateAp *state ); virtual std::ostream &TRANS_ACTION( RedTransAp *trans ); virtual void writeData(); virtual void writeExec(); }; /* * CFFlatCodeGen */ struct CFFlatCodeGen : public FFlatCodeGen, public CCodeGen { CFFlatCodeGen( ostream &out ) : FsmCodeGen(out), FFlatCodeGen(out), CCodeGen(out) {} }; /* * DFFlatCodeGen */ struct DFFlatCodeGen : public FFlatCodeGen, public DCodeGen { DFFlatCodeGen( ostream &out ) : FsmCodeGen(out), FFlatCodeGen(out), DCodeGen(out) {} }; /* * D2FFlatCodeGen */ struct D2FFlatCodeGen : public FFlatCodeGen, public D2CodeGen { D2FFlatCodeGen( ostream &out ) : FsmCodeGen(out), FFlatCodeGen(out), D2CodeGen(out) {} }; #endif ragel-6.8/ragel/common.h0000664000175000017500000002122312106050031012123 00000000000000/* * Copyright 2001-2006 Adrian Thurston */ /* This file is part of Ragel. * * Ragel is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Ragel is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Ragel; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef _COMMON_H #define _COMMON_H #include #include #include "dlist.h" /* Location in an input file. */ struct InputLoc { const char *fileName; long line; long col; }; typedef unsigned long long Size; struct Key { private: long key; public: friend inline Key operator+(const Key key1, const Key key2); friend inline Key operator-(const Key key1, const Key key2); friend inline Key operator/(const Key key1, const Key key2); friend inline long operator&(const Key key1, const Key key2); friend inline bool operator<( const Key key1, const Key key2 ); friend inline bool operator<=( const Key key1, const Key key2 ); friend inline bool operator>( const Key key1, const Key key2 ); friend inline bool operator>=( const Key key1, const Key key2 ); friend inline bool operator==( const Key key1, const Key key2 ); friend inline bool operator!=( const Key key1, const Key key2 ); friend struct KeyOps; Key( ) {} Key( const Key &key ) : key(key.key) {} Key( long key ) : key(key) {} /* Returns the value used to represent the key. This value must be * interpreted based on signedness. */ long getVal() const { return key; }; /* Returns the key casted to a long long. This form of the key does not * require any signedness interpretation. */ long long getLongLong() const; /* Returns the distance from the key value to the maximum value that the * key implementation can hold. */ Size availableSpace() const; bool isUpper() const { return ( 'A' <= key && key <= 'Z' ); } bool isLower() const { return ( 'a' <= key && key <= 'z' ); } bool isPrintable() const { return ( 7 <= key && key <= 13 ) || ( 32 <= key && key < 127 ); } Key toUpper() const { return Key( 'A' + ( key - 'a' ) ); } Key toLower() const { return Key( 'a' + ( key - 'A' ) ); } void operator+=( const Key other ) { /* FIXME: must be made aware of isSigned. */ key += other.key; } void operator-=( const Key other ) { /* FIXME: must be made aware of isSigned. */ key -= other.key; } void operator|=( const Key other ) { /* FIXME: must be made aware of isSigned. */ key |= other.key; } /* Decrement. Needed only for ranges. */ inline void decrement(); inline void increment(); }; struct HostType { const char *data1; const char *data2; const char *internalName; bool isSigned; bool isOrd; bool isChar; long long minVal; long long maxVal; unsigned int size; }; struct HostLang { /* Target language. */ enum Lang { C, D, D2, Go, Java, Ruby, CSharp, OCaml }; Lang lang; HostType *hostTypes; int numHostTypes; HostType *defaultAlphType; bool explicitUnsigned; }; extern HostLang *hostLang; extern HostLang hostLangC; extern HostLang hostLangD; extern HostLang hostLangD2; extern HostLang hostLangGo; extern HostLang hostLangJava; extern HostLang hostLangRuby; extern HostLang hostLangCSharp; extern HostLang hostLangOCaml; HostType *findAlphType( const char *s1 ); HostType *findAlphType( const char *s1, const char *s2 ); HostType *findAlphTypeInternal( const char *s1 ); /* An abstraction of the key operators that manages key operations such as * comparison and increment according the signedness of the key. */ struct KeyOps { /* Default to signed alphabet. */ KeyOps() : isSigned(true), alphType(0) {} /* Default to signed alphabet. */ KeyOps( bool isSigned ) :isSigned(isSigned) {} bool isSigned; Key minKey, maxKey; HostType *alphType; void setAlphType( HostType *alphType ) { this->alphType = alphType; isSigned = alphType->isSigned; if ( isSigned ) { minKey = (long) alphType->minVal; maxKey = (long) alphType->maxVal; } else { minKey = (long) (unsigned long) alphType->minVal; maxKey = (long) (unsigned long) alphType->maxVal; } } /* Compute the distance between two keys. */ Size span( Key key1, Key key2 ) { return isSigned ? (unsigned long long)( (long long)key2.key - (long long)key1.key + 1) : (unsigned long long)( (unsigned long)key2.key) - (unsigned long long)((unsigned long)key1.key) + 1; } Size alphSize() { return span( minKey, maxKey ); } HostType *typeSubsumes( long long maxVal ) { for ( int i = 0; i < hostLang->numHostTypes; i++ ) { if ( maxVal <= hostLang->hostTypes[i].maxVal ) return hostLang->hostTypes + i; } return 0; } HostType *typeSubsumes( bool isSigned, long long maxVal ) { for ( int i = 0; i < hostLang->numHostTypes; i++ ) { if ( ( ( isSigned && hostLang->hostTypes[i].isSigned ) || !isSigned ) && maxVal <= hostLang->hostTypes[i].maxVal ) return hostLang->hostTypes + i; } return 0; } }; extern KeyOps *keyOps; inline bool operator<( const Key key1, const Key key2 ) { return keyOps->isSigned ? key1.key < key2.key : (unsigned long)key1.key < (unsigned long)key2.key; } inline bool operator<=( const Key key1, const Key key2 ) { return keyOps->isSigned ? key1.key <= key2.key : (unsigned long)key1.key <= (unsigned long)key2.key; } inline bool operator>( const Key key1, const Key key2 ) { return keyOps->isSigned ? key1.key > key2.key : (unsigned long)key1.key > (unsigned long)key2.key; } inline bool operator>=( const Key key1, const Key key2 ) { return keyOps->isSigned ? key1.key >= key2.key : (unsigned long)key1.key >= (unsigned long)key2.key; } inline bool operator==( const Key key1, const Key key2 ) { return key1.key == key2.key; } inline bool operator!=( const Key key1, const Key key2 ) { return key1.key != key2.key; } /* Decrement. Needed only for ranges. */ inline void Key::decrement() { key = keyOps->isSigned ? key - 1 : ((unsigned long)key)-1; } /* Increment. Needed only for ranges. */ inline void Key::increment() { key = keyOps->isSigned ? key+1 : ((unsigned long)key)+1; } inline long long Key::getLongLong() const { return keyOps->isSigned ? (long long)key : (long long)(unsigned long)key; } inline Size Key::availableSpace() const { if ( keyOps->isSigned ) return (long long)LONG_MAX - (long long)key; else return (unsigned long long)ULONG_MAX - (unsigned long long)(unsigned long)key; } inline Key operator+(const Key key1, const Key key2) { /* FIXME: must be made aware of isSigned. */ return Key( key1.key + key2.key ); } inline Key operator-(const Key key1, const Key key2) { /* FIXME: must be made aware of isSigned. */ return Key( key1.key - key2.key ); } inline long operator&(const Key key1, const Key key2) { /* FIXME: must be made aware of isSigned. */ return key1.key & key2.key; } inline Key operator/(const Key key1, const Key key2) { /* FIXME: must be made aware of isSigned. */ return key1.key / key2.key; } /* Filter on the output stream that keeps track of the number of lines * output. */ class output_filter : public std::filebuf { public: output_filter( const char *fileName ) : fileName(fileName), line(1) { } virtual int sync(); virtual std::streamsize xsputn(const char* s, std::streamsize n); const char *fileName; int line; }; class cfilebuf : public std::streambuf { public: cfilebuf( char *fileName, FILE* file ) : fileName(fileName), file(file) { } char *fileName; FILE *file; int sync() { fflush( file ); return 0; } int overflow( int c ) { if ( c != EOF ) fputc( c, file ); return 0; } std::streamsize xsputn( const char* s, std::streamsize n ) { std::streamsize written = fwrite( s, 1, n, file ); return written; } }; class costream : public std::ostream { public: costream( cfilebuf *b ) : std::ostream(b), b(b) {} ~costream() { delete b; } void fclose() { ::fclose( b->file ); } cfilebuf *b; }; const char *findFileExtension( const char *stemFile ); const char *fileNameFromStem( const char *stemFile, const char *suffix ); struct Export { Export( const char *name, Key key ) : name(name), key(key) {} const char *name; Key key; Export *prev, *next; }; typedef DList ExportList; struct exit_object { }; extern exit_object endp; void operator<<( std::ostream &out, exit_object & ); #endif ragel-6.8/ragel/gogoto.cpp0000664000175000017500000005163012106050031012471 00000000000000/* * Copyright 2001-2006 Adrian Thurston * 2004 Erich Ocean * 2005 Alan West */ /* This file is part of Ragel. * * Ragel is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Ragel is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Ragel; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "ragel.h" #include "gogoto.h" #include "redfsm.h" #include "bstmap.h" #include "gendata.h" using std::endl; /* Emit the goto to take for a given transition. */ std::ostream &GoGotoCodeGen::TRANS_GOTO( RedTransAp *trans, int level ) { out << TABS(level) << "goto tr" << trans->id << ";"; return out; } int GoGotoCodeGen::TRANS_NR( RedTransAp *trans ) { return trans->id; } std::ostream &GoGotoCodeGen::TO_STATE_ACTION_SWITCH( int level ) { /* Walk the list of functions, printing the cases. */ for ( GenActionList::Iter act = actionList; act.lte(); act++ ) { /* Write out referenced actions. */ if ( act->numToStateRefs > 0 ) { /* Write the case label, the action and the case break. */ out << TABS(level) << "case " << act->actionId << ":" << endl; ACTION( out, act, 0, false, false ); } } genLineDirective( out ); return out; } std::ostream &GoGotoCodeGen::FROM_STATE_ACTION_SWITCH( int level ) { /* Walk the list of functions, printing the cases. */ for ( GenActionList::Iter act = actionList; act.lte(); act++ ) { /* Write out referenced actions. */ if ( act->numFromStateRefs > 0 ) { /* Write the case label, the action and the case break. */ out << TABS(level) << "case " << act->actionId << ":" << endl; ACTION( out, act, 0, false, false ); } } genLineDirective( out ); return out; } std::ostream &GoGotoCodeGen::EOF_ACTION_SWITCH( int level ) { /* Walk the list of functions, printing the cases. */ for ( GenActionList::Iter act = actionList; act.lte(); act++ ) { /* Write out referenced actions. */ if ( act->numEofRefs > 0 ) { /* Write the case label, the action and the case break. */ out << TABS(level) << "case " << act->actionId << ":" << endl; ACTION( out, act, 0, true, false ); } } genLineDirective( out ); return out; } std::ostream &GoGotoCodeGen::ACTION_SWITCH( int level ) { /* Walk the list of functions, printing the cases. */ for ( GenActionList::Iter act = actionList; act.lte(); act++ ) { /* Write out referenced actions. */ if ( act->numTransRefs > 0 ) { /* Write the case label, the action and the case break. */ out << TABS(level) << "case " << act->actionId << ":" << endl; ACTION( out, act, 0, false, false ); } } genLineDirective( out ); return out; } void GoGotoCodeGen::GOTO_HEADER( RedStateAp *state, int level ) { /* Label the state. */ out << TABS(level) << "case " << state->id << ":" << endl; } void GoGotoCodeGen::emitSingleSwitch( RedStateAp *state, int level ) { /* Load up the singles. */ int numSingles = state->outSingle.length(); RedTransEl *data = state->outSingle.data; if ( numSingles == 1 ) { /* If there is a single single key then write it out as an if. */ out << TABS(level) << "if " << GET_WIDE_KEY(state) << " == " << WIDE_KEY(state, data[0].lowKey) << " {" << endl; /* Virtual function for writing the target of the transition. */ TRANS_GOTO(data[0].value, level + 1) << endl; out << TABS(level) << "}" << endl; } else if ( numSingles > 1 ) { /* Write out single keys in a switch if there is more than one. */ out << TABS(level) << "switch " << GET_WIDE_KEY(state) << " {" << endl; /* Write out the single indicies. */ for ( int j = 0; j < numSingles; j++ ) { out << TABS(level) << "case " << WIDE_KEY(state, data[j].lowKey) << ":" << endl; TRANS_GOTO(data[j].value, level + 1) << endl; } /* Close off the transition switch. */ out << TABS(level) << "}" << endl; } } void GoGotoCodeGen::emitRangeBSearch( RedStateAp *state, int level, int low, int high ) { /* Get the mid position, staying on the lower end of the range. */ int mid = (low + high) >> 1; RedTransEl *data = state->outRange.data; /* Determine if we need to look higher or lower. */ bool anyLower = mid > low; bool anyHigher = mid < high; /* Determine if the keys at mid are the limits of the alphabet. */ bool limitLow = data[mid].lowKey == keyOps->minKey; bool limitHigh = data[mid].highKey == keyOps->maxKey; if ( anyLower && anyHigher ) { /* Can go lower and higher than mid. */ out << TABS(level) << "switch {" << endl; out << TABS(level) << "case " << GET_WIDE_KEY(state) << " < " << WIDE_KEY(state, data[mid].lowKey) << ":" << endl; emitRangeBSearch( state, level+1, low, mid-1 ); out << TABS(level) << "case " << GET_WIDE_KEY(state) << " > " << WIDE_KEY(state, data[mid].highKey) << ":" << endl; emitRangeBSearch( state, level+1, mid+1, high ); out << TABS(level) << "default:" << endl; TRANS_GOTO(data[mid].value, level+1) << endl; out << TABS(level) << "}" << endl; } else if ( anyLower && !anyHigher ) { /* Can go lower than mid but not higher. */ out << TABS(level) << "switch {" << endl; out << TABS(level) << "case " << GET_WIDE_KEY(state) << " < " << WIDE_KEY(state, data[mid].lowKey) << ":" << endl; emitRangeBSearch( state, level+1, low, mid-1 ); /* if the higher is the highest in the alphabet then there is no * sense testing it. */ if ( limitHigh ) { out << TABS(level) << "default:" << endl; TRANS_GOTO(data[mid].value, level+1) << endl; } else { out << TABS(level) << "case " << GET_WIDE_KEY(state) << " <= " << WIDE_KEY(state, data[mid].highKey) << ":" << endl; TRANS_GOTO(data[mid].value, level+1) << endl; } out << TABS(level) << "}" << endl; } else if ( !anyLower && anyHigher ) { /* Can go higher than mid but not lower. */ out << TABS(level) << "switch {" << endl; out << TABS(level) << "case " << GET_WIDE_KEY(state) << " > " << WIDE_KEY(state, data[mid].highKey) << ":" << endl; emitRangeBSearch( state, level+1, mid+1, high ); /* If the lower end is the lowest in the alphabet then there is no * sense testing it. */ if ( limitLow ) { out << TABS(level) << "default:" << endl; TRANS_GOTO(data[mid].value, level+1) << endl; } else { out << TABS(level) << "case " << GET_WIDE_KEY(state) << " >= " << WIDE_KEY(state, data[mid].lowKey) << ":" << endl; TRANS_GOTO(data[mid].value, level+1) << endl; } out << TABS(level) << "}" << endl; } else { /* Cannot go higher or lower than mid. It's mid or bust. What * tests to do depends on limits of alphabet. */ if ( !limitLow && !limitHigh ) { out << TABS(level) << "if " << WIDE_KEY(state, data[mid].lowKey) << " <= " << GET_WIDE_KEY(state) << " && " << GET_WIDE_KEY(state) << " <= " << WIDE_KEY(state, data[mid].highKey) << " {" << endl; TRANS_GOTO(data[mid].value, level+1) << endl; out << TABS(level) << "}" << endl; } else if ( limitLow && !limitHigh ) { out << TABS(level) << "if " << GET_WIDE_KEY(state) << " <= " << WIDE_KEY(state, data[mid].highKey) << " {" << endl; TRANS_GOTO(data[mid].value, level+1) << endl; out << TABS(level) << "}" << endl; } else if ( !limitLow && limitHigh ) { out << TABS(level) << "if " << WIDE_KEY(state, data[mid].lowKey) << " <= " << GET_WIDE_KEY(state) << " {" << endl; TRANS_GOTO(data[mid].value, level+1) << endl; out << TABS(level) << "}" << endl; } else { /* Both high and low are at the limit. No tests to do. */ TRANS_GOTO(data[mid].value, level) << endl; } } } void GoGotoCodeGen::STATE_GOTO_ERROR( int level ) { /* Label the state and bail immediately. */ outLabelUsed = true; RedStateAp *state = redFsm->errState; out << TABS(level) << "case " << state->id << ":" << endl; out << TABS(level + 1) << "goto _out" << endl; } void GoGotoCodeGen::COND_TRANSLATE( GenStateCond *stateCond, int level ) { GenCondSpace *condSpace = stateCond->condSpace; out << TABS(level) << "_widec = " << KEY(condSpace->baseKey) << " + (" << CAST(WIDE_ALPH_TYPE(), GET_KEY()) << " - " << KEY(keyOps->minKey) << ")" << endl; for ( GenCondSet::Iter csi = condSpace->condSet; csi.lte(); csi++ ) { out << TABS(level) << "if "; CONDITION( out, *csi ); Size condValOffset = ((1 << csi.pos()) * keyOps->alphSize()); out << " {" << endl; out << TABS(level + 1) << "_widec += " << condValOffset << endl; out << TABS(level) << "}" << endl; } } void GoGotoCodeGen::emitCondBSearch( RedStateAp *state, int level, int low, int high ) { /* Get the mid position, staying on the lower end of the range. */ int mid = (low + high) >> 1; GenStateCond **data = state->stateCondVect.data; /* Determine if we need to look higher or lower. */ bool anyLower = mid > low; bool anyHigher = mid < high; /* Determine if the keys at mid are the limits of the alphabet. */ bool limitLow = data[mid]->lowKey == keyOps->minKey; bool limitHigh = data[mid]->highKey == keyOps->maxKey; if ( anyLower && anyHigher ) { /* Can go lower and higher than mid. */ out << TABS(level) << "switch {" << endl; out << TABS(level) << "case " << GET_KEY() << " < " << KEY(data[mid]->lowKey) << ":" << endl; emitCondBSearch( state, level+1, low, mid-1 ); out << TABS(level) << "case " << GET_KEY() << " > " << KEY(data[mid]->highKey) << ":" << endl; emitCondBSearch( state, level+1, mid+1, high ); out << TABS(level) << "default:" << endl; COND_TRANSLATE(data[mid], level+1); out << TABS(level) << "}" << endl; } else if ( anyLower && !anyHigher ) { /* Can go lower than mid but not higher. */ out << TABS(level) << "switch {" << endl; out << TABS(level) << "case " << GET_KEY() << " < " << KEY(data[mid]->lowKey) << ":" << endl; emitCondBSearch( state, level+1, low, mid-1 ); /* if the higher is the highest in the alphabet then there is no * sense testing it. */ if ( limitHigh ) { out << TABS(level) << "default:" << endl; COND_TRANSLATE(data[mid], level+1); } else { out << TABS(level) << "case " << GET_KEY() << " <= " << KEY(data[mid]->highKey) << ":" << endl; COND_TRANSLATE(data[mid], level+1); } out << TABS(level) << "}" << endl; } else if ( !anyLower && anyHigher ) { /* Can go higher than mid but not lower. */ out << TABS(level) << "switch {" << endl; out << TABS(level) << "case " << GET_KEY() << " > " << KEY(data[mid]->highKey) << ":" << endl; emitCondBSearch( state, level+1, mid+1, high ); /* If the lower end is the lowest in the alphabet then there is no * sense testing it. */ if ( limitLow ) { out << TABS(level) << "default:" << endl; COND_TRANSLATE(data[mid], level+1); } else { out << TABS(level) << "case " << GET_KEY() << " >= " << KEY(data[mid]->lowKey) << ":" << endl; COND_TRANSLATE(data[mid], level+1); } out << TABS(level) << "}" << endl; } else { /* Cannot go higher or lower than mid. It's mid or bust. What * tests to do depends on limits of alphabet. */ if ( !limitLow && !limitHigh ) { out << TABS(level) << "if " << KEY(data[mid]->lowKey) << " <= " << GET_KEY() << " && " << GET_KEY() << " <= " << KEY(data[mid]->highKey) << " {" << endl; COND_TRANSLATE(data[mid], level+1); out << TABS(level) << "}" << endl; } else if ( limitLow && !limitHigh ) { out << TABS(level) << "if " << GET_KEY() << " <= " << KEY(data[mid]->highKey) << " {" << endl; COND_TRANSLATE(data[mid], level+1); out << TABS(level) << "}" << endl; } else if ( !limitLow && limitHigh ) { out << TABS(level) << "if " << KEY(data[mid]->lowKey) << " <= " << GET_KEY() << " {" << endl; COND_TRANSLATE(data[mid], level+1); out << TABS(level) << "}" << endl; } else { /* Both high and low are at the limit. No tests to do. */ COND_TRANSLATE(data[mid], level); } } } std::ostream &GoGotoCodeGen::STATE_GOTOS( int level ) { for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { if ( st == redFsm->errState ) STATE_GOTO_ERROR(level); else { /* Writing code above state gotos. */ GOTO_HEADER( st, level ); if ( st->stateCondVect.length() > 0 ) { out << TABS(level + 1) << "_widec = " << CAST(WIDE_ALPH_TYPE(), GET_KEY()) << endl; emitCondBSearch( st, level + 1, 0, st->stateCondVect.length() - 1 ); } /* Try singles. */ if ( st->outSingle.length() > 0 ) emitSingleSwitch( st, level + 1 ); /* Default case is to binary search for the ranges, if that fails then */ if ( st->outRange.length() > 0 ) emitRangeBSearch( st, level + 1, 0, st->outRange.length() - 1 ); /* Write the default transition. */ TRANS_GOTO( st->defTrans, level + 1 ) << endl; } } return out; } std::ostream &GoGotoCodeGen::TRANSITIONS() { /* Emit any transitions that have functions and that go to * this state. */ for ( TransApSet::Iter trans = redFsm->transSet; trans.lte(); trans++ ) { /* Write the label for the transition so it can be jumped to. */ out << " tr" << trans->id << ": "; /* Destination state. */ if ( trans->action != 0 && trans->action->anyCurStateRef() ) out << "_ps = " << vCS() << ";"; out << vCS() << " = " << trans->targ->id << "; "; if ( trans->action != 0 ) { /* Write out the transition func. */ out << "goto f" << trans->action->actListId << endl; } else { /* No code to execute, just loop around. */ out << "goto _again" << endl; } } return out; } std::ostream &GoGotoCodeGen::EXEC_FUNCS() { /* Make labels that set acts and jump to execFuncs. Loop func indicies. */ for ( GenActionTableMap::Iter redAct = redFsm->actionMap; redAct.lte(); redAct++ ) { if ( redAct->numTransRefs > 0 ) { out << " f" << redAct->actListId << ": " << "_acts = " << (redAct->location + 1) << ";" " goto execFuncs" << endl; } } out << endl << "execFuncs:" << endl << " _nacts = " << CAST(UINT(), A() + "[_acts]") << "; _acts++" << endl << " for ; _nacts > 0; _nacts-- {" << endl << " _acts++" << endl << " switch " << A() << "[_acts - 1]" << " {" << endl; ACTION_SWITCH(2); out << " }" << endl << " }" << endl << " goto _again" << endl; return out; } unsigned int GoGotoCodeGen::TO_STATE_ACTION( RedStateAp *state ) { int act = 0; if ( state->toStateAction != 0 ) act = state->toStateAction->location+1; return act; } unsigned int GoGotoCodeGen::FROM_STATE_ACTION( RedStateAp *state ) { int act = 0; if ( state->fromStateAction != 0 ) act = state->fromStateAction->location+1; return act; } unsigned int GoGotoCodeGen::EOF_ACTION( RedStateAp *state ) { int act = 0; if ( state->eofAction != 0 ) act = state->eofAction->location+1; return act; } std::ostream &GoGotoCodeGen::TO_STATE_ACTIONS() { /* Take one off for the psuedo start state. */ int numStates = redFsm->stateList.length(); unsigned int *vals = new unsigned int[numStates]; memset( vals, 0, sizeof(unsigned int)*numStates ); for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) vals[st->id] = TO_STATE_ACTION(st); out << " "; for ( int st = 0; st < redFsm->nextStateId; st++ ) { /* Write any eof action. */ out << vals[st] << ", "; if ( st < numStates-1 ) { if ( (st+1) % IALL == 0 ) out << endl << " "; } } out << endl; delete[] vals; return out; } std::ostream &GoGotoCodeGen::FROM_STATE_ACTIONS() { /* Take one off for the psuedo start state. */ int numStates = redFsm->stateList.length(); unsigned int *vals = new unsigned int[numStates]; memset( vals, 0, sizeof(unsigned int)*numStates ); for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) vals[st->id] = FROM_STATE_ACTION(st); out << " "; for ( int st = 0; st < redFsm->nextStateId; st++ ) { /* Write any eof action. */ out << vals[st] << ", "; if ( st < numStates-1 ) { if ( (st+1) % IALL == 0 ) out << endl << " "; } } out << endl; delete[] vals; return out; } std::ostream &GoGotoCodeGen::EOF_ACTIONS() { /* Take one off for the psuedo start state. */ int numStates = redFsm->stateList.length(); unsigned int *vals = new unsigned int[numStates]; memset( vals, 0, sizeof(unsigned int)*numStates ); for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) vals[st->id] = EOF_ACTION(st); out << " "; for ( int st = 0; st < redFsm->nextStateId; st++ ) { /* Write any eof action. */ out << vals[st] << ", "; if ( st < numStates-1 ) { if ( (st+1) % IALL == 0 ) out << endl << " "; } } out << endl; delete[] vals; return out; } std::ostream &GoGotoCodeGen::FINISH_CASES() { for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { /* States that are final and have an out action need a case. */ if ( st->eofAction != 0 ) { /* Write the case label. */ out << TABS(2) << "case " << st->id << ":" << endl; /* Write the goto func. */ out << TABS(3) << "goto f" << st->eofAction->actListId << endl; } } return out; } void GoGotoCodeGen::writeData() { if ( redFsm->anyActions() ) { OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActArrItem), A() ); ACTIONS_ARRAY(); CLOSE_ARRAY() << endl; } if ( redFsm->anyToStateActions() ) { OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActionLoc), TSA() ); TO_STATE_ACTIONS(); CLOSE_ARRAY() << endl; } if ( redFsm->anyFromStateActions() ) { OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActionLoc), FSA() ); FROM_STATE_ACTIONS(); CLOSE_ARRAY() << endl; } if ( redFsm->anyEofActions() ) { OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActionLoc), EA() ); EOF_ACTIONS(); CLOSE_ARRAY() << endl; } STATE_IDS(); } void GoGotoCodeGen::writeExec() { testEofUsed = false; outLabelUsed = false; out << " {" << endl; if ( redFsm->anyRegCurStateRef() ) out << " var _ps " << INT() << " = 0" << endl; if ( redFsm->anyToStateActions() || redFsm->anyRegActions() || redFsm->anyFromStateActions() ) { out << " var _acts " << INT() << endl << " var _nacts " << UINT() << endl; } if ( redFsm->anyConditions() ) out << " var _widec " << WIDE_ALPH_TYPE() << endl; out << endl; if ( !noEnd ) { testEofUsed = true; out << " if " << P() << " == " << PE() << " {" << endl << " goto _test_eof" << endl << " }" << endl; } if ( redFsm->errState != 0 ) { outLabelUsed = true; out << " if " << vCS() << " == " << redFsm->errState->id << " {" << endl << " goto _out" << endl << " }" << endl; } out << "_resume:" << endl; if ( redFsm->anyFromStateActions() ) { out << " _acts = " << CAST(INT(), FSA() + "[" + vCS() + "]") << endl << " _nacts = " << CAST(UINT(), A() + "[_acts]") << "; _acts++" << endl << " for ; _nacts > 0; _nacts-- {" << endl << " _acts++" << endl << " switch " << A() << "[_acts - 1]" << " {" << endl; FROM_STATE_ACTION_SWITCH(2); out << " }" << endl << " }" << endl << endl; } out << " switch " << vCS() << " {" << endl; STATE_GOTOS(1); out << " }" << endl << endl; TRANSITIONS() << endl; if ( redFsm->anyRegActions() ) EXEC_FUNCS() << endl; out << "_again:" << endl; if ( redFsm->anyToStateActions() ) { out << " _acts = " << CAST(INT(), TSA() + "[" + vCS() + "]") << endl << " _nacts = " << CAST(UINT(), A() + "[_acts]") << "; _acts++" << endl << " for ; _nacts > 0; _nacts-- {" << endl << " _acts++" << endl << " switch " << A() << "[_acts - 1]" << " {" << endl; TO_STATE_ACTION_SWITCH(2); out << " }" << endl << " }" << endl << endl; } if ( redFsm->errState != 0 ) { outLabelUsed = true; out << " if " << vCS() << " == " << redFsm->errState->id << " {" << endl << " goto _out" << endl << " }" << endl; } if ( !noEnd ) { out << " if " << P() << "++; " << P() << " != " << PE() << " {" << endl << " goto _resume" << endl << " }" << endl; } else { out << " " << P() << "++" << endl << " goto _resume" << endl; } if ( testEofUsed ) out << " _test_eof: {}" << endl; if ( redFsm->anyEofTrans() || redFsm->anyEofActions() ) { out << " if " << P() << " == " << vEOF() << " {" << endl; if ( redFsm->anyEofTrans() ) { out << " switch " << vCS() << " {" << endl; for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { if ( st->eofTrans != 0 ) out << " case " << st->id << ":" << endl << " goto tr" << st->eofTrans->id << endl; } out << " }" << endl; } if ( redFsm->anyEofActions() ) { out << " __acts := " << CAST(INT(), EA() + "[" + vCS() + "]") << endl << " __nacts := " << CAST(UINT(), A() + "[__acts]") << "; __acts++" << endl << " for ; __nacts > 0; __nacts-- {" << endl << " __acts++" << endl << " switch " << A() << "[__acts - 1]" << " {" << endl; EOF_ACTION_SWITCH(3); out << " }" << endl << " }" << endl; } out << " }" << endl << endl; } if ( outLabelUsed ) out << " _out: {}" << endl; out << " }" << endl; } ragel-6.8/ragel/rlscan.cpp0000664000175000017500000041737412106307076012506 00000000000000 #line 1 "rlscan.rl" /* * Copyright 2006-2007 Adrian Thurston * Copyright 2011 Josef Goettgens */ /* This file is part of Ragel. * * Ragel is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Ragel is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Ragel; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #include #include "ragel.h" #include "rlscan.h" #include "inputdata.h" //#define LOG_TOKENS using std::ifstream; using std::istream; using std::ostream; using std::cout; using std::cerr; using std::endl; enum InlineBlockType { CurlyDelimited, SemiTerminated }; #ifdef _WIN32 #define PATH_SEP '\\' #else #define PATH_SEP '/' #endif /* * The Scanner for Importing */ #line 125 "rlscan.rl" #line 65 "rlscan.cpp" static const int inline_token_scan_start = 2; static const int inline_token_scan_first_final = 2; static const int inline_token_scan_error = -1; static const int inline_token_scan_en_main = 2; #line 128 "rlscan.rl" void Scanner::flushImport() { int *p = token_data; int *pe = token_data + cur_token; int *eof = 0; #line 82 "rlscan.cpp" { tok_cs = inline_token_scan_start; tok_ts = 0; tok_te = 0; tok_act = 0; } #line 90 "rlscan.cpp" { if ( p == pe ) goto _test_eof; switch ( tok_cs ) { tr0: #line 123 "rlscan.rl" {{p = (( tok_te))-1;}} goto st2; tr1: #line 109 "rlscan.rl" { tok_te = p+1;{ int base = tok_ts - token_data; int nameOff = 0; int litOff = 2; directToParser( inclToParser, fileName, line, column, TK_Word, token_strings[base+nameOff], token_lens[base+nameOff] ); directToParser( inclToParser, fileName, line, column, '=', 0, 0 ); directToParser( inclToParser, fileName, line, column, TK_Literal, token_strings[base+litOff], token_lens[base+litOff] ); directToParser( inclToParser, fileName, line, column, ';', 0, 0 ); }} goto st2; tr2: #line 81 "rlscan.rl" { tok_te = p+1;{ int base = tok_ts - token_data; int nameOff = 0; int numOff = 2; directToParser( inclToParser, fileName, line, column, TK_Word, token_strings[base+nameOff], token_lens[base+nameOff] ); directToParser( inclToParser, fileName, line, column, '=', 0, 0 ); directToParser( inclToParser, fileName, line, column, TK_UInt, token_strings[base+numOff], token_lens[base+numOff] ); directToParser( inclToParser, fileName, line, column, ';', 0, 0 ); }} goto st2; tr3: #line 95 "rlscan.rl" { tok_te = p+1;{ int base = tok_ts - token_data; int nameOff = 1; int litOff = 2; directToParser( inclToParser, fileName, line, column, TK_Word, token_strings[base+nameOff], token_lens[base+nameOff] ); directToParser( inclToParser, fileName, line, column, '=', 0, 0 ); directToParser( inclToParser, fileName, line, column, TK_Literal, token_strings[base+litOff], token_lens[base+litOff] ); directToParser( inclToParser, fileName, line, column, ';', 0, 0 ); }} goto st2; tr4: #line 67 "rlscan.rl" { tok_te = p+1;{ int base = tok_ts - token_data; int nameOff = 1; int numOff = 2; directToParser( inclToParser, fileName, line, column, TK_Word, token_strings[base+nameOff], token_lens[base+nameOff] ); directToParser( inclToParser, fileName, line, column, '=', 0, 0 ); directToParser( inclToParser, fileName, line, column, TK_UInt, token_strings[base+numOff], token_lens[base+numOff] ); directToParser( inclToParser, fileName, line, column, ';', 0, 0 ); }} goto st2; tr5: #line 123 "rlscan.rl" { tok_te = p+1;} goto st2; tr8: #line 123 "rlscan.rl" { tok_te = p;p--;} goto st2; st2: #line 1 "NONE" { tok_ts = 0;} if ( ++p == pe ) goto _test_eof2; case 2: #line 1 "NONE" { tok_ts = p;} #line 176 "rlscan.cpp" switch( (*p) ) { case 128: goto tr6; case 131: goto tr7; } goto tr5; tr6: #line 1 "NONE" { tok_te = p+1;} goto st3; st3: if ( ++p == pe ) goto _test_eof3; case 3: #line 190 "rlscan.cpp" if ( (*p) == 61 ) goto st0; goto tr8; st0: if ( ++p == pe ) goto _test_eof0; case 0: switch( (*p) ) { case 129: goto tr1; case 130: goto tr2; } goto tr0; tr7: #line 1 "NONE" { tok_te = p+1;} goto st4; st4: if ( ++p == pe ) goto _test_eof4; case 4: #line 211 "rlscan.cpp" if ( (*p) == 128 ) goto st1; goto tr8; st1: if ( ++p == pe ) goto _test_eof1; case 1: switch( (*p) ) { case 129: goto tr3; case 130: goto tr4; } goto tr0; } _test_eof2: tok_cs = 2; goto _test_eof; _test_eof3: tok_cs = 3; goto _test_eof; _test_eof0: tok_cs = 0; goto _test_eof; _test_eof4: tok_cs = 4; goto _test_eof; _test_eof1: tok_cs = 1; goto _test_eof; _test_eof: {} if ( p == eof ) { switch ( tok_cs ) { case 3: goto tr8; case 0: goto tr0; case 4: goto tr8; case 1: goto tr0; } } } #line 139 "rlscan.rl" if ( tok_ts == 0 ) cur_token = 0; else { cur_token = pe - tok_ts; int ts_offset = tok_ts - token_data; memmove( token_data, token_data+ts_offset, cur_token*sizeof(token_data[0]) ); memmove( token_strings, token_strings+ts_offset, cur_token*sizeof(token_strings[0]) ); memmove( token_lens, token_lens+ts_offset, cur_token*sizeof(token_lens[0]) ); } } void Scanner::directToParser( Parser *toParser, const char *tokFileName, int tokLine, int tokColumn, int type, char *tokdata, int toklen ) { InputLoc loc; #ifdef LOG_TOKENS cerr << "scanner:" << tokLine << ":" << tokColumn << ": sending token to the parser " << Parser_lelNames[type]; cerr << " " << toklen; if ( tokdata != 0 ) cerr << " " << tokdata; cerr << endl; #endif loc.fileName = tokFileName; loc.line = tokLine; loc.col = tokColumn; toParser->token( loc, type, tokdata, toklen ); } void Scanner::importToken( int token, char *start, char *end ) { if ( cur_token == max_tokens ) flushImport(); token_data[cur_token] = token; if ( start == 0 ) { token_strings[cur_token] = 0; token_lens[cur_token] = 0; } else { int toklen = end-start; token_lens[cur_token] = toklen; token_strings[cur_token] = new char[toklen+1]; memcpy( token_strings[cur_token], start, toklen ); token_strings[cur_token][toklen] = 0; } cur_token++; } void Scanner::pass( int token, char *start, char *end ) { if ( importMachines ) importToken( token, start, end ); pass(); } void Scanner::pass() { updateCol(); /* If no errors and we are at the bottom of the include stack (the * source file listed on the command line) then write out the data. */ if ( includeDepth == 0 && machineSpec == 0 && machineName == 0 ) id.inputItems.tail->data.write( ts, te-ts ); } /* * The scanner for processing sections, includes, imports, etc. */ #line 321 "rlscan.cpp" static const int section_parse_start = 10; static const int section_parse_first_final = 10; static const int section_parse_error = 0; static const int section_parse_en_main = 10; #line 218 "rlscan.rl" void Scanner::init( ) { #line 336 "rlscan.cpp" { cs = section_parse_start; } #line 224 "rlscan.rl" } bool Scanner::active() { if ( ignoreSection ) return false; if ( parser == 0 && ! parserExistsError ) { scan_error() << "this specification has no name, nor does any previous" " specification" << endl; parserExistsError = true; } if ( parser == 0 ) return false; return true; } ostream &Scanner::scan_error() { /* Maintain the error count. */ gblErrorCount += 1; cerr << makeInputLoc( fileName, line, column ) << ": "; return cerr; } /* An approximate check for duplicate includes. Due to aliasing of files it's * possible for duplicates to creep in. */ bool Scanner::duplicateInclude( char *inclFileName, char *inclSectionName ) { for ( IncludeHistory::Iter hi = parser->includeHistory; hi.lte(); hi++ ) { if ( strcmp( hi->fileName, inclFileName ) == 0 && strcmp( hi->sectionName, inclSectionName ) == 0 ) { return true; } } return false; } void Scanner::updateCol() { char *from = lastnl; if ( from == 0 ) from = ts; //cerr << "adding " << te - from << " to column" << endl; column += te - from; lastnl = 0; } void Scanner::handleMachine() { /* Assign a name to the machine. */ char *machine = word; if ( !importMachines && inclSectionTarg == 0 ) { ignoreSection = false; ParserDictEl *pdEl = id.parserDict.find( machine ); if ( pdEl == 0 ) { pdEl = new ParserDictEl( machine ); pdEl->value = new Parser( fileName, machine, sectionLoc ); pdEl->value->init(); id.parserDict.insert( pdEl ); id.parserList.append( pdEl->value ); } parser = pdEl->value; } else if ( !importMachines && strcmp( inclSectionTarg, machine ) == 0 ) { /* found include target */ ignoreSection = false; parser = inclToParser; } else { /* ignoring section */ ignoreSection = true; parser = 0; } } void Scanner::handleInclude() { if ( active() ) { char *inclSectionName = word; char **includeChecks = 0; /* Implement defaults for the input file and section name. */ if ( inclSectionName == 0 ) inclSectionName = parser->sectionName; if ( lit != 0 ) includeChecks = makeIncludePathChecks( fileName, lit, lit_len ); else { char *test = new char[strlen(fileName)+1]; strcpy( test, fileName ); includeChecks = new char*[2]; includeChecks[0] = test; includeChecks[1] = 0; } long found = 0; ifstream *inFile = tryOpenInclude( includeChecks, found ); if ( inFile == 0 ) { scan_error() << "include: failed to locate file" << endl; char **tried = includeChecks; while ( *tried != 0 ) scan_error() << "include: attempted: \"" << *tried++ << '\"' << endl; } else { /* Don't include anything that's already been included. */ if ( !duplicateInclude( includeChecks[found], inclSectionName ) ) { parser->includeHistory.append( IncludeHistoryItem( includeChecks[found], inclSectionName ) ); Scanner scanner( id, includeChecks[found], *inFile, parser, inclSectionName, includeDepth+1, false ); scanner.do_scan( ); delete inFile; } } } } void Scanner::handleImport() { if ( active() ) { char **importChecks = makeIncludePathChecks( fileName, lit, lit_len ); /* Open the input file for reading. */ long found = 0; ifstream *inFile = tryOpenInclude( importChecks, found ); if ( inFile == 0 ) { scan_error() << "import: could not open import file " << "for reading" << endl; char **tried = importChecks; while ( *tried != 0 ) scan_error() << "import: attempted: \"" << *tried++ << '\"' << endl; } Scanner scanner( id, importChecks[found], *inFile, parser, 0, includeDepth+1, true ); scanner.do_scan( ); scanner.importToken( 0, 0, 0 ); scanner.flushImport(); delete inFile; } } #line 461 "rlscan.rl" void Scanner::token( int type, char c ) { token( type, &c, &c + 1 ); } void Scanner::token( int type ) { token( type, 0, 0 ); } void Scanner::token( int type, char *start, char *end ) { char *tokdata = 0; int toklen = 0; if ( start != 0 ) { toklen = end-start; tokdata = new char[toklen+1]; memcpy( tokdata, start, toklen ); tokdata[toklen] = 0; } processToken( type, tokdata, toklen ); } void Scanner::processToken( int type, char *tokdata, int toklen ) { int *p, *pe, *eof; if ( type < 0 ) p = pe = eof = 0; else { p = &type; pe = &type + 1; eof = 0; } #line 535 "rlscan.cpp" { if ( p == pe ) goto _test_eof; switch ( cs ) { tr2: #line 391 "rlscan.rl" { handleMachine(); } goto st10; tr6: #line 392 "rlscan.rl" { handleInclude(); } goto st10; tr10: #line 393 "rlscan.rl" { handleImport(); } goto st10; tr13: #line 433 "rlscan.rl" { if ( active() && machineSpec == 0 && machineName == 0 ) id.inputItems.tail->writeArgs.append( 0 ); } goto st10; tr14: #line 444 "rlscan.rl" { /* Send the token off to the parser. */ if ( active() ) directToParser( parser, fileName, line, column, type, tokdata, toklen ); } goto st10; st10: if ( ++p == pe ) goto _test_eof10; case 10: #line 572 "rlscan.cpp" switch( (*p) ) { case 191: goto st1; case 192: goto st3; case 193: goto st6; case 194: goto tr18; } goto tr14; st1: if ( ++p == pe ) goto _test_eof1; case 1: if ( (*p) == 128 ) goto tr1; goto tr0; tr0: #line 386 "rlscan.rl" { scan_error() << "bad machine statement" << endl; } goto st0; tr3: #line 387 "rlscan.rl" { scan_error() << "bad include statement" << endl; } goto st0; tr8: #line 388 "rlscan.rl" { scan_error() << "bad import statement" << endl; } goto st0; tr11: #line 389 "rlscan.rl" { scan_error() << "bad write statement" << endl; } goto st0; #line 603 "rlscan.cpp" st0: cs = 0; goto _out; tr1: #line 383 "rlscan.rl" { word = tokdata; word_len = toklen; } goto st2; st2: if ( ++p == pe ) goto _test_eof2; case 2: #line 615 "rlscan.cpp" if ( (*p) == 59 ) goto tr2; goto tr0; st3: if ( ++p == pe ) goto _test_eof3; case 3: switch( (*p) ) { case 128: goto tr4; case 129: goto tr5; } goto tr3; tr4: #line 382 "rlscan.rl" { word = lit = 0; word_len = lit_len = 0; } #line 383 "rlscan.rl" { word = tokdata; word_len = toklen; } goto st4; st4: if ( ++p == pe ) goto _test_eof4; case 4: #line 638 "rlscan.cpp" switch( (*p) ) { case 59: goto tr6; case 129: goto tr7; } goto tr3; tr5: #line 382 "rlscan.rl" { word = lit = 0; word_len = lit_len = 0; } #line 384 "rlscan.rl" { lit = tokdata; lit_len = toklen; } goto st5; tr7: #line 384 "rlscan.rl" { lit = tokdata; lit_len = toklen; } goto st5; st5: if ( ++p == pe ) goto _test_eof5; case 5: #line 658 "rlscan.cpp" if ( (*p) == 59 ) goto tr6; goto tr3; st6: if ( ++p == pe ) goto _test_eof6; case 6: if ( (*p) == 129 ) goto tr9; goto tr8; tr9: #line 384 "rlscan.rl" { lit = tokdata; lit_len = toklen; } goto st7; st7: if ( ++p == pe ) goto _test_eof7; case 7: #line 677 "rlscan.cpp" if ( (*p) == 59 ) goto tr10; goto tr8; tr18: #line 413 "rlscan.rl" { if ( active() && machineSpec == 0 && machineName == 0 ) { InputItem *inputItem = new InputItem; inputItem->type = InputItem::Write; inputItem->loc.fileName = fileName; inputItem->loc.line = line; inputItem->loc.col = column; inputItem->name = parser->sectionName; inputItem->pd = parser->pd; id.inputItems.append( inputItem ); } } goto st8; st8: if ( ++p == pe ) goto _test_eof8; case 8: #line 700 "rlscan.cpp" if ( (*p) == 128 ) goto tr12; goto tr11; tr12: #line 427 "rlscan.rl" { if ( active() && machineSpec == 0 && machineName == 0 ) id.inputItems.tail->writeArgs.append( strdup(tokdata) ); } goto st9; st9: if ( ++p == pe ) goto _test_eof9; case 9: #line 715 "rlscan.cpp" switch( (*p) ) { case 59: goto tr13; case 128: goto tr12; } goto tr11; } _test_eof10: cs = 10; goto _test_eof; _test_eof1: cs = 1; goto _test_eof; _test_eof2: cs = 2; goto _test_eof; _test_eof3: cs = 3; goto _test_eof; _test_eof4: cs = 4; goto _test_eof; _test_eof5: cs = 5; goto _test_eof; _test_eof6: cs = 6; goto _test_eof; _test_eof7: cs = 7; goto _test_eof; _test_eof8: cs = 8; goto _test_eof; _test_eof9: cs = 9; goto _test_eof; _test_eof: {} if ( p == eof ) { switch ( cs ) { case 1: case 2: #line 386 "rlscan.rl" { scan_error() << "bad machine statement" << endl; } break; case 3: case 4: case 5: #line 387 "rlscan.rl" { scan_error() << "bad include statement" << endl; } break; case 6: case 7: #line 388 "rlscan.rl" { scan_error() << "bad import statement" << endl; } break; case 8: case 9: #line 389 "rlscan.rl" { scan_error() << "bad write statement" << endl; } break; #line 758 "rlscan.cpp" } } _out: {} } #line 502 "rlscan.rl" updateCol(); /* Record the last token for use in controlling the scan of subsequent * tokens. */ lastToken = type; } void Scanner::startSection( ) { parserExistsError = false; sectionLoc.fileName = fileName; sectionLoc.line = line; sectionLoc.col = column; } void Scanner::endSection( ) { /* Execute the eof actions for the section parser. */ processToken( -1, 0, 0 ); /* Close off the section with the parser. */ if ( active() ) { InputLoc loc; loc.fileName = fileName; loc.line = line; loc.col = column; parser->token( loc, TK_EndSection, 0, 0 ); } if ( includeDepth == 0 ) { if ( machineSpec == 0 && machineName == 0 ) { /* The end section may include a newline on the end, so * we use the last line, which will count the newline. */ InputItem *inputItem = new InputItem; inputItem->type = InputItem::HostData; inputItem->loc.line = line; inputItem->loc.col = column; id.inputItems.append( inputItem ); } } } bool isAbsolutePath( const char *path ) { #ifdef _WIN32 return isalpha( path[0] ) && path[1] == ':' && path[2] == '\\'; #else return path[0] == '/'; #endif } char **Scanner::makeIncludePathChecks( const char *thisFileName, const char *fileName, int fnlen ) { char **checks = 0; long nextCheck = 0; long length = 0; bool caseInsensitive = false; char *data = prepareLitString( InputLoc(), fileName, fnlen, length, caseInsensitive ); /* Absolute path? */ if ( isAbsolutePath( data ) ) { checks = new char*[2]; checks[nextCheck++] = data; } else { checks = new char*[2 + id.includePaths.length()]; /* Search from the the location of the current file. */ const char *lastSlash = strrchr( thisFileName, PATH_SEP ); if ( lastSlash == 0 ) checks[nextCheck++] = data; else { long givenPathLen = (lastSlash - thisFileName) + 1; long checklen = givenPathLen + length; char *check = new char[checklen+1]; memcpy( check, thisFileName, givenPathLen ); memcpy( check+givenPathLen, data, length ); check[checklen] = 0; checks[nextCheck++] = check; } /* Search from the include paths given on the command line. */ for ( ArgsVector::Iter incp = id.includePaths; incp.lte(); incp++ ) { long pathLen = strlen( *incp ); long checkLen = pathLen + 1 + length; char *check = new char[checkLen+1]; memcpy( check, *incp, pathLen ); check[pathLen] = PATH_SEP; memcpy( check+pathLen+1, data, length ); check[checkLen] = 0; checks[nextCheck++] = check; } } checks[nextCheck] = 0; return checks; } ifstream *Scanner::tryOpenInclude( char **pathChecks, long &found ) { char **check = pathChecks; ifstream *inFile = new ifstream; while ( *check != 0 ) { inFile->open( *check ); if ( inFile->is_open() ) { found = check - pathChecks; return inFile; } /* * 03/26/2011 jg: * Don't rely on sloppy runtime behaviour: reset the state of the stream explicitly. * If inFile->open() fails, which happens when include dirs are tested, the fail bit * is set by the runtime library. Currently the VS runtime library opens new files, * but when it comes to reading it refuses to work. */ inFile->clear(); check += 1; } found = -1; delete inFile; return 0; } #line 1173 "rlscan.rl" #line 904 "rlscan.cpp" static const int rlscan_start = 38; static const int rlscan_first_final = 38; static const int rlscan_error = 0; static const int rlscan_en_inline_code_ruby = 52; static const int rlscan_en_inline_code = 95; static const int rlscan_en_or_literal = 137; static const int rlscan_en_ragel_re_literal = 139; static const int rlscan_en_write_statement = 143; static const int rlscan_en_parser_def = 146; static const int rlscan_en_main_ruby = 253; static const int rlscan_en_main = 38; #line 1176 "rlscan.rl" void Scanner::do_scan() { int bufsize = 8; char *buf = new char[bufsize]; int cs, act, have = 0; int top; /* The stack is two deep, one level for going into ragel defs from the main * machines which process outside code, and another for going into or literals * from either a ragel spec, or a regular expression. */ int stack[2]; int curly_count = 0; bool execute = true; bool singleLineSpec = false; InlineBlockType inlineBlockType = CurlyDelimited; /* Init the section parser and the character scanner. */ init(); #line 940 "rlscan.cpp" { cs = rlscan_start; top = 0; ts = 0; te = 0; act = 0; } #line 1196 "rlscan.rl" /* Set up the start state. FIXME: After 5.20 is released the nocs write * init option should be used, the main machine eliminated and this statement moved * above the write init. */ if ( hostLang->lang == HostLang::Ruby ) cs = rlscan_en_main_ruby; else cs = rlscan_en_main; while ( execute ) { char *p = buf + have; int space = bufsize - have; if ( space == 0 ) { /* We filled up the buffer trying to scan a token. Grow it. */ bufsize = bufsize * 2; char *newbuf = new char[bufsize]; /* Recompute p and space. */ p = newbuf + have; space = bufsize - have; /* Patch up pointers possibly in use. */ if ( ts != 0 ) ts = newbuf + ( ts - buf ); te = newbuf + ( te - buf ); /* Copy the new buffer in. */ memcpy( newbuf, buf, have ); delete[] buf; buf = newbuf; } input.read( p, space ); int len = input.gcount(); char *pe = p + len; /* If we see eof then append the eof var. */ char *eof = 0; if ( len == 0 ) { eof = pe; execute = false; } #line 995 "rlscan.cpp" { if ( p == pe ) goto _test_eof; goto _resume; _again: switch ( cs ) { case 38: goto st38; case 39: goto st39; case 40: goto st40; case 1: goto st1; case 2: goto st2; case 41: goto st41; case 42: goto st42; case 43: goto st43; case 3: goto st3; case 4: goto st4; case 44: goto st44; case 5: goto st5; case 6: goto st6; case 7: goto st7; case 45: goto st45; case 46: goto st46; case 47: goto st47; case 48: goto st48; case 49: goto st49; case 50: goto st50; case 51: goto st51; case 52: goto st52; case 53: goto st53; case 54: goto st54; case 8: goto st8; case 9: goto st9; case 55: goto st55; case 10: goto st10; case 56: goto st56; case 11: goto st11; case 12: goto st12; case 57: goto st57; case 13: goto st13; case 14: goto st14; case 58: goto st58; case 59: goto st59; case 15: goto st15; case 60: goto st60; case 61: goto st61; case 62: goto st62; case 63: goto st63; case 64: goto st64; case 65: goto st65; case 66: goto st66; case 67: goto st67; case 68: goto st68; case 69: goto st69; case 70: goto st70; case 71: goto st71; case 72: goto st72; case 73: goto st73; case 74: goto st74; case 75: goto st75; case 76: goto st76; case 77: goto st77; case 78: goto st78; case 79: goto st79; case 80: goto st80; case 81: goto st81; case 82: goto st82; case 83: goto st83; case 84: goto st84; case 85: goto st85; case 86: goto st86; case 87: goto st87; case 88: goto st88; case 89: goto st89; case 90: goto st90; case 91: goto st91; case 92: goto st92; case 93: goto st93; case 94: goto st94; case 95: goto st95; case 96: goto st96; case 97: goto st97; case 16: goto st16; case 17: goto st17; case 98: goto st98; case 18: goto st18; case 19: goto st19; case 99: goto st99; case 20: goto st20; case 21: goto st21; case 22: goto st22; case 100: goto st100; case 101: goto st101; case 23: goto st23; case 102: goto st102; case 103: goto st103; case 104: goto st104; case 105: goto st105; case 106: goto st106; case 107: goto st107; case 108: goto st108; case 109: goto st109; case 110: goto st110; case 111: goto st111; case 112: goto st112; case 113: goto st113; case 114: goto st114; case 115: goto st115; case 116: goto st116; case 117: goto st117; case 118: goto st118; case 119: goto st119; case 120: goto st120; case 121: goto st121; case 122: goto st122; case 123: goto st123; case 124: goto st124; case 125: goto st125; case 126: goto st126; case 127: goto st127; case 128: goto st128; case 129: goto st129; case 130: goto st130; case 131: goto st131; case 132: goto st132; case 133: goto st133; case 134: goto st134; case 135: goto st135; case 136: goto st136; case 137: goto st137; case 138: goto st138; case 139: goto st139; case 140: goto st140; case 141: goto st141; case 142: goto st142; case 143: goto st143; case 0: goto st0; case 144: goto st144; case 145: goto st145; case 146: goto st146; case 147: goto st147; case 148: goto st148; case 24: goto st24; case 149: goto st149; case 25: goto st25; case 150: goto st150; case 26: goto st26; case 151: goto st151; case 152: goto st152; case 153: goto st153; case 27: goto st27; case 28: goto st28; case 154: goto st154; case 155: goto st155; case 156: goto st156; case 157: goto st157; case 158: goto st158; case 29: goto st29; case 159: goto st159; case 160: goto st160; case 161: goto st161; case 162: goto st162; case 163: goto st163; case 164: goto st164; case 165: goto st165; case 166: goto st166; case 167: goto st167; case 168: goto st168; case 169: goto st169; case 170: goto st170; case 171: goto st171; case 172: goto st172; case 173: goto st173; case 174: goto st174; case 175: goto st175; case 176: goto st176; case 177: goto st177; case 178: goto st178; case 179: goto st179; case 180: goto st180; case 181: goto st181; case 182: goto st182; case 183: goto st183; case 184: goto st184; case 185: goto st185; case 186: goto st186; case 187: goto st187; case 188: goto st188; case 189: goto st189; case 190: goto st190; case 191: goto st191; case 192: goto st192; case 193: goto st193; case 194: goto st194; case 195: goto st195; case 196: goto st196; case 197: goto st197; case 198: goto st198; case 199: goto st199; case 200: goto st200; case 201: goto st201; case 202: goto st202; case 203: goto st203; case 204: goto st204; case 205: goto st205; case 206: goto st206; case 207: goto st207; case 208: goto st208; case 209: goto st209; case 210: goto st210; case 211: goto st211; case 212: goto st212; case 213: goto st213; case 214: goto st214; case 215: goto st215; case 216: goto st216; case 217: goto st217; case 218: goto st218; case 219: goto st219; case 220: goto st220; case 221: goto st221; case 222: goto st222; case 223: goto st223; case 224: goto st224; case 225: goto st225; case 226: goto st226; case 227: goto st227; case 228: goto st228; case 229: goto st229; case 230: goto st230; case 231: goto st231; case 232: goto st232; case 233: goto st233; case 234: goto st234; case 235: goto st235; case 236: goto st236; case 237: goto st237; case 238: goto st238; case 239: goto st239; case 240: goto st240; case 241: goto st241; case 242: goto st242; case 243: goto st243; case 244: goto st244; case 245: goto st245; case 246: goto st246; case 247: goto st247; case 248: goto st248; case 249: goto st249; case 250: goto st250; case 251: goto st251; case 252: goto st252; case 30: goto st30; case 253: goto st253; case 254: goto st254; case 255: goto st255; case 31: goto st31; case 32: goto st32; case 256: goto st256; case 33: goto st33; case 257: goto st257; case 258: goto st258; case 259: goto st259; case 34: goto st34; case 35: goto st35; case 260: goto st260; case 36: goto st36; case 37: goto st37; case 261: goto st261; case 262: goto st262; default: break; } if ( ++p == pe ) goto _test_eof; _resume: switch ( cs ) { tr0: #line 1171 "rlscan.rl" {{p = ((te))-1;}{ pass( *ts, 0, 0 ); }} goto st38; tr3: #line 1155 "rlscan.rl" {te = p+1;{ pass( IMP_Literal, ts, te ); }} goto st38; tr11: #line 1154 "rlscan.rl" {te = p+1;{ pass(); }} goto st38; tr13: #line 641 "rlscan.rl" { lastnl = p; column = 0; line++; } #line 1154 "rlscan.rl" {te = p+1;{ pass(); }} goto st38; tr71: #line 1171 "rlscan.rl" {te = p+1;{ pass( *ts, 0, 0 ); }} goto st38; tr72: #line 1170 "rlscan.rl" {te = p+1;} goto st38; tr82: #line 1169 "rlscan.rl" {te = p;p--;{ pass(); }} goto st38; tr83: #line 1171 "rlscan.rl" {te = p;p--;{ pass( *ts, 0, 0 ); }} goto st38; tr85: #line 1163 "rlscan.rl" {te = p;p--;{ updateCol(); singleLineSpec = true; startSection(); {stack[top++] = 38; goto st146;} }} goto st38; tr86: #line 1157 "rlscan.rl" {te = p+1;{ updateCol(); singleLineSpec = false; startSection(); {stack[top++] = 38; goto st146;} }} goto st38; tr87: #line 1153 "rlscan.rl" {te = p;p--;{ pass( IMP_UInt, ts, te ); }} goto st38; tr88: #line 1 "NONE" { switch( act ) { case 176: {{p = ((te))-1;} pass( IMP_Define, 0, 0 ); } break; case 177: {{p = ((te))-1;} pass( IMP_Word, ts, te ); } break; } } goto st38; tr89: #line 1152 "rlscan.rl" {te = p;p--;{ pass( IMP_Word, ts, te ); }} goto st38; st38: #line 1 "NONE" {ts = 0;} if ( ++p == pe ) goto _test_eof38; case 38: #line 1 "NONE" {ts = p;} #line 1358 "rlscan.cpp" switch( (*p) ) { case 0: goto tr72; case 9: goto st39; case 10: goto tr74; case 32: goto st39; case 34: goto tr75; case 37: goto st41; case 39: goto tr77; case 47: goto tr78; case 95: goto tr80; case 100: goto st47; } if ( (*p) < 65 ) { if ( 48 <= (*p) && (*p) <= 57 ) goto st45; } else if ( (*p) > 90 ) { if ( 97 <= (*p) && (*p) <= 122 ) goto tr80; } else goto tr80; goto tr71; tr74: #line 641 "rlscan.rl" { lastnl = p; column = 0; line++; } goto st39; st39: if ( ++p == pe ) goto _test_eof39; case 39: #line 1392 "rlscan.cpp" switch( (*p) ) { case 9: goto st39; case 10: goto tr74; case 32: goto st39; } goto tr82; tr75: #line 1 "NONE" {te = p+1;} goto st40; st40: if ( ++p == pe ) goto _test_eof40; case 40: #line 1407 "rlscan.cpp" switch( (*p) ) { case 10: goto tr2; case 34: goto tr3; case 92: goto st2; } goto st1; tr2: #line 641 "rlscan.rl" { lastnl = p; column = 0; line++; } goto st1; st1: if ( ++p == pe ) goto _test_eof1; case 1: #line 1426 "rlscan.cpp" switch( (*p) ) { case 10: goto tr2; case 34: goto tr3; case 92: goto st2; } goto st1; st2: if ( ++p == pe ) goto _test_eof2; case 2: if ( (*p) == 10 ) goto tr2; goto st1; st41: if ( ++p == pe ) goto _test_eof41; case 41: if ( (*p) == 37 ) goto st42; goto tr83; st42: if ( ++p == pe ) goto _test_eof42; case 42: if ( (*p) == 123 ) goto tr86; goto tr85; tr77: #line 1 "NONE" {te = p+1;} goto st43; st43: if ( ++p == pe ) goto _test_eof43; case 43: #line 1462 "rlscan.cpp" switch( (*p) ) { case 10: goto tr6; case 39: goto tr3; case 92: goto st4; } goto st3; tr6: #line 641 "rlscan.rl" { lastnl = p; column = 0; line++; } goto st3; st3: if ( ++p == pe ) goto _test_eof3; case 3: #line 1481 "rlscan.cpp" switch( (*p) ) { case 10: goto tr6; case 39: goto tr3; case 92: goto st4; } goto st3; st4: if ( ++p == pe ) goto _test_eof4; case 4: if ( (*p) == 10 ) goto tr6; goto st3; tr78: #line 1 "NONE" {te = p+1;} goto st44; st44: if ( ++p == pe ) goto _test_eof44; case 44: #line 1503 "rlscan.cpp" switch( (*p) ) { case 42: goto st5; case 47: goto st7; } goto tr83; tr9: #line 641 "rlscan.rl" { lastnl = p; column = 0; line++; } goto st5; st5: if ( ++p == pe ) goto _test_eof5; case 5: #line 1521 "rlscan.cpp" switch( (*p) ) { case 10: goto tr9; case 42: goto st6; } goto st5; st6: if ( ++p == pe ) goto _test_eof6; case 6: switch( (*p) ) { case 10: goto tr9; case 42: goto st6; case 47: goto tr11; } goto st5; st7: if ( ++p == pe ) goto _test_eof7; case 7: if ( (*p) == 10 ) goto tr13; goto st7; st45: if ( ++p == pe ) goto _test_eof45; case 45: if ( 48 <= (*p) && (*p) <= 57 ) goto st45; goto tr87; tr80: #line 1 "NONE" {te = p+1;} #line 1152 "rlscan.rl" {act = 177;} goto st46; tr94: #line 1 "NONE" {te = p+1;} #line 1151 "rlscan.rl" {act = 176;} goto st46; st46: if ( ++p == pe ) goto _test_eof46; case 46: #line 1567 "rlscan.cpp" if ( (*p) == 95 ) goto tr80; if ( (*p) < 65 ) { if ( 48 <= (*p) && (*p) <= 57 ) goto tr80; } else if ( (*p) > 90 ) { if ( 97 <= (*p) && (*p) <= 122 ) goto tr80; } else goto tr80; goto tr88; st47: if ( ++p == pe ) goto _test_eof47; case 47: switch( (*p) ) { case 95: goto tr80; case 101: goto st48; } if ( (*p) < 65 ) { if ( 48 <= (*p) && (*p) <= 57 ) goto tr80; } else if ( (*p) > 90 ) { if ( 97 <= (*p) && (*p) <= 122 ) goto tr80; } else goto tr80; goto tr89; st48: if ( ++p == pe ) goto _test_eof48; case 48: switch( (*p) ) { case 95: goto tr80; case 102: goto st49; } if ( (*p) < 65 ) { if ( 48 <= (*p) && (*p) <= 57 ) goto tr80; } else if ( (*p) > 90 ) { if ( 97 <= (*p) && (*p) <= 122 ) goto tr80; } else goto tr80; goto tr89; st49: if ( ++p == pe ) goto _test_eof49; case 49: switch( (*p) ) { case 95: goto tr80; case 105: goto st50; } if ( (*p) < 65 ) { if ( 48 <= (*p) && (*p) <= 57 ) goto tr80; } else if ( (*p) > 90 ) { if ( 97 <= (*p) && (*p) <= 122 ) goto tr80; } else goto tr80; goto tr89; st50: if ( ++p == pe ) goto _test_eof50; case 50: switch( (*p) ) { case 95: goto tr80; case 110: goto st51; } if ( (*p) < 65 ) { if ( 48 <= (*p) && (*p) <= 57 ) goto tr80; } else if ( (*p) > 90 ) { if ( 97 <= (*p) && (*p) <= 122 ) goto tr80; } else goto tr80; goto tr89; st51: if ( ++p == pe ) goto _test_eof51; case 51: switch( (*p) ) { case 95: goto tr80; case 101: goto tr94; } if ( (*p) < 65 ) { if ( 48 <= (*p) && (*p) <= 57 ) goto tr80; } else if ( (*p) > 90 ) { if ( 97 <= (*p) && (*p) <= 122 ) goto tr80; } else goto tr80; goto tr89; tr14: #line 770 "rlscan.rl" {{p = ((te))-1;}{ token( IL_Symbol, ts, te ); }} goto st52; tr17: #line 716 "rlscan.rl" {te = p+1;{ token( IL_Literal, ts, te ); }} goto st52; tr20: #line 641 "rlscan.rl" { lastnl = p; column = 0; line++; } #line 723 "rlscan.rl" {te = p+1;{ token( IL_Comment, ts, te ); }} goto st52; tr27: #line 712 "rlscan.rl" {{p = ((te))-1;}{ token( TK_UInt, ts, te ); }} goto st52; tr95: #line 770 "rlscan.rl" {te = p+1;{ token( IL_Symbol, ts, te ); }} goto st52; tr96: #line 765 "rlscan.rl" {te = p+1;{ scan_error() << "unterminated code block" << endl; }} goto st52; tr102: #line 745 "rlscan.rl" {te = p+1;{ token( *ts, ts, te ); }} goto st52; tr103: #line 740 "rlscan.rl" {te = p+1;{ whitespaceOn = true; token( *ts, ts, te ); }} goto st52; tr108: #line 733 "rlscan.rl" {te = p+1;{ whitespaceOn = true; token( *ts, ts, te ); if ( inlineBlockType == SemiTerminated ) {cs = stack[--top];goto _again;} }} goto st52; tr111: #line 747 "rlscan.rl" {te = p+1;{ token( IL_Symbol, ts, te ); curly_count += 1; }} goto st52; tr112: #line 752 "rlscan.rl" {te = p+1;{ if ( --curly_count == 0 && inlineBlockType == CurlyDelimited ) { /* Inline code block ends. */ token( '}' ); {cs = stack[--top];goto _again;} } else { /* Either a semi terminated inline block or only the closing * brace of some inner scope, not the block's closing brace. */ token( IL_Symbol, ts, te ); } }} goto st52; tr113: #line 718 "rlscan.rl" {te = p;p--;{ if ( whitespaceOn ) token( IL_WhiteSpace, ts, te ); }} goto st52; tr114: #line 770 "rlscan.rl" {te = p;p--;{ token( IL_Symbol, ts, te ); }} goto st52; tr115: #line 712 "rlscan.rl" {te = p;p--;{ token( TK_UInt, ts, te ); }} goto st52; tr117: #line 713 "rlscan.rl" {te = p;p--;{ token( TK_Hex, ts, te ); }} goto st52; tr118: #line 725 "rlscan.rl" {te = p+1;{ token( TK_NameSep, ts, te ); }} goto st52; tr119: #line 1 "NONE" { switch( act ) { case 1: {{p = ((te))-1;} token( KW_PChar ); } break; case 3: {{p = ((te))-1;} token( KW_CurState ); } break; case 4: {{p = ((te))-1;} token( KW_TargState ); } break; case 5: {{p = ((te))-1;} whitespaceOn = false; token( KW_Entry ); } break; case 6: {{p = ((te))-1;} whitespaceOn = false; token( KW_Hold ); } break; case 7: {{p = ((te))-1;} token( KW_Exec, 0, 0 ); } break; case 8: {{p = ((te))-1;} whitespaceOn = false; token( KW_Goto ); } break; case 9: {{p = ((te))-1;} whitespaceOn = false; token( KW_Next ); } break; case 10: {{p = ((te))-1;} whitespaceOn = false; token( KW_Call ); } break; case 11: {{p = ((te))-1;} whitespaceOn = false; token( KW_Ret ); } break; case 12: {{p = ((te))-1;} whitespaceOn = false; token( KW_Break ); } break; case 13: {{p = ((te))-1;} token( TK_Word, ts, te ); } break; } } goto st52; tr120: #line 710 "rlscan.rl" {te = p;p--;{ token( TK_Word, ts, te ); }} goto st52; tr134: #line 675 "rlscan.rl" {te = p;p--;{ token( KW_Char ); }} goto st52; st52: #line 1 "NONE" {ts = 0;} if ( ++p == pe ) goto _test_eof52; case 52: #line 1 "NONE" {ts = p;} #line 1840 "rlscan.cpp" switch( (*p) ) { case 0: goto tr96; case 9: goto st53; case 10: goto tr98; case 32: goto st53; case 34: goto tr99; case 35: goto tr100; case 39: goto tr101; case 40: goto tr102; case 44: goto tr102; case 47: goto tr104; case 48: goto tr105; case 58: goto st61; case 59: goto tr108; case 95: goto tr109; case 102: goto st63; case 123: goto tr111; case 125: goto tr112; } if ( (*p) < 49 ) { if ( 41 <= (*p) && (*p) <= 42 ) goto tr103; } else if ( (*p) > 57 ) { if ( (*p) > 90 ) { if ( 97 <= (*p) && (*p) <= 122 ) goto tr109; } else if ( (*p) >= 65 ) goto tr109; } else goto st59; goto tr95; tr98: #line 641 "rlscan.rl" { lastnl = p; column = 0; line++; } goto st53; st53: if ( ++p == pe ) goto _test_eof53; case 53: #line 1884 "rlscan.cpp" switch( (*p) ) { case 9: goto st53; case 10: goto tr98; case 32: goto st53; } goto tr113; tr99: #line 1 "NONE" {te = p+1;} goto st54; st54: if ( ++p == pe ) goto _test_eof54; case 54: #line 1899 "rlscan.cpp" switch( (*p) ) { case 10: goto tr16; case 34: goto tr17; case 92: goto st9; } goto st8; tr16: #line 641 "rlscan.rl" { lastnl = p; column = 0; line++; } goto st8; st8: if ( ++p == pe ) goto _test_eof8; case 8: #line 1918 "rlscan.cpp" switch( (*p) ) { case 10: goto tr16; case 34: goto tr17; case 92: goto st9; } goto st8; st9: if ( ++p == pe ) goto _test_eof9; case 9: if ( (*p) == 10 ) goto tr16; goto st8; tr100: #line 1 "NONE" {te = p+1;} goto st55; st55: if ( ++p == pe ) goto _test_eof55; case 55: #line 1940 "rlscan.cpp" if ( (*p) == 10 ) goto tr20; goto st10; st10: if ( ++p == pe ) goto _test_eof10; case 10: if ( (*p) == 10 ) goto tr20; goto st10; tr101: #line 1 "NONE" {te = p+1;} goto st56; st56: if ( ++p == pe ) goto _test_eof56; case 56: #line 1959 "rlscan.cpp" switch( (*p) ) { case 10: goto tr22; case 39: goto tr17; case 92: goto st12; } goto st11; tr22: #line 641 "rlscan.rl" { lastnl = p; column = 0; line++; } goto st11; st11: if ( ++p == pe ) goto _test_eof11; case 11: #line 1978 "rlscan.cpp" switch( (*p) ) { case 10: goto tr22; case 39: goto tr17; case 92: goto st12; } goto st11; st12: if ( ++p == pe ) goto _test_eof12; case 12: if ( (*p) == 10 ) goto tr22; goto st11; tr104: #line 1 "NONE" {te = p+1;} goto st57; st57: if ( ++p == pe ) goto _test_eof57; case 57: #line 2000 "rlscan.cpp" switch( (*p) ) { case 10: goto tr25; case 47: goto tr17; case 92: goto st14; } goto st13; tr25: #line 641 "rlscan.rl" { lastnl = p; column = 0; line++; } goto st13; st13: if ( ++p == pe ) goto _test_eof13; case 13: #line 2019 "rlscan.cpp" switch( (*p) ) { case 10: goto tr25; case 47: goto tr17; case 92: goto st14; } goto st13; st14: if ( ++p == pe ) goto _test_eof14; case 14: if ( (*p) == 10 ) goto tr25; goto st13; tr105: #line 1 "NONE" {te = p+1;} goto st58; st58: if ( ++p == pe ) goto _test_eof58; case 58: #line 2041 "rlscan.cpp" if ( (*p) == 120 ) goto st15; if ( 48 <= (*p) && (*p) <= 57 ) goto st59; goto tr115; st59: if ( ++p == pe ) goto _test_eof59; case 59: if ( 48 <= (*p) && (*p) <= 57 ) goto st59; goto tr115; st15: if ( ++p == pe ) goto _test_eof15; case 15: if ( (*p) < 65 ) { if ( 48 <= (*p) && (*p) <= 57 ) goto st60; } else if ( (*p) > 70 ) { if ( 97 <= (*p) && (*p) <= 102 ) goto st60; } else goto st60; goto tr27; st60: if ( ++p == pe ) goto _test_eof60; case 60: if ( (*p) < 65 ) { if ( 48 <= (*p) && (*p) <= 57 ) goto st60; } else if ( (*p) > 70 ) { if ( 97 <= (*p) && (*p) <= 102 ) goto st60; } else goto st60; goto tr117; st61: if ( ++p == pe ) goto _test_eof61; case 61: if ( (*p) == 58 ) goto tr118; goto tr114; tr109: #line 1 "NONE" {te = p+1;} #line 710 "rlscan.rl" {act = 13;} goto st62; tr133: #line 1 "NONE" {te = p+1;} #line 705 "rlscan.rl" {act = 12;} goto st62; tr138: #line 1 "NONE" {te = p+1;} #line 697 "rlscan.rl" {act = 10;} goto st62; tr140: #line 1 "NONE" {te = p+1;} #line 676 "rlscan.rl" {act = 3;} goto st62; tr145: #line 1 "NONE" {te = p+1;} #line 678 "rlscan.rl" {act = 5;} goto st62; tr147: #line 1 "NONE" {te = p+1;} #line 688 "rlscan.rl" {act = 7;} goto st62; tr150: #line 1 "NONE" {te = p+1;} #line 689 "rlscan.rl" {act = 8;} goto st62; tr153: #line 1 "NONE" {te = p+1;} #line 684 "rlscan.rl" {act = 6;} goto st62; tr156: #line 1 "NONE" {te = p+1;} #line 693 "rlscan.rl" {act = 9;} goto st62; tr157: #line 1 "NONE" {te = p+1;} #line 674 "rlscan.rl" {act = 1;} goto st62; tr159: #line 1 "NONE" {te = p+1;} #line 701 "rlscan.rl" {act = 11;} goto st62; tr163: #line 1 "NONE" {te = p+1;} #line 677 "rlscan.rl" {act = 4;} goto st62; st62: if ( ++p == pe ) goto _test_eof62; case 62: #line 2163 "rlscan.cpp" if ( (*p) == 95 ) goto tr109; if ( (*p) < 65 ) { if ( 48 <= (*p) && (*p) <= 57 ) goto tr109; } else if ( (*p) > 90 ) { if ( 97 <= (*p) && (*p) <= 122 ) goto tr109; } else goto tr109; goto tr119; st63: if ( ++p == pe ) goto _test_eof63; case 63: switch( (*p) ) { case 95: goto tr109; case 98: goto st64; case 99: goto st68; case 101: goto st73; case 103: goto st79; case 104: goto st82; case 110: goto st85; case 112: goto st88; case 114: goto st89; case 116: goto st91; } if ( (*p) < 65 ) { if ( 48 <= (*p) && (*p) <= 57 ) goto tr109; } else if ( (*p) > 90 ) { if ( 97 <= (*p) && (*p) <= 122 ) goto tr109; } else goto tr109; goto tr120; st64: if ( ++p == pe ) goto _test_eof64; case 64: switch( (*p) ) { case 95: goto tr109; case 114: goto st65; } if ( (*p) < 65 ) { if ( 48 <= (*p) && (*p) <= 57 ) goto tr109; } else if ( (*p) > 90 ) { if ( 97 <= (*p) && (*p) <= 122 ) goto tr109; } else goto tr109; goto tr120; st65: if ( ++p == pe ) goto _test_eof65; case 65: switch( (*p) ) { case 95: goto tr109; case 101: goto st66; } if ( (*p) < 65 ) { if ( 48 <= (*p) && (*p) <= 57 ) goto tr109; } else if ( (*p) > 90 ) { if ( 97 <= (*p) && (*p) <= 122 ) goto tr109; } else goto tr109; goto tr120; st66: if ( ++p == pe ) goto _test_eof66; case 66: switch( (*p) ) { case 95: goto tr109; case 97: goto st67; } if ( (*p) < 65 ) { if ( 48 <= (*p) && (*p) <= 57 ) goto tr109; } else if ( (*p) > 90 ) { if ( 98 <= (*p) && (*p) <= 122 ) goto tr109; } else goto tr109; goto tr120; st67: if ( ++p == pe ) goto _test_eof67; case 67: switch( (*p) ) { case 95: goto tr109; case 107: goto tr133; } if ( (*p) < 65 ) { if ( 48 <= (*p) && (*p) <= 57 ) goto tr109; } else if ( (*p) > 90 ) { if ( 97 <= (*p) && (*p) <= 122 ) goto tr109; } else goto tr109; goto tr120; st68: if ( ++p == pe ) goto _test_eof68; case 68: switch( (*p) ) { case 95: goto tr109; case 97: goto st69; case 117: goto st71; } if ( (*p) < 65 ) { if ( 48 <= (*p) && (*p) <= 57 ) goto tr109; } else if ( (*p) > 90 ) { if ( 98 <= (*p) && (*p) <= 122 ) goto tr109; } else goto tr109; goto tr134; st69: if ( ++p == pe ) goto _test_eof69; case 69: switch( (*p) ) { case 95: goto tr109; case 108: goto st70; } if ( (*p) < 65 ) { if ( 48 <= (*p) && (*p) <= 57 ) goto tr109; } else if ( (*p) > 90 ) { if ( 97 <= (*p) && (*p) <= 122 ) goto tr109; } else goto tr109; goto tr120; st70: if ( ++p == pe ) goto _test_eof70; case 70: switch( (*p) ) { case 95: goto tr109; case 108: goto tr138; } if ( (*p) < 65 ) { if ( 48 <= (*p) && (*p) <= 57 ) goto tr109; } else if ( (*p) > 90 ) { if ( 97 <= (*p) && (*p) <= 122 ) goto tr109; } else goto tr109; goto tr120; st71: if ( ++p == pe ) goto _test_eof71; case 71: switch( (*p) ) { case 95: goto tr109; case 114: goto st72; } if ( (*p) < 65 ) { if ( 48 <= (*p) && (*p) <= 57 ) goto tr109; } else if ( (*p) > 90 ) { if ( 97 <= (*p) && (*p) <= 122 ) goto tr109; } else goto tr109; goto tr120; st72: if ( ++p == pe ) goto _test_eof72; case 72: switch( (*p) ) { case 95: goto tr109; case 115: goto tr140; } if ( (*p) < 65 ) { if ( 48 <= (*p) && (*p) <= 57 ) goto tr109; } else if ( (*p) > 90 ) { if ( 97 <= (*p) && (*p) <= 122 ) goto tr109; } else goto tr109; goto tr120; st73: if ( ++p == pe ) goto _test_eof73; case 73: switch( (*p) ) { case 95: goto tr109; case 110: goto st74; case 120: goto st77; } if ( (*p) < 65 ) { if ( 48 <= (*p) && (*p) <= 57 ) goto tr109; } else if ( (*p) > 90 ) { if ( 97 <= (*p) && (*p) <= 122 ) goto tr109; } else goto tr109; goto tr120; st74: if ( ++p == pe ) goto _test_eof74; case 74: switch( (*p) ) { case 95: goto tr109; case 116: goto st75; } if ( (*p) < 65 ) { if ( 48 <= (*p) && (*p) <= 57 ) goto tr109; } else if ( (*p) > 90 ) { if ( 97 <= (*p) && (*p) <= 122 ) goto tr109; } else goto tr109; goto tr120; st75: if ( ++p == pe ) goto _test_eof75; case 75: switch( (*p) ) { case 95: goto tr109; case 114: goto st76; } if ( (*p) < 65 ) { if ( 48 <= (*p) && (*p) <= 57 ) goto tr109; } else if ( (*p) > 90 ) { if ( 97 <= (*p) && (*p) <= 122 ) goto tr109; } else goto tr109; goto tr120; st76: if ( ++p == pe ) goto _test_eof76; case 76: switch( (*p) ) { case 95: goto tr109; case 121: goto tr145; } if ( (*p) < 65 ) { if ( 48 <= (*p) && (*p) <= 57 ) goto tr109; } else if ( (*p) > 90 ) { if ( 97 <= (*p) && (*p) <= 122 ) goto tr109; } else goto tr109; goto tr120; st77: if ( ++p == pe ) goto _test_eof77; case 77: switch( (*p) ) { case 95: goto tr109; case 101: goto st78; } if ( (*p) < 65 ) { if ( 48 <= (*p) && (*p) <= 57 ) goto tr109; } else if ( (*p) > 90 ) { if ( 97 <= (*p) && (*p) <= 122 ) goto tr109; } else goto tr109; goto tr120; st78: if ( ++p == pe ) goto _test_eof78; case 78: switch( (*p) ) { case 95: goto tr109; case 99: goto tr147; } if ( (*p) < 65 ) { if ( 48 <= (*p) && (*p) <= 57 ) goto tr109; } else if ( (*p) > 90 ) { if ( 97 <= (*p) && (*p) <= 122 ) goto tr109; } else goto tr109; goto tr120; st79: if ( ++p == pe ) goto _test_eof79; case 79: switch( (*p) ) { case 95: goto tr109; case 111: goto st80; } if ( (*p) < 65 ) { if ( 48 <= (*p) && (*p) <= 57 ) goto tr109; } else if ( (*p) > 90 ) { if ( 97 <= (*p) && (*p) <= 122 ) goto tr109; } else goto tr109; goto tr120; st80: if ( ++p == pe ) goto _test_eof80; case 80: switch( (*p) ) { case 95: goto tr109; case 116: goto st81; } if ( (*p) < 65 ) { if ( 48 <= (*p) && (*p) <= 57 ) goto tr109; } else if ( (*p) > 90 ) { if ( 97 <= (*p) && (*p) <= 122 ) goto tr109; } else goto tr109; goto tr120; st81: if ( ++p == pe ) goto _test_eof81; case 81: switch( (*p) ) { case 95: goto tr109; case 111: goto tr150; } if ( (*p) < 65 ) { if ( 48 <= (*p) && (*p) <= 57 ) goto tr109; } else if ( (*p) > 90 ) { if ( 97 <= (*p) && (*p) <= 122 ) goto tr109; } else goto tr109; goto tr120; st82: if ( ++p == pe ) goto _test_eof82; case 82: switch( (*p) ) { case 95: goto tr109; case 111: goto st83; } if ( (*p) < 65 ) { if ( 48 <= (*p) && (*p) <= 57 ) goto tr109; } else if ( (*p) > 90 ) { if ( 97 <= (*p) && (*p) <= 122 ) goto tr109; } else goto tr109; goto tr120; st83: if ( ++p == pe ) goto _test_eof83; case 83: switch( (*p) ) { case 95: goto tr109; case 108: goto st84; } if ( (*p) < 65 ) { if ( 48 <= (*p) && (*p) <= 57 ) goto tr109; } else if ( (*p) > 90 ) { if ( 97 <= (*p) && (*p) <= 122 ) goto tr109; } else goto tr109; goto tr120; st84: if ( ++p == pe ) goto _test_eof84; case 84: switch( (*p) ) { case 95: goto tr109; case 100: goto tr153; } if ( (*p) < 65 ) { if ( 48 <= (*p) && (*p) <= 57 ) goto tr109; } else if ( (*p) > 90 ) { if ( 97 <= (*p) && (*p) <= 122 ) goto tr109; } else goto tr109; goto tr120; st85: if ( ++p == pe ) goto _test_eof85; case 85: switch( (*p) ) { case 95: goto tr109; case 101: goto st86; } if ( (*p) < 65 ) { if ( 48 <= (*p) && (*p) <= 57 ) goto tr109; } else if ( (*p) > 90 ) { if ( 97 <= (*p) && (*p) <= 122 ) goto tr109; } else goto tr109; goto tr120; st86: if ( ++p == pe ) goto _test_eof86; case 86: switch( (*p) ) { case 95: goto tr109; case 120: goto st87; } if ( (*p) < 65 ) { if ( 48 <= (*p) && (*p) <= 57 ) goto tr109; } else if ( (*p) > 90 ) { if ( 97 <= (*p) && (*p) <= 122 ) goto tr109; } else goto tr109; goto tr120; st87: if ( ++p == pe ) goto _test_eof87; case 87: switch( (*p) ) { case 95: goto tr109; case 116: goto tr156; } if ( (*p) < 65 ) { if ( 48 <= (*p) && (*p) <= 57 ) goto tr109; } else if ( (*p) > 90 ) { if ( 97 <= (*p) && (*p) <= 122 ) goto tr109; } else goto tr109; goto tr120; st88: if ( ++p == pe ) goto _test_eof88; case 88: switch( (*p) ) { case 95: goto tr109; case 99: goto tr157; } if ( (*p) < 65 ) { if ( 48 <= (*p) && (*p) <= 57 ) goto tr109; } else if ( (*p) > 90 ) { if ( 97 <= (*p) && (*p) <= 122 ) goto tr109; } else goto tr109; goto tr120; st89: if ( ++p == pe ) goto _test_eof89; case 89: switch( (*p) ) { case 95: goto tr109; case 101: goto st90; } if ( (*p) < 65 ) { if ( 48 <= (*p) && (*p) <= 57 ) goto tr109; } else if ( (*p) > 90 ) { if ( 97 <= (*p) && (*p) <= 122 ) goto tr109; } else goto tr109; goto tr120; st90: if ( ++p == pe ) goto _test_eof90; case 90: switch( (*p) ) { case 95: goto tr109; case 116: goto tr159; } if ( (*p) < 65 ) { if ( 48 <= (*p) && (*p) <= 57 ) goto tr109; } else if ( (*p) > 90 ) { if ( 97 <= (*p) && (*p) <= 122 ) goto tr109; } else goto tr109; goto tr120; st91: if ( ++p == pe ) goto _test_eof91; case 91: switch( (*p) ) { case 95: goto tr109; case 97: goto st92; } if ( (*p) < 65 ) { if ( 48 <= (*p) && (*p) <= 57 ) goto tr109; } else if ( (*p) > 90 ) { if ( 98 <= (*p) && (*p) <= 122 ) goto tr109; } else goto tr109; goto tr120; st92: if ( ++p == pe ) goto _test_eof92; case 92: switch( (*p) ) { case 95: goto tr109; case 114: goto st93; } if ( (*p) < 65 ) { if ( 48 <= (*p) && (*p) <= 57 ) goto tr109; } else if ( (*p) > 90 ) { if ( 97 <= (*p) && (*p) <= 122 ) goto tr109; } else goto tr109; goto tr120; st93: if ( ++p == pe ) goto _test_eof93; case 93: switch( (*p) ) { case 95: goto tr109; case 103: goto st94; } if ( (*p) < 65 ) { if ( 48 <= (*p) && (*p) <= 57 ) goto tr109; } else if ( (*p) > 90 ) { if ( 97 <= (*p) && (*p) <= 122 ) goto tr109; } else goto tr109; goto tr120; st94: if ( ++p == pe ) goto _test_eof94; case 94: switch( (*p) ) { case 95: goto tr109; case 115: goto tr163; } if ( (*p) < 65 ) { if ( 48 <= (*p) && (*p) <= 57 ) goto tr109; } else if ( (*p) > 90 ) { if ( 97 <= (*p) && (*p) <= 122 ) goto tr109; } else goto tr109; goto tr120; tr29: #line 873 "rlscan.rl" {{p = ((te))-1;}{ token( IL_Symbol, ts, te ); }} goto st95; tr32: #line 819 "rlscan.rl" {te = p+1;{ token( IL_Literal, ts, te ); }} goto st95; tr40: #line 826 "rlscan.rl" {te = p+1;{ token( IL_Comment, ts, te ); }} goto st95; tr42: #line 641 "rlscan.rl" { lastnl = p; column = 0; line++; } #line 826 "rlscan.rl" {te = p+1;{ token( IL_Comment, ts, te ); }} goto st95; tr43: #line 815 "rlscan.rl" {{p = ((te))-1;}{ token( TK_UInt, ts, te ); }} goto st95; tr164: #line 873 "rlscan.rl" {te = p+1;{ token( IL_Symbol, ts, te ); }} goto st95; tr165: #line 868 "rlscan.rl" {te = p+1;{ scan_error() << "unterminated code block" << endl; }} goto st95; tr170: #line 848 "rlscan.rl" {te = p+1;{ token( *ts, ts, te ); }} goto st95; tr171: #line 843 "rlscan.rl" {te = p+1;{ whitespaceOn = true; token( *ts, ts, te ); }} goto st95; tr176: #line 836 "rlscan.rl" {te = p+1;{ whitespaceOn = true; token( *ts, ts, te ); if ( inlineBlockType == SemiTerminated ) {cs = stack[--top];goto _again;} }} goto st95; tr179: #line 850 "rlscan.rl" {te = p+1;{ token( IL_Symbol, ts, te ); curly_count += 1; }} goto st95; tr180: #line 855 "rlscan.rl" {te = p+1;{ if ( --curly_count == 0 && inlineBlockType == CurlyDelimited ) { /* Inline code block ends. */ token( '}' ); {cs = stack[--top];goto _again;} } else { /* Either a semi terminated inline block or only the closing * brace of some inner scope, not the block's closing brace. */ token( IL_Symbol, ts, te ); } }} goto st95; tr181: #line 821 "rlscan.rl" {te = p;p--;{ if ( whitespaceOn ) token( IL_WhiteSpace, ts, te ); }} goto st95; tr182: #line 873 "rlscan.rl" {te = p;p--;{ token( IL_Symbol, ts, te ); }} goto st95; tr183: #line 815 "rlscan.rl" {te = p;p--;{ token( TK_UInt, ts, te ); }} goto st95; tr185: #line 816 "rlscan.rl" {te = p;p--;{ token( TK_Hex, ts, te ); }} goto st95; tr186: #line 828 "rlscan.rl" {te = p+1;{ token( TK_NameSep, ts, te ); }} goto st95; tr187: #line 1 "NONE" { switch( act ) { case 27: {{p = ((te))-1;} token( KW_PChar ); } break; case 29: {{p = ((te))-1;} token( KW_CurState ); } break; case 30: {{p = ((te))-1;} token( KW_TargState ); } break; case 31: {{p = ((te))-1;} whitespaceOn = false; token( KW_Entry ); } break; case 32: {{p = ((te))-1;} whitespaceOn = false; token( KW_Hold ); } break; case 33: {{p = ((te))-1;} token( KW_Exec, 0, 0 ); } break; case 34: {{p = ((te))-1;} whitespaceOn = false; token( KW_Goto ); } break; case 35: {{p = ((te))-1;} whitespaceOn = false; token( KW_Next ); } break; case 36: {{p = ((te))-1;} whitespaceOn = false; token( KW_Call ); } break; case 37: {{p = ((te))-1;} whitespaceOn = false; token( KW_Ret ); } break; case 38: {{p = ((te))-1;} whitespaceOn = false; token( KW_Break ); } break; case 39: {{p = ((te))-1;} token( TK_Word, ts, te ); } break; } } goto st95; tr188: #line 813 "rlscan.rl" {te = p;p--;{ token( TK_Word, ts, te ); }} goto st95; tr202: #line 778 "rlscan.rl" {te = p;p--;{ token( KW_Char ); }} goto st95; st95: #line 1 "NONE" {ts = 0;} if ( ++p == pe ) goto _test_eof95; case 95: #line 1 "NONE" {ts = p;} #line 2909 "rlscan.cpp" switch( (*p) ) { case 0: goto tr165; case 9: goto st96; case 10: goto tr167; case 32: goto st96; case 34: goto tr168; case 39: goto tr169; case 40: goto tr170; case 44: goto tr170; case 47: goto tr172; case 48: goto tr173; case 58: goto st103; case 59: goto tr176; case 95: goto tr177; case 102: goto st105; case 123: goto tr179; case 125: goto tr180; } if ( (*p) < 49 ) { if ( 41 <= (*p) && (*p) <= 42 ) goto tr171; } else if ( (*p) > 57 ) { if ( (*p) > 90 ) { if ( 97 <= (*p) && (*p) <= 122 ) goto tr177; } else if ( (*p) >= 65 ) goto tr177; } else goto st101; goto tr164; tr167: #line 641 "rlscan.rl" { lastnl = p; column = 0; line++; } goto st96; st96: if ( ++p == pe ) goto _test_eof96; case 96: #line 2952 "rlscan.cpp" switch( (*p) ) { case 9: goto st96; case 10: goto tr167; case 32: goto st96; } goto tr181; tr168: #line 1 "NONE" {te = p+1;} goto st97; st97: if ( ++p == pe ) goto _test_eof97; case 97: #line 2967 "rlscan.cpp" switch( (*p) ) { case 10: goto tr31; case 34: goto tr32; case 92: goto st17; } goto st16; tr31: #line 641 "rlscan.rl" { lastnl = p; column = 0; line++; } goto st16; st16: if ( ++p == pe ) goto _test_eof16; case 16: #line 2986 "rlscan.cpp" switch( (*p) ) { case 10: goto tr31; case 34: goto tr32; case 92: goto st17; } goto st16; st17: if ( ++p == pe ) goto _test_eof17; case 17: if ( (*p) == 10 ) goto tr31; goto st16; tr169: #line 1 "NONE" {te = p+1;} goto st98; st98: if ( ++p == pe ) goto _test_eof98; case 98: #line 3008 "rlscan.cpp" switch( (*p) ) { case 10: goto tr35; case 39: goto tr32; case 92: goto st19; } goto st18; tr35: #line 641 "rlscan.rl" { lastnl = p; column = 0; line++; } goto st18; st18: if ( ++p == pe ) goto _test_eof18; case 18: #line 3027 "rlscan.cpp" switch( (*p) ) { case 10: goto tr35; case 39: goto tr32; case 92: goto st19; } goto st18; st19: if ( ++p == pe ) goto _test_eof19; case 19: if ( (*p) == 10 ) goto tr35; goto st18; tr172: #line 1 "NONE" {te = p+1;} goto st99; st99: if ( ++p == pe ) goto _test_eof99; case 99: #line 3049 "rlscan.cpp" switch( (*p) ) { case 42: goto st20; case 47: goto st22; } goto tr182; tr38: #line 641 "rlscan.rl" { lastnl = p; column = 0; line++; } goto st20; st20: if ( ++p == pe ) goto _test_eof20; case 20: #line 3067 "rlscan.cpp" switch( (*p) ) { case 10: goto tr38; case 42: goto st21; } goto st20; st21: if ( ++p == pe ) goto _test_eof21; case 21: switch( (*p) ) { case 10: goto tr38; case 42: goto st21; case 47: goto tr40; } goto st20; st22: if ( ++p == pe ) goto _test_eof22; case 22: if ( (*p) == 10 ) goto tr42; goto st22; tr173: #line 1 "NONE" {te = p+1;} goto st100; st100: if ( ++p == pe ) goto _test_eof100; case 100: #line 3098 "rlscan.cpp" if ( (*p) == 120 ) goto st23; if ( 48 <= (*p) && (*p) <= 57 ) goto st101; goto tr183; st101: if ( ++p == pe ) goto _test_eof101; case 101: if ( 48 <= (*p) && (*p) <= 57 ) goto st101; goto tr183; st23: if ( ++p == pe ) goto _test_eof23; case 23: if ( (*p) < 65 ) { if ( 48 <= (*p) && (*p) <= 57 ) goto st102; } else if ( (*p) > 70 ) { if ( 97 <= (*p) && (*p) <= 102 ) goto st102; } else goto st102; goto tr43; st102: if ( ++p == pe ) goto _test_eof102; case 102: if ( (*p) < 65 ) { if ( 48 <= (*p) && (*p) <= 57 ) goto st102; } else if ( (*p) > 70 ) { if ( 97 <= (*p) && (*p) <= 102 ) goto st102; } else goto st102; goto tr185; st103: if ( ++p == pe ) goto _test_eof103; case 103: if ( (*p) == 58 ) goto tr186; goto tr182; tr177: #line 1 "NONE" {te = p+1;} #line 813 "rlscan.rl" {act = 39;} goto st104; tr201: #line 1 "NONE" {te = p+1;} #line 808 "rlscan.rl" {act = 38;} goto st104; tr206: #line 1 "NONE" {te = p+1;} #line 800 "rlscan.rl" {act = 36;} goto st104; tr208: #line 1 "NONE" {te = p+1;} #line 779 "rlscan.rl" {act = 29;} goto st104; tr213: #line 1 "NONE" {te = p+1;} #line 781 "rlscan.rl" {act = 31;} goto st104; tr215: #line 1 "NONE" {te = p+1;} #line 791 "rlscan.rl" {act = 33;} goto st104; tr218: #line 1 "NONE" {te = p+1;} #line 792 "rlscan.rl" {act = 34;} goto st104; tr221: #line 1 "NONE" {te = p+1;} #line 787 "rlscan.rl" {act = 32;} goto st104; tr224: #line 1 "NONE" {te = p+1;} #line 796 "rlscan.rl" {act = 35;} goto st104; tr225: #line 1 "NONE" {te = p+1;} #line 777 "rlscan.rl" {act = 27;} goto st104; tr227: #line 1 "NONE" {te = p+1;} #line 804 "rlscan.rl" {act = 37;} goto st104; tr231: #line 1 "NONE" {te = p+1;} #line 780 "rlscan.rl" {act = 30;} goto st104; st104: if ( ++p == pe ) goto _test_eof104; case 104: #line 3220 "rlscan.cpp" if ( (*p) == 95 ) goto tr177; if ( (*p) < 65 ) { if ( 48 <= (*p) && (*p) <= 57 ) goto tr177; } else if ( (*p) > 90 ) { if ( 97 <= (*p) && (*p) <= 122 ) goto tr177; } else goto tr177; goto tr187; st105: if ( ++p == pe ) goto _test_eof105; case 105: switch( (*p) ) { case 95: goto tr177; case 98: goto st106; case 99: goto st110; case 101: goto st115; case 103: goto st121; case 104: goto st124; case 110: goto st127; case 112: goto st130; case 114: goto st131; case 116: goto st133; } if ( (*p) < 65 ) { if ( 48 <= (*p) && (*p) <= 57 ) goto tr177; } else if ( (*p) > 90 ) { if ( 97 <= (*p) && (*p) <= 122 ) goto tr177; } else goto tr177; goto tr188; st106: if ( ++p == pe ) goto _test_eof106; case 106: switch( (*p) ) { case 95: goto tr177; case 114: goto st107; } if ( (*p) < 65 ) { if ( 48 <= (*p) && (*p) <= 57 ) goto tr177; } else if ( (*p) > 90 ) { if ( 97 <= (*p) && (*p) <= 122 ) goto tr177; } else goto tr177; goto tr188; st107: if ( ++p == pe ) goto _test_eof107; case 107: switch( (*p) ) { case 95: goto tr177; case 101: goto st108; } if ( (*p) < 65 ) { if ( 48 <= (*p) && (*p) <= 57 ) goto tr177; } else if ( (*p) > 90 ) { if ( 97 <= (*p) && (*p) <= 122 ) goto tr177; } else goto tr177; goto tr188; st108: if ( ++p == pe ) goto _test_eof108; case 108: switch( (*p) ) { case 95: goto tr177; case 97: goto st109; } if ( (*p) < 65 ) { if ( 48 <= (*p) && (*p) <= 57 ) goto tr177; } else if ( (*p) > 90 ) { if ( 98 <= (*p) && (*p) <= 122 ) goto tr177; } else goto tr177; goto tr188; st109: if ( ++p == pe ) goto _test_eof109; case 109: switch( (*p) ) { case 95: goto tr177; case 107: goto tr201; } if ( (*p) < 65 ) { if ( 48 <= (*p) && (*p) <= 57 ) goto tr177; } else if ( (*p) > 90 ) { if ( 97 <= (*p) && (*p) <= 122 ) goto tr177; } else goto tr177; goto tr188; st110: if ( ++p == pe ) goto _test_eof110; case 110: switch( (*p) ) { case 95: goto tr177; case 97: goto st111; case 117: goto st113; } if ( (*p) < 65 ) { if ( 48 <= (*p) && (*p) <= 57 ) goto tr177; } else if ( (*p) > 90 ) { if ( 98 <= (*p) && (*p) <= 122 ) goto tr177; } else goto tr177; goto tr202; st111: if ( ++p == pe ) goto _test_eof111; case 111: switch( (*p) ) { case 95: goto tr177; case 108: goto st112; } if ( (*p) < 65 ) { if ( 48 <= (*p) && (*p) <= 57 ) goto tr177; } else if ( (*p) > 90 ) { if ( 97 <= (*p) && (*p) <= 122 ) goto tr177; } else goto tr177; goto tr188; st112: if ( ++p == pe ) goto _test_eof112; case 112: switch( (*p) ) { case 95: goto tr177; case 108: goto tr206; } if ( (*p) < 65 ) { if ( 48 <= (*p) && (*p) <= 57 ) goto tr177; } else if ( (*p) > 90 ) { if ( 97 <= (*p) && (*p) <= 122 ) goto tr177; } else goto tr177; goto tr188; st113: if ( ++p == pe ) goto _test_eof113; case 113: switch( (*p) ) { case 95: goto tr177; case 114: goto st114; } if ( (*p) < 65 ) { if ( 48 <= (*p) && (*p) <= 57 ) goto tr177; } else if ( (*p) > 90 ) { if ( 97 <= (*p) && (*p) <= 122 ) goto tr177; } else goto tr177; goto tr188; st114: if ( ++p == pe ) goto _test_eof114; case 114: switch( (*p) ) { case 95: goto tr177; case 115: goto tr208; } if ( (*p) < 65 ) { if ( 48 <= (*p) && (*p) <= 57 ) goto tr177; } else if ( (*p) > 90 ) { if ( 97 <= (*p) && (*p) <= 122 ) goto tr177; } else goto tr177; goto tr188; st115: if ( ++p == pe ) goto _test_eof115; case 115: switch( (*p) ) { case 95: goto tr177; case 110: goto st116; case 120: goto st119; } if ( (*p) < 65 ) { if ( 48 <= (*p) && (*p) <= 57 ) goto tr177; } else if ( (*p) > 90 ) { if ( 97 <= (*p) && (*p) <= 122 ) goto tr177; } else goto tr177; goto tr188; st116: if ( ++p == pe ) goto _test_eof116; case 116: switch( (*p) ) { case 95: goto tr177; case 116: goto st117; } if ( (*p) < 65 ) { if ( 48 <= (*p) && (*p) <= 57 ) goto tr177; } else if ( (*p) > 90 ) { if ( 97 <= (*p) && (*p) <= 122 ) goto tr177; } else goto tr177; goto tr188; st117: if ( ++p == pe ) goto _test_eof117; case 117: switch( (*p) ) { case 95: goto tr177; case 114: goto st118; } if ( (*p) < 65 ) { if ( 48 <= (*p) && (*p) <= 57 ) goto tr177; } else if ( (*p) > 90 ) { if ( 97 <= (*p) && (*p) <= 122 ) goto tr177; } else goto tr177; goto tr188; st118: if ( ++p == pe ) goto _test_eof118; case 118: switch( (*p) ) { case 95: goto tr177; case 121: goto tr213; } if ( (*p) < 65 ) { if ( 48 <= (*p) && (*p) <= 57 ) goto tr177; } else if ( (*p) > 90 ) { if ( 97 <= (*p) && (*p) <= 122 ) goto tr177; } else goto tr177; goto tr188; st119: if ( ++p == pe ) goto _test_eof119; case 119: switch( (*p) ) { case 95: goto tr177; case 101: goto st120; } if ( (*p) < 65 ) { if ( 48 <= (*p) && (*p) <= 57 ) goto tr177; } else if ( (*p) > 90 ) { if ( 97 <= (*p) && (*p) <= 122 ) goto tr177; } else goto tr177; goto tr188; st120: if ( ++p == pe ) goto _test_eof120; case 120: switch( (*p) ) { case 95: goto tr177; case 99: goto tr215; } if ( (*p) < 65 ) { if ( 48 <= (*p) && (*p) <= 57 ) goto tr177; } else if ( (*p) > 90 ) { if ( 97 <= (*p) && (*p) <= 122 ) goto tr177; } else goto tr177; goto tr188; st121: if ( ++p == pe ) goto _test_eof121; case 121: switch( (*p) ) { case 95: goto tr177; case 111: goto st122; } if ( (*p) < 65 ) { if ( 48 <= (*p) && (*p) <= 57 ) goto tr177; } else if ( (*p) > 90 ) { if ( 97 <= (*p) && (*p) <= 122 ) goto tr177; } else goto tr177; goto tr188; st122: if ( ++p == pe ) goto _test_eof122; case 122: switch( (*p) ) { case 95: goto tr177; case 116: goto st123; } if ( (*p) < 65 ) { if ( 48 <= (*p) && (*p) <= 57 ) goto tr177; } else if ( (*p) > 90 ) { if ( 97 <= (*p) && (*p) <= 122 ) goto tr177; } else goto tr177; goto tr188; st123: if ( ++p == pe ) goto _test_eof123; case 123: switch( (*p) ) { case 95: goto tr177; case 111: goto tr218; } if ( (*p) < 65 ) { if ( 48 <= (*p) && (*p) <= 57 ) goto tr177; } else if ( (*p) > 90 ) { if ( 97 <= (*p) && (*p) <= 122 ) goto tr177; } else goto tr177; goto tr188; st124: if ( ++p == pe ) goto _test_eof124; case 124: switch( (*p) ) { case 95: goto tr177; case 111: goto st125; } if ( (*p) < 65 ) { if ( 48 <= (*p) && (*p) <= 57 ) goto tr177; } else if ( (*p) > 90 ) { if ( 97 <= (*p) && (*p) <= 122 ) goto tr177; } else goto tr177; goto tr188; st125: if ( ++p == pe ) goto _test_eof125; case 125: switch( (*p) ) { case 95: goto tr177; case 108: goto st126; } if ( (*p) < 65 ) { if ( 48 <= (*p) && (*p) <= 57 ) goto tr177; } else if ( (*p) > 90 ) { if ( 97 <= (*p) && (*p) <= 122 ) goto tr177; } else goto tr177; goto tr188; st126: if ( ++p == pe ) goto _test_eof126; case 126: switch( (*p) ) { case 95: goto tr177; case 100: goto tr221; } if ( (*p) < 65 ) { if ( 48 <= (*p) && (*p) <= 57 ) goto tr177; } else if ( (*p) > 90 ) { if ( 97 <= (*p) && (*p) <= 122 ) goto tr177; } else goto tr177; goto tr188; st127: if ( ++p == pe ) goto _test_eof127; case 127: switch( (*p) ) { case 95: goto tr177; case 101: goto st128; } if ( (*p) < 65 ) { if ( 48 <= (*p) && (*p) <= 57 ) goto tr177; } else if ( (*p) > 90 ) { if ( 97 <= (*p) && (*p) <= 122 ) goto tr177; } else goto tr177; goto tr188; st128: if ( ++p == pe ) goto _test_eof128; case 128: switch( (*p) ) { case 95: goto tr177; case 120: goto st129; } if ( (*p) < 65 ) { if ( 48 <= (*p) && (*p) <= 57 ) goto tr177; } else if ( (*p) > 90 ) { if ( 97 <= (*p) && (*p) <= 122 ) goto tr177; } else goto tr177; goto tr188; st129: if ( ++p == pe ) goto _test_eof129; case 129: switch( (*p) ) { case 95: goto tr177; case 116: goto tr224; } if ( (*p) < 65 ) { if ( 48 <= (*p) && (*p) <= 57 ) goto tr177; } else if ( (*p) > 90 ) { if ( 97 <= (*p) && (*p) <= 122 ) goto tr177; } else goto tr177; goto tr188; st130: if ( ++p == pe ) goto _test_eof130; case 130: switch( (*p) ) { case 95: goto tr177; case 99: goto tr225; } if ( (*p) < 65 ) { if ( 48 <= (*p) && (*p) <= 57 ) goto tr177; } else if ( (*p) > 90 ) { if ( 97 <= (*p) && (*p) <= 122 ) goto tr177; } else goto tr177; goto tr188; st131: if ( ++p == pe ) goto _test_eof131; case 131: switch( (*p) ) { case 95: goto tr177; case 101: goto st132; } if ( (*p) < 65 ) { if ( 48 <= (*p) && (*p) <= 57 ) goto tr177; } else if ( (*p) > 90 ) { if ( 97 <= (*p) && (*p) <= 122 ) goto tr177; } else goto tr177; goto tr188; st132: if ( ++p == pe ) goto _test_eof132; case 132: switch( (*p) ) { case 95: goto tr177; case 116: goto tr227; } if ( (*p) < 65 ) { if ( 48 <= (*p) && (*p) <= 57 ) goto tr177; } else if ( (*p) > 90 ) { if ( 97 <= (*p) && (*p) <= 122 ) goto tr177; } else goto tr177; goto tr188; st133: if ( ++p == pe ) goto _test_eof133; case 133: switch( (*p) ) { case 95: goto tr177; case 97: goto st134; } if ( (*p) < 65 ) { if ( 48 <= (*p) && (*p) <= 57 ) goto tr177; } else if ( (*p) > 90 ) { if ( 98 <= (*p) && (*p) <= 122 ) goto tr177; } else goto tr177; goto tr188; st134: if ( ++p == pe ) goto _test_eof134; case 134: switch( (*p) ) { case 95: goto tr177; case 114: goto st135; } if ( (*p) < 65 ) { if ( 48 <= (*p) && (*p) <= 57 ) goto tr177; } else if ( (*p) > 90 ) { if ( 97 <= (*p) && (*p) <= 122 ) goto tr177; } else goto tr177; goto tr188; st135: if ( ++p == pe ) goto _test_eof135; case 135: switch( (*p) ) { case 95: goto tr177; case 103: goto st136; } if ( (*p) < 65 ) { if ( 48 <= (*p) && (*p) <= 57 ) goto tr177; } else if ( (*p) > 90 ) { if ( 97 <= (*p) && (*p) <= 122 ) goto tr177; } else goto tr177; goto tr188; st136: if ( ++p == pe ) goto _test_eof136; case 136: switch( (*p) ) { case 95: goto tr177; case 115: goto tr231; } if ( (*p) < 65 ) { if ( 48 <= (*p) && (*p) <= 57 ) goto tr177; } else if ( (*p) > 90 ) { if ( 97 <= (*p) && (*p) <= 122 ) goto tr177; } else goto tr177; goto tr188; tr232: #line 900 "rlscan.rl" {te = p+1;{ token( RE_Char, ts, te ); }} goto st137; tr233: #line 895 "rlscan.rl" {te = p+1;{ scan_error() << "unterminated OR literal" << endl; }} goto st137; tr234: #line 890 "rlscan.rl" {te = p+1;{ token( RE_Dash, 0, 0 ); }} goto st137; tr236: #line 893 "rlscan.rl" {te = p+1;{ token( RE_SqClose ); {cs = stack[--top];goto _again;} }} goto st137; tr237: #line 900 "rlscan.rl" {te = p;p--;{ token( RE_Char, ts, te ); }} goto st137; tr238: #line 887 "rlscan.rl" {te = p+1;{ token( RE_Char, ts+1, te ); }} goto st137; tr239: #line 886 "rlscan.rl" {te = p+1;{ updateCol(); }} goto st137; tr240: #line 878 "rlscan.rl" {te = p+1;{ token( RE_Char, '\0' ); }} goto st137; tr241: #line 879 "rlscan.rl" {te = p+1;{ token( RE_Char, '\a' ); }} goto st137; tr242: #line 880 "rlscan.rl" {te = p+1;{ token( RE_Char, '\b' ); }} goto st137; tr243: #line 884 "rlscan.rl" {te = p+1;{ token( RE_Char, '\f' ); }} goto st137; tr244: #line 882 "rlscan.rl" {te = p+1;{ token( RE_Char, '\n' ); }} goto st137; tr245: #line 885 "rlscan.rl" {te = p+1;{ token( RE_Char, '\r' ); }} goto st137; tr246: #line 881 "rlscan.rl" {te = p+1;{ token( RE_Char, '\t' ); }} goto st137; tr247: #line 883 "rlscan.rl" {te = p+1;{ token( RE_Char, '\v' ); }} goto st137; st137: #line 1 "NONE" {ts = 0;} if ( ++p == pe ) goto _test_eof137; case 137: #line 1 "NONE" {ts = p;} #line 3856 "rlscan.cpp" switch( (*p) ) { case 0: goto tr233; case 45: goto tr234; case 92: goto st138; case 93: goto tr236; } goto tr232; st138: if ( ++p == pe ) goto _test_eof138; case 138: switch( (*p) ) { case 10: goto tr239; case 48: goto tr240; case 97: goto tr241; case 98: goto tr242; case 102: goto tr243; case 110: goto tr244; case 114: goto tr245; case 116: goto tr246; case 118: goto tr247; } goto tr238; tr248: #line 935 "rlscan.rl" {te = p+1;{ token( RE_Char, ts, te ); }} goto st139; tr249: #line 930 "rlscan.rl" {te = p+1;{ scan_error() << "unterminated regular expression" << endl; }} goto st139; tr250: #line 925 "rlscan.rl" {te = p+1;{ token( RE_Star ); }} goto st139; tr251: #line 924 "rlscan.rl" {te = p+1;{ token( RE_Dot ); }} goto st139; tr255: #line 918 "rlscan.rl" {te = p;p--;{ token( RE_Slash, ts, te ); {goto st146;} }} goto st139; tr256: #line 918 "rlscan.rl" {te = p+1;{ token( RE_Slash, ts, te ); {goto st146;} }} goto st139; tr257: #line 927 "rlscan.rl" {te = p;p--;{ token( RE_SqOpen ); {stack[top++] = 139; goto st137;} }} goto st139; tr258: #line 928 "rlscan.rl" {te = p+1;{ token( RE_SqOpenNeg ); {stack[top++] = 139; goto st137;} }} goto st139; tr259: #line 935 "rlscan.rl" {te = p;p--;{ token( RE_Char, ts, te ); }} goto st139; tr260: #line 915 "rlscan.rl" {te = p+1;{ token( RE_Char, ts+1, te ); }} goto st139; tr261: #line 914 "rlscan.rl" {te = p+1;{ updateCol(); }} goto st139; tr262: #line 906 "rlscan.rl" {te = p+1;{ token( RE_Char, '\0' ); }} goto st139; tr263: #line 907 "rlscan.rl" {te = p+1;{ token( RE_Char, '\a' ); }} goto st139; tr264: #line 908 "rlscan.rl" {te = p+1;{ token( RE_Char, '\b' ); }} goto st139; tr265: #line 912 "rlscan.rl" {te = p+1;{ token( RE_Char, '\f' ); }} goto st139; tr266: #line 910 "rlscan.rl" {te = p+1;{ token( RE_Char, '\n' ); }} goto st139; tr267: #line 913 "rlscan.rl" {te = p+1;{ token( RE_Char, '\r' ); }} goto st139; tr268: #line 909 "rlscan.rl" {te = p+1;{ token( RE_Char, '\t' ); }} goto st139; tr269: #line 911 "rlscan.rl" {te = p+1;{ token( RE_Char, '\v' ); }} goto st139; st139: #line 1 "NONE" {ts = 0;} if ( ++p == pe ) goto _test_eof139; case 139: #line 1 "NONE" {ts = p;} #line 3972 "rlscan.cpp" switch( (*p) ) { case 0: goto tr249; case 42: goto tr250; case 46: goto tr251; case 47: goto st140; case 91: goto st141; case 92: goto st142; } goto tr248; st140: if ( ++p == pe ) goto _test_eof140; case 140: if ( (*p) == 105 ) goto tr256; goto tr255; st141: if ( ++p == pe ) goto _test_eof141; case 141: if ( (*p) == 94 ) goto tr258; goto tr257; st142: if ( ++p == pe ) goto _test_eof142; case 142: switch( (*p) ) { case 10: goto tr261; case 48: goto tr262; case 97: goto tr263; case 98: goto tr264; case 102: goto tr265; case 110: goto tr266; case 114: goto tr267; case 116: goto tr268; case 118: goto tr269; } goto tr260; tr270: #line 944 "rlscan.rl" {te = p+1;{ scan_error() << "unterminated write statement" << endl; }} goto st143; tr273: #line 942 "rlscan.rl" {te = p+1;{ token( ';' ); {goto st146;} }} goto st143; tr275: #line 941 "rlscan.rl" {te = p;p--;{ updateCol(); }} goto st143; tr276: #line 940 "rlscan.rl" {te = p;p--;{ token( TK_Word, ts, te ); }} goto st143; st143: #line 1 "NONE" {ts = 0;} if ( ++p == pe ) goto _test_eof143; case 143: #line 1 "NONE" {ts = p;} #line 4038 "rlscan.cpp" switch( (*p) ) { case 0: goto tr270; case 32: goto st144; case 59: goto tr273; case 95: goto st145; } if ( (*p) < 65 ) { if ( 9 <= (*p) && (*p) <= 10 ) goto st144; } else if ( (*p) > 90 ) { if ( 97 <= (*p) && (*p) <= 122 ) goto st145; } else goto st145; goto st0; st0: cs = 0; goto _out; st144: if ( ++p == pe ) goto _test_eof144; case 144: if ( (*p) == 32 ) goto st144; if ( 9 <= (*p) && (*p) <= 10 ) goto st144; goto tr275; st145: if ( ++p == pe ) goto _test_eof145; case 145: if ( (*p) == 95 ) goto st145; if ( (*p) < 65 ) { if ( 48 <= (*p) && (*p) <= 57 ) goto st145; } else if ( (*p) > 90 ) { if ( 97 <= (*p) && (*p) <= 122 ) goto st145; } else goto st145; goto tr276; tr45: #line 1121 "rlscan.rl" {{p = ((te))-1;}{ token( *ts ); }} goto st146; tr51: #line 641 "rlscan.rl" { lastnl = p; column = 0; line++; } #line 1018 "rlscan.rl" {te = p+1;{ updateCol(); }} goto st146; tr55: #line 1005 "rlscan.rl" {{p = ((te))-1;}{ token( TK_UInt, ts, te ); }} goto st146; tr57: #line 1086 "rlscan.rl" {te = p+1;{ updateCol(); endSection(); {cs = stack[--top];goto _again;} }} goto st146; tr277: #line 1121 "rlscan.rl" {te = p+1;{ token( *ts ); }} goto st146; tr278: #line 1117 "rlscan.rl" {te = p+1;{ scan_error() << "unterminated ragel section" << endl; }} goto st146; tr280: #line 641 "rlscan.rl" { lastnl = p; column = 0; line++; } #line 1095 "rlscan.rl" {te = p+1;{ updateCol(); if ( singleLineSpec ) { endSection(); {cs = stack[--top];goto _again;} } }} goto st146; tr289: #line 1015 "rlscan.rl" {te = p+1;{ token( RE_Slash ); {goto st139;} }} goto st146; tr311: #line 1103 "rlscan.rl" {te = p+1;{ if ( lastToken == KW_Export || lastToken == KW_Entry ) token( '{' ); else { token( '{' ); curly_count = 1; inlineBlockType = CurlyDelimited; if ( hostLang->lang == HostLang::Ruby ) {stack[top++] = 146; goto st52;} else {stack[top++] = 146; goto st95;} } }} goto st146; tr314: #line 1092 "rlscan.rl" {te = p;p--;{ updateCol(); }} goto st146; tr315: #line 1121 "rlscan.rl" {te = p;p--;{ token( *ts ); }} goto st146; tr316: #line 1010 "rlscan.rl" {te = p;p--;{ token( TK_Literal, ts, te ); }} goto st146; tr317: #line 1010 "rlscan.rl" {te = p+1;{ token( TK_Literal, ts, te ); }} goto st146; tr318: #line 1048 "rlscan.rl" {te = p+1;{ token( TK_AllGblError ); }} goto st146; tr319: #line 1032 "rlscan.rl" {te = p+1;{ token( TK_AllFromState ); }} goto st146; tr320: #line 1040 "rlscan.rl" {te = p+1;{ token( TK_AllEOF ); }} goto st146; tr321: #line 1067 "rlscan.rl" {te = p+1;{ token( TK_AllCond ); }} goto st146; tr322: #line 1056 "rlscan.rl" {te = p+1;{ token( TK_AllLocalError ); }} goto st146; tr323: #line 1024 "rlscan.rl" {te = p+1;{ token( TK_AllToState ); }} goto st146; tr324: #line 1049 "rlscan.rl" {te = p+1;{ token( TK_FinalGblError ); }} goto st146; tr325: #line 1033 "rlscan.rl" {te = p+1;{ token( TK_FinalFromState ); }} goto st146; tr326: #line 1041 "rlscan.rl" {te = p+1;{ token( TK_FinalEOF ); }} goto st146; tr327: #line 1068 "rlscan.rl" {te = p+1;{ token( TK_LeavingCond ); }} goto st146; tr328: #line 1057 "rlscan.rl" {te = p+1;{ token( TK_FinalLocalError ); }} goto st146; tr329: #line 1025 "rlscan.rl" {te = p+1;{ token( TK_FinalToState ); }} goto st146; tr330: #line 1071 "rlscan.rl" {te = p+1;{ token( TK_StarStar ); }} goto st146; tr331: #line 1072 "rlscan.rl" {te = p+1;{ token( TK_DashDash ); }} goto st146; tr332: #line 1073 "rlscan.rl" {te = p+1;{ token( TK_Arrow ); }} goto st146; tr333: #line 1070 "rlscan.rl" {te = p+1;{ token( TK_DotDot ); }} goto st146; tr334: #line 1005 "rlscan.rl" {te = p;p--;{ token( TK_UInt, ts, te ); }} goto st146; tr336: #line 1006 "rlscan.rl" {te = p;p--;{ token( TK_Hex, ts, te ); }} goto st146; tr337: #line 1084 "rlscan.rl" {te = p+1;{ token( TK_NameSep, ts, te ); }} goto st146; tr338: #line 1020 "rlscan.rl" {te = p+1;{ token( TK_ColonEquals ); }} goto st146; tr340: #line 1076 "rlscan.rl" {te = p;p--;{ token( TK_ColonGt ); }} goto st146; tr341: #line 1077 "rlscan.rl" {te = p+1;{ token( TK_ColonGtGt ); }} goto st146; tr342: #line 1050 "rlscan.rl" {te = p+1;{ token( TK_NotStartGblError ); }} goto st146; tr343: #line 1034 "rlscan.rl" {te = p+1;{ token( TK_NotStartFromState ); }} goto st146; tr344: #line 1042 "rlscan.rl" {te = p+1;{ token( TK_NotStartEOF ); }} goto st146; tr345: #line 1078 "rlscan.rl" {te = p+1;{ token( TK_LtColon ); }} goto st146; tr347: #line 1058 "rlscan.rl" {te = p+1;{ token( TK_NotStartLocalError ); }} goto st146; tr348: #line 1026 "rlscan.rl" {te = p+1;{ token( TK_NotStartToState ); }} goto st146; tr349: #line 1063 "rlscan.rl" {te = p;p--;{ token( TK_Middle ); }} goto st146; tr350: #line 1052 "rlscan.rl" {te = p+1;{ token( TK_MiddleGblError ); }} goto st146; tr351: #line 1036 "rlscan.rl" {te = p+1;{ token( TK_MiddleFromState ); }} goto st146; tr352: #line 1044 "rlscan.rl" {te = p+1;{ token( TK_MiddleEOF ); }} goto st146; tr353: #line 1060 "rlscan.rl" {te = p+1;{ token( TK_MiddleLocalError ); }} goto st146; tr354: #line 1028 "rlscan.rl" {te = p+1;{ token( TK_MiddleToState ); }} goto st146; tr355: #line 1074 "rlscan.rl" {te = p+1;{ token( TK_DoubleArrow ); }} goto st146; tr356: #line 1047 "rlscan.rl" {te = p+1;{ token( TK_StartGblError ); }} goto st146; tr357: #line 1031 "rlscan.rl" {te = p+1;{ token( TK_StartFromState ); }} goto st146; tr358: #line 1039 "rlscan.rl" {te = p+1;{ token( TK_StartEOF ); }} goto st146; tr359: #line 1066 "rlscan.rl" {te = p+1;{ token( TK_StartCond ); }} goto st146; tr360: #line 1055 "rlscan.rl" {te = p+1;{ token( TK_StartLocalError ); }} goto st146; tr361: #line 1023 "rlscan.rl" {te = p+1;{ token( TK_StartToState ); }} goto st146; tr362: #line 1051 "rlscan.rl" {te = p+1;{ token( TK_NotFinalGblError ); }} goto st146; tr363: #line 1035 "rlscan.rl" {te = p+1;{ token( TK_NotFinalFromState ); }} goto st146; tr364: #line 1043 "rlscan.rl" {te = p+1;{ token( TK_NotFinalEOF ); }} goto st146; tr365: #line 1059 "rlscan.rl" {te = p+1;{ token( TK_NotFinalLocalError ); }} goto st146; tr366: #line 1027 "rlscan.rl" {te = p+1;{ token( TK_NotFinalToState ); }} goto st146; tr367: #line 1 "NONE" { switch( act ) { case 88: {{p = ((te))-1;} token( KW_Machine ); } break; case 89: {{p = ((te))-1;} token( KW_Include ); } break; case 90: {{p = ((te))-1;} token( KW_Import ); } break; case 91: {{p = ((te))-1;} token( KW_Write ); {goto st143;} } break; case 92: {{p = ((te))-1;} token( KW_Action ); } break; case 93: {{p = ((te))-1;} token( KW_AlphType ); } break; case 94: {{p = ((te))-1;} token( KW_PrePush ); } break; case 95: {{p = ((te))-1;} token( KW_PostPop ); } break; case 96: {{p = ((te))-1;} token( KW_GetKey ); inlineBlockType = SemiTerminated; if ( hostLang->lang == HostLang::Ruby ) {stack[top++] = 146; goto st52;} else {stack[top++] = 146; goto st95;} } break; case 97: {{p = ((te))-1;} token( KW_Access ); inlineBlockType = SemiTerminated; if ( hostLang->lang == HostLang::Ruby ) {stack[top++] = 146; goto st52;} else {stack[top++] = 146; goto st95;} } break; case 98: {{p = ((te))-1;} token( KW_Variable ); inlineBlockType = SemiTerminated; if ( hostLang->lang == HostLang::Ruby ) {stack[top++] = 146; goto st52;} else {stack[top++] = 146; goto st95;} } break; case 99: {{p = ((te))-1;} token( KW_When ); } break; case 100: {{p = ((te))-1;} token( KW_InWhen ); } break; case 101: {{p = ((te))-1;} token( KW_OutWhen ); } break; case 102: {{p = ((te))-1;} token( KW_Eof ); } break; case 103: {{p = ((te))-1;} token( KW_Err ); } break; case 104: {{p = ((te))-1;} token( KW_Lerr ); } break; case 105: {{p = ((te))-1;} token( KW_To ); } break; case 106: {{p = ((te))-1;} token( KW_From ); } break; case 107: {{p = ((te))-1;} token( KW_Export ); } break; case 108: {{p = ((te))-1;} token( TK_Word, ts, te ); } break; } } goto st146; tr368: #line 1012 "rlscan.rl" {te = p;p--;{ token( RE_SqOpen ); {stack[top++] = 146; goto st137;} }} goto st146; tr369: #line 1013 "rlscan.rl" {te = p+1;{ token( RE_SqOpenNeg ); {stack[top++] = 146; goto st137;} }} goto st146; tr370: #line 1002 "rlscan.rl" {te = p;p--;{ token( TK_Word, ts, te ); }} goto st146; tr461: #line 1081 "rlscan.rl" {te = p+1;{ token( TK_BarStar ); }} goto st146; st146: #line 1 "NONE" {ts = 0;} if ( ++p == pe ) goto _test_eof146; case 146: #line 1 "NONE" {ts = p;} #line 4470 "rlscan.cpp" switch( (*p) ) { case 0: goto tr278; case 9: goto st147; case 10: goto tr280; case 13: goto st147; case 32: goto st147; case 34: goto tr281; case 35: goto tr282; case 36: goto st151; case 37: goto st152; case 39: goto tr285; case 42: goto st154; case 45: goto st155; case 46: goto st156; case 47: goto tr289; case 48: goto tr290; case 58: goto st160; case 60: goto st162; case 61: goto st164; case 62: goto st165; case 64: goto st166; case 91: goto st168; case 95: goto tr297; case 97: goto st169; case 101: goto st183; case 102: goto st190; case 103: goto st193; case 105: goto st198; case 108: goto st211; case 109: goto st214; case 111: goto st220; case 112: goto st226; case 116: goto st237; case 118: goto st238; case 119: goto st245; case 123: goto tr311; case 124: goto st251; case 125: goto tr313; } if ( (*p) < 65 ) { if ( 49 <= (*p) && (*p) <= 57 ) goto st158; } else if ( (*p) > 90 ) { if ( 98 <= (*p) && (*p) <= 122 ) goto tr297; } else goto tr297; goto tr277; st147: if ( ++p == pe ) goto _test_eof147; case 147: switch( (*p) ) { case 9: goto st147; case 13: goto st147; case 32: goto st147; } goto tr314; tr281: #line 1 "NONE" {te = p+1;} goto st148; st148: if ( ++p == pe ) goto _test_eof148; case 148: #line 4537 "rlscan.cpp" switch( (*p) ) { case 10: goto tr47; case 34: goto st149; case 92: goto st25; } goto st24; tr47: #line 641 "rlscan.rl" { lastnl = p; column = 0; line++; } goto st24; st24: if ( ++p == pe ) goto _test_eof24; case 24: #line 4556 "rlscan.cpp" switch( (*p) ) { case 10: goto tr47; case 34: goto st149; case 92: goto st25; } goto st24; st149: if ( ++p == pe ) goto _test_eof149; case 149: if ( (*p) == 105 ) goto tr317; goto tr316; st25: if ( ++p == pe ) goto _test_eof25; case 25: if ( (*p) == 10 ) goto tr47; goto st24; tr282: #line 1 "NONE" {te = p+1;} goto st150; st150: if ( ++p == pe ) goto _test_eof150; case 150: #line 4585 "rlscan.cpp" if ( (*p) == 10 ) goto tr51; goto st26; st26: if ( ++p == pe ) goto _test_eof26; case 26: if ( (*p) == 10 ) goto tr51; goto st26; st151: if ( ++p == pe ) goto _test_eof151; case 151: switch( (*p) ) { case 33: goto tr318; case 42: goto tr319; case 47: goto tr320; case 63: goto tr321; case 94: goto tr322; case 126: goto tr323; } goto tr315; st152: if ( ++p == pe ) goto _test_eof152; case 152: switch( (*p) ) { case 33: goto tr324; case 42: goto tr325; case 47: goto tr326; case 63: goto tr327; case 94: goto tr328; case 126: goto tr329; } goto tr315; tr285: #line 1 "NONE" {te = p+1;} goto st153; st153: if ( ++p == pe ) goto _test_eof153; case 153: #line 4630 "rlscan.cpp" switch( (*p) ) { case 10: goto tr53; case 39: goto st149; case 92: goto st28; } goto st27; tr53: #line 641 "rlscan.rl" { lastnl = p; column = 0; line++; } goto st27; st27: if ( ++p == pe ) goto _test_eof27; case 27: #line 4649 "rlscan.cpp" switch( (*p) ) { case 10: goto tr53; case 39: goto st149; case 92: goto st28; } goto st27; st28: if ( ++p == pe ) goto _test_eof28; case 28: if ( (*p) == 10 ) goto tr53; goto st27; st154: if ( ++p == pe ) goto _test_eof154; case 154: if ( (*p) == 42 ) goto tr330; goto tr315; st155: if ( ++p == pe ) goto _test_eof155; case 155: switch( (*p) ) { case 45: goto tr331; case 62: goto tr332; } goto tr315; st156: if ( ++p == pe ) goto _test_eof156; case 156: if ( (*p) == 46 ) goto tr333; goto tr315; tr290: #line 1 "NONE" {te = p+1;} goto st157; st157: if ( ++p == pe ) goto _test_eof157; case 157: #line 4694 "rlscan.cpp" if ( (*p) == 120 ) goto st29; if ( 48 <= (*p) && (*p) <= 57 ) goto st158; goto tr334; st158: if ( ++p == pe ) goto _test_eof158; case 158: if ( 48 <= (*p) && (*p) <= 57 ) goto st158; goto tr334; st29: if ( ++p == pe ) goto _test_eof29; case 29: if ( (*p) < 65 ) { if ( 48 <= (*p) && (*p) <= 57 ) goto st159; } else if ( (*p) > 70 ) { if ( 97 <= (*p) && (*p) <= 102 ) goto st159; } else goto st159; goto tr55; st159: if ( ++p == pe ) goto _test_eof159; case 159: if ( (*p) < 65 ) { if ( 48 <= (*p) && (*p) <= 57 ) goto st159; } else if ( (*p) > 70 ) { if ( 97 <= (*p) && (*p) <= 102 ) goto st159; } else goto st159; goto tr336; st160: if ( ++p == pe ) goto _test_eof160; case 160: switch( (*p) ) { case 58: goto tr337; case 61: goto tr338; case 62: goto st161; } goto tr315; st161: if ( ++p == pe ) goto _test_eof161; case 161: if ( (*p) == 62 ) goto tr341; goto tr340; st162: if ( ++p == pe ) goto _test_eof162; case 162: switch( (*p) ) { case 33: goto tr342; case 42: goto tr343; case 47: goto tr344; case 58: goto tr345; case 62: goto st163; case 94: goto tr347; case 126: goto tr348; } goto tr315; st163: if ( ++p == pe ) goto _test_eof163; case 163: switch( (*p) ) { case 33: goto tr350; case 42: goto tr351; case 47: goto tr352; case 94: goto tr353; case 126: goto tr354; } goto tr349; st164: if ( ++p == pe ) goto _test_eof164; case 164: if ( (*p) == 62 ) goto tr355; goto tr315; st165: if ( ++p == pe ) goto _test_eof165; case 165: switch( (*p) ) { case 33: goto tr356; case 42: goto tr357; case 47: goto tr358; case 63: goto tr359; case 94: goto tr360; case 126: goto tr361; } goto tr315; st166: if ( ++p == pe ) goto _test_eof166; case 166: switch( (*p) ) { case 33: goto tr362; case 42: goto tr363; case 47: goto tr364; case 94: goto tr365; case 126: goto tr366; } goto tr315; tr297: #line 1 "NONE" {te = p+1;} #line 1002 "rlscan.rl" {act = 108;} goto st167; tr377: #line 1 "NONE" {te = p+1;} #line 975 "rlscan.rl" {act = 97;} goto st167; tr380: #line 1 "NONE" {te = p+1;} #line 959 "rlscan.rl" {act = 92;} goto st167; tr386: #line 1 "NONE" {te = p+1;} #line 960 "rlscan.rl" {act = 93;} goto st167; tr390: #line 1 "NONE" {te = p+1;} #line 994 "rlscan.rl" {act = 102;} goto st167; tr391: #line 1 "NONE" {te = p+1;} #line 995 "rlscan.rl" {act = 103;} goto st167; tr395: #line 1 "NONE" {te = p+1;} #line 999 "rlscan.rl" {act = 107;} goto st167; tr398: #line 1 "NONE" {te = p+1;} #line 998 "rlscan.rl" {act = 106;} goto st167; tr403: #line 1 "NONE" {te = p+1;} #line 967 "rlscan.rl" {act = 96;} goto st167; tr409: #line 1 "NONE" {te = p+1;} #line 954 "rlscan.rl" {act = 90;} goto st167; tr415: #line 1 "NONE" {te = p+1;} #line 953 "rlscan.rl" {act = 89;} goto st167; tr418: #line 1 "NONE" {te = p+1;} #line 992 "rlscan.rl" {act = 100;} goto st167; tr421: #line 1 "NONE" {te = p+1;} #line 996 "rlscan.rl" {act = 104;} goto st167; tr427: #line 1 "NONE" {te = p+1;} #line 952 "rlscan.rl" {act = 88;} goto st167; tr433: #line 1 "NONE" {te = p+1;} #line 993 "rlscan.rl" {act = 101;} goto st167; tr440: #line 1 "NONE" {te = p+1;} #line 962 "rlscan.rl" {act = 95;} goto st167; tr445: #line 1 "NONE" {te = p+1;} #line 961 "rlscan.rl" {act = 94;} goto st167; tr446: #line 1 "NONE" {te = p+1;} #line 997 "rlscan.rl" {act = 105;} goto st167; tr453: #line 1 "NONE" {te = p+1;} #line 983 "rlscan.rl" {act = 98;} goto st167; tr457: #line 1 "NONE" {te = p+1;} #line 991 "rlscan.rl" {act = 99;} goto st167; tr460: #line 1 "NONE" {te = p+1;} #line 955 "rlscan.rl" {act = 91;} goto st167; st167: if ( ++p == pe ) goto _test_eof167; case 167: #line 4938 "rlscan.cpp" if ( (*p) == 95 ) goto tr297; if ( (*p) < 65 ) { if ( 48 <= (*p) && (*p) <= 57 ) goto tr297; } else if ( (*p) > 90 ) { if ( 97 <= (*p) && (*p) <= 122 ) goto tr297; } else goto tr297; goto tr367; st168: if ( ++p == pe ) goto _test_eof168; case 168: if ( (*p) == 94 ) goto tr369; goto tr368; st169: if ( ++p == pe ) goto _test_eof169; case 169: switch( (*p) ) { case 95: goto tr297; case 99: goto st170; case 108: goto st177; } if ( (*p) < 65 ) { if ( 48 <= (*p) && (*p) <= 57 ) goto tr297; } else if ( (*p) > 90 ) { if ( 97 <= (*p) && (*p) <= 122 ) goto tr297; } else goto tr297; goto tr370; st170: if ( ++p == pe ) goto _test_eof170; case 170: switch( (*p) ) { case 95: goto tr297; case 99: goto st171; case 116: goto st174; } if ( (*p) < 65 ) { if ( 48 <= (*p) && (*p) <= 57 ) goto tr297; } else if ( (*p) > 90 ) { if ( 97 <= (*p) && (*p) <= 122 ) goto tr297; } else goto tr297; goto tr370; st171: if ( ++p == pe ) goto _test_eof171; case 171: switch( (*p) ) { case 95: goto tr297; case 101: goto st172; } if ( (*p) < 65 ) { if ( 48 <= (*p) && (*p) <= 57 ) goto tr297; } else if ( (*p) > 90 ) { if ( 97 <= (*p) && (*p) <= 122 ) goto tr297; } else goto tr297; goto tr370; st172: if ( ++p == pe ) goto _test_eof172; case 172: switch( (*p) ) { case 95: goto tr297; case 115: goto st173; } if ( (*p) < 65 ) { if ( 48 <= (*p) && (*p) <= 57 ) goto tr297; } else if ( (*p) > 90 ) { if ( 97 <= (*p) && (*p) <= 122 ) goto tr297; } else goto tr297; goto tr370; st173: if ( ++p == pe ) goto _test_eof173; case 173: switch( (*p) ) { case 95: goto tr297; case 115: goto tr377; } if ( (*p) < 65 ) { if ( 48 <= (*p) && (*p) <= 57 ) goto tr297; } else if ( (*p) > 90 ) { if ( 97 <= (*p) && (*p) <= 122 ) goto tr297; } else goto tr297; goto tr370; st174: if ( ++p == pe ) goto _test_eof174; case 174: switch( (*p) ) { case 95: goto tr297; case 105: goto st175; } if ( (*p) < 65 ) { if ( 48 <= (*p) && (*p) <= 57 ) goto tr297; } else if ( (*p) > 90 ) { if ( 97 <= (*p) && (*p) <= 122 ) goto tr297; } else goto tr297; goto tr370; st175: if ( ++p == pe ) goto _test_eof175; case 175: switch( (*p) ) { case 95: goto tr297; case 111: goto st176; } if ( (*p) < 65 ) { if ( 48 <= (*p) && (*p) <= 57 ) goto tr297; } else if ( (*p) > 90 ) { if ( 97 <= (*p) && (*p) <= 122 ) goto tr297; } else goto tr297; goto tr370; st176: if ( ++p == pe ) goto _test_eof176; case 176: switch( (*p) ) { case 95: goto tr297; case 110: goto tr380; } if ( (*p) < 65 ) { if ( 48 <= (*p) && (*p) <= 57 ) goto tr297; } else if ( (*p) > 90 ) { if ( 97 <= (*p) && (*p) <= 122 ) goto tr297; } else goto tr297; goto tr370; st177: if ( ++p == pe ) goto _test_eof177; case 177: switch( (*p) ) { case 95: goto tr297; case 112: goto st178; } if ( (*p) < 65 ) { if ( 48 <= (*p) && (*p) <= 57 ) goto tr297; } else if ( (*p) > 90 ) { if ( 97 <= (*p) && (*p) <= 122 ) goto tr297; } else goto tr297; goto tr370; st178: if ( ++p == pe ) goto _test_eof178; case 178: switch( (*p) ) { case 95: goto tr297; case 104: goto st179; } if ( (*p) < 65 ) { if ( 48 <= (*p) && (*p) <= 57 ) goto tr297; } else if ( (*p) > 90 ) { if ( 97 <= (*p) && (*p) <= 122 ) goto tr297; } else goto tr297; goto tr370; st179: if ( ++p == pe ) goto _test_eof179; case 179: switch( (*p) ) { case 95: goto tr297; case 116: goto st180; } if ( (*p) < 65 ) { if ( 48 <= (*p) && (*p) <= 57 ) goto tr297; } else if ( (*p) > 90 ) { if ( 97 <= (*p) && (*p) <= 122 ) goto tr297; } else goto tr297; goto tr370; st180: if ( ++p == pe ) goto _test_eof180; case 180: switch( (*p) ) { case 95: goto tr297; case 121: goto st181; } if ( (*p) < 65 ) { if ( 48 <= (*p) && (*p) <= 57 ) goto tr297; } else if ( (*p) > 90 ) { if ( 97 <= (*p) && (*p) <= 122 ) goto tr297; } else goto tr297; goto tr370; st181: if ( ++p == pe ) goto _test_eof181; case 181: switch( (*p) ) { case 95: goto tr297; case 112: goto st182; } if ( (*p) < 65 ) { if ( 48 <= (*p) && (*p) <= 57 ) goto tr297; } else if ( (*p) > 90 ) { if ( 97 <= (*p) && (*p) <= 122 ) goto tr297; } else goto tr297; goto tr370; st182: if ( ++p == pe ) goto _test_eof182; case 182: switch( (*p) ) { case 95: goto tr297; case 101: goto tr386; } if ( (*p) < 65 ) { if ( 48 <= (*p) && (*p) <= 57 ) goto tr297; } else if ( (*p) > 90 ) { if ( 97 <= (*p) && (*p) <= 122 ) goto tr297; } else goto tr297; goto tr370; st183: if ( ++p == pe ) goto _test_eof183; case 183: switch( (*p) ) { case 95: goto tr297; case 111: goto st184; case 114: goto st185; case 120: goto st186; } if ( (*p) < 65 ) { if ( 48 <= (*p) && (*p) <= 57 ) goto tr297; } else if ( (*p) > 90 ) { if ( 97 <= (*p) && (*p) <= 122 ) goto tr297; } else goto tr297; goto tr370; st184: if ( ++p == pe ) goto _test_eof184; case 184: switch( (*p) ) { case 95: goto tr297; case 102: goto tr390; } if ( (*p) < 65 ) { if ( 48 <= (*p) && (*p) <= 57 ) goto tr297; } else if ( (*p) > 90 ) { if ( 97 <= (*p) && (*p) <= 122 ) goto tr297; } else goto tr297; goto tr370; st185: if ( ++p == pe ) goto _test_eof185; case 185: switch( (*p) ) { case 95: goto tr297; case 114: goto tr391; } if ( (*p) < 65 ) { if ( 48 <= (*p) && (*p) <= 57 ) goto tr297; } else if ( (*p) > 90 ) { if ( 97 <= (*p) && (*p) <= 122 ) goto tr297; } else goto tr297; goto tr370; st186: if ( ++p == pe ) goto _test_eof186; case 186: switch( (*p) ) { case 95: goto tr297; case 112: goto st187; } if ( (*p) < 65 ) { if ( 48 <= (*p) && (*p) <= 57 ) goto tr297; } else if ( (*p) > 90 ) { if ( 97 <= (*p) && (*p) <= 122 ) goto tr297; } else goto tr297; goto tr370; st187: if ( ++p == pe ) goto _test_eof187; case 187: switch( (*p) ) { case 95: goto tr297; case 111: goto st188; } if ( (*p) < 65 ) { if ( 48 <= (*p) && (*p) <= 57 ) goto tr297; } else if ( (*p) > 90 ) { if ( 97 <= (*p) && (*p) <= 122 ) goto tr297; } else goto tr297; goto tr370; st188: if ( ++p == pe ) goto _test_eof188; case 188: switch( (*p) ) { case 95: goto tr297; case 114: goto st189; } if ( (*p) < 65 ) { if ( 48 <= (*p) && (*p) <= 57 ) goto tr297; } else if ( (*p) > 90 ) { if ( 97 <= (*p) && (*p) <= 122 ) goto tr297; } else goto tr297; goto tr370; st189: if ( ++p == pe ) goto _test_eof189; case 189: switch( (*p) ) { case 95: goto tr297; case 116: goto tr395; } if ( (*p) < 65 ) { if ( 48 <= (*p) && (*p) <= 57 ) goto tr297; } else if ( (*p) > 90 ) { if ( 97 <= (*p) && (*p) <= 122 ) goto tr297; } else goto tr297; goto tr370; st190: if ( ++p == pe ) goto _test_eof190; case 190: switch( (*p) ) { case 95: goto tr297; case 114: goto st191; } if ( (*p) < 65 ) { if ( 48 <= (*p) && (*p) <= 57 ) goto tr297; } else if ( (*p) > 90 ) { if ( 97 <= (*p) && (*p) <= 122 ) goto tr297; } else goto tr297; goto tr370; st191: if ( ++p == pe ) goto _test_eof191; case 191: switch( (*p) ) { case 95: goto tr297; case 111: goto st192; } if ( (*p) < 65 ) { if ( 48 <= (*p) && (*p) <= 57 ) goto tr297; } else if ( (*p) > 90 ) { if ( 97 <= (*p) && (*p) <= 122 ) goto tr297; } else goto tr297; goto tr370; st192: if ( ++p == pe ) goto _test_eof192; case 192: switch( (*p) ) { case 95: goto tr297; case 109: goto tr398; } if ( (*p) < 65 ) { if ( 48 <= (*p) && (*p) <= 57 ) goto tr297; } else if ( (*p) > 90 ) { if ( 97 <= (*p) && (*p) <= 122 ) goto tr297; } else goto tr297; goto tr370; st193: if ( ++p == pe ) goto _test_eof193; case 193: switch( (*p) ) { case 95: goto tr297; case 101: goto st194; } if ( (*p) < 65 ) { if ( 48 <= (*p) && (*p) <= 57 ) goto tr297; } else if ( (*p) > 90 ) { if ( 97 <= (*p) && (*p) <= 122 ) goto tr297; } else goto tr297; goto tr370; st194: if ( ++p == pe ) goto _test_eof194; case 194: switch( (*p) ) { case 95: goto tr297; case 116: goto st195; } if ( (*p) < 65 ) { if ( 48 <= (*p) && (*p) <= 57 ) goto tr297; } else if ( (*p) > 90 ) { if ( 97 <= (*p) && (*p) <= 122 ) goto tr297; } else goto tr297; goto tr370; st195: if ( ++p == pe ) goto _test_eof195; case 195: switch( (*p) ) { case 95: goto tr297; case 107: goto st196; } if ( (*p) < 65 ) { if ( 48 <= (*p) && (*p) <= 57 ) goto tr297; } else if ( (*p) > 90 ) { if ( 97 <= (*p) && (*p) <= 122 ) goto tr297; } else goto tr297; goto tr370; st196: if ( ++p == pe ) goto _test_eof196; case 196: switch( (*p) ) { case 95: goto tr297; case 101: goto st197; } if ( (*p) < 65 ) { if ( 48 <= (*p) && (*p) <= 57 ) goto tr297; } else if ( (*p) > 90 ) { if ( 97 <= (*p) && (*p) <= 122 ) goto tr297; } else goto tr297; goto tr370; st197: if ( ++p == pe ) goto _test_eof197; case 197: switch( (*p) ) { case 95: goto tr297; case 121: goto tr403; } if ( (*p) < 65 ) { if ( 48 <= (*p) && (*p) <= 57 ) goto tr297; } else if ( (*p) > 90 ) { if ( 97 <= (*p) && (*p) <= 122 ) goto tr297; } else goto tr297; goto tr370; st198: if ( ++p == pe ) goto _test_eof198; case 198: switch( (*p) ) { case 95: goto tr297; case 109: goto st199; case 110: goto st203; } if ( (*p) < 65 ) { if ( 48 <= (*p) && (*p) <= 57 ) goto tr297; } else if ( (*p) > 90 ) { if ( 97 <= (*p) && (*p) <= 122 ) goto tr297; } else goto tr297; goto tr370; st199: if ( ++p == pe ) goto _test_eof199; case 199: switch( (*p) ) { case 95: goto tr297; case 112: goto st200; } if ( (*p) < 65 ) { if ( 48 <= (*p) && (*p) <= 57 ) goto tr297; } else if ( (*p) > 90 ) { if ( 97 <= (*p) && (*p) <= 122 ) goto tr297; } else goto tr297; goto tr370; st200: if ( ++p == pe ) goto _test_eof200; case 200: switch( (*p) ) { case 95: goto tr297; case 111: goto st201; } if ( (*p) < 65 ) { if ( 48 <= (*p) && (*p) <= 57 ) goto tr297; } else if ( (*p) > 90 ) { if ( 97 <= (*p) && (*p) <= 122 ) goto tr297; } else goto tr297; goto tr370; st201: if ( ++p == pe ) goto _test_eof201; case 201: switch( (*p) ) { case 95: goto tr297; case 114: goto st202; } if ( (*p) < 65 ) { if ( 48 <= (*p) && (*p) <= 57 ) goto tr297; } else if ( (*p) > 90 ) { if ( 97 <= (*p) && (*p) <= 122 ) goto tr297; } else goto tr297; goto tr370; st202: if ( ++p == pe ) goto _test_eof202; case 202: switch( (*p) ) { case 95: goto tr297; case 116: goto tr409; } if ( (*p) < 65 ) { if ( 48 <= (*p) && (*p) <= 57 ) goto tr297; } else if ( (*p) > 90 ) { if ( 97 <= (*p) && (*p) <= 122 ) goto tr297; } else goto tr297; goto tr370; st203: if ( ++p == pe ) goto _test_eof203; case 203: switch( (*p) ) { case 95: goto tr297; case 99: goto st204; case 119: goto st208; } if ( (*p) < 65 ) { if ( 48 <= (*p) && (*p) <= 57 ) goto tr297; } else if ( (*p) > 90 ) { if ( 97 <= (*p) && (*p) <= 122 ) goto tr297; } else goto tr297; goto tr370; st204: if ( ++p == pe ) goto _test_eof204; case 204: switch( (*p) ) { case 95: goto tr297; case 108: goto st205; } if ( (*p) < 65 ) { if ( 48 <= (*p) && (*p) <= 57 ) goto tr297; } else if ( (*p) > 90 ) { if ( 97 <= (*p) && (*p) <= 122 ) goto tr297; } else goto tr297; goto tr370; st205: if ( ++p == pe ) goto _test_eof205; case 205: switch( (*p) ) { case 95: goto tr297; case 117: goto st206; } if ( (*p) < 65 ) { if ( 48 <= (*p) && (*p) <= 57 ) goto tr297; } else if ( (*p) > 90 ) { if ( 97 <= (*p) && (*p) <= 122 ) goto tr297; } else goto tr297; goto tr370; st206: if ( ++p == pe ) goto _test_eof206; case 206: switch( (*p) ) { case 95: goto tr297; case 100: goto st207; } if ( (*p) < 65 ) { if ( 48 <= (*p) && (*p) <= 57 ) goto tr297; } else if ( (*p) > 90 ) { if ( 97 <= (*p) && (*p) <= 122 ) goto tr297; } else goto tr297; goto tr370; st207: if ( ++p == pe ) goto _test_eof207; case 207: switch( (*p) ) { case 95: goto tr297; case 101: goto tr415; } if ( (*p) < 65 ) { if ( 48 <= (*p) && (*p) <= 57 ) goto tr297; } else if ( (*p) > 90 ) { if ( 97 <= (*p) && (*p) <= 122 ) goto tr297; } else goto tr297; goto tr370; st208: if ( ++p == pe ) goto _test_eof208; case 208: switch( (*p) ) { case 95: goto tr297; case 104: goto st209; } if ( (*p) < 65 ) { if ( 48 <= (*p) && (*p) <= 57 ) goto tr297; } else if ( (*p) > 90 ) { if ( 97 <= (*p) && (*p) <= 122 ) goto tr297; } else goto tr297; goto tr370; st209: if ( ++p == pe ) goto _test_eof209; case 209: switch( (*p) ) { case 95: goto tr297; case 101: goto st210; } if ( (*p) < 65 ) { if ( 48 <= (*p) && (*p) <= 57 ) goto tr297; } else if ( (*p) > 90 ) { if ( 97 <= (*p) && (*p) <= 122 ) goto tr297; } else goto tr297; goto tr370; st210: if ( ++p == pe ) goto _test_eof210; case 210: switch( (*p) ) { case 95: goto tr297; case 110: goto tr418; } if ( (*p) < 65 ) { if ( 48 <= (*p) && (*p) <= 57 ) goto tr297; } else if ( (*p) > 90 ) { if ( 97 <= (*p) && (*p) <= 122 ) goto tr297; } else goto tr297; goto tr370; st211: if ( ++p == pe ) goto _test_eof211; case 211: switch( (*p) ) { case 95: goto tr297; case 101: goto st212; } if ( (*p) < 65 ) { if ( 48 <= (*p) && (*p) <= 57 ) goto tr297; } else if ( (*p) > 90 ) { if ( 97 <= (*p) && (*p) <= 122 ) goto tr297; } else goto tr297; goto tr370; st212: if ( ++p == pe ) goto _test_eof212; case 212: switch( (*p) ) { case 95: goto tr297; case 114: goto st213; } if ( (*p) < 65 ) { if ( 48 <= (*p) && (*p) <= 57 ) goto tr297; } else if ( (*p) > 90 ) { if ( 97 <= (*p) && (*p) <= 122 ) goto tr297; } else goto tr297; goto tr370; st213: if ( ++p == pe ) goto _test_eof213; case 213: switch( (*p) ) { case 95: goto tr297; case 114: goto tr421; } if ( (*p) < 65 ) { if ( 48 <= (*p) && (*p) <= 57 ) goto tr297; } else if ( (*p) > 90 ) { if ( 97 <= (*p) && (*p) <= 122 ) goto tr297; } else goto tr297; goto tr370; st214: if ( ++p == pe ) goto _test_eof214; case 214: switch( (*p) ) { case 95: goto tr297; case 97: goto st215; } if ( (*p) < 65 ) { if ( 48 <= (*p) && (*p) <= 57 ) goto tr297; } else if ( (*p) > 90 ) { if ( 98 <= (*p) && (*p) <= 122 ) goto tr297; } else goto tr297; goto tr370; st215: if ( ++p == pe ) goto _test_eof215; case 215: switch( (*p) ) { case 95: goto tr297; case 99: goto st216; } if ( (*p) < 65 ) { if ( 48 <= (*p) && (*p) <= 57 ) goto tr297; } else if ( (*p) > 90 ) { if ( 97 <= (*p) && (*p) <= 122 ) goto tr297; } else goto tr297; goto tr370; st216: if ( ++p == pe ) goto _test_eof216; case 216: switch( (*p) ) { case 95: goto tr297; case 104: goto st217; } if ( (*p) < 65 ) { if ( 48 <= (*p) && (*p) <= 57 ) goto tr297; } else if ( (*p) > 90 ) { if ( 97 <= (*p) && (*p) <= 122 ) goto tr297; } else goto tr297; goto tr370; st217: if ( ++p == pe ) goto _test_eof217; case 217: switch( (*p) ) { case 95: goto tr297; case 105: goto st218; } if ( (*p) < 65 ) { if ( 48 <= (*p) && (*p) <= 57 ) goto tr297; } else if ( (*p) > 90 ) { if ( 97 <= (*p) && (*p) <= 122 ) goto tr297; } else goto tr297; goto tr370; st218: if ( ++p == pe ) goto _test_eof218; case 218: switch( (*p) ) { case 95: goto tr297; case 110: goto st219; } if ( (*p) < 65 ) { if ( 48 <= (*p) && (*p) <= 57 ) goto tr297; } else if ( (*p) > 90 ) { if ( 97 <= (*p) && (*p) <= 122 ) goto tr297; } else goto tr297; goto tr370; st219: if ( ++p == pe ) goto _test_eof219; case 219: switch( (*p) ) { case 95: goto tr297; case 101: goto tr427; } if ( (*p) < 65 ) { if ( 48 <= (*p) && (*p) <= 57 ) goto tr297; } else if ( (*p) > 90 ) { if ( 97 <= (*p) && (*p) <= 122 ) goto tr297; } else goto tr297; goto tr370; st220: if ( ++p == pe ) goto _test_eof220; case 220: switch( (*p) ) { case 95: goto tr297; case 117: goto st221; } if ( (*p) < 65 ) { if ( 48 <= (*p) && (*p) <= 57 ) goto tr297; } else if ( (*p) > 90 ) { if ( 97 <= (*p) && (*p) <= 122 ) goto tr297; } else goto tr297; goto tr370; st221: if ( ++p == pe ) goto _test_eof221; case 221: switch( (*p) ) { case 95: goto tr297; case 116: goto st222; } if ( (*p) < 65 ) { if ( 48 <= (*p) && (*p) <= 57 ) goto tr297; } else if ( (*p) > 90 ) { if ( 97 <= (*p) && (*p) <= 122 ) goto tr297; } else goto tr297; goto tr370; st222: if ( ++p == pe ) goto _test_eof222; case 222: switch( (*p) ) { case 95: goto tr297; case 119: goto st223; } if ( (*p) < 65 ) { if ( 48 <= (*p) && (*p) <= 57 ) goto tr297; } else if ( (*p) > 90 ) { if ( 97 <= (*p) && (*p) <= 122 ) goto tr297; } else goto tr297; goto tr370; st223: if ( ++p == pe ) goto _test_eof223; case 223: switch( (*p) ) { case 95: goto tr297; case 104: goto st224; } if ( (*p) < 65 ) { if ( 48 <= (*p) && (*p) <= 57 ) goto tr297; } else if ( (*p) > 90 ) { if ( 97 <= (*p) && (*p) <= 122 ) goto tr297; } else goto tr297; goto tr370; st224: if ( ++p == pe ) goto _test_eof224; case 224: switch( (*p) ) { case 95: goto tr297; case 101: goto st225; } if ( (*p) < 65 ) { if ( 48 <= (*p) && (*p) <= 57 ) goto tr297; } else if ( (*p) > 90 ) { if ( 97 <= (*p) && (*p) <= 122 ) goto tr297; } else goto tr297; goto tr370; st225: if ( ++p == pe ) goto _test_eof225; case 225: switch( (*p) ) { case 95: goto tr297; case 110: goto tr433; } if ( (*p) < 65 ) { if ( 48 <= (*p) && (*p) <= 57 ) goto tr297; } else if ( (*p) > 90 ) { if ( 97 <= (*p) && (*p) <= 122 ) goto tr297; } else goto tr297; goto tr370; st226: if ( ++p == pe ) goto _test_eof226; case 226: switch( (*p) ) { case 95: goto tr297; case 111: goto st227; case 114: goto st232; } if ( (*p) < 65 ) { if ( 48 <= (*p) && (*p) <= 57 ) goto tr297; } else if ( (*p) > 90 ) { if ( 97 <= (*p) && (*p) <= 122 ) goto tr297; } else goto tr297; goto tr370; st227: if ( ++p == pe ) goto _test_eof227; case 227: switch( (*p) ) { case 95: goto tr297; case 115: goto st228; } if ( (*p) < 65 ) { if ( 48 <= (*p) && (*p) <= 57 ) goto tr297; } else if ( (*p) > 90 ) { if ( 97 <= (*p) && (*p) <= 122 ) goto tr297; } else goto tr297; goto tr370; st228: if ( ++p == pe ) goto _test_eof228; case 228: switch( (*p) ) { case 95: goto tr297; case 116: goto st229; } if ( (*p) < 65 ) { if ( 48 <= (*p) && (*p) <= 57 ) goto tr297; } else if ( (*p) > 90 ) { if ( 97 <= (*p) && (*p) <= 122 ) goto tr297; } else goto tr297; goto tr370; st229: if ( ++p == pe ) goto _test_eof229; case 229: switch( (*p) ) { case 95: goto tr297; case 112: goto st230; } if ( (*p) < 65 ) { if ( 48 <= (*p) && (*p) <= 57 ) goto tr297; } else if ( (*p) > 90 ) { if ( 97 <= (*p) && (*p) <= 122 ) goto tr297; } else goto tr297; goto tr370; st230: if ( ++p == pe ) goto _test_eof230; case 230: switch( (*p) ) { case 95: goto tr297; case 111: goto st231; } if ( (*p) < 65 ) { if ( 48 <= (*p) && (*p) <= 57 ) goto tr297; } else if ( (*p) > 90 ) { if ( 97 <= (*p) && (*p) <= 122 ) goto tr297; } else goto tr297; goto tr370; st231: if ( ++p == pe ) goto _test_eof231; case 231: switch( (*p) ) { case 95: goto tr297; case 112: goto tr440; } if ( (*p) < 65 ) { if ( 48 <= (*p) && (*p) <= 57 ) goto tr297; } else if ( (*p) > 90 ) { if ( 97 <= (*p) && (*p) <= 122 ) goto tr297; } else goto tr297; goto tr370; st232: if ( ++p == pe ) goto _test_eof232; case 232: switch( (*p) ) { case 95: goto tr297; case 101: goto st233; } if ( (*p) < 65 ) { if ( 48 <= (*p) && (*p) <= 57 ) goto tr297; } else if ( (*p) > 90 ) { if ( 97 <= (*p) && (*p) <= 122 ) goto tr297; } else goto tr297; goto tr370; st233: if ( ++p == pe ) goto _test_eof233; case 233: switch( (*p) ) { case 95: goto tr297; case 112: goto st234; } if ( (*p) < 65 ) { if ( 48 <= (*p) && (*p) <= 57 ) goto tr297; } else if ( (*p) > 90 ) { if ( 97 <= (*p) && (*p) <= 122 ) goto tr297; } else goto tr297; goto tr370; st234: if ( ++p == pe ) goto _test_eof234; case 234: switch( (*p) ) { case 95: goto tr297; case 117: goto st235; } if ( (*p) < 65 ) { if ( 48 <= (*p) && (*p) <= 57 ) goto tr297; } else if ( (*p) > 90 ) { if ( 97 <= (*p) && (*p) <= 122 ) goto tr297; } else goto tr297; goto tr370; st235: if ( ++p == pe ) goto _test_eof235; case 235: switch( (*p) ) { case 95: goto tr297; case 115: goto st236; } if ( (*p) < 65 ) { if ( 48 <= (*p) && (*p) <= 57 ) goto tr297; } else if ( (*p) > 90 ) { if ( 97 <= (*p) && (*p) <= 122 ) goto tr297; } else goto tr297; goto tr370; st236: if ( ++p == pe ) goto _test_eof236; case 236: switch( (*p) ) { case 95: goto tr297; case 104: goto tr445; } if ( (*p) < 65 ) { if ( 48 <= (*p) && (*p) <= 57 ) goto tr297; } else if ( (*p) > 90 ) { if ( 97 <= (*p) && (*p) <= 122 ) goto tr297; } else goto tr297; goto tr370; st237: if ( ++p == pe ) goto _test_eof237; case 237: switch( (*p) ) { case 95: goto tr297; case 111: goto tr446; } if ( (*p) < 65 ) { if ( 48 <= (*p) && (*p) <= 57 ) goto tr297; } else if ( (*p) > 90 ) { if ( 97 <= (*p) && (*p) <= 122 ) goto tr297; } else goto tr297; goto tr370; st238: if ( ++p == pe ) goto _test_eof238; case 238: switch( (*p) ) { case 95: goto tr297; case 97: goto st239; } if ( (*p) < 65 ) { if ( 48 <= (*p) && (*p) <= 57 ) goto tr297; } else if ( (*p) > 90 ) { if ( 98 <= (*p) && (*p) <= 122 ) goto tr297; } else goto tr297; goto tr370; st239: if ( ++p == pe ) goto _test_eof239; case 239: switch( (*p) ) { case 95: goto tr297; case 114: goto st240; } if ( (*p) < 65 ) { if ( 48 <= (*p) && (*p) <= 57 ) goto tr297; } else if ( (*p) > 90 ) { if ( 97 <= (*p) && (*p) <= 122 ) goto tr297; } else goto tr297; goto tr370; st240: if ( ++p == pe ) goto _test_eof240; case 240: switch( (*p) ) { case 95: goto tr297; case 105: goto st241; } if ( (*p) < 65 ) { if ( 48 <= (*p) && (*p) <= 57 ) goto tr297; } else if ( (*p) > 90 ) { if ( 97 <= (*p) && (*p) <= 122 ) goto tr297; } else goto tr297; goto tr370; st241: if ( ++p == pe ) goto _test_eof241; case 241: switch( (*p) ) { case 95: goto tr297; case 97: goto st242; } if ( (*p) < 65 ) { if ( 48 <= (*p) && (*p) <= 57 ) goto tr297; } else if ( (*p) > 90 ) { if ( 98 <= (*p) && (*p) <= 122 ) goto tr297; } else goto tr297; goto tr370; st242: if ( ++p == pe ) goto _test_eof242; case 242: switch( (*p) ) { case 95: goto tr297; case 98: goto st243; } if ( (*p) < 65 ) { if ( 48 <= (*p) && (*p) <= 57 ) goto tr297; } else if ( (*p) > 90 ) { if ( 97 <= (*p) && (*p) <= 122 ) goto tr297; } else goto tr297; goto tr370; st243: if ( ++p == pe ) goto _test_eof243; case 243: switch( (*p) ) { case 95: goto tr297; case 108: goto st244; } if ( (*p) < 65 ) { if ( 48 <= (*p) && (*p) <= 57 ) goto tr297; } else if ( (*p) > 90 ) { if ( 97 <= (*p) && (*p) <= 122 ) goto tr297; } else goto tr297; goto tr370; st244: if ( ++p == pe ) goto _test_eof244; case 244: switch( (*p) ) { case 95: goto tr297; case 101: goto tr453; } if ( (*p) < 65 ) { if ( 48 <= (*p) && (*p) <= 57 ) goto tr297; } else if ( (*p) > 90 ) { if ( 97 <= (*p) && (*p) <= 122 ) goto tr297; } else goto tr297; goto tr370; st245: if ( ++p == pe ) goto _test_eof245; case 245: switch( (*p) ) { case 95: goto tr297; case 104: goto st246; case 114: goto st248; } if ( (*p) < 65 ) { if ( 48 <= (*p) && (*p) <= 57 ) goto tr297; } else if ( (*p) > 90 ) { if ( 97 <= (*p) && (*p) <= 122 ) goto tr297; } else goto tr297; goto tr370; st246: if ( ++p == pe ) goto _test_eof246; case 246: switch( (*p) ) { case 95: goto tr297; case 101: goto st247; } if ( (*p) < 65 ) { if ( 48 <= (*p) && (*p) <= 57 ) goto tr297; } else if ( (*p) > 90 ) { if ( 97 <= (*p) && (*p) <= 122 ) goto tr297; } else goto tr297; goto tr370; st247: if ( ++p == pe ) goto _test_eof247; case 247: switch( (*p) ) { case 95: goto tr297; case 110: goto tr457; } if ( (*p) < 65 ) { if ( 48 <= (*p) && (*p) <= 57 ) goto tr297; } else if ( (*p) > 90 ) { if ( 97 <= (*p) && (*p) <= 122 ) goto tr297; } else goto tr297; goto tr370; st248: if ( ++p == pe ) goto _test_eof248; case 248: switch( (*p) ) { case 95: goto tr297; case 105: goto st249; } if ( (*p) < 65 ) { if ( 48 <= (*p) && (*p) <= 57 ) goto tr297; } else if ( (*p) > 90 ) { if ( 97 <= (*p) && (*p) <= 122 ) goto tr297; } else goto tr297; goto tr370; st249: if ( ++p == pe ) goto _test_eof249; case 249: switch( (*p) ) { case 95: goto tr297; case 116: goto st250; } if ( (*p) < 65 ) { if ( 48 <= (*p) && (*p) <= 57 ) goto tr297; } else if ( (*p) > 90 ) { if ( 97 <= (*p) && (*p) <= 122 ) goto tr297; } else goto tr297; goto tr370; st250: if ( ++p == pe ) goto _test_eof250; case 250: switch( (*p) ) { case 95: goto tr297; case 101: goto tr460; } if ( (*p) < 65 ) { if ( 48 <= (*p) && (*p) <= 57 ) goto tr297; } else if ( (*p) > 90 ) { if ( 97 <= (*p) && (*p) <= 122 ) goto tr297; } else goto tr297; goto tr370; st251: if ( ++p == pe ) goto _test_eof251; case 251: if ( (*p) == 42 ) goto tr461; goto tr315; tr313: #line 1 "NONE" {te = p+1;} goto st252; st252: if ( ++p == pe ) goto _test_eof252; case 252: #line 6374 "rlscan.cpp" if ( (*p) == 37 ) goto st30; goto tr315; st30: if ( ++p == pe ) goto _test_eof30; case 30: if ( (*p) == 37 ) goto tr57; goto tr45; tr58: #line 1146 "rlscan.rl" {{p = ((te))-1;}{ pass( *ts, 0, 0 ); }} goto st253; tr61: #line 1130 "rlscan.rl" {te = p+1;{ pass( IMP_Literal, ts, te ); }} goto st253; tr64: #line 641 "rlscan.rl" { lastnl = p; column = 0; line++; } #line 1128 "rlscan.rl" {te = p+1;{ pass(); }} goto st253; tr463: #line 1146 "rlscan.rl" {te = p+1;{ pass( *ts, 0, 0 ); }} goto st253; tr464: #line 1145 "rlscan.rl" {te = p+1;} goto st253; tr474: #line 1144 "rlscan.rl" {te = p;p--;{ pass(); }} goto st253; tr475: #line 1146 "rlscan.rl" {te = p;p--;{ pass( *ts, 0, 0 ); }} goto st253; tr477: #line 1138 "rlscan.rl" {te = p;p--;{ updateCol(); singleLineSpec = true; startSection(); {stack[top++] = 253; goto st146;} }} goto st253; tr478: #line 1132 "rlscan.rl" {te = p+1;{ updateCol(); singleLineSpec = false; startSection(); {stack[top++] = 253; goto st146;} }} goto st253; tr479: #line 1127 "rlscan.rl" {te = p;p--;{ pass( IMP_UInt, ts, te ); }} goto st253; tr480: #line 1126 "rlscan.rl" {te = p;p--;{ pass( IMP_Word, ts, te ); }} goto st253; st253: #line 1 "NONE" {ts = 0;} if ( ++p == pe ) goto _test_eof253; case 253: #line 1 "NONE" {ts = p;} #line 6453 "rlscan.cpp" switch( (*p) ) { case 0: goto tr464; case 9: goto st254; case 10: goto tr466; case 32: goto st254; case 34: goto tr467; case 35: goto tr468; case 37: goto st257; case 39: goto tr470; case 47: goto tr471; case 95: goto st262; } if ( (*p) < 65 ) { if ( 48 <= (*p) && (*p) <= 57 ) goto st261; } else if ( (*p) > 90 ) { if ( 97 <= (*p) && (*p) <= 122 ) goto st262; } else goto st262; goto tr463; tr466: #line 641 "rlscan.rl" { lastnl = p; column = 0; line++; } goto st254; st254: if ( ++p == pe ) goto _test_eof254; case 254: #line 6487 "rlscan.cpp" switch( (*p) ) { case 9: goto st254; case 10: goto tr466; case 32: goto st254; } goto tr474; tr467: #line 1 "NONE" {te = p+1;} goto st255; st255: if ( ++p == pe ) goto _test_eof255; case 255: #line 6502 "rlscan.cpp" switch( (*p) ) { case 10: goto tr60; case 34: goto tr61; case 92: goto st32; } goto st31; tr60: #line 641 "rlscan.rl" { lastnl = p; column = 0; line++; } goto st31; st31: if ( ++p == pe ) goto _test_eof31; case 31: #line 6521 "rlscan.cpp" switch( (*p) ) { case 10: goto tr60; case 34: goto tr61; case 92: goto st32; } goto st31; st32: if ( ++p == pe ) goto _test_eof32; case 32: if ( (*p) == 10 ) goto tr60; goto st31; tr468: #line 1 "NONE" {te = p+1;} goto st256; st256: if ( ++p == pe ) goto _test_eof256; case 256: #line 6543 "rlscan.cpp" if ( (*p) == 10 ) goto tr64; goto st33; st33: if ( ++p == pe ) goto _test_eof33; case 33: if ( (*p) == 10 ) goto tr64; goto st33; st257: if ( ++p == pe ) goto _test_eof257; case 257: if ( (*p) == 37 ) goto st258; goto tr475; st258: if ( ++p == pe ) goto _test_eof258; case 258: if ( (*p) == 123 ) goto tr478; goto tr477; tr470: #line 1 "NONE" {te = p+1;} goto st259; st259: if ( ++p == pe ) goto _test_eof259; case 259: #line 6576 "rlscan.cpp" switch( (*p) ) { case 10: goto tr66; case 39: goto tr61; case 92: goto st35; } goto st34; tr66: #line 641 "rlscan.rl" { lastnl = p; column = 0; line++; } goto st34; st34: if ( ++p == pe ) goto _test_eof34; case 34: #line 6595 "rlscan.cpp" switch( (*p) ) { case 10: goto tr66; case 39: goto tr61; case 92: goto st35; } goto st34; st35: if ( ++p == pe ) goto _test_eof35; case 35: if ( (*p) == 10 ) goto tr66; goto st34; tr471: #line 1 "NONE" {te = p+1;} goto st260; st260: if ( ++p == pe ) goto _test_eof260; case 260: #line 6617 "rlscan.cpp" switch( (*p) ) { case 10: goto tr69; case 47: goto tr61; case 92: goto st37; } goto st36; tr69: #line 641 "rlscan.rl" { lastnl = p; column = 0; line++; } goto st36; st36: if ( ++p == pe ) goto _test_eof36; case 36: #line 6636 "rlscan.cpp" switch( (*p) ) { case 10: goto tr69; case 47: goto tr61; case 92: goto st37; } goto st36; st37: if ( ++p == pe ) goto _test_eof37; case 37: if ( (*p) == 10 ) goto tr69; goto st36; st261: if ( ++p == pe ) goto _test_eof261; case 261: if ( 48 <= (*p) && (*p) <= 57 ) goto st261; goto tr479; st262: if ( ++p == pe ) goto _test_eof262; case 262: if ( (*p) == 95 ) goto st262; if ( (*p) < 65 ) { if ( 48 <= (*p) && (*p) <= 57 ) goto st262; } else if ( (*p) > 90 ) { if ( 97 <= (*p) && (*p) <= 122 ) goto st262; } else goto st262; goto tr480; } _test_eof38: cs = 38; goto _test_eof; _test_eof39: cs = 39; goto _test_eof; _test_eof40: cs = 40; goto _test_eof; _test_eof1: cs = 1; goto _test_eof; _test_eof2: cs = 2; goto _test_eof; _test_eof41: cs = 41; goto _test_eof; _test_eof42: cs = 42; goto _test_eof; _test_eof43: cs = 43; goto _test_eof; _test_eof3: cs = 3; goto _test_eof; _test_eof4: cs = 4; goto _test_eof; _test_eof44: cs = 44; goto _test_eof; _test_eof5: cs = 5; goto _test_eof; _test_eof6: cs = 6; goto _test_eof; _test_eof7: cs = 7; goto _test_eof; _test_eof45: cs = 45; goto _test_eof; _test_eof46: cs = 46; goto _test_eof; _test_eof47: cs = 47; goto _test_eof; _test_eof48: cs = 48; goto _test_eof; _test_eof49: cs = 49; goto _test_eof; _test_eof50: cs = 50; goto _test_eof; _test_eof51: cs = 51; goto _test_eof; _test_eof52: cs = 52; goto _test_eof; _test_eof53: cs = 53; goto _test_eof; _test_eof54: cs = 54; goto _test_eof; _test_eof8: cs = 8; goto _test_eof; _test_eof9: cs = 9; goto _test_eof; _test_eof55: cs = 55; goto _test_eof; _test_eof10: cs = 10; goto _test_eof; _test_eof56: cs = 56; goto _test_eof; _test_eof11: cs = 11; goto _test_eof; _test_eof12: cs = 12; goto _test_eof; _test_eof57: cs = 57; goto _test_eof; _test_eof13: cs = 13; goto _test_eof; _test_eof14: cs = 14; goto _test_eof; _test_eof58: cs = 58; goto _test_eof; _test_eof59: cs = 59; goto _test_eof; _test_eof15: cs = 15; goto _test_eof; _test_eof60: cs = 60; goto _test_eof; _test_eof61: cs = 61; goto _test_eof; _test_eof62: cs = 62; goto _test_eof; _test_eof63: cs = 63; goto _test_eof; _test_eof64: cs = 64; goto _test_eof; _test_eof65: cs = 65; goto _test_eof; _test_eof66: cs = 66; goto _test_eof; _test_eof67: cs = 67; goto _test_eof; _test_eof68: cs = 68; goto _test_eof; _test_eof69: cs = 69; goto _test_eof; _test_eof70: cs = 70; goto _test_eof; _test_eof71: cs = 71; goto _test_eof; _test_eof72: cs = 72; goto _test_eof; _test_eof73: cs = 73; goto _test_eof; _test_eof74: cs = 74; goto _test_eof; _test_eof75: cs = 75; goto _test_eof; _test_eof76: cs = 76; goto _test_eof; _test_eof77: cs = 77; goto _test_eof; _test_eof78: cs = 78; goto _test_eof; _test_eof79: cs = 79; goto _test_eof; _test_eof80: cs = 80; goto _test_eof; _test_eof81: cs = 81; goto _test_eof; _test_eof82: cs = 82; goto _test_eof; _test_eof83: cs = 83; goto _test_eof; _test_eof84: cs = 84; goto _test_eof; _test_eof85: cs = 85; goto _test_eof; _test_eof86: cs = 86; goto _test_eof; _test_eof87: cs = 87; goto _test_eof; _test_eof88: cs = 88; goto _test_eof; _test_eof89: cs = 89; goto _test_eof; _test_eof90: cs = 90; goto _test_eof; _test_eof91: cs = 91; goto _test_eof; _test_eof92: cs = 92; goto _test_eof; _test_eof93: cs = 93; goto _test_eof; _test_eof94: cs = 94; goto _test_eof; _test_eof95: cs = 95; goto _test_eof; _test_eof96: cs = 96; goto _test_eof; _test_eof97: cs = 97; goto _test_eof; _test_eof16: cs = 16; goto _test_eof; _test_eof17: cs = 17; goto _test_eof; _test_eof98: cs = 98; goto _test_eof; _test_eof18: cs = 18; goto _test_eof; _test_eof19: cs = 19; goto _test_eof; _test_eof99: cs = 99; goto _test_eof; _test_eof20: cs = 20; goto _test_eof; _test_eof21: cs = 21; goto _test_eof; _test_eof22: cs = 22; goto _test_eof; _test_eof100: cs = 100; goto _test_eof; _test_eof101: cs = 101; goto _test_eof; _test_eof23: cs = 23; goto _test_eof; _test_eof102: cs = 102; goto _test_eof; _test_eof103: cs = 103; goto _test_eof; _test_eof104: cs = 104; goto _test_eof; _test_eof105: cs = 105; goto _test_eof; _test_eof106: cs = 106; goto _test_eof; _test_eof107: cs = 107; goto _test_eof; _test_eof108: cs = 108; goto _test_eof; _test_eof109: cs = 109; goto _test_eof; _test_eof110: cs = 110; goto _test_eof; _test_eof111: cs = 111; goto _test_eof; _test_eof112: cs = 112; goto _test_eof; _test_eof113: cs = 113; goto _test_eof; _test_eof114: cs = 114; goto _test_eof; _test_eof115: cs = 115; goto _test_eof; _test_eof116: cs = 116; goto _test_eof; _test_eof117: cs = 117; goto _test_eof; _test_eof118: cs = 118; goto _test_eof; _test_eof119: cs = 119; goto _test_eof; _test_eof120: cs = 120; goto _test_eof; _test_eof121: cs = 121; goto _test_eof; _test_eof122: cs = 122; goto _test_eof; _test_eof123: cs = 123; goto _test_eof; _test_eof124: cs = 124; goto _test_eof; _test_eof125: cs = 125; goto _test_eof; _test_eof126: cs = 126; goto _test_eof; _test_eof127: cs = 127; goto _test_eof; _test_eof128: cs = 128; goto _test_eof; _test_eof129: cs = 129; goto _test_eof; _test_eof130: cs = 130; goto _test_eof; _test_eof131: cs = 131; goto _test_eof; _test_eof132: cs = 132; goto _test_eof; _test_eof133: cs = 133; goto _test_eof; _test_eof134: cs = 134; goto _test_eof; _test_eof135: cs = 135; goto _test_eof; _test_eof136: cs = 136; goto _test_eof; _test_eof137: cs = 137; goto _test_eof; _test_eof138: cs = 138; goto _test_eof; _test_eof139: cs = 139; goto _test_eof; _test_eof140: cs = 140; goto _test_eof; _test_eof141: cs = 141; goto _test_eof; _test_eof142: cs = 142; goto _test_eof; _test_eof143: cs = 143; goto _test_eof; _test_eof144: cs = 144; goto _test_eof; _test_eof145: cs = 145; goto _test_eof; _test_eof146: cs = 146; goto _test_eof; _test_eof147: cs = 147; goto _test_eof; _test_eof148: cs = 148; goto _test_eof; _test_eof24: cs = 24; goto _test_eof; _test_eof149: cs = 149; goto _test_eof; _test_eof25: cs = 25; goto _test_eof; _test_eof150: cs = 150; goto _test_eof; _test_eof26: cs = 26; goto _test_eof; _test_eof151: cs = 151; goto _test_eof; _test_eof152: cs = 152; goto _test_eof; _test_eof153: cs = 153; goto _test_eof; _test_eof27: cs = 27; goto _test_eof; _test_eof28: cs = 28; goto _test_eof; _test_eof154: cs = 154; goto _test_eof; _test_eof155: cs = 155; goto _test_eof; _test_eof156: cs = 156; goto _test_eof; _test_eof157: cs = 157; goto _test_eof; _test_eof158: cs = 158; goto _test_eof; _test_eof29: cs = 29; goto _test_eof; _test_eof159: cs = 159; goto _test_eof; _test_eof160: cs = 160; goto _test_eof; _test_eof161: cs = 161; goto _test_eof; _test_eof162: cs = 162; goto _test_eof; _test_eof163: cs = 163; goto _test_eof; _test_eof164: cs = 164; goto _test_eof; _test_eof165: cs = 165; goto _test_eof; _test_eof166: cs = 166; goto _test_eof; _test_eof167: cs = 167; goto _test_eof; _test_eof168: cs = 168; goto _test_eof; _test_eof169: cs = 169; goto _test_eof; _test_eof170: cs = 170; goto _test_eof; _test_eof171: cs = 171; goto _test_eof; _test_eof172: cs = 172; goto _test_eof; _test_eof173: cs = 173; goto _test_eof; _test_eof174: cs = 174; goto _test_eof; _test_eof175: cs = 175; goto _test_eof; _test_eof176: cs = 176; goto _test_eof; _test_eof177: cs = 177; goto _test_eof; _test_eof178: cs = 178; goto _test_eof; _test_eof179: cs = 179; goto _test_eof; _test_eof180: cs = 180; goto _test_eof; _test_eof181: cs = 181; goto _test_eof; _test_eof182: cs = 182; goto _test_eof; _test_eof183: cs = 183; goto _test_eof; _test_eof184: cs = 184; goto _test_eof; _test_eof185: cs = 185; goto _test_eof; _test_eof186: cs = 186; goto _test_eof; _test_eof187: cs = 187; goto _test_eof; _test_eof188: cs = 188; goto _test_eof; _test_eof189: cs = 189; goto _test_eof; _test_eof190: cs = 190; goto _test_eof; _test_eof191: cs = 191; goto _test_eof; _test_eof192: cs = 192; goto _test_eof; _test_eof193: cs = 193; goto _test_eof; _test_eof194: cs = 194; goto _test_eof; _test_eof195: cs = 195; goto _test_eof; _test_eof196: cs = 196; goto _test_eof; _test_eof197: cs = 197; goto _test_eof; _test_eof198: cs = 198; goto _test_eof; _test_eof199: cs = 199; goto _test_eof; _test_eof200: cs = 200; goto _test_eof; _test_eof201: cs = 201; goto _test_eof; _test_eof202: cs = 202; goto _test_eof; _test_eof203: cs = 203; goto _test_eof; _test_eof204: cs = 204; goto _test_eof; _test_eof205: cs = 205; goto _test_eof; _test_eof206: cs = 206; goto _test_eof; _test_eof207: cs = 207; goto _test_eof; _test_eof208: cs = 208; goto _test_eof; _test_eof209: cs = 209; goto _test_eof; _test_eof210: cs = 210; goto _test_eof; _test_eof211: cs = 211; goto _test_eof; _test_eof212: cs = 212; goto _test_eof; _test_eof213: cs = 213; goto _test_eof; _test_eof214: cs = 214; goto _test_eof; _test_eof215: cs = 215; goto _test_eof; _test_eof216: cs = 216; goto _test_eof; _test_eof217: cs = 217; goto _test_eof; _test_eof218: cs = 218; goto _test_eof; _test_eof219: cs = 219; goto _test_eof; _test_eof220: cs = 220; goto _test_eof; _test_eof221: cs = 221; goto _test_eof; _test_eof222: cs = 222; goto _test_eof; _test_eof223: cs = 223; goto _test_eof; _test_eof224: cs = 224; goto _test_eof; _test_eof225: cs = 225; goto _test_eof; _test_eof226: cs = 226; goto _test_eof; _test_eof227: cs = 227; goto _test_eof; _test_eof228: cs = 228; goto _test_eof; _test_eof229: cs = 229; goto _test_eof; _test_eof230: cs = 230; goto _test_eof; _test_eof231: cs = 231; goto _test_eof; _test_eof232: cs = 232; goto _test_eof; _test_eof233: cs = 233; goto _test_eof; _test_eof234: cs = 234; goto _test_eof; _test_eof235: cs = 235; goto _test_eof; _test_eof236: cs = 236; goto _test_eof; _test_eof237: cs = 237; goto _test_eof; _test_eof238: cs = 238; goto _test_eof; _test_eof239: cs = 239; goto _test_eof; _test_eof240: cs = 240; goto _test_eof; _test_eof241: cs = 241; goto _test_eof; _test_eof242: cs = 242; goto _test_eof; _test_eof243: cs = 243; goto _test_eof; _test_eof244: cs = 244; goto _test_eof; _test_eof245: cs = 245; goto _test_eof; _test_eof246: cs = 246; goto _test_eof; _test_eof247: cs = 247; goto _test_eof; _test_eof248: cs = 248; goto _test_eof; _test_eof249: cs = 249; goto _test_eof; _test_eof250: cs = 250; goto _test_eof; _test_eof251: cs = 251; goto _test_eof; _test_eof252: cs = 252; goto _test_eof; _test_eof30: cs = 30; goto _test_eof; _test_eof253: cs = 253; goto _test_eof; _test_eof254: cs = 254; goto _test_eof; _test_eof255: cs = 255; goto _test_eof; _test_eof31: cs = 31; goto _test_eof; _test_eof32: cs = 32; goto _test_eof; _test_eof256: cs = 256; goto _test_eof; _test_eof33: cs = 33; goto _test_eof; _test_eof257: cs = 257; goto _test_eof; _test_eof258: cs = 258; goto _test_eof; _test_eof259: cs = 259; goto _test_eof; _test_eof34: cs = 34; goto _test_eof; _test_eof35: cs = 35; goto _test_eof; _test_eof260: cs = 260; goto _test_eof; _test_eof36: cs = 36; goto _test_eof; _test_eof37: cs = 37; goto _test_eof; _test_eof261: cs = 261; goto _test_eof; _test_eof262: cs = 262; goto _test_eof; _test_eof: {} if ( p == eof ) { switch ( cs ) { case 39: goto tr82; case 40: goto tr83; case 1: goto tr0; case 2: goto tr0; case 41: goto tr83; case 42: goto tr85; case 43: goto tr83; case 3: goto tr0; case 4: goto tr0; case 44: goto tr83; case 5: goto tr0; case 6: goto tr0; case 7: goto tr0; case 45: goto tr87; case 46: goto tr88; case 47: goto tr89; case 48: goto tr89; case 49: goto tr89; case 50: goto tr89; case 51: goto tr89; case 53: goto tr113; case 54: goto tr114; case 8: goto tr14; case 9: goto tr14; case 55: goto tr114; case 10: goto tr14; case 56: goto tr114; case 11: goto tr14; case 12: goto tr14; case 57: goto tr114; case 13: goto tr14; case 14: goto tr14; case 58: goto tr115; case 59: goto tr115; case 15: goto tr27; case 60: goto tr117; case 61: goto tr114; case 62: goto tr119; case 63: goto tr120; case 64: goto tr120; case 65: goto tr120; case 66: goto tr120; case 67: goto tr120; case 68: goto tr134; case 69: goto tr120; case 70: goto tr120; case 71: goto tr120; case 72: goto tr120; case 73: goto tr120; case 74: goto tr120; case 75: goto tr120; case 76: goto tr120; case 77: goto tr120; case 78: goto tr120; case 79: goto tr120; case 80: goto tr120; case 81: goto tr120; case 82: goto tr120; case 83: goto tr120; case 84: goto tr120; case 85: goto tr120; case 86: goto tr120; case 87: goto tr120; case 88: goto tr120; case 89: goto tr120; case 90: goto tr120; case 91: goto tr120; case 92: goto tr120; case 93: goto tr120; case 94: goto tr120; case 96: goto tr181; case 97: goto tr182; case 16: goto tr29; case 17: goto tr29; case 98: goto tr182; case 18: goto tr29; case 19: goto tr29; case 99: goto tr182; case 20: goto tr29; case 21: goto tr29; case 22: goto tr29; case 100: goto tr183; case 101: goto tr183; case 23: goto tr43; case 102: goto tr185; case 103: goto tr182; case 104: goto tr187; case 105: goto tr188; case 106: goto tr188; case 107: goto tr188; case 108: goto tr188; case 109: goto tr188; case 110: goto tr202; case 111: goto tr188; case 112: goto tr188; case 113: goto tr188; case 114: goto tr188; case 115: goto tr188; case 116: goto tr188; case 117: goto tr188; case 118: goto tr188; case 119: goto tr188; case 120: goto tr188; case 121: goto tr188; case 122: goto tr188; case 123: goto tr188; case 124: goto tr188; case 125: goto tr188; case 126: goto tr188; case 127: goto tr188; case 128: goto tr188; case 129: goto tr188; case 130: goto tr188; case 131: goto tr188; case 132: goto tr188; case 133: goto tr188; case 134: goto tr188; case 135: goto tr188; case 136: goto tr188; case 138: goto tr237; case 140: goto tr255; case 141: goto tr257; case 142: goto tr259; case 144: goto tr275; case 145: goto tr276; case 147: goto tr314; case 148: goto tr315; case 24: goto tr45; case 149: goto tr316; case 25: goto tr45; case 150: goto tr315; case 26: goto tr45; case 151: goto tr315; case 152: goto tr315; case 153: goto tr315; case 27: goto tr45; case 28: goto tr45; case 154: goto tr315; case 155: goto tr315; case 156: goto tr315; case 157: goto tr334; case 158: goto tr334; case 29: goto tr55; case 159: goto tr336; case 160: goto tr315; case 161: goto tr340; case 162: goto tr315; case 163: goto tr349; case 164: goto tr315; case 165: goto tr315; case 166: goto tr315; case 167: goto tr367; case 168: goto tr368; case 169: goto tr370; case 170: goto tr370; case 171: goto tr370; case 172: goto tr370; case 173: goto tr370; case 174: goto tr370; case 175: goto tr370; case 176: goto tr370; case 177: goto tr370; case 178: goto tr370; case 179: goto tr370; case 180: goto tr370; case 181: goto tr370; case 182: goto tr370; case 183: goto tr370; case 184: goto tr370; case 185: goto tr370; case 186: goto tr370; case 187: goto tr370; case 188: goto tr370; case 189: goto tr370; case 190: goto tr370; case 191: goto tr370; case 192: goto tr370; case 193: goto tr370; case 194: goto tr370; case 195: goto tr370; case 196: goto tr370; case 197: goto tr370; case 198: goto tr370; case 199: goto tr370; case 200: goto tr370; case 201: goto tr370; case 202: goto tr370; case 203: goto tr370; case 204: goto tr370; case 205: goto tr370; case 206: goto tr370; case 207: goto tr370; case 208: goto tr370; case 209: goto tr370; case 210: goto tr370; case 211: goto tr370; case 212: goto tr370; case 213: goto tr370; case 214: goto tr370; case 215: goto tr370; case 216: goto tr370; case 217: goto tr370; case 218: goto tr370; case 219: goto tr370; case 220: goto tr370; case 221: goto tr370; case 222: goto tr370; case 223: goto tr370; case 224: goto tr370; case 225: goto tr370; case 226: goto tr370; case 227: goto tr370; case 228: goto tr370; case 229: goto tr370; case 230: goto tr370; case 231: goto tr370; case 232: goto tr370; case 233: goto tr370; case 234: goto tr370; case 235: goto tr370; case 236: goto tr370; case 237: goto tr370; case 238: goto tr370; case 239: goto tr370; case 240: goto tr370; case 241: goto tr370; case 242: goto tr370; case 243: goto tr370; case 244: goto tr370; case 245: goto tr370; case 246: goto tr370; case 247: goto tr370; case 248: goto tr370; case 249: goto tr370; case 250: goto tr370; case 251: goto tr315; case 252: goto tr315; case 30: goto tr45; case 254: goto tr474; case 255: goto tr475; case 31: goto tr58; case 32: goto tr58; case 256: goto tr475; case 33: goto tr58; case 257: goto tr475; case 258: goto tr477; case 259: goto tr475; case 34: goto tr58; case 35: goto tr58; case 260: goto tr475; case 36: goto tr58; case 37: goto tr58; case 261: goto tr479; case 262: goto tr480; } } _out: {} } #line 1241 "rlscan.rl" /* Check if we failed. */ if ( cs == rlscan_error ) { /* Machine failed before finding a token. I'm not yet sure if this * is reachable. */ scan_error() << "scanner error" << endl; exit(1); } /* Decide if we need to preserve anything. */ char *preserve = ts; /* Now set up the prefix. */ if ( preserve == 0 ) have = 0; else { /* There is data that needs to be shifted over. */ have = pe - preserve; memmove( buf, preserve, have ); unsigned int shiftback = preserve - buf; if ( ts != 0 ) ts -= shiftback; te -= shiftback; preserve = buf; } } delete[] buf; } ragel-6.8/ragel/fsmstate.cpp0000664000175000017500000003146212106050031013022 00000000000000/* * Copyright 2002 Adrian Thurston */ /* This file is part of Ragel. * * Ragel is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Ragel is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Ragel; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #include "fsmgraph.h" #include using namespace std; /* Construct a mark index for a specified number of states. Must new up * an array that is states^2 in size. */ MarkIndex::MarkIndex( int states ) : numStates(states) { /* Total pairs is states^2. Actually only use half of these, but we allocate * them all to make indexing into the array easier. */ int total = states * states; /* New up chars so that individual DListEl constructors are * not called. Zero out the mem manually. */ array = new bool[total]; memset( array, 0, sizeof(bool) * total ); } /* Free the array used to store state pairs. */ MarkIndex::~MarkIndex() { delete[] array; } /* Mark a pair of states. States are specified by their number. The * marked states are moved from the unmarked list to the marked list. */ void MarkIndex::markPair(int state1, int state2) { int pos = ( state1 >= state2 ) ? ( state1 * numStates ) + state2 : ( state2 * numStates ) + state1; array[pos] = true; } /* Returns true if the pair of states are marked. Returns false otherwise. * Ordering of states given does not matter. */ bool MarkIndex::isPairMarked(int state1, int state2) { int pos = ( state1 >= state2 ) ? ( state1 * numStates ) + state2 : ( state2 * numStates ) + state1; return array[pos]; } /* Create a new fsm state. State has not out transitions or in transitions, not * out out transition data and not number. */ StateAp::StateAp() : /* No out or in transitions. */ outList(), inList(), /* No EOF target. */ eofTarget(0), /* No entry points, or epsilon trans. */ entryIds(), epsilonTrans(), /* Conditions. */ stateCondList(), /* No transitions in from other states. */ foreignInTrans(0), /* Only used during merging. Normally null. */ stateDictEl(0), eptVect(0), /* No state identification bits. */ stateBits(0), /* No Priority data. */ outPriorTable(), /* No Action data. */ toStateActionTable(), fromStateActionTable(), outActionTable(), outCondSet(), errActionTable(), eofActionTable() { } /* Copy everything except actual the transitions. That is left up to the * FsmAp copy constructor. */ StateAp::StateAp(const StateAp &other) : /* All lists are cleared. They will be filled in when the * individual transitions are duplicated and attached. */ outList(), inList(), /* Set this using the original state's eofTarget. It will get mapped back * to the new machine in the Fsm copy constructor. */ eofTarget(other.eofTarget), /* Duplicate the entry id set and epsilon transitions. These * are sets of integers and as such need no fixing. */ entryIds(other.entryIds), epsilonTrans(other.epsilonTrans), /* Copy in the elements of the conditions. */ stateCondList( other.stateCondList ), /* No transitions in from other states. */ foreignInTrans(0), /* This is only used during merging. Normally null. */ stateDictEl(0), eptVect(0), /* Fsm state data. */ stateBits(other.stateBits), /* Copy in priority data. */ outPriorTable(other.outPriorTable), /* Copy in action data. */ toStateActionTable(other.toStateActionTable), fromStateActionTable(other.fromStateActionTable), outActionTable(other.outActionTable), outCondSet(other.outCondSet), errActionTable(other.errActionTable), eofActionTable(other.eofActionTable) { /* Duplicate all the transitions. */ for ( TransList::Iter trans = other.outList; trans.lte(); trans++ ) { /* Dupicate and store the orginal target in the transition. This will * be corrected once all the states have been created. */ TransAp *newTrans = new TransAp(*trans); assert( trans->lmActionTable.length() == 0 ); newTrans->toState = trans->toState; outList.append( newTrans ); } } /* If there is a state dict element, then delete it. Everything else is left * up to the FsmGraph destructor. */ StateAp::~StateAp() { if ( stateDictEl != 0 ) delete stateDictEl; } /* Compare two states using pointers to the states. With the approximate * compare, the idea is that if the compare finds them the same, they can * immediately be merged. */ int ApproxCompare::compare( const StateAp *state1, const StateAp *state2 ) { int compareRes; /* Test final state status. */ if ( (state1->stateBits & STB_ISFINAL) && !(state2->stateBits & STB_ISFINAL) ) return -1; else if ( !(state1->stateBits & STB_ISFINAL) && (state2->stateBits & STB_ISFINAL) ) return 1; /* Test epsilon transition sets. */ compareRes = CmpEpsilonTrans::compare( state1->epsilonTrans, state2->epsilonTrans ); if ( compareRes != 0 ) return compareRes; /* Compare the out transitions. */ compareRes = FsmAp::compareStateData( state1, state2 ); if ( compareRes != 0 ) return compareRes; /* Use a pair iterator to get the transition pairs. */ PairIter outPair( state1->outList.head, state2->outList.head ); for ( ; !outPair.end(); outPair++ ) { switch ( outPair.userState ) { case RangeInS1: compareRes = FsmAp::compareFullPtr( outPair.s1Tel.trans, 0 ); if ( compareRes != 0 ) return compareRes; break; case RangeInS2: compareRes = FsmAp::compareFullPtr( 0, outPair.s2Tel.trans ); if ( compareRes != 0 ) return compareRes; break; case RangeOverlap: compareRes = FsmAp::compareFullPtr( outPair.s1Tel.trans, outPair.s2Tel.trans ); if ( compareRes != 0 ) return compareRes; break; case BreakS1: case BreakS2: break; } } /* Check EOF targets. */ if ( state1->eofTarget < state2->eofTarget ) return -1; else if ( state1->eofTarget > state2->eofTarget ) return 1; /* Got through the entire state comparison, deem them equal. */ return 0; } /* Compare class used in the initial partition. */ int InitPartitionCompare::compare( const StateAp *state1 , const StateAp *state2 ) { int compareRes; /* Test final state status. */ if ( (state1->stateBits & STB_ISFINAL) && !(state2->stateBits & STB_ISFINAL) ) return -1; else if ( !(state1->stateBits & STB_ISFINAL) && (state2->stateBits & STB_ISFINAL) ) return 1; /* Test epsilon transition sets. */ compareRes = CmpEpsilonTrans::compare( state1->epsilonTrans, state2->epsilonTrans ); if ( compareRes != 0 ) return compareRes; /* Compare the out transitions. */ compareRes = FsmAp::compareStateData( state1, state2 ); if ( compareRes != 0 ) return compareRes; /* Use a pair iterator to test the condition pairs. */ PairIter condPair( state1->stateCondList.head, state2->stateCondList.head ); for ( ; !condPair.end(); condPair++ ) { switch ( condPair.userState ) { case RangeInS1: return 1; case RangeInS2: return -1; case RangeOverlap: { CondSpace *condSpace1 = condPair.s1Tel.trans->condSpace; CondSpace *condSpace2 = condPair.s2Tel.trans->condSpace; if ( condSpace1 < condSpace2 ) return -1; else if ( condSpace1 > condSpace2 ) return 1; break; } case BreakS1: case BreakS2: break; } } /* Use a pair iterator to test the transition pairs. */ PairIter outPair( state1->outList.head, state2->outList.head ); for ( ; !outPair.end(); outPair++ ) { switch ( outPair.userState ) { case RangeInS1: compareRes = FsmAp::compareDataPtr( outPair.s1Tel.trans, 0 ); if ( compareRes != 0 ) return compareRes; break; case RangeInS2: compareRes = FsmAp::compareDataPtr( 0, outPair.s2Tel.trans ); if ( compareRes != 0 ) return compareRes; break; case RangeOverlap: compareRes = FsmAp::compareDataPtr( outPair.s1Tel.trans, outPair.s2Tel.trans ); if ( compareRes != 0 ) return compareRes; break; case BreakS1: case BreakS2: break; } } return 0; } /* Compare class for the sort that does the partitioning. */ int PartitionCompare::compare( const StateAp *state1, const StateAp *state2 ) { int compareRes; /* Use a pair iterator to get the transition pairs. */ PairIter outPair( state1->outList.head, state2->outList.head ); for ( ; !outPair.end(); outPair++ ) { switch ( outPair.userState ) { case RangeInS1: compareRes = FsmAp::comparePartPtr( outPair.s1Tel.trans, 0 ); if ( compareRes != 0 ) return compareRes; break; case RangeInS2: compareRes = FsmAp::comparePartPtr( 0, outPair.s2Tel.trans ); if ( compareRes != 0 ) return compareRes; break; case RangeOverlap: compareRes = FsmAp::comparePartPtr( outPair.s1Tel.trans, outPair.s2Tel.trans ); if ( compareRes != 0 ) return compareRes; break; case BreakS1: case BreakS2: break; } } /* Test eof targets. */ if ( state1->eofTarget == 0 && state2->eofTarget != 0 ) return -1; else if ( state1->eofTarget != 0 && state2->eofTarget == 0 ) return 1; else if ( state1->eofTarget != 0 ) { /* Both eof targets are set. */ compareRes = CmpOrd< MinPartition* >::compare( state1->eofTarget->alg.partition, state2->eofTarget->alg.partition ); if ( compareRes != 0 ) return compareRes; } return 0; } /* Compare class for the sort that does the partitioning. */ bool MarkCompare::shouldMark( MarkIndex &markIndex, const StateAp *state1, const StateAp *state2 ) { /* Use a pair iterator to get the transition pairs. */ PairIter outPair( state1->outList.head, state2->outList.head ); for ( ; !outPair.end(); outPair++ ) { switch ( outPair.userState ) { case RangeInS1: if ( FsmAp::shouldMarkPtr( markIndex, outPair.s1Tel.trans, 0 ) ) return true; break; case RangeInS2: if ( FsmAp::shouldMarkPtr( markIndex, 0, outPair.s2Tel.trans ) ) return true; break; case RangeOverlap: if ( FsmAp::shouldMarkPtr( markIndex, outPair.s1Tel.trans, outPair.s2Tel.trans ) ) return true; break; case BreakS1: case BreakS2: break; } } return false; } /* * Transition Comparison. */ /* Compare target partitions. Either pointer may be null. */ int FsmAp::comparePartPtr( TransAp *trans1, TransAp *trans2 ) { if ( trans1 != 0 ) { /* If trans1 is set then so should trans2. The initial partitioning * guarantees this for us. */ if ( trans1->toState == 0 && trans2->toState != 0 ) return -1; else if ( trans1->toState != 0 && trans2->toState == 0 ) return 1; else if ( trans1->toState != 0 ) { /* Both of targets are set. */ return CmpOrd< MinPartition* >::compare( trans1->toState->alg.partition, trans2->toState->alg.partition ); } } return 0; } /* Compares two transition pointers according to priority and functions. * Either pointer may be null. Does not consider to state or from state. */ int FsmAp::compareDataPtr( TransAp *trans1, TransAp *trans2 ) { if ( trans1 == 0 && trans2 != 0 ) return -1; else if ( trans1 != 0 && trans2 == 0 ) return 1; else if ( trans1 != 0 ) { /* Both of the transition pointers are set. */ int compareRes = compareTransData( trans1, trans2 ); if ( compareRes != 0 ) return compareRes; } return 0; } /* Compares two transitions according to target state, priority and functions. * Does not consider from state. Either of the pointers may be null. */ int FsmAp::compareFullPtr( TransAp *trans1, TransAp *trans2 ) { if ( (trans1 != 0) ^ (trans2 != 0) ) { /* Exactly one of the transitions is set. */ if ( trans1 != 0 ) return -1; else return 1; } else if ( trans1 != 0 ) { /* Both of the transition pointers are set. Test target state, * priority and funcs. */ if ( trans1->toState < trans2->toState ) return -1; else if ( trans1->toState > trans2->toState ) return 1; else if ( trans1->toState != 0 ) { /* Test transition data. */ int compareRes = compareTransData( trans1, trans2 ); if ( compareRes != 0 ) return compareRes; } } return 0; } bool FsmAp::shouldMarkPtr( MarkIndex &markIndex, TransAp *trans1, TransAp *trans2 ) { if ( (trans1 != 0) ^ (trans2 != 0) ) { /* Exactly one of the transitions is set. The initial mark round * should rule out this case. */ assert( false ); } else if ( trans1 != 0 ) { /* Both of the transitions are set. If the target pair is marked, then * the pair we are considering gets marked. */ return markIndex.isPairMarked( trans1->toState->alg.stateNum, trans2->toState->alg.stateNum ); } /* Neither of the transitiosn are set. */ return false; } ragel-6.8/ragel/fsmap.cpp0000664000175000017500000007157312106050031012311 00000000000000/* * Copyright 2002-2004 Adrian Thurston */ /* This file is part of Ragel. * * Ragel is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Ragel is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Ragel; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "fsmgraph.h" #include using std::cerr; using std::endl; CondData *condData = 0; KeyOps *keyOps = 0; /* Insert an action into an action table. */ void ActionTable::setAction( int ordering, Action *action ) { /* Multi-insert in case specific instances of an action appear in a * transition more than once. */ insertMulti( ordering, action ); } /* Set all the action from another action table in this table. */ void ActionTable::setActions( const ActionTable &other ) { for ( ActionTable::Iter action = other; action.lte(); action++ ) insertMulti( action->key, action->value ); } void ActionTable::setActions( int *orderings, Action **actions, int nActs ) { for ( int a = 0; a < nActs; a++ ) insertMulti( orderings[a], actions[a] ); } bool ActionTable::hasAction( Action *action ) { for ( int a = 0; a < length(); a++ ) { if ( data[a].value == action ) return true; } return false; } /* Insert an action into an action table. */ void LmActionTable::setAction( int ordering, LongestMatchPart *action ) { /* Multi-insert in case specific instances of an action appear in a * transition more than once. */ insertMulti( ordering, action ); } /* Set all the action from another action table in this table. */ void LmActionTable::setActions( const LmActionTable &other ) { for ( LmActionTable::Iter action = other; action.lte(); action++ ) insertMulti( action->key, action->value ); } void ErrActionTable::setAction( int ordering, Action *action, int transferPoint ) { insertMulti( ErrActionTableEl( action, ordering, transferPoint ) ); } void ErrActionTable::setActions( const ErrActionTable &other ) { for ( ErrActionTable::Iter act = other; act.lte(); act++ ) insertMulti( ErrActionTableEl( act->action, act->ordering, act->transferPoint ) ); } /* Insert a priority into this priority table. Looks out for priorities on * duplicate keys. */ void PriorTable::setPrior( int ordering, PriorDesc *desc ) { PriorEl *lastHit = 0; PriorEl *insed = insert( PriorEl(ordering, desc), &lastHit ); if ( insed == 0 ) { /* This already has a priority on the same key as desc. Overwrite the * priority if the ordering is larger (later in time). */ if ( ordering >= lastHit->ordering ) *lastHit = PriorEl( ordering, desc ); } } /* Set all the priorities from a priorTable in this table. */ void PriorTable::setPriors( const PriorTable &other ) { /* Loop src priorities once to overwrite duplicates. */ PriorTable::Iter priorIt = other; for ( ; priorIt.lte(); priorIt++ ) setPrior( priorIt->ordering, priorIt->desc ); } /* Set the priority of starting transitions. Isolates the start state so it has * no other entry points, then sets the priorities of all the transitions out * of the start state. If the start state is final, then the outPrior of the * start state is also set. The idea is that a machine that accepts the null * string can still specify the starting trans prior for when it accepts the * null word. */ void FsmAp::startFsmPrior( int ordering, PriorDesc *prior ) { /* Make sure the start state has no other entry points. */ isolateStartState(); /* Walk all transitions out of the start state. */ for ( TransList::Iter trans = startState->outList; trans.lte(); trans++ ) { if ( trans->toState != 0 ) trans->priorTable.setPrior( ordering, prior ); } /* If the new start state is final then set the out priority. This follows * the same convention as setting start action in the out action table of * a final start state. */ if ( startState->stateBits & STB_ISFINAL ) startState->outPriorTable.setPrior( ordering, prior ); } /* Set the priority of all transitions in a graph. Walks all transition lists * and all def transitions. */ void FsmAp::allTransPrior( int ordering, PriorDesc *prior ) { /* Walk the list of all states. */ for ( StateList::Iter state = stateList; state.lte(); state++ ) { /* Walk the out list of the state. */ for ( TransList::Iter trans = state->outList; trans.lte(); trans++ ) { if ( trans->toState != 0 ) trans->priorTable.setPrior( ordering, prior ); } } } /* Set the priority of all transitions that go into a final state. Note that if * any entry states are final, we will not be setting the priority of any * transitions that may go into those states in the future. The graph does not * support pending in transitions in the same way pending out transitions are * supported. */ void FsmAp::finishFsmPrior( int ordering, PriorDesc *prior ) { /* Walk all final states. */ for ( StateSet::Iter state = finStateSet; state.lte(); state++ ) { /* Walk all in transitions of the final state. */ for ( TransInList::Iter trans = (*state)->inList; trans.lte(); trans++ ) trans->priorTable.setPrior( ordering, prior ); } } /* Set the priority of any future out transitions that may be made going out of * this state machine. */ void FsmAp::leaveFsmPrior( int ordering, PriorDesc *prior ) { /* Set priority in all final states. */ for ( StateSet::Iter state = finStateSet; state.lte(); state++ ) (*state)->outPriorTable.setPrior( ordering, prior ); } /* Set actions to execute on starting transitions. Isolates the start state * so it has no other entry points, then adds to the transition functions * of all the transitions out of the start state. If the start state is final, * then the func is also added to the start state's out func list. The idea is * that a machine that accepts the null string can execute a start func when it * matches the null word, which can only be done when leaving the start/final * state. */ void FsmAp::startFsmAction( int ordering, Action *action ) { /* Make sure the start state has no other entry points. */ isolateStartState(); /* Walk the start state's transitions, setting functions. */ for ( TransList::Iter trans = startState->outList; trans.lte(); trans++ ) { if ( trans->toState != 0 ) trans->actionTable.setAction( ordering, action ); } /* If start state is final then add the action to the out action table. * This means that when the null string is accepted the start action will * not be bypassed. */ if ( startState->stateBits & STB_ISFINAL ) startState->outActionTable.setAction( ordering, action ); } /* Set functions to execute on all transitions. Walks the out lists of all * states. */ void FsmAp::allTransAction( int ordering, Action *action ) { /* Walk all states. */ for ( StateList::Iter state = stateList; state.lte(); state++ ) { /* Walk the out list of the state. */ for ( TransList::Iter trans = state->outList; trans.lte(); trans++ ) { if ( trans->toState != 0 ) trans->actionTable.setAction( ordering, action ); } } } /* Specify functions to execute upon entering final states. If the start state * is final we can't really specify a function to execute upon entering that * final state the first time. So function really means whenever entering a * final state from within the same fsm. */ void FsmAp::finishFsmAction( int ordering, Action *action ) { /* Walk all final states. */ for ( StateSet::Iter state = finStateSet; state.lte(); state++ ) { /* Walk the final state's in list. */ for ( TransInList::Iter trans = (*state)->inList; trans.lte(); trans++ ) trans->actionTable.setAction( ordering, action ); } } /* Add functions to any future out transitions that may be made going out of * this state machine. */ void FsmAp::leaveFsmAction( int ordering, Action *action ) { /* Insert the action in the outActionTable of all final states. */ for ( StateSet::Iter state = finStateSet; state.lte(); state++ ) (*state)->outActionTable.setAction( ordering, action ); } /* Add functions to the longest match action table for constructing scanners. */ void FsmAp::longMatchAction( int ordering, LongestMatchPart *lmPart ) { /* Walk all final states. */ for ( StateSet::Iter state = finStateSet; state.lte(); state++ ) { /* Walk the final state's in list. */ for ( TransInList::Iter trans = (*state)->inList; trans.lte(); trans++ ) trans->lmActionTable.setAction( ordering, lmPart ); } } void FsmAp::fillGaps( StateAp *state ) { if ( state->outList.length() == 0 ) { /* Add the range on the lower and upper bound. */ attachNewTrans( state, 0, keyOps->minKey, keyOps->maxKey ); } else { TransList srcList; srcList.transfer( state->outList ); /* Check for a gap at the beginning. */ TransList::Iter trans = srcList, next; if ( keyOps->minKey < trans->lowKey ) { /* Make the high key and append. */ Key highKey = trans->lowKey; highKey.decrement(); attachNewTrans( state, 0, keyOps->minKey, highKey ); } /* Write the transition. */ next = trans.next(); state->outList.append( trans ); /* Keep the last high end. */ Key lastHigh = trans->highKey; /* Loop each source range. */ for ( trans = next; trans.lte(); trans = next ) { /* Make the next key following the last range. */ Key nextKey = lastHigh; nextKey.increment(); /* Check for a gap from last up to here. */ if ( nextKey < trans->lowKey ) { /* Make the high end of the range that fills the gap. */ Key highKey = trans->lowKey; highKey.decrement(); attachNewTrans( state, 0, nextKey, highKey ); } /* Reduce the transition. If it reduced to anything then add it. */ next = trans.next(); state->outList.append( trans ); /* Keep the last high end. */ lastHigh = trans->highKey; } /* Now check for a gap on the end to fill. */ if ( lastHigh < keyOps->maxKey ) { /* Get a copy of the default. */ lastHigh.increment(); attachNewTrans( state, 0, lastHigh, keyOps->maxKey ); } } } void FsmAp::setErrorActions( StateAp *state, const ActionTable &other ) { /* Fill any gaps in the out list with an error transition. */ fillGaps( state ); /* Set error transitions in the transitions that go to error. */ for ( TransList::Iter trans = state->outList; trans.lte(); trans++ ) { if ( trans->toState == 0 ) trans->actionTable.setActions( other ); } } void FsmAp::setErrorAction( StateAp *state, int ordering, Action *action ) { /* Fill any gaps in the out list with an error transition. */ fillGaps( state ); /* Set error transitions in the transitions that go to error. */ for ( TransList::Iter trans = state->outList; trans.lte(); trans++ ) { if ( trans->toState == 0 ) trans->actionTable.setAction( ordering, action ); } } /* Give a target state for error transitions. */ void FsmAp::setErrorTarget( StateAp *state, StateAp *target, int *orderings, Action **actions, int nActs ) { /* Fill any gaps in the out list with an error transition. */ fillGaps( state ); /* Set error target in the transitions that go to error. */ for ( TransList::Iter trans = state->outList; trans.lte(); trans++ ) { if ( trans->toState == 0 ) { /* The trans goes to error, redirect it. */ redirectErrorTrans( trans->fromState, target, trans ); trans->actionTable.setActions( orderings, actions, nActs ); } } } void FsmAp::transferOutActions( StateAp *state ) { for ( ActionTable::Iter act = state->outActionTable; act.lte(); act++ ) state->eofActionTable.setAction( act->key, act->value ); state->outActionTable.empty(); } void FsmAp::transferErrorActions( StateAp *state, int transferPoint ) { for ( int i = 0; i < state->errActionTable.length(); ) { ErrActionTableEl *act = state->errActionTable.data + i; if ( act->transferPoint == transferPoint ) { /* Transfer the error action and remove it. */ setErrorAction( state, act->ordering, act->action ); if ( ! state->isFinState() ) state->eofActionTable.setAction( act->ordering, act->action ); state->errActionTable.vremove( i ); } else { /* Not transfering and deleting, skip over the item. */ i += 1; } } } /* Set error actions in the start state. */ void FsmAp::startErrorAction( int ordering, Action *action, int transferPoint ) { /* Make sure the start state has no other entry points. */ isolateStartState(); /* Add the actions. */ startState->errActionTable.setAction( ordering, action, transferPoint ); } /* Set error actions in all states where there is a transition out. */ void FsmAp::allErrorAction( int ordering, Action *action, int transferPoint ) { /* Insert actions in the error action table of all states. */ for ( StateList::Iter state = stateList; state.lte(); state++ ) state->errActionTable.setAction( ordering, action, transferPoint ); } /* Set error actions in final states. */ void FsmAp::finalErrorAction( int ordering, Action *action, int transferPoint ) { /* Add the action to the error table of final states. */ for ( StateSet::Iter state = finStateSet; state.lte(); state++ ) (*state)->errActionTable.setAction( ordering, action, transferPoint ); } void FsmAp::notStartErrorAction( int ordering, Action *action, int transferPoint ) { for ( StateList::Iter state = stateList; state.lte(); state++ ) { if ( state != startState ) state->errActionTable.setAction( ordering, action, transferPoint ); } } void FsmAp::notFinalErrorAction( int ordering, Action *action, int transferPoint ) { for ( StateList::Iter state = stateList; state.lte(); state++ ) { if ( ! state->isFinState() ) state->errActionTable.setAction( ordering, action, transferPoint ); } } /* Set error actions in the states that have transitions into a final state. */ void FsmAp::middleErrorAction( int ordering, Action *action, int transferPoint ) { /* Isolate the start state in case it is reachable from in inside the * machine, in which case we don't want it set. */ for ( StateList::Iter state = stateList; state.lte(); state++ ) { if ( state != startState && ! state->isFinState() ) state->errActionTable.setAction( ordering, action, transferPoint ); } } /* Set EOF actions in the start state. */ void FsmAp::startEOFAction( int ordering, Action *action ) { /* Make sure the start state has no other entry points. */ isolateStartState(); /* Add the actions. */ startState->eofActionTable.setAction( ordering, action ); } /* Set EOF actions in all states where there is a transition out. */ void FsmAp::allEOFAction( int ordering, Action *action ) { /* Insert actions in the EOF action table of all states. */ for ( StateList::Iter state = stateList; state.lte(); state++ ) state->eofActionTable.setAction( ordering, action ); } /* Set EOF actions in final states. */ void FsmAp::finalEOFAction( int ordering, Action *action ) { /* Add the action to the error table of final states. */ for ( StateSet::Iter state = finStateSet; state.lte(); state++ ) (*state)->eofActionTable.setAction( ordering, action ); } void FsmAp::notStartEOFAction( int ordering, Action *action ) { for ( StateList::Iter state = stateList; state.lte(); state++ ) { if ( state != startState ) state->eofActionTable.setAction( ordering, action ); } } void FsmAp::notFinalEOFAction( int ordering, Action *action ) { for ( StateList::Iter state = stateList; state.lte(); state++ ) { if ( ! state->isFinState() ) state->eofActionTable.setAction( ordering, action ); } } /* Set EOF actions in the states that have transitions into a final state. */ void FsmAp::middleEOFAction( int ordering, Action *action ) { /* Set the actions in all states that are not the start state and not final. */ for ( StateList::Iter state = stateList; state.lte(); state++ ) { if ( state != startState && ! state->isFinState() ) state->eofActionTable.setAction( ordering, action ); } } /* * Set To State Actions. */ /* Set to state actions in the start state. */ void FsmAp::startToStateAction( int ordering, Action *action ) { /* Make sure the start state has no other entry points. */ isolateStartState(); startState->toStateActionTable.setAction( ordering, action ); } /* Set to state actions in all states. */ void FsmAp::allToStateAction( int ordering, Action *action ) { /* Insert the action on all states. */ for ( StateList::Iter state = stateList; state.lte(); state++ ) state->toStateActionTable.setAction( ordering, action ); } /* Set to state actions in final states. */ void FsmAp::finalToStateAction( int ordering, Action *action ) { /* Add the action to the error table of final states. */ for ( StateSet::Iter state = finStateSet; state.lte(); state++ ) (*state)->toStateActionTable.setAction( ordering, action ); } void FsmAp::notStartToStateAction( int ordering, Action *action ) { for ( StateList::Iter state = stateList; state.lte(); state++ ) { if ( state != startState ) state->toStateActionTable.setAction( ordering, action ); } } void FsmAp::notFinalToStateAction( int ordering, Action *action ) { for ( StateList::Iter state = stateList; state.lte(); state++ ) { if ( ! state->isFinState() ) state->toStateActionTable.setAction( ordering, action ); } } /* Set to state actions in states that are not final and not the start state. */ void FsmAp::middleToStateAction( int ordering, Action *action ) { /* Set the action in all states that are not the start state and not final. */ for ( StateList::Iter state = stateList; state.lte(); state++ ) { if ( state != startState && ! state->isFinState() ) state->toStateActionTable.setAction( ordering, action ); } } /* * Set From State Actions. */ void FsmAp::startFromStateAction( int ordering, Action *action ) { /* Make sure the start state has no other entry points. */ isolateStartState(); startState->fromStateActionTable.setAction( ordering, action ); } void FsmAp::allFromStateAction( int ordering, Action *action ) { /* Insert the action on all states. */ for ( StateList::Iter state = stateList; state.lte(); state++ ) state->fromStateActionTable.setAction( ordering, action ); } void FsmAp::finalFromStateAction( int ordering, Action *action ) { /* Add the action to the error table of final states. */ for ( StateSet::Iter state = finStateSet; state.lte(); state++ ) (*state)->fromStateActionTable.setAction( ordering, action ); } void FsmAp::notStartFromStateAction( int ordering, Action *action ) { for ( StateList::Iter state = stateList; state.lte(); state++ ) { if ( state != startState ) state->fromStateActionTable.setAction( ordering, action ); } } void FsmAp::notFinalFromStateAction( int ordering, Action *action ) { for ( StateList::Iter state = stateList; state.lte(); state++ ) { if ( ! state->isFinState() ) state->fromStateActionTable.setAction( ordering, action ); } } void FsmAp::middleFromStateAction( int ordering, Action *action ) { /* Set the action in all states that are not the start state and not final. */ for ( StateList::Iter state = stateList; state.lte(); state++ ) { if ( state != startState && ! state->isFinState() ) state->fromStateActionTable.setAction( ordering, action ); } } /* Shift the function ordering of the start transitions to start * at fromOrder and increase in units of 1. Useful before staring. * Returns the maximum number of order numbers used. */ int FsmAp::shiftStartActionOrder( int fromOrder ) { int maxUsed = 0; /* Walk the start state's transitions, shifting function ordering. */ for ( TransList::Iter trans = startState->outList; trans.lte(); trans++ ) { /* Walk the function data for the transition and set the keys to * increasing values starting at fromOrder. */ int curFromOrder = fromOrder; ActionTable::Iter action = trans->actionTable; for ( ; action.lte(); action++ ) action->key = curFromOrder++; /* Keep track of the max number of orders used. */ if ( curFromOrder - fromOrder > maxUsed ) maxUsed = curFromOrder - fromOrder; } return maxUsed; } /* Remove all priorities. */ void FsmAp::clearAllPriorities() { for ( StateList::Iter state = stateList; state.lte(); state++ ) { /* Clear out priority data. */ state->outPriorTable.empty(); /* Clear transition data from the out transitions. */ for ( TransList::Iter trans = state->outList; trans.lte(); trans++ ) trans->priorTable.empty(); } } /* Zeros out the function ordering keys. This may be called before minimization * when it is known that no more fsm operations are going to be done. This * will achieve greater reduction as states will not be separated on the basis * of function ordering. */ void FsmAp::nullActionKeys( ) { /* For each state... */ for ( StateList::Iter state = stateList; state.lte(); state++ ) { /* Walk the transitions for the state. */ for ( TransList::Iter trans = state->outList; trans.lte(); trans++ ) { /* Walk the action table for the transition. */ for ( ActionTable::Iter action = trans->actionTable; action.lte(); action++ ) action->key = 0; /* Walk the action table for the transition. */ for ( LmActionTable::Iter action = trans->lmActionTable; action.lte(); action++ ) action->key = 0; } /* Null the action keys of the to state action table. */ for ( ActionTable::Iter action = state->toStateActionTable; action.lte(); action++ ) action->key = 0; /* Null the action keys of the from state action table. */ for ( ActionTable::Iter action = state->fromStateActionTable; action.lte(); action++ ) action->key = 0; /* Null the action keys of the out transtions. */ for ( ActionTable::Iter action = state->outActionTable; action.lte(); action++ ) action->key = 0; /* Null the action keys of the error action table. */ for ( ErrActionTable::Iter action = state->errActionTable; action.lte(); action++ ) action->ordering = 0; /* Null the action keys eof action table. */ for ( ActionTable::Iter action = state->eofActionTable; action.lte(); action++ ) action->key = 0; } } /* Walk the list of states and verify that non final states do not have out * data, that all stateBits are cleared, and that there are no states with * zero foreign in transitions. */ void FsmAp::verifyStates() { for ( StateList::Iter state = stateList; state.lte(); state++ ) { /* Non final states should not have leaving data. */ if ( ! (state->stateBits & STB_ISFINAL) ) { assert( state->outActionTable.length() == 0 ); assert( state->outCondSet.length() == 0 ); assert( state->outPriorTable.length() == 0 ); } /* Data used in algorithms should be cleared. */ assert( (state->stateBits & STB_BOTH) == 0 ); assert( state->foreignInTrans > 0 ); } } /* Compare two transitions according to their relative priority. Since the * base transition has no priority associated with it, the default is to * return equal. */ int FsmAp::comparePrior( const PriorTable &priorTable1, const PriorTable &priorTable2 ) { /* Looking for differing priorities on same keys. Need to concurrently * scan the priority lists. */ PriorTable::Iter pd1 = priorTable1; PriorTable::Iter pd2 = priorTable2; while ( pd1.lte() && pd2.lte() ) { /* Check keys. */ if ( pd1->desc->key < pd2->desc->key ) pd1.increment(); else if ( pd1->desc->key > pd2->desc->key ) pd2.increment(); /* Keys are the same, check priorities. */ else if ( pd1->desc->priority < pd2->desc->priority ) return -1; else if ( pd1->desc->priority > pd2->desc->priority ) return 1; else { /* Keys and priorities are equal, advance both. */ pd1.increment(); pd2.increment(); } } /* No differing priorities on the same key. */ return 0; } /* Compares two transitions according to priority and functions. Pointers * should not be null. Does not consider to state or from state. Compare two * transitions according to the data contained in the transitions. Data means * any properties added to user transitions that may differentiate them. Since * the base transition has no data, the default is to return equal. */ int FsmAp::compareTransData( TransAp *trans1, TransAp *trans2 ) { /* Compare the prior table. */ int cmpRes = CmpPriorTable::compare( trans1->priorTable, trans2->priorTable ); if ( cmpRes != 0 ) return cmpRes; /* Compare longest match action tables. */ cmpRes = CmpLmActionTable::compare(trans1->lmActionTable, trans2->lmActionTable); if ( cmpRes != 0 ) return cmpRes; /* Compare action tables. */ return CmpActionTable::compare(trans1->actionTable, trans2->actionTable); } /* Callback invoked when another trans (or possibly this) is added into this * transition during the merging process. Draw in any properties of srcTrans * into this transition. AddInTrans is called when a new transitions is made * that will be a duplicate of another transition or a combination of several * other transitions. AddInTrans will be called for each transition that the * new transition is to represent. */ void FsmAp::addInTrans( TransAp *destTrans, TransAp *srcTrans ) { /* Protect against adding in from ourselves. */ if ( srcTrans == destTrans ) { /* Adding in ourselves, need to make a copy of the source transitions. * The priorities are not copied in as that would have no effect. */ destTrans->lmActionTable.setActions( LmActionTable(srcTrans->lmActionTable) ); destTrans->actionTable.setActions( ActionTable(srcTrans->actionTable) ); } else { /* Not a copy of ourself, get the functions and priorities. */ destTrans->lmActionTable.setActions( srcTrans->lmActionTable ); destTrans->actionTable.setActions( srcTrans->actionTable ); destTrans->priorTable.setPriors( srcTrans->priorTable ); } } /* Compare the properties of states that are embedded by users. Compares out * priorities, out transitions, to, from, out, error and eof action tables. */ int FsmAp::compareStateData( const StateAp *state1, const StateAp *state2 ) { /* Compare the out priority table. */ int cmpRes = CmpPriorTable:: compare( state1->outPriorTable, state2->outPriorTable ); if ( cmpRes != 0 ) return cmpRes; /* Test to state action tables. */ cmpRes = CmpActionTable::compare( state1->toStateActionTable, state2->toStateActionTable ); if ( cmpRes != 0 ) return cmpRes; /* Test from state action tables. */ cmpRes = CmpActionTable::compare( state1->fromStateActionTable, state2->fromStateActionTable ); if ( cmpRes != 0 ) return cmpRes; /* Test out action tables. */ cmpRes = CmpActionTable::compare( state1->outActionTable, state2->outActionTable ); if ( cmpRes != 0 ) return cmpRes; /* Test out condition sets. */ cmpRes = CmpOutCondSet::compare( state1->outCondSet, state2->outCondSet ); if ( cmpRes != 0 ) return cmpRes; /* Test out error action tables. */ cmpRes = CmpErrActionTable::compare( state1->errActionTable, state2->errActionTable ); if ( cmpRes != 0 ) return cmpRes; /* Test eof action tables. */ return CmpActionTable::compare( state1->eofActionTable, state2->eofActionTable ); } /* Invoked when a state looses its final state status and the leaving * transition embedding data should be deleted. */ void FsmAp::clearOutData( StateAp *state ) { /* Kill the out actions and priorities. */ state->outActionTable.empty(); state->outCondSet.empty(); state->outPriorTable.empty(); } bool FsmAp::hasOutData( StateAp *state ) { return ( state->outActionTable.length() > 0 || state->outCondSet.length() > 0 || state->outPriorTable.length() > 0 ); } /* * Setting Conditions. */ void logNewExpansion( Expansion *exp ); void logCondSpace( CondSpace *condSpace ); CondSpace *FsmAp::addCondSpace( const CondSet &condSet ) { CondSpace *condSpace = condData->condSpaceMap.find( condSet ); if ( condSpace == 0 ) { /* Do we have enough keyspace left? */ Size availableSpace = condData->lastCondKey.availableSpace(); Size neededSpace = (1 << condSet.length() ) * keyOps->alphSize(); if ( neededSpace > availableSpace ) throw FsmConstructFail( FsmConstructFail::CondNoKeySpace ); Key baseKey = condData->lastCondKey; baseKey.increment(); condData->lastCondKey += (1 << condSet.length() ) * keyOps->alphSize(); condSpace = new CondSpace( condSet ); condSpace->baseKey = baseKey; condData->condSpaceMap.insert( condSpace ); #ifdef LOG_CONDS cerr << "adding new condition space" << endl; cerr << " condition set: "; logCondSpace( condSpace ); cerr << endl; cerr << " baseKey: " << baseKey.getVal() << endl; #endif } return condSpace; } void FsmAp::startFsmCondition( Action *condAction, bool sense ) { /* Make sure the start state has no other entry points. */ isolateStartState(); embedCondition( startState, condAction, sense ); } void FsmAp::allTransCondition( Action *condAction, bool sense ) { for ( StateList::Iter state = stateList; state.lte(); state++ ) embedCondition( state, condAction, sense ); } void FsmAp::leaveFsmCondition( Action *condAction, bool sense ) { for ( StateSet::Iter state = finStateSet; state.lte(); state++ ) (*state)->outCondSet.insert( OutCond( condAction, sense ) ); } ragel-6.8/ragel/cdsplit.cpp0000664000175000017500000003255312106050031012640 00000000000000/* * Copyright 2006 Adrian Thurston */ /* This file is part of Ragel. * * Ragel is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Ragel is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Ragel; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "ragel.h" #include "cdsplit.h" #include "gendata.h" #include using std::ostream; using std::ios; using std::endl; /* Emit the goto to take for a given transition. */ std::ostream &SplitCodeGen::TRANS_GOTO( RedTransAp *trans, int level ) { if ( trans->targ->partition == currentPartition ) { if ( trans->action != 0 ) { /* Go to the transition which will go to the state. */ out << TABS(level) << "goto tr" << trans->id << ";"; } else { /* Go directly to the target state. */ out << TABS(level) << "goto st" << trans->targ->id << ";"; } } else { if ( trans->action != 0 ) { /* Go to the transition which will go to the state. */ out << TABS(level) << "goto ptr" << trans->id << ";"; trans->partitionBoundary = true; } else { /* Go directly to the target state. */ out << TABS(level) << "goto pst" << trans->targ->id << ";"; trans->targ->partitionBoundary = true; } } return out; } /* Called from before writing the gotos for each state. */ void SplitCodeGen::GOTO_HEADER( RedStateAp *state, bool stateInPartition ) { bool anyWritten = IN_TRANS_ACTIONS( state ); if ( state->labelNeeded ) out << "st" << state->id << ":\n"; if ( state->toStateAction != 0 ) { /* Remember that we wrote an action. Write every action in the list. */ anyWritten = true; for ( GenActionTable::Iter item = state->toStateAction->key; item.lte(); item++ ) { ACTION( out, item->value, state->id, false, state->toStateAction->anyNextStmt() ); } } /* Advance and test buffer pos. */ if ( state->labelNeeded ) { if ( !noEnd ) { out << " if ( ++" << P() << " == " << PE() << " )\n" " goto _out" << state->id << ";\n"; } else { out << " " << P() << " += 1;\n"; } } /* Give the state a switch case. */ out << "case " << state->id << ":\n"; if ( state->fromStateAction != 0 ) { /* Remember that we wrote an action. Write every action in the list. */ anyWritten = true; for ( GenActionTable::Iter item = state->fromStateAction->key; item.lte(); item++ ) { ACTION( out, item->value, state->id, false, state->fromStateAction->anyNextStmt() ); } } if ( anyWritten ) genLineDirective( out ); /* Record the prev state if necessary. */ if ( state->anyRegCurStateRef() ) out << " _ps = " << state->id << ";\n"; } std::ostream &SplitCodeGen::STATE_GOTOS( int partition ) { for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { if ( st->partition == partition ) { if ( st == redFsm->errState ) STATE_GOTO_ERROR(); else { /* We call into the base of the goto which calls back into us * using virtual functions. Set the current partition rather * than coding parameter passing throughout. */ currentPartition = partition; /* Writing code above state gotos. */ GOTO_HEADER( st, st->partition == partition ); if ( st->stateCondVect.length() > 0 ) { out << " _widec = " << GET_KEY() << ";\n"; emitCondBSearch( st, 1, 0, st->stateCondVect.length() - 1 ); } /* Try singles. */ if ( st->outSingle.length() > 0 ) emitSingleSwitch( st ); /* Default case is to binary search for the ranges, if that fails then */ if ( st->outRange.length() > 0 ) emitRangeBSearch( st, 1, 0, st->outRange.length() - 1 ); /* Write the default transition. */ TRANS_GOTO( st->defTrans, 1 ) << "\n"; } } } return out; } std::ostream &SplitCodeGen::PART_TRANS( int partition ) { for ( TransApSet::Iter trans = redFsm->transSet; trans.lte(); trans++ ) { if ( trans->partitionBoundary ) { out << "ptr" << trans->id << ":\n"; if ( trans->action != 0 ) { /* If the action contains a next, then we must preload the current * state since the action may or may not set it. */ if ( trans->action->anyNextStmt() ) out << " " << vCS() << " = " << trans->targ->id << ";\n"; /* Write each action in the list. */ for ( GenActionTable::Iter item = trans->action->key; item.lte(); item++ ) { ACTION( out, item->value, trans->targ->id, false, trans->action->anyNextStmt() ); } } out << " goto pst" << trans->targ->id << ";\n"; trans->targ->partitionBoundary = true; } } for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { if ( st->partitionBoundary ) { out << " pst" << st->id << ":\n" " " << vCS() << " = " << st->id << ";\n"; if ( st->toStateAction != 0 ) { /* Remember that we wrote an action. Write every action in the list. */ for ( GenActionTable::Iter item = st->toStateAction->key; item.lte(); item++ ) { ACTION( out, item->value, st->id, false, st->toStateAction->anyNextStmt() ); } genLineDirective( out ); } ptOutLabelUsed = true; out << " goto _pt_out; \n"; } } return out; } std::ostream &SplitCodeGen::EXIT_STATES( int partition ) { for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { if ( st->partition == partition && st->outNeeded ) { outLabelUsed = true; out << " _out" << st->id << ": " << vCS() << " = " << st->id << "; goto _out; \n"; } } return out; } std::ostream &SplitCodeGen::PARTITION( int partition ) { outLabelUsed = false; ptOutLabelUsed = false; /* Initialize the partition boundaries, which get set during the writing * of states. After the state writing we will */ for ( TransApSet::Iter trans = redFsm->transSet; trans.lte(); trans++ ) trans->partitionBoundary = false; for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) st->partitionBoundary = false; out << " " << ALPH_TYPE() << " *p = *_pp, *pe = *_ppe;\n"; if ( redFsm->anyRegCurStateRef() ) out << " int _ps = 0;\n"; if ( redFsm->anyConditions() ) out << " " << WIDE_ALPH_TYPE() << " _widec;\n"; if ( useAgainLabel() ) { out << " goto _resume;\n" "\n" "_again:\n" " switch ( " << vCS() << " ) {\n"; AGAIN_CASES() << " default: break;\n" " }\n" "\n"; if ( !noEnd ) { outLabelUsed = true; out << " if ( ++" << P() << " == " << PE() << " )\n" " goto _out;\n"; } else { out << " " << P() << " += 1;\n"; } out << "_resume:\n"; } out << " switch ( " << vCS() << " )\n {\n"; STATE_GOTOS( partition ); SWITCH_DEFAULT() << " }\n"; PART_TRANS( partition ); EXIT_STATES( partition ); if ( outLabelUsed ) { out << "\n" " _out:\n" " *_pp = p;\n" " *_ppe = pe;\n" " return 0;\n"; } if ( ptOutLabelUsed ) { out << "\n" " _pt_out:\n" " *_pp = p;\n" " *_ppe = pe;\n" " return 1;\n"; } return out; } std::ostream &SplitCodeGen::PART_MAP() { int *partMap = new int[redFsm->stateList.length()]; for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) partMap[st->id] = st->partition; out << "\t"; int totalItem = 0; for ( int i = 0; i < redFsm->stateList.length(); i++ ) { out << partMap[i]; if ( i != redFsm->stateList.length() - 1 ) { out << ", "; if ( ++totalItem % IALL == 0 ) out << "\n\t"; } } delete[] partMap; return out; } void SplitCodeGen::writeData() { out << "static const int " << START() << " = " << START_STATE_ID() << ";\n" "\n"; if ( !noFinal ) { out << "static const int " << FIRST_FINAL() << " = " << FIRST_FINAL_STATE() << ";\n" "\n"; } if ( !noError ) { out << "static const int " << ERROR() << " = " << ERROR_STATE() << ";\n" "\n"; } OPEN_ARRAY( ARRAY_TYPE(numSplitPartitions), PM() ); PART_MAP(); CLOSE_ARRAY() << "\n"; for ( int p = 0; p < redFsm->nParts; p++ ) { out << "int partition" << p << "( " << ALPH_TYPE() << " **_pp, " << ALPH_TYPE() << " **_ppe, struct " << FSM_NAME() << " *fsm );\n"; } out << "\n"; } std::ostream &SplitCodeGen::ALL_PARTITIONS() { /* compute the format string. */ int width = 0, high = redFsm->nParts - 1; while ( high > 0 ) { width++; high /= 10; } assert( width <= 8 ); char suffFormat[] = "_%6.6d.c"; suffFormat[2] = suffFormat[4] = ( '0' + width ); for ( int p = 0; p < redFsm->nParts; p++ ) { char suffix[10]; sprintf( suffix, suffFormat, p ); const char *fn = fileNameFromStem( sourceFileName, suffix ); const char *include = fileNameFromStem( sourceFileName, ".h" ); /* Create the filter on the output and open it. */ output_filter *partFilter = new output_filter( fn ); partFilter->open( fn, ios::out|ios::trunc ); if ( !partFilter->is_open() ) { error() << "error opening " << fn << " for writing" << endl; exit(1); } /* Attach the new file to the output stream. */ std::streambuf *prev_rdbuf = out.rdbuf( partFilter ); out << "#include \"" << include << "\"\n" "int partition" << p << "( " << ALPH_TYPE() << " **_pp, " << ALPH_TYPE() << " **_ppe, struct " << FSM_NAME() << " *fsm )\n" "{\n"; PARTITION( p ) << "}\n\n"; out.flush(); /* Fix the output stream. */ out.rdbuf( prev_rdbuf ); } return out; } void SplitCodeGen::writeExec() { /* Must set labels immediately before writing because we may depend on the * noend write option. */ setLabelsNeeded(); out << " {\n" " int _stat = 0;\n"; if ( !noEnd ) { out << " if ( " << P() << " == " << PE() << " )\n" " goto _out;\n"; } out << " goto _resume;\n"; /* In this reentry, to-state actions have already been executed on the * partition-switch exit from the last partition. */ out << "_reenter:\n"; if ( !noEnd ) { out << " if ( ++" << P() << " == " << PE() << " )\n" " goto _out;\n"; } else { out << " " << P() << " += 1;\n"; } out << "_resume:\n"; out << " switch ( " << PM() << "[" << vCS() << "] ) {\n"; for ( int p = 0; p < redFsm->nParts; p++ ) { out << " case " << p << ":\n" " _stat = partition" << p << "( &p, &pe, fsm );\n" " break;\n"; } out << " }\n" " if ( _stat )\n" " goto _reenter;\n"; if ( !noEnd ) out << " _out: {}\n"; out << " }\n"; ALL_PARTITIONS(); } void SplitCodeGen::setLabelsNeeded( RedStateAp *fromState, GenInlineList *inlineList ) { for ( GenInlineList::Iter item = *inlineList; item.lte(); item++ ) { switch ( item->type ) { case GenInlineItem::Goto: case GenInlineItem::Call: { /* In split code gen we only need labels for transitions across * partitions. */ if ( fromState->partition == item->targState->partition ){ /* Mark the target as needing a label. */ item->targState->labelNeeded = true; } break; } default: break; } if ( item->children != 0 ) setLabelsNeeded( fromState, item->children ); } } void SplitCodeGen::setLabelsNeeded( RedStateAp *fromState, RedTransAp *trans ) { /* In the split code gen we don't need labels for transitions across * partitions. */ if ( fromState->partition == trans->targ->partition ) { /* If there is no action with a next statement, then the label will be * needed. */ trans->labelNeeded = true; if ( trans->action == 0 || !trans->action->anyNextStmt() ) trans->targ->labelNeeded = true; } /* Need labels for states that have goto or calls in action code * invoked on characters (ie, not from out action code). */ if ( trans->action != 0 ) { /* Loop the actions. */ for ( GenActionTable::Iter act = trans->action->key; act.lte(); act++ ) { /* Get the action and walk it's tree. */ setLabelsNeeded( fromState, act->value->inlineList ); } } } /* Set up labelNeeded flag for each state. */ void SplitCodeGen::setLabelsNeeded() { /* If we use the _again label, then we the _again switch, which uses all * labels. */ if ( useAgainLabel() ) { for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) st->labelNeeded = true; } else { /* Do not use all labels by default, init all labelNeeded vars to false. */ for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) st->labelNeeded = false; for ( TransApSet::Iter trans = redFsm->transSet; trans.lte(); trans++ ) trans->labelNeeded = false; /* Walk all transitions and set only those that have targs. */ for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { for ( RedTransList::Iter tel = st->outRange; tel.lte(); tel++ ) setLabelsNeeded( st, tel->value ); for ( RedTransList::Iter tel = st->outSingle; tel.lte(); tel++ ) setLabelsNeeded( st, tel->value ); if ( st->defTrans != 0 ) setLabelsNeeded( st, st->defTrans ); } } if ( !noEnd ) { for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) st->outNeeded = st->labelNeeded; } else { if ( redFsm->errState != 0 ) redFsm->errState->outNeeded = true; for ( TransApSet::Iter trans = redFsm->transSet; trans.lte(); trans++ ) { /* Any state with a transition in that has a break will need an * out label. */ if ( trans->action != 0 && trans->action->anyBreakStmt() ) trans->targ->outNeeded = true; } } } ragel-6.8/ragel/dotcodegen.h0000664000175000017500000000265712106050031012760 00000000000000/* * Copyright 2001-2007 Adrian Thurston */ /* This file is part of Ragel. * * Ragel is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Ragel is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Ragel; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef _GVDOTGEN_H #define _GVDOTGEN_H #include #include "gendata.h" class GraphvizDotGen : public CodeGenData { public: GraphvizDotGen( ostream &out ) : CodeGenData(out) { } /* Print an fsm to out stream. */ void writeTransList( RedStateAp *state ); void writeDotFile( ); virtual void finishRagelDef(); virtual void writeStatement( InputLoc &, int, char ** ); private: /* Writing labels and actions. */ std::ostream &ONCHAR( Key lowKey, Key highKey ); std::ostream &TRANS_ACTION( RedStateAp *fromState, RedTransAp *trans ); std::ostream &ACTION( RedAction *action ); std::ostream &KEY( Key key ); }; #endif ragel-6.8/ragel/rlscan.h0000664000175000017500000000703612106050031012123 00000000000000/* * Copyright 2007 Adrian Thurston */ /* This file is part of Ragel. * * Ragel is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Ragel is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Ragel; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef _RLSCAN_H #define _RLSCAN_H #include #include "rlscan.h" #include "vector.h" #include "rlparse.h" #include "parsedata.h" #include "avltree.h" #include "vector.h" using std::istream; using std::ostream; extern char *Parser_lelNames[]; struct Scanner { Scanner( InputData &id, const char *fileName, istream &input, Parser *inclToParser, char *inclSectionTarg, int includeDepth, bool importMachines ) : id(id), fileName(fileName), input(input), inclToParser(inclToParser), inclSectionTarg(inclSectionTarg), includeDepth(includeDepth), importMachines(importMachines), cur_token(0), line(1), column(1), lastnl(0), parser(0), ignoreSection(false), parserExistsError(false), whitespaceOn(true), lastToken(0) {} bool duplicateInclude( char *inclFileName, char *inclSectionName ); /* Make a list of places to look for an included file. */ char **makeIncludePathChecks( const char *curFileName, const char *fileName, int len ); std::ifstream *tryOpenInclude( char **pathChecks, long &found ); void handleMachine(); void handleInclude(); void handleImport(); void init(); void token( int type, char *start, char *end ); void token( int type, char c ); void token( int type ); void processToken( int type, char *tokdata, int toklen ); void directToParser( Parser *toParser, const char *tokFileName, int tokLine, int tokColumn, int type, char *tokdata, int toklen ); void flushImport( ); void importToken( int type, char *start, char *end ); void pass( int token, char *start, char *end ); void pass(); void updateCol(); void startSection(); void endSection(); void do_scan(); bool active(); ostream &scan_error(); InputData &id; const char *fileName; istream &input; Parser *inclToParser; char *inclSectionTarg; int includeDepth; bool importMachines; /* For import parsing. */ int tok_cs, tok_act; int *tok_ts, *tok_te; int cur_token; static const int max_tokens = 32; int token_data[max_tokens]; char *token_strings[max_tokens]; int token_lens[max_tokens]; /* For section processing. */ int cs; char *word, *lit; int word_len, lit_len; /* For character scanning. */ int line; InputLoc sectionLoc; char *ts, *te; int column; char *lastnl; /* Set by machine statements, these persist from section to section * allowing for unnamed sections. */ Parser *parser; bool ignoreSection; /* This is set if ragel has already emitted an error stating that * no section name has been seen and thus no parser exists. */ bool parserExistsError; /* This is for inline code. By default it is on. It goes off for * statements and values in inline blocks which are parsed. */ bool whitespaceOn; /* Keeps a record of the previous token sent to the section parser. */ int lastToken; }; #endif ragel-6.8/ragel/rubytable.h0000664000175000017500000000703212106050031012626 00000000000000/* * Copyright 2007 Victor Hugo Borja * 2006-2007 Adrian Thurston */ /* This file is part of Ragel. * * Ragel is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Ragel is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Ragel; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef _RUBY_TABCODEGEN_H #define _RUBY_TABCODEGEN_H #include #include #include #include "common.h" #include "gendata.h" #include "rubycodegen.h" using std::string; using std::ostream; /* * RubyCodeGen */ class RubyTabCodeGen : public RubyCodeGen { public: RubyTabCodeGen( ostream &out ) : RubyCodeGen(out) {} virtual ~RubyTabCodeGen() {} public: void BREAK( ostream &ret, int targState ); void GOTO( ostream &ret, int gotoDest, bool inFinish ); void GOTO_EXPR( ostream &ret, GenInlineItem *ilItem, bool inFinish ); void CALL( ostream &ret, int callDest, int targState, bool inFinish ); void CALL_EXPR( ostream &ret, GenInlineItem *ilItem, int targState, bool inFinish ); void RET( ostream &ret, bool inFinish ); void COND_TRANSLATE(); void LOCATE_TRANS(); virtual void writeExec(); virtual void writeData(); protected: virtual std::ostream &TO_STATE_ACTION_SWITCH(); virtual std::ostream &FROM_STATE_ACTION_SWITCH(); virtual std::ostream &EOF_ACTION_SWITCH(); virtual std::ostream &ACTION_SWITCH(); std::ostream &COND_KEYS(); std::ostream &COND_SPACES(); std::ostream &KEYS(); std::ostream &INDICIES(); std::ostream &COND_OFFSETS(); std::ostream &KEY_OFFSETS(); std::ostream &INDEX_OFFSETS(); std::ostream &COND_LENS(); std::ostream &SINGLE_LENS(); std::ostream &RANGE_LENS(); std::ostream &TO_STATE_ACTIONS(); std::ostream &FROM_STATE_ACTIONS(); std::ostream &EOF_ACTIONS(); std::ostream &EOF_TRANS(); std::ostream &TRANS_TARGS(); std::ostream &TRANS_ACTIONS(); std::ostream &TRANS_TARGS_WI(); std::ostream &TRANS_ACTIONS_WI(); void NEXT( ostream &ret, int nextDest, bool inFinish ); void NEXT_EXPR( ostream &ret, GenInlineItem *ilItem, bool inFinish ); virtual int TO_STATE_ACTION( RedStateAp *state ); virtual int FROM_STATE_ACTION( RedStateAp *state ); virtual int EOF_ACTION( RedStateAp *state ); private: string array_type; string array_name; public: void EXEC( ostream &ret, GenInlineItem *item, int targState, int inFinish ); void EXECTE( ostream &ret, GenInlineItem *item, int targState, int inFinish ); void LM_SWITCH( ostream &ret, GenInlineItem *item, int targState, int inFinish ); void SET_ACT( ostream &ret, GenInlineItem *item ); void INIT_TOKSTART( ostream &ret, GenInlineItem *item ); void INIT_ACT( ostream &ret, GenInlineItem *item ); void SET_TOKSTART( ostream &ret, GenInlineItem *item ); void SET_TOKEND( ostream &ret, GenInlineItem *item ); void GET_TOKEND( ostream &ret, GenInlineItem *item ); void SUB_ACTION( ostream &ret, GenInlineItem *item, int targState, bool inFinish ); }; #endif /* * Local Variables: * mode: c++ * indent-tabs-mode: 1 * c-file-style: "bsd" * End: */ ragel-6.8/ragel/mlcodegen.cpp0000664000175000017500000004226112106050031013130 00000000000000/* * Copyright 2001-2006 Adrian Thurston * 2004 Erich Ocean * 2005 Alan West */ /* This file is part of Ragel. * * Ragel is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Ragel is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Ragel; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "ragel.h" #include "mlcodegen.h" #include "redfsm.h" #include "gendata.h" #include #include #include #include using std::ostream; using std::ostringstream; using std::string; using std::cerr; using std::endl; using std::istream; using std::ifstream; using std::ostream; using std::ios; using std::cin; using std::cout; using std::cerr; using std::endl; void ocamlLineDirective( ostream &out, const char *fileName, int line ) { if ( noLineDirectives ) return; /* Write the line info for to the input file. */ out << "# " << line << " \""; for ( const char *pc = fileName; *pc != 0; pc++ ) { if ( *pc == '\\' || *pc == '"' ) out << "\\"; out << *pc; } out << "\"\n"; } void OCamlCodeGen::genLineDirective( ostream &out ) { std::streambuf *sbuf = out.rdbuf(); output_filter *filter = static_cast(sbuf); ocamlLineDirective( out, filter->fileName, filter->line + 1 ); } /* Init code gen with in parameters. */ OCamlCodeGen::OCamlCodeGen( ostream &out ) : CodeGenData(out) { } unsigned int OCamlCodeGen::arrayTypeSize( unsigned long maxVal ) { long long maxValLL = (long long) maxVal; HostType *arrayType = keyOps->typeSubsumes( maxValLL ); assert( arrayType != 0 ); return arrayType->size; } string OCamlCodeGen::ARRAY_TYPE( unsigned long maxVal ) { return ARRAY_TYPE( maxVal, false ); } string OCamlCodeGen::ARRAY_TYPE( unsigned long maxVal, bool forceSigned ) { long long maxValLL = (long long) maxVal; HostType *arrayType; if (forceSigned) arrayType = keyOps->typeSubsumes(true, maxValLL); else arrayType = keyOps->typeSubsumes( maxValLL ); assert( arrayType != 0 ); string ret = arrayType->data1; if ( arrayType->data2 != 0 ) { ret += " "; ret += arrayType->data2; } return ret; } /* Write out the fsm name. */ string OCamlCodeGen::FSM_NAME() { return fsmName; } /* Emit the offset of the start state as a decimal integer. */ string OCamlCodeGen::START_STATE_ID() { ostringstream ret; ret << redFsm->startState->id; return ret.str(); }; /* Write out the array of actions. */ std::ostream &OCamlCodeGen::ACTIONS_ARRAY() { out << "\t0; "; int totalActions = 1; for ( GenActionTableMap::Iter act = redFsm->actionMap; act.lte(); act++ ) { /* Write out the length, which will never be the last character. */ out << act->key.length() << ARR_SEP(); /* Put in a line break every 8 */ if ( totalActions++ % 8 == 7 ) out << "\n\t"; for ( GenActionTable::Iter item = act->key; item.lte(); item++ ) { out << item->value->actionId; if ( ! (act.last() && item.last()) ) out << ARR_SEP(); /* Put in a line break every 8 */ if ( totalActions++ % 8 == 7 ) out << "\n\t"; } } out << "\n"; return out; } /* string OCamlCodeGen::ACCESS() { ostringstream ret; if ( accessExpr != 0 ) INLINE_LIST( ret, accessExpr, 0, false ); return ret.str(); } */ string OCamlCodeGen::make_access(char const* name, GenInlineList* x, bool prefix = true) { ostringstream ret; if ( x == 0 ) { if (prefix && accessExpr != 0) { INLINE_LIST( ret, accessExpr, 0, false); ret << name; } else ret << name << ".contents"; // ref cell } else { ret << "("; INLINE_LIST( ret, x, 0, false ); ret << ")"; } return ret.str(); } string OCamlCodeGen::P() { return make_access("p", pExpr, false); } string OCamlCodeGen::PE() { return make_access("pe", peExpr, false); } string OCamlCodeGen::vEOF() { return make_access("eof", eofExpr, false); } string OCamlCodeGen::vCS() { return make_access("cs", csExpr); } string OCamlCodeGen::TOP() { return make_access("top", topExpr); } string OCamlCodeGen::STACK() { return make_access("stack", stackExpr); } string OCamlCodeGen::ACT() { return make_access("act", actExpr); } string OCamlCodeGen::TOKSTART() { return make_access("ts", tokstartExpr); } string OCamlCodeGen::TOKEND() { return make_access("te", tokendExpr); } string OCamlCodeGen::GET_WIDE_KEY() { if ( redFsm->anyConditions() ) return "_widec"; else { ostringstream ret; ret << "Char.code " << GET_KEY(); return ret.str(); } } string OCamlCodeGen::GET_WIDE_KEY( RedStateAp *state ) { if ( state->stateCondList.length() > 0 ) return "_widec"; else { ostringstream ret; ret << "Char.code " << GET_KEY(); return ret.str(); } } /* Write out level number of tabs. Makes the nested binary search nice * looking. */ string OCamlCodeGen::TABS( int level ) { string result; while ( level-- > 0 ) result += "\t"; return result; } /* Write out a key from the fsm code gen. Depends on wether or not the key is * signed. */ string OCamlCodeGen::KEY( Key key ) { ostringstream ret; if ( keyOps->isSigned || !hostLang->explicitUnsigned ) ret << key.getVal(); else ret << (unsigned long) key.getVal() << 'u'; return ret.str(); } string OCamlCodeGen::ALPHA_KEY( Key key ) { ostringstream ret; ret << key.getVal(); /* if (key.getVal() > 0xFFFF) { ret << key.getVal(); } else { ret << "'\\u" << std::hex << std::setw(4) << std::setfill('0') << key.getVal() << "'"; } */ //ret << "(char) " << key.getVal(); return ret.str(); } void OCamlCodeGen::EXEC( ostream &ret, GenInlineItem *item, int targState, int inFinish ) { // The parser gives fexec two children. ret << "begin " << P() << " <- "; INLINE_LIST( ret, item->children, targState, inFinish ); ret << " - 1 end; "; } void OCamlCodeGen::LM_SWITCH( ostream &ret, GenInlineItem *item, int targState, int inFinish ) { bool catch_all = false; ret << " begin match " << ACT() << " with\n"; for ( GenInlineList::Iter lma = *item->children; lma.lte(); lma++ ) { /* Write the case label, the action and the case break. */ if ( lma->lmId < 0 ) { catch_all = true; ret << " | _ ->\n"; } else ret << " | " << lma->lmId << " ->\n"; /* Write the block and close it off. */ ret << " begin "; INLINE_LIST( ret, lma->children, targState, inFinish ); ret << " end\n"; } if (!catch_all) ret << " | _ -> assert false\n"; ret << " end;\n" "\t"; } void OCamlCodeGen::SET_ACT( ostream &ret, GenInlineItem *item ) { ret << ACT() << " <- " << item->lmId << "; "; } void OCamlCodeGen::SET_TOKEND( ostream &ret, GenInlineItem *item ) { /* The tokend action sets tokend. */ ret << TOKEND() << " <- " << P(); if ( item->offset != 0 ) out << "+" << item->offset; out << "; "; } void OCamlCodeGen::GET_TOKEND( ostream &ret, GenInlineItem *item ) { ret << TOKEND(); } void OCamlCodeGen::INIT_TOKSTART( ostream &ret, GenInlineItem *item ) { ret << TOKSTART() << " <- " << NULL_ITEM() << "; "; } void OCamlCodeGen::INIT_ACT( ostream &ret, GenInlineItem *item ) { ret << ACT() << " <- 0;"; } void OCamlCodeGen::SET_TOKSTART( ostream &ret, GenInlineItem *item ) { ret << TOKSTART() << " <- " << P() << "; "; } void OCamlCodeGen::SUB_ACTION( ostream &ret, GenInlineItem *item, int targState, bool inFinish ) { if ( item->children->length() > 0 ) { /* Write the block and close it off. */ ret << "begin "; INLINE_LIST( ret, item->children, targState, inFinish ); ret << " end"; } } /* Write out an inline tree structure. Walks the list and possibly calls out * to virtual functions than handle language specific items in the tree. */ void OCamlCodeGen::INLINE_LIST( ostream &ret, GenInlineList *inlineList, int targState, bool inFinish ) { for ( GenInlineList::Iter item = *inlineList; item.lte(); item++ ) { switch ( item->type ) { case GenInlineItem::Text: ret << item->data; break; case GenInlineItem::Goto: GOTO( ret, item->targState->id, inFinish ); break; case GenInlineItem::Call: CALL( ret, item->targState->id, targState, inFinish ); break; case GenInlineItem::Next: NEXT( ret, item->targState->id, inFinish ); break; case GenInlineItem::Ret: RET( ret, inFinish ); break; case GenInlineItem::PChar: ret << P(); break; case GenInlineItem::Char: ret << GET_KEY(); break; case GenInlineItem::Hold: ret << P() << " <- " << P() << " - 1; "; break; case GenInlineItem::Exec: EXEC( ret, item, targState, inFinish ); break; case GenInlineItem::Curs: CURS( ret, inFinish ); break; case GenInlineItem::Targs: TARGS( ret, inFinish, targState ); break; case GenInlineItem::Entry: ret << item->targState->id; break; case GenInlineItem::GotoExpr: GOTO_EXPR( ret, item, inFinish ); break; case GenInlineItem::CallExpr: CALL_EXPR( ret, item, targState, inFinish ); break; case GenInlineItem::NextExpr: NEXT_EXPR( ret, item, inFinish ); break; case GenInlineItem::LmSwitch: LM_SWITCH( ret, item, targState, inFinish ); break; case GenInlineItem::LmSetActId: SET_ACT( ret, item ); break; case GenInlineItem::LmSetTokEnd: SET_TOKEND( ret, item ); break; case GenInlineItem::LmGetTokEnd: GET_TOKEND( ret, item ); break; case GenInlineItem::LmInitTokStart: INIT_TOKSTART( ret, item ); break; case GenInlineItem::LmInitAct: INIT_ACT( ret, item ); break; case GenInlineItem::LmSetTokStart: SET_TOKSTART( ret, item ); break; case GenInlineItem::SubAction: SUB_ACTION( ret, item, targState, inFinish ); break; case GenInlineItem::Break: BREAK( ret, targState ); break; } } } /* Write out paths in line directives. Escapes any special characters. */ string OCamlCodeGen::LDIR_PATH( char *path ) { ostringstream ret; for ( char *pc = path; *pc != 0; pc++ ) { if ( *pc == '\\' ) ret << "\\\\"; else ret << *pc; } return ret.str(); } void OCamlCodeGen::ACTION( ostream &ret, GenAction *action, int targState, bool inFinish ) { /* Write the preprocessor line info for going into the source file. */ ocamlLineDirective( ret, action->loc.fileName, action->loc.line ); /* Write the block and close it off. */ ret << "\t\tbegin "; INLINE_LIST( ret, action->inlineList, targState, inFinish ); ret << " end;\n"; } void OCamlCodeGen::CONDITION( ostream &ret, GenAction *condition ) { ret << "\n"; ocamlLineDirective( ret, condition->loc.fileName, condition->loc.line ); INLINE_LIST( ret, condition->inlineList, 0, false ); } string OCamlCodeGen::ERROR_STATE() { ostringstream ret; if ( redFsm->errState != 0 ) ret << redFsm->errState->id; else ret << "-1"; return ret.str(); } string OCamlCodeGen::FIRST_FINAL_STATE() { ostringstream ret; if ( redFsm->firstFinState != 0 ) ret << redFsm->firstFinState->id; else ret << redFsm->nextStateId; return ret.str(); } void OCamlCodeGen::writeInit() { out << " begin\n"; if ( !noCS ) out << "\t" << vCS() << " <- " << START() << ";\n"; /* If there are any calls, then the stack top needs initialization. */ if ( redFsm->anyActionCalls() || redFsm->anyActionRets() ) out << "\t" << TOP() << " <- 0;\n"; if ( hasLongestMatch ) { out << " " << TOKSTART() << " <- " << NULL_ITEM() << ";\n" " " << TOKEND() << " <- " << NULL_ITEM() << ";\n" " " << ACT() << " <- 0;\n"; } out << " end;\n"; } string OCamlCodeGen::PRE_INCR(string val) { ostringstream ret; ret << "(" << val << " <- " << val << " + 1; " << val << ")"; return ret.str(); } string OCamlCodeGen::POST_INCR(string val) { ostringstream ret; ret << "(let temp = " << val << " in " << val << " <- " << val << " + 1; temp)"; return ret.str(); } string OCamlCodeGen::PRE_DECR(string val) { ostringstream ret; ret << "(" << val << " <- " << val << " - 1; " << val << ")"; return ret.str(); } string OCamlCodeGen::POST_DECR(string val) { ostringstream ret; ret << "(let temp = " << val << " in " << val << " <- " << val << " - 1; temp)"; return ret.str(); } string OCamlCodeGen::DATA_PREFIX() { if ( data_prefix.empty() ) // init { data_prefix = string(fsmName) + "_"; if (data_prefix.size() > 0) data_prefix[0] = ::tolower(data_prefix[0]); // uncapitalize } if ( !noPrefix ) return data_prefix; return ""; } /* Emit the alphabet data type. */ string OCamlCodeGen::ALPH_TYPE() { string ret = keyOps->alphType->data1; if ( keyOps->alphType->data2 != 0 ) { ret += " "; ret += + keyOps->alphType->data2; } return ret; } /* Emit the alphabet data type. */ string OCamlCodeGen::WIDE_ALPH_TYPE() { string ret; if ( redFsm->maxKey <= keyOps->maxKey ) ret = ALPH_TYPE(); else { long long maxKeyVal = redFsm->maxKey.getLongLong(); HostType *wideType = keyOps->typeSubsumes( keyOps->isSigned, maxKeyVal ); assert( wideType != 0 ); ret = wideType->data1; if ( wideType->data2 != 0 ) { ret += " "; ret += wideType->data2; } } return ret; } void OCamlCodeGen::STATE_IDS() { if ( redFsm->startState != 0 ) STATIC_VAR( "int", START() ) << " = " << START_STATE_ID() << TOP_SEP (); if ( !noFinal ) STATIC_VAR( "int" , FIRST_FINAL() ) << " = " << FIRST_FINAL_STATE() << TOP_SEP(); if ( !noError ) STATIC_VAR( "int", ERROR() ) << " = " << ERROR_STATE() << TOP_SEP(); out << "\n"; if ( entryPointNames.length() > 0 ) { for ( EntryNameVect::Iter en = entryPointNames; en.lte(); en++ ) { STATIC_VAR( "int", DATA_PREFIX() + "en_" + *en ) << " = " << entryPointIds[en.pos()] << TOP_SEP(); } out << "\n"; } } void OCamlCodeGen::writeStart() { out << START_STATE_ID(); } void OCamlCodeGen::writeFirstFinal() { out << FIRST_FINAL_STATE(); } void OCamlCodeGen::writeError() { out << ERROR_STATE(); } string OCamlCodeGen::GET_KEY() { ostringstream ret; if ( getKeyExpr != 0 ) { /* Emit the user supplied method of retrieving the key. */ ret << "("; INLINE_LIST( ret, getKeyExpr, 0, false ); ret << ")"; } else { /* Expression for retrieving the key, use simple dereference. */ ret << "data.[" << P() << "]"; } return ret.str(); } string OCamlCodeGen::NULL_ITEM() { return "-1"; } string OCamlCodeGen::POINTER() { // XXX C# has no pointers // multiple items seperated by commas can also be pointer types. return " "; } string OCamlCodeGen::PTR_CONST() { return ""; } std::ostream &OCamlCodeGen::OPEN_ARRAY( string type, string name ) { out << "let " << name << " : " << type << " array = [|" << endl; return out; } std::ostream &OCamlCodeGen::CLOSE_ARRAY() { return out << "|]" << TOP_SEP(); } string OCamlCodeGen::TOP_SEP() { return "\n"; // original syntax } string OCamlCodeGen::ARR_SEP() { return "; "; } string OCamlCodeGen::AT(const string& array, const string& index) { ostringstream ret; ret << array << ".(" << index << ")"; return ret.str(); } std::ostream &OCamlCodeGen::STATIC_VAR( string type, string name ) { out << "let " << name << " : " << type; return out; } string OCamlCodeGen::ARR_OFF( string ptr, string offset ) { // XXX C# can't do pointer arithmetic return "&" + ptr + "[" + offset + "]"; } string OCamlCodeGen::CAST( string type ) { return ""; // return "(" + type + ")"; } string OCamlCodeGen::UINT( ) { return "uint"; } std::ostream &OCamlCodeGen::SWITCH_DEFAULT() { out << " | _ -> ()\n"; return out; } string OCamlCodeGen::CTRL_FLOW() { return "if true then "; } void OCamlCodeGen::finishRagelDef() { if ( codeStyle == GenGoto || codeStyle == GenFGoto || codeStyle == GenIpGoto || codeStyle == GenSplit ) { /* For directly executable machines there is no required state * ordering. Choose a depth-first ordering to increase the * potential for fall-throughs. */ redFsm->depthFirstOrdering(); } else { /* The frontend will do this for us, but it may be a good idea to * force it if the intermediate file is edited. */ redFsm->sortByStateId(); } /* Choose default transitions and the single transition. */ redFsm->chooseDefaultSpan(); /* Maybe do flat expand, otherwise choose single. */ if ( codeStyle == GenFlat || codeStyle == GenFFlat ) redFsm->makeFlat(); else redFsm->chooseSingle(); /* If any errors have occured in the input file then don't write anything. */ if ( gblErrorCount > 0 ) return; if ( codeStyle == GenSplit ) redFsm->partitionFsm( numSplitPartitions ); if ( codeStyle == GenIpGoto || codeStyle == GenSplit ) redFsm->setInTrans(); /* Anlayze Machine will find the final action reference counts, among * other things. We will use these in reporting the usage * of fsm directives in action code. */ analyzeMachine(); /* Determine if we should use indicies. */ calcIndexSize(); } ostream &OCamlCodeGen::source_warning( const InputLoc &loc ) { cerr << sourceFileName << ":" << loc.line << ":" << loc.col << ": warning: "; return cerr; } ostream &OCamlCodeGen::source_error( const InputLoc &loc ) { gblErrorCount += 1; assert( sourceFileName != 0 ); cerr << sourceFileName << ":" << loc.line << ":" << loc.col << ": "; return cerr; } ragel-6.8/ragel/parsedata.cpp0000664000175000017500000012132312106050031013134 00000000000000/* * Copyright 2001-2008 Adrian Thurston */ /* This file is part of Ragel. * * Ragel is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Ragel is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Ragel; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #include #include #include #include "ragel.h" #include "rlparse.h" #include "parsedata.h" #include "parsetree.h" #include "mergesort.h" #include "xmlcodegen.h" #include "version.h" #include "inputdata.h" using namespace std; char mainMachine[] = "main"; void Token::set( const char *str, int len ) { length = len; data = new char[len+1]; memcpy( data, str, len ); data[len] = 0; } void Token::append( const Token &other ) { int newLength = length + other.length; char *newString = new char[newLength+1]; memcpy( newString, data, length ); memcpy( newString + length, other.data, other.length ); newString[newLength] = 0; data = newString; length = newLength; } /* Perform minimization after an operation according * to the command line args. */ void afterOpMinimize( FsmAp *fsm, bool lastInSeq ) { /* Switch on the prefered minimization algorithm. */ if ( minimizeOpt == MinimizeEveryOp || ( minimizeOpt == MinimizeMostOps && lastInSeq ) ) { /* First clean up the graph. FsmAp operations may leave these * lying around. There should be no dead end states. The subtract * intersection operators are the only places where they may be * created and those operators clean them up. */ fsm->removeUnreachableStates(); switch ( minimizeLevel ) { case MinimizeApprox: fsm->minimizeApproximate(); break; case MinimizePartition1: fsm->minimizePartition1(); break; case MinimizePartition2: fsm->minimizePartition2(); break; case MinimizeStable: fsm->minimizeStable(); break; } } } /* Count the transitions in the fsm by walking the state list. */ int countTransitions( FsmAp *fsm ) { int numTrans = 0; StateAp *state = fsm->stateList.head; while ( state != 0 ) { numTrans += state->outList.length(); state = state->next; } return numTrans; } Key makeFsmKeyHex( char *str, const InputLoc &loc, ParseData *pd ) { /* Reset errno so we can check for overflow or underflow. In the event of * an error, sets the return val to the upper or lower bound being tested * against. */ errno = 0; unsigned int size = keyOps->alphType->size; bool unusedBits = size < sizeof(unsigned long); unsigned long ul = strtoul( str, 0, 16 ); if ( errno == ERANGE || ( unusedBits && ul >> (size * 8) ) ) { error(loc) << "literal " << str << " overflows the alphabet type" << endl; ul = 1 << (size * 8); } if ( unusedBits && keyOps->alphType->isSigned && ul >> (size * 8 - 1) ) ul |= ( -1L >> (size*8) ) << (size*8); return Key( (long)ul ); } Key makeFsmKeyDec( char *str, const InputLoc &loc, ParseData *pd ) { /* Convert the number to a decimal. First reset errno so we can check * for overflow or underflow. */ errno = 0; long long minVal = keyOps->alphType->minVal; long long maxVal = keyOps->alphType->maxVal; long long ll = strtoll( str, 0, 10 ); /* Check for underflow. */ if ( ( errno == ERANGE && ll < 0 ) || ll < minVal) { error(loc) << "literal " << str << " underflows the alphabet type" << endl; ll = minVal; } /* Check for overflow. */ else if ( ( errno == ERANGE && ll > 0 ) || ll > maxVal ) { error(loc) << "literal " << str << " overflows the alphabet type" << endl; ll = maxVal; } if ( keyOps->alphType->isSigned ) return Key( (long)ll ); else return Key( (unsigned long)ll ); } /* Make an fsm key in int format (what the fsm graph uses) from an alphabet * number returned by the parser. Validates that the number doesn't overflow * the alphabet type. */ Key makeFsmKeyNum( char *str, const InputLoc &loc, ParseData *pd ) { /* Switch on hex/decimal format. */ if ( str[0] == '0' && str[1] == 'x' ) return makeFsmKeyHex( str, loc, pd ); else return makeFsmKeyDec( str, loc, pd ); } /* Make an fsm int format (what the fsm graph uses) from a single character. * Performs proper conversion depending on signed/unsigned property of the * alphabet. */ Key makeFsmKeyChar( char c, ParseData *pd ) { if ( keyOps->isSigned ) { /* Copy from a char type. */ return Key( c ); } else { /* Copy from an unsigned byte type. */ return Key( (unsigned char)c ); } } /* Make an fsm key array in int format (what the fsm graph uses) from a string * of characters. Performs proper conversion depending on signed/unsigned * property of the alphabet. */ void makeFsmKeyArray( Key *result, char *data, int len, ParseData *pd ) { if ( keyOps->isSigned ) { /* Copy from a char star type. */ char *src = data; for ( int i = 0; i < len; i++ ) result[i] = Key(src[i]); } else { /* Copy from an unsigned byte ptr type. */ unsigned char *src = (unsigned char*) data; for ( int i = 0; i < len; i++ ) result[i] = Key(src[i]); } } /* Like makeFsmKeyArray except the result has only unique keys. They ordering * will be changed. */ void makeFsmUniqueKeyArray( KeySet &result, char *data, int len, bool caseInsensitive, ParseData *pd ) { /* Use a transitions list for getting unique keys. */ if ( keyOps->isSigned ) { /* Copy from a char star type. */ char *src = data; for ( int si = 0; si < len; si++ ) { Key key( src[si] ); result.insert( key ); if ( caseInsensitive ) { if ( key.isLower() ) result.insert( key.toUpper() ); else if ( key.isUpper() ) result.insert( key.toLower() ); } } } else { /* Copy from an unsigned byte ptr type. */ unsigned char *src = (unsigned char*) data; for ( int si = 0; si < len; si++ ) { Key key( src[si] ); result.insert( key ); if ( caseInsensitive ) { if ( key.isLower() ) result.insert( key.toUpper() ); else if ( key.isUpper() ) result.insert( key.toLower() ); } } } } FsmAp *dotFsm( ParseData *pd ) { FsmAp *retFsm = new FsmAp(); retFsm->rangeFsm( keyOps->minKey, keyOps->maxKey ); return retFsm; } FsmAp *dotStarFsm( ParseData *pd ) { FsmAp *retFsm = new FsmAp(); retFsm->rangeStarFsm( keyOps->minKey, keyOps->maxKey ); return retFsm; } /* Make a builtin type. Depends on the signed nature of the alphabet type. */ FsmAp *makeBuiltin( BuiltinMachine builtin, ParseData *pd ) { /* FsmAp created to return. */ FsmAp *retFsm = 0; bool isSigned = keyOps->isSigned; switch ( builtin ) { case BT_Any: { /* All characters. */ retFsm = dotFsm( pd ); break; } case BT_Ascii: { /* Ascii characters 0 to 127. */ retFsm = new FsmAp(); retFsm->rangeFsm( 0, 127 ); break; } case BT_Extend: { /* Ascii extended characters. This is the full byte range. Dependent * on signed, vs no signed. If the alphabet is one byte then just use * dot fsm. */ if ( isSigned ) { retFsm = new FsmAp(); retFsm->rangeFsm( -128, 127 ); } else { retFsm = new FsmAp(); retFsm->rangeFsm( 0, 255 ); } break; } case BT_Alpha: { /* Alpha [A-Za-z]. */ FsmAp *upper = new FsmAp(), *lower = new FsmAp(); upper->rangeFsm( 'A', 'Z' ); lower->rangeFsm( 'a', 'z' ); upper->unionOp( lower ); upper->minimizePartition2(); retFsm = upper; break; } case BT_Digit: { /* Digits [0-9]. */ retFsm = new FsmAp(); retFsm->rangeFsm( '0', '9' ); break; } case BT_Alnum: { /* Alpha numerics [0-9A-Za-z]. */ FsmAp *digit = new FsmAp(), *lower = new FsmAp(); FsmAp *upper = new FsmAp(); digit->rangeFsm( '0', '9' ); upper->rangeFsm( 'A', 'Z' ); lower->rangeFsm( 'a', 'z' ); digit->unionOp( upper ); digit->unionOp( lower ); digit->minimizePartition2(); retFsm = digit; break; } case BT_Lower: { /* Lower case characters. */ retFsm = new FsmAp(); retFsm->rangeFsm( 'a', 'z' ); break; } case BT_Upper: { /* Upper case characters. */ retFsm = new FsmAp(); retFsm->rangeFsm( 'A', 'Z' ); break; } case BT_Cntrl: { /* Control characters. */ FsmAp *cntrl = new FsmAp(); FsmAp *highChar = new FsmAp(); cntrl->rangeFsm( 0, 31 ); highChar->concatFsm( 127 ); cntrl->unionOp( highChar ); cntrl->minimizePartition2(); retFsm = cntrl; break; } case BT_Graph: { /* Graphical ascii characters [!-~]. */ retFsm = new FsmAp(); retFsm->rangeFsm( '!', '~' ); break; } case BT_Print: { /* Printable characters. Same as graph except includes space. */ retFsm = new FsmAp(); retFsm->rangeFsm( ' ', '~' ); break; } case BT_Punct: { /* Punctuation. */ FsmAp *range1 = new FsmAp(); FsmAp *range2 = new FsmAp(); FsmAp *range3 = new FsmAp(); FsmAp *range4 = new FsmAp(); range1->rangeFsm( '!', '/' ); range2->rangeFsm( ':', '@' ); range3->rangeFsm( '[', '`' ); range4->rangeFsm( '{', '~' ); range1->unionOp( range2 ); range1->unionOp( range3 ); range1->unionOp( range4 ); range1->minimizePartition2(); retFsm = range1; break; } case BT_Space: { /* Whitespace: [\t\v\f\n\r ]. */ FsmAp *cntrl = new FsmAp(); FsmAp *space = new FsmAp(); cntrl->rangeFsm( '\t', '\r' ); space->concatFsm( ' ' ); cntrl->unionOp( space ); cntrl->minimizePartition2(); retFsm = cntrl; break; } case BT_Xdigit: { /* Hex digits [0-9A-Fa-f]. */ FsmAp *digit = new FsmAp(); FsmAp *upper = new FsmAp(); FsmAp *lower = new FsmAp(); digit->rangeFsm( '0', '9' ); upper->rangeFsm( 'A', 'F' ); lower->rangeFsm( 'a', 'f' ); digit->unionOp( upper ); digit->unionOp( lower ); digit->minimizePartition2(); retFsm = digit; break; } case BT_Lambda: { retFsm = new FsmAp(); retFsm->lambdaFsm(); break; } case BT_Empty: { retFsm = new FsmAp(); retFsm->emptyFsm(); break; }} return retFsm; } /* Check if this name inst or any name inst below is referenced. */ bool NameInst::anyRefsRec() { if ( numRefs > 0 ) return true; /* Recurse on children until true. */ for ( NameVect::Iter ch = childVect; ch.lte(); ch++ ) { if ( (*ch)->anyRefsRec() ) return true; } return false; } /* * ParseData */ /* Initialize the structure that will collect info during the parse of a * machine. */ ParseData::ParseData( const char *fileName, char *sectionName, const InputLoc §ionLoc ) : sectionGraph(0), generatingSectionSubset(false), nextPriorKey(0), /* 0 is reserved for global error actions. */ nextLocalErrKey(1), nextNameId(0), nextCondId(0), alphTypeSet(false), getKeyExpr(0), accessExpr(0), prePushExpr(0), postPopExpr(0), pExpr(0), peExpr(0), eofExpr(0), csExpr(0), topExpr(0), stackExpr(0), actExpr(0), tokstartExpr(0), tokendExpr(0), dataExpr(0), lowerNum(0), upperNum(0), fileName(fileName), sectionName(sectionName), sectionLoc(sectionLoc), curActionOrd(0), curPriorOrd(0), rootName(0), exportsRootName(0), nextEpsilonResolvedLink(0), nextLongestMatchId(1), lmRequiresErrorState(false), cgd(0) { /* Initialize the dictionary of graphs. This is our symbol table. The * initialization needs to be done on construction which happens at the * beginning of a machine spec so any assignment operators can reference * the builtins. */ initGraphDict(); } /* Clean up the data collected during a parse. */ ParseData::~ParseData() { /* Delete all the nodes in the action list. Will cause all the * string data that represents the actions to be deallocated. */ actionList.empty(); } /* Make a name id in the current name instantiation scope if it is not * already there. */ NameInst *ParseData::addNameInst( const InputLoc &loc, const char *data, bool isLabel ) { /* Create the name instantitaion object and insert it. */ NameInst *newNameInst = new NameInst( loc, curNameInst, data, nextNameId++, isLabel ); curNameInst->childVect.append( newNameInst ); if ( data != 0 ) curNameInst->children.insertMulti( data, newNameInst ); return newNameInst; } void ParseData::initNameWalk() { curNameInst = rootName; curNameChild = 0; } void ParseData::initExportsNameWalk() { curNameInst = exportsRootName; curNameChild = 0; } /* Goes into the next child scope. The number of the child is already set up. * We need this for the syncronous name tree and parse tree walk to work * properly. It is reset on entry into a scope and advanced on poping of a * scope. A call to enterNameScope should be accompanied by a corresponding * popNameScope. */ NameFrame ParseData::enterNameScope( bool isLocal, int numScopes ) { /* Save off the current data. */ NameFrame retFrame; retFrame.prevNameInst = curNameInst; retFrame.prevNameChild = curNameChild; retFrame.prevLocalScope = localNameScope; /* Enter into the new name scope. */ for ( int i = 0; i < numScopes; i++ ) { curNameInst = curNameInst->childVect[curNameChild]; curNameChild = 0; } if ( isLocal ) localNameScope = curNameInst; return retFrame; } /* Return from a child scope to a parent. The parent info must be specified as * an argument and is obtained from the corresponding call to enterNameScope. * */ void ParseData::popNameScope( const NameFrame &frame ) { /* Pop the name scope. */ curNameInst = frame.prevNameInst; curNameChild = frame.prevNameChild+1; localNameScope = frame.prevLocalScope; } void ParseData::resetNameScope( const NameFrame &frame ) { /* Pop the name scope. */ curNameInst = frame.prevNameInst; curNameChild = frame.prevNameChild; localNameScope = frame.prevLocalScope; } void ParseData::unsetObsoleteEntries( FsmAp *graph ) { /* Loop the reference names and increment the usage. Names that are no * longer needed will be unset in graph. */ for ( NameVect::Iter ref = curNameInst->referencedNames; ref.lte(); ref++ ) { /* Get the name. */ NameInst *name = *ref; name->numUses += 1; /* If the name is no longer needed unset its corresponding entry. */ if ( name->numUses == name->numRefs ) { assert( graph->entryPoints.find( name->id ) != 0 ); graph->unsetEntry( name->id ); assert( graph->entryPoints.find( name->id ) == 0 ); } } } NameSet ParseData::resolvePart( NameInst *refFrom, const char *data, bool recLabelsOnly ) { /* Queue needed for breadth-first search, load it with the start node. */ NameInstList nameQueue; nameQueue.append( refFrom ); NameSet result; while ( nameQueue.length() > 0 ) { /* Pull the next from location off the queue. */ NameInst *from = nameQueue.detachFirst(); /* Look for the name. */ NameMapEl *low, *high; if ( from->children.findMulti( data, low, high ) ) { /* Record all instances of the name. */ for ( ; low <= high; low++ ) result.insert( low->value ); } /* Name not there, do breadth-first operation of appending all * childrent to the processing queue. */ for ( NameVect::Iter name = from->childVect; name.lte(); name++ ) { if ( !recLabelsOnly || (*name)->isLabel ) nameQueue.append( *name ); } } /* Queue exhausted and name never found. */ return result; } void ParseData::resolveFrom( NameSet &result, NameInst *refFrom, const NameRef &nameRef, int namePos ) { /* Look for the name in the owning scope of the factor with aug. */ NameSet partResult = resolvePart( refFrom, nameRef[namePos], false ); /* If there are more parts to the name then continue on. */ if ( ++namePos < nameRef.length() ) { /* There are more components to the name, search using all the part * results as the base. */ for ( NameSet::Iter name = partResult; name.lte(); name++ ) resolveFrom( result, *name, nameRef, namePos ); } else { /* This is the last component, append the part results to the final * results. */ result.insert( partResult ); } } /* Write out a name reference. */ ostream &operator<<( ostream &out, const NameRef &nameRef ) { int pos = 0; if ( nameRef[pos] == 0 ) { out << "::"; pos += 1; } out << nameRef[pos++]; for ( ; pos < nameRef.length(); pos++ ) out << "::" << nameRef[pos]; return out; } ostream &operator<<( ostream &out, const NameInst &nameInst ) { /* Count the number fully qualified name parts. */ int numParents = 0; NameInst *curParent = nameInst.parent; while ( curParent != 0 ) { numParents += 1; curParent = curParent->parent; } /* Make an array and fill it in. */ curParent = nameInst.parent; NameInst **parents = new NameInst*[numParents]; for ( int p = numParents-1; p >= 0; p-- ) { parents[p] = curParent; curParent = curParent->parent; } /* Write the parents out, skip the root. */ for ( int p = 1; p < numParents; p++ ) out << "::" << ( parents[p]->name != 0 ? parents[p]->name : "" ); /* Write the name and cleanup. */ out << "::" << ( nameInst.name != 0 ? nameInst.name : "" ); delete[] parents; return out; } struct CmpNameInstLoc { static int compare( const NameInst *ni1, const NameInst *ni2 ) { if ( ni1->loc.line < ni2->loc.line ) return -1; else if ( ni1->loc.line > ni2->loc.line ) return 1; else if ( ni1->loc.col < ni2->loc.col ) return -1; else if ( ni1->loc.col > ni2->loc.col ) return 1; return 0; } }; void errorStateLabels( const NameSet &resolved ) { MergeSort mergeSort; mergeSort.sort( resolved.data, resolved.length() ); for ( NameSet::Iter res = resolved; res.lte(); res++ ) error((*res)->loc) << " -> " << **res << endl; } NameInst *ParseData::resolveStateRef( const NameRef &nameRef, InputLoc &loc, Action *action ) { NameInst *nameInst = 0; /* Do the local search if the name is not strictly a root level name * search. */ if ( nameRef[0] != 0 ) { /* If the action is referenced, resolve all of them. */ if ( action != 0 && action->actionRefs.length() > 0 ) { /* Look for the name in all referencing scopes. */ NameSet resolved; for ( ActionRefs::Iter actRef = action->actionRefs; actRef.lte(); actRef++ ) resolveFrom( resolved, *actRef, nameRef, 0 ); if ( resolved.length() > 0 ) { /* Take the first one. */ nameInst = resolved[0]; if ( resolved.length() > 1 ) { /* Complain about the multiple references. */ error(loc) << "state reference " << nameRef << " resolves to multiple entry points" << endl; errorStateLabels( resolved ); } } } } /* If not found in the local scope, look in global. */ if ( nameInst == 0 ) { NameSet resolved; int fromPos = nameRef[0] != 0 ? 0 : 1; resolveFrom( resolved, rootName, nameRef, fromPos ); if ( resolved.length() > 0 ) { /* Take the first. */ nameInst = resolved[0]; if ( resolved.length() > 1 ) { /* Complain about the multiple references. */ error(loc) << "state reference " << nameRef << " resolves to multiple entry points" << endl; errorStateLabels( resolved ); } } } if ( nameInst == 0 ) { /* If not found then complain. */ error(loc) << "could not resolve state reference " << nameRef << endl; } return nameInst; } void ParseData::resolveNameRefs( InlineList *inlineList, Action *action ) { for ( InlineList::Iter item = *inlineList; item.lte(); item++ ) { switch ( item->type ) { case InlineItem::Entry: case InlineItem::Goto: case InlineItem::Call: case InlineItem::Next: { /* Resolve, pass action for local search. */ NameInst *target = resolveStateRef( *item->nameRef, item->loc, action ); /* Name lookup error reporting is handled by resolveStateRef. */ if ( target != 0 ) { /* Check if the target goes into a longest match. */ NameInst *search = target->parent; while ( search != 0 ) { if ( search->isLongestMatch ) { error(item->loc) << "cannot enter inside a longest " "match construction as an entry point" << endl; break; } search = search->parent; } /* Record the reference in the name. This will cause the * entry point to survive to the end of the graph * generating walk. */ target->numRefs += 1; } item->nameTarg = target; break; } default: break; } /* Some of the item types may have children. */ if ( item->children != 0 ) resolveNameRefs( item->children, action ); } } /* Resolve references to labels in actions. */ void ParseData::resolveActionNameRefs() { for ( ActionList::Iter act = actionList; act.lte(); act++ ) { /* Only care about the actions that are referenced. */ if ( act->actionRefs.length() > 0 ) resolveNameRefs( act->inlineList, act ); } } /* Walk a name tree starting at from and fill the name index. */ void ParseData::fillNameIndex( NameInst *from ) { /* Fill the value for from in the name index. */ nameIndex[from->id] = from; /* Recurse on the implicit final state and then all children. */ if ( from->final != 0 ) fillNameIndex( from->final ); for ( NameVect::Iter name = from->childVect; name.lte(); name++ ) fillNameIndex( *name ); } void ParseData::makeRootNames() { /* Create the root name. */ rootName = new NameInst( InputLoc(), 0, 0, nextNameId++, false ); exportsRootName = new NameInst( InputLoc(), 0, 0, nextNameId++, false ); } /* Build the name tree and supporting data structures. */ void ParseData::makeNameTree( GraphDictEl *dictEl ) { /* Set up curNameInst for the walk. */ initNameWalk(); if ( dictEl != 0 ) { /* A start location has been specified. */ dictEl->value->makeNameTree( dictEl->loc, this ); } else { /* First make the name tree. */ for ( GraphList::Iter glel = instanceList; glel.lte(); glel++ ) { /* Recurse on the instance. */ glel->value->makeNameTree( glel->loc, this ); } } /* The number of nodes in the tree can now be given by nextNameId */ nameIndex = new NameInst*[nextNameId]; memset( nameIndex, 0, sizeof(NameInst*)*nextNameId ); fillNameIndex( rootName ); fillNameIndex( exportsRootName ); } void ParseData::createBuiltin( const char *name, BuiltinMachine builtin ) { Expression *expression = new Expression( builtin ); Join *join = new Join( expression ); MachineDef *machineDef = new MachineDef( join ); VarDef *varDef = new VarDef( name, machineDef ); GraphDictEl *graphDictEl = new GraphDictEl( name, varDef ); graphDict.insert( graphDictEl ); } /* Initialize the graph dict with builtin types. */ void ParseData::initGraphDict( ) { createBuiltin( "any", BT_Any ); createBuiltin( "ascii", BT_Ascii ); createBuiltin( "extend", BT_Extend ); createBuiltin( "alpha", BT_Alpha ); createBuiltin( "digit", BT_Digit ); createBuiltin( "alnum", BT_Alnum ); createBuiltin( "lower", BT_Lower ); createBuiltin( "upper", BT_Upper ); createBuiltin( "cntrl", BT_Cntrl ); createBuiltin( "graph", BT_Graph ); createBuiltin( "print", BT_Print ); createBuiltin( "punct", BT_Punct ); createBuiltin( "space", BT_Space ); createBuiltin( "xdigit", BT_Xdigit ); createBuiltin( "null", BT_Lambda ); createBuiltin( "zlen", BT_Lambda ); createBuiltin( "empty", BT_Empty ); } /* Set the alphabet type. If the types are not valid returns false. */ bool ParseData::setAlphType( const InputLoc &loc, char *s1, char *s2 ) { alphTypeLoc = loc; userAlphType = findAlphType( s1, s2 ); alphTypeSet = true; return userAlphType != 0; } /* Set the alphabet type. If the types are not valid returns false. */ bool ParseData::setAlphType( const InputLoc &loc, char *s1 ) { alphTypeLoc = loc; userAlphType = findAlphType( s1 ); alphTypeSet = true; return userAlphType != 0; } bool ParseData::setVariable( char *var, InlineList *inlineList ) { bool set = true; if ( strcmp( var, "p" ) == 0 ) pExpr = inlineList; else if ( strcmp( var, "pe" ) == 0 ) peExpr = inlineList; else if ( strcmp( var, "eof" ) == 0 ) eofExpr = inlineList; else if ( strcmp( var, "cs" ) == 0 ) csExpr = inlineList; else if ( strcmp( var, "data" ) == 0 ) dataExpr = inlineList; else if ( strcmp( var, "top" ) == 0 ) topExpr = inlineList; else if ( strcmp( var, "stack" ) == 0 ) stackExpr = inlineList; else if ( strcmp( var, "act" ) == 0 ) actExpr = inlineList; else if ( strcmp( var, "ts" ) == 0 ) tokstartExpr = inlineList; else if ( strcmp( var, "te" ) == 0 ) tokendExpr = inlineList; else set = false; return set; } /* Initialize the key operators object that will be referenced by all fsms * created. */ void ParseData::initKeyOps( ) { /* Signedness and bounds. */ HostType *alphType = alphTypeSet ? userAlphType : hostLang->defaultAlphType; thisKeyOps.setAlphType( alphType ); if ( lowerNum != 0 ) { /* If ranges are given then interpret the alphabet type. */ thisKeyOps.minKey = makeFsmKeyNum( lowerNum, rangeLowLoc, this ); thisKeyOps.maxKey = makeFsmKeyNum( upperNum, rangeHighLoc, this ); } thisCondData.lastCondKey = thisKeyOps.maxKey; } void ParseData::printNameInst( NameInst *nameInst, int level ) { for ( int i = 0; i < level; i++ ) cerr << " "; cerr << (nameInst->name != 0 ? nameInst->name : "") << " id: " << nameInst->id << " refs: " << nameInst->numRefs << " uses: " << nameInst->numUses << endl; for ( NameVect::Iter name = nameInst->childVect; name.lte(); name++ ) printNameInst( *name, level+1 ); } /* Remove duplicates of unique actions from an action table. */ void ParseData::removeDups( ActionTable &table ) { /* Scan through the table looking for unique actions to * remove duplicates of. */ for ( int i = 0; i < table.length(); i++ ) { /* Remove any duplicates ahead of i. */ for ( int r = i+1; r < table.length(); ) { if ( table[r].value == table[i].value ) table.vremove(r); else r += 1; } } } /* Remove duplicates from action lists. This operates only on transition and * eof action lists and so should be called once all actions have been * transfered to their final resting place. */ void ParseData::removeActionDups( FsmAp *graph ) { /* Loop all states. */ for ( StateList::Iter state = graph->stateList; state.lte(); state++ ) { /* Loop all transitions. */ for ( TransList::Iter trans = state->outList; trans.lte(); trans++ ) removeDups( trans->actionTable ); removeDups( state->toStateActionTable ); removeDups( state->fromStateActionTable ); removeDups( state->eofActionTable ); } } Action *ParseData::newAction( const char *name, InlineList *inlineList ) { InputLoc loc; loc.line = 1; loc.col = 1; loc.fileName = "NONE"; Action *action = new Action( loc, name, inlineList, nextCondId++ ); action->actionRefs.append( rootName ); actionList.append( action ); return action; } void ParseData::initLongestMatchData() { if ( lmList.length() > 0 ) { /* The initTokStart action resets the token start. */ InlineList *il1 = new InlineList; il1->append( new InlineItem( InputLoc(), InlineItem::LmInitTokStart ) ); initTokStart = newAction( "initts", il1 ); initTokStart->isLmAction = true; /* The initActId action gives act a default value. */ InlineList *il4 = new InlineList; il4->append( new InlineItem( InputLoc(), InlineItem::LmInitAct ) ); initActId = newAction( "initact", il4 ); initActId->isLmAction = true; /* The setTokStart action sets tokstart. */ InlineList *il5 = new InlineList; il5->append( new InlineItem( InputLoc(), InlineItem::LmSetTokStart ) ); setTokStart = newAction( "ts", il5 ); setTokStart->isLmAction = true; /* The setTokEnd action sets tokend. */ InlineList *il3 = new InlineList; il3->append( new InlineItem( InputLoc(), InlineItem::LmSetTokEnd ) ); setTokEnd = newAction( "te", il3 ); setTokEnd->isLmAction = true; /* The action will also need an ordering: ahead of all user action * embeddings. */ initTokStartOrd = curActionOrd++; initActIdOrd = curActionOrd++; setTokStartOrd = curActionOrd++; setTokEndOrd = curActionOrd++; } } /* After building the graph, do some extra processing to ensure the runtime * data of the longest mactch operators is consistent. */ void ParseData::setLongestMatchData( FsmAp *graph ) { if ( lmList.length() > 0 ) { /* Make sure all entry points (targets of fgoto, fcall, fnext, fentry) * init the tokstart. */ for ( EntryMap::Iter en = graph->entryPoints; en.lte(); en++ ) { /* This is run after duplicates are removed, we must guard against * inserting a duplicate. */ ActionTable &actionTable = en->value->toStateActionTable; if ( ! actionTable.hasAction( initTokStart ) ) actionTable.setAction( initTokStartOrd, initTokStart ); } /* Find the set of states that are the target of transitions with * actions that have calls. These states will be targeted by fret * statements. */ StateSet states; for ( StateList::Iter state = graph->stateList; state.lte(); state++ ) { for ( TransList::Iter trans = state->outList; trans.lte(); trans++ ) { for ( ActionTable::Iter ati = trans->actionTable; ati.lte(); ati++ ) { if ( ati->value->anyCall && trans->toState != 0 ) states.insert( trans->toState ); } } } /* Init tokstart upon entering the above collected states. */ for ( StateSet::Iter ps = states; ps.lte(); ps++ ) { /* This is run after duplicates are removed, we must guard against * inserting a duplicate. */ ActionTable &actionTable = (*ps)->toStateActionTable; if ( ! actionTable.hasAction( initTokStart ) ) actionTable.setAction( initTokStartOrd, initTokStart ); } } } /* Make the graph from a graph dict node. Does minimization and state sorting. */ FsmAp *ParseData::makeInstance( GraphDictEl *gdNode ) { /* Build the graph from a walk of the parse tree. */ FsmAp *graph = gdNode->value->walk( this ); /* Resolve any labels that point to multiple states. Any labels that are * still around are referenced only by gotos and calls and they need to be * made into deterministic entry points. */ graph->deterministicEntry(); /* * All state construction is now complete. */ /* Transfer actions from the out action tables to eof action tables. */ for ( StateSet::Iter state = graph->finStateSet; state.lte(); state++ ) graph->transferOutActions( *state ); /* Transfer global error actions. */ for ( StateList::Iter state = graph->stateList; state.lte(); state++ ) graph->transferErrorActions( state, 0 ); if ( ::wantDupsRemoved ) removeActionDups( graph ); /* Remove unreachable states. There should be no dead end states. The * subtract and intersection operators are the only places where they may * be created and those operators clean them up. */ graph->removeUnreachableStates(); /* No more fsm operations are to be done. Action ordering numbers are * no longer of use and will just hinder minimization. Clear them. */ graph->nullActionKeys(); /* Transition priorities are no longer of use. We can clear them * because they will just hinder minimization as well. Clear them. */ graph->clearAllPriorities(); if ( minimizeOpt != MinimizeNone ) { /* Minimize here even if we minimized at every op. Now that function * keys have been cleared we may get a more minimal fsm. */ switch ( minimizeLevel ) { case MinimizeApprox: graph->minimizeApproximate(); break; case MinimizeStable: graph->minimizeStable(); break; case MinimizePartition1: graph->minimizePartition1(); break; case MinimizePartition2: graph->minimizePartition2(); break; } } graph->compressTransitions(); return graph; } void ParseData::printNameTree() { /* Print the name instance map. */ for ( NameVect::Iter name = rootName->childVect; name.lte(); name++ ) printNameInst( *name, 0 ); cerr << "name index:" << endl; /* Show that the name index is correct. */ for ( int ni = 0; ni < nextNameId; ni++ ) { cerr << ni << ": "; const char *name = nameIndex[ni]->name; cerr << ( name != 0 ? name : "" ) << endl; } } FsmAp *ParseData::makeSpecific( GraphDictEl *gdNode ) { /* Build the name tree and supporting data structures. */ makeNameTree( gdNode ); /* Resove name references from gdNode. */ initNameWalk(); gdNode->value->resolveNameRefs( this ); /* Do not resolve action references. Since we are not building the entire * graph there's a good chance that many name references will fail. This * is okay since generating part of the graph is usually only done when * inspecting the compiled machine. */ /* Same story for extern entry point references. */ /* Flag this case so that the XML code generator is aware that we haven't * looked up name references in actions. It can then avoid segfaulting. */ generatingSectionSubset = true; /* Just building the specified graph. */ initNameWalk(); FsmAp *mainGraph = makeInstance( gdNode ); return mainGraph; } FsmAp *ParseData::makeAll() { /* Build the name tree and supporting data structures. */ makeNameTree( 0 ); /* Resove name references in the tree. */ initNameWalk(); for ( GraphList::Iter glel = instanceList; glel.lte(); glel++ ) glel->value->resolveNameRefs( this ); /* Resolve action code name references. */ resolveActionNameRefs(); /* Force name references to the top level instantiations. */ for ( NameVect::Iter inst = rootName->childVect; inst.lte(); inst++ ) (*inst)->numRefs += 1; FsmAp *mainGraph = 0; FsmAp **graphs = new FsmAp*[instanceList.length()]; int numOthers = 0; /* Make all the instantiations, we know that main exists in this list. */ initNameWalk(); for ( GraphList::Iter glel = instanceList; glel.lte(); glel++ ) { if ( strcmp( glel->key, mainMachine ) == 0 ) { /* Main graph is always instantiated. */ mainGraph = makeInstance( glel ); } else { /* Instantiate and store in others array. */ graphs[numOthers++] = makeInstance( glel ); } } if ( mainGraph == 0 ) mainGraph = graphs[--numOthers]; if ( numOthers > 0 ) { /* Add all the other graphs into main. */ mainGraph->globOp( graphs, numOthers ); } delete[] graphs; return mainGraph; } void ParseData::analyzeAction( Action *action, InlineList *inlineList ) { /* FIXME: Actions used as conditions should be very constrained. */ for ( InlineList::Iter item = *inlineList; item.lte(); item++ ) { if ( item->type == InlineItem::Call || item->type == InlineItem::CallExpr ) action->anyCall = true; /* Need to recurse into longest match items. */ if ( item->type == InlineItem::LmSwitch ) { LongestMatch *lm = item->longestMatch; for ( LmPartList::Iter lmi = *lm->longestMatchList; lmi.lte(); lmi++ ) { if ( lmi->action != 0 ) analyzeAction( action, lmi->action->inlineList ); } } if ( item->type == InlineItem::LmOnLast || item->type == InlineItem::LmOnNext || item->type == InlineItem::LmOnLagBehind ) { LongestMatchPart *lmi = item->longestMatchPart; if ( lmi->action != 0 ) analyzeAction( action, lmi->action->inlineList ); } if ( item->children != 0 ) analyzeAction( action, item->children ); } } /* Check actions for bad uses of fsm directives. We don't go inside longest * match items in actions created by ragel, since we just want the user * actions. */ void ParseData::checkInlineList( Action *act, InlineList *inlineList ) { for ( InlineList::Iter item = *inlineList; item.lte(); item++ ) { /* EOF checks. */ if ( act->numEofRefs > 0 ) { switch ( item->type ) { /* Currently no checks. */ default: break; } } /* Recurse. */ if ( item->children != 0 ) checkInlineList( act, item->children ); } } void ParseData::checkAction( Action *action ) { /* Check for actions with calls that are embedded within a longest match * machine. */ if ( !action->isLmAction && action->numRefs() > 0 && action->anyCall ) { for ( ActionRefs::Iter ar = action->actionRefs; ar.lte(); ar++ ) { NameInst *check = *ar; while ( check != 0 ) { if ( check->isLongestMatch ) { error(action->loc) << "within a scanner, fcall is permitted" " only in pattern actions" << endl; break; } check = check->parent; } } } checkInlineList( action, action->inlineList ); } void ParseData::analyzeGraph( FsmAp *graph ) { for ( ActionList::Iter act = actionList; act.lte(); act++ ) analyzeAction( act, act->inlineList ); for ( StateList::Iter st = graph->stateList; st.lte(); st++ ) { /* The transition list. */ for ( TransList::Iter trans = st->outList; trans.lte(); trans++ ) { for ( ActionTable::Iter at = trans->actionTable; at.lte(); at++ ) at->value->numTransRefs += 1; } for ( ActionTable::Iter at = st->toStateActionTable; at.lte(); at++ ) at->value->numToStateRefs += 1; for ( ActionTable::Iter at = st->fromStateActionTable; at.lte(); at++ ) at->value->numFromStateRefs += 1; for ( ActionTable::Iter at = st->eofActionTable; at.lte(); at++ ) at->value->numEofRefs += 1; for ( StateCondList::Iter sc = st->stateCondList; sc.lte(); sc++ ) { for ( CondSet::Iter sci = sc->condSpace->condSet; sci.lte(); sci++ ) (*sci)->numCondRefs += 1; } } /* Checks for bad usage of directives in action code. */ for ( ActionList::Iter act = actionList; act.lte(); act++ ) checkAction( act ); } void ParseData::makeExportsNameTree() { /* Make a name tree for the exports. */ initExportsNameWalk(); /* First make the name tree. */ for ( GraphDict::Iter gdel = graphDict; gdel.lte(); gdel++ ) { if ( gdel->value->isExport ) { /* Recurse on the instance. */ gdel->value->makeNameTree( gdel->loc, this ); } } } void ParseData::makeExports() { makeExportsNameTree(); /* Resove name references in the tree. */ initExportsNameWalk(); for ( GraphDict::Iter gdel = graphDict; gdel.lte(); gdel++ ) { if ( gdel->value->isExport ) gdel->value->resolveNameRefs( this ); } /* Make all the instantiations, we know that main exists in this list. */ initExportsNameWalk(); for ( GraphDict::Iter gdel = graphDict; gdel.lte(); gdel++ ) { /* Check if this var def is an export. */ if ( gdel->value->isExport ) { /* Build the graph from a walk of the parse tree. */ FsmAp *graph = gdel->value->walk( this ); /* Build the graph from a walk of the parse tree. */ if ( !graph->checkSingleCharMachine() ) { error(gdel->loc) << "bad export machine, must define " "a single character" << endl; } else { /* Safe to extract the key and declare the export. */ Key exportKey = graph->startState->outList.head->lowKey; exportList.append( new Export( gdel->value->name, exportKey ) ); } } } } /* Construct the machine and catch failures which can occur during * construction. */ void ParseData::prepareMachineGen( GraphDictEl *graphDictEl ) { try { /* This machine construction can fail. */ prepareMachineGenTBWrapped( graphDictEl ); } catch ( FsmConstructFail fail ) { switch ( fail.reason ) { case FsmConstructFail::CondNoKeySpace: { InputLoc &loc = alphTypeSet ? alphTypeLoc : sectionLoc; error(loc) << "sorry, no more characters are " "available in the alphabet space" << endl; error(loc) << " for conditions, please use a " "smaller alphtype or reduce" << endl; error(loc) << " the span of characters on which " "conditions are embedded" << endl; break; } } } } void ParseData::prepareMachineGenTBWrapped( GraphDictEl *graphDictEl ) { beginProcessing(); initKeyOps(); makeRootNames(); initLongestMatchData(); /* Make the graph, do minimization. */ if ( graphDictEl == 0 ) sectionGraph = makeAll(); else sectionGraph = makeSpecific( graphDictEl ); /* Compute exports from the export definitions. */ makeExports(); /* If any errors have occured in the input file then don't write anything. */ if ( gblErrorCount > 0 ) return; analyzeGraph( sectionGraph ); /* Depends on the graph analysis. */ setLongestMatchData( sectionGraph ); /* Decide if an error state is necessary. * 1. There is an error transition * 2. There is a gap in the transitions * 3. The longest match operator requires it. */ if ( lmRequiresErrorState || sectionGraph->hasErrorTrans() ) sectionGraph->errState = sectionGraph->addState(); /* State numbers need to be assigned such that all final states have a * larger state id number than all non-final states. This enables the * first_final mechanism to function correctly. We also want states to be * ordered in a predictable fashion. So we first apply a depth-first * search, then do a stable sort by final state status, then assign * numbers. */ sectionGraph->depthFirstOrdering(); sectionGraph->sortStatesByFinal(); sectionGraph->setStateNumbers( 0 ); } void ParseData::generateReduced( InputData &inputData ) { beginProcessing(); cgd = makeCodeGen( inputData.inputFileName, sectionName, *inputData.outStream ); /* Make the generator. */ BackendGen backendGen( sectionName, this, sectionGraph, cgd ); /* Write out with it. */ backendGen.makeBackend(); if ( printStatistics ) { cerr << "fsm name : " << sectionName << endl; cerr << "num states: " << sectionGraph->stateList.length() << endl; cerr << endl; } } void ParseData::generateXML( ostream &out ) { beginProcessing(); /* Make the generator. */ XMLCodeGen codeGen( sectionName, this, sectionGraph, out ); /* Write out with it. */ codeGen.writeXML(); if ( printStatistics ) { cerr << "fsm name : " << sectionName << endl; cerr << "num states: " << sectionGraph->stateList.length() << endl; cerr << endl; } } ragel-6.8/ragel/csfgoto.cpp0000664000175000017500000001547212106050031012643 00000000000000/* * Copyright 2001-2006 Adrian Thurston * 2004 Erich Ocean * 2005 Alan West */ /* This file is part of Ragel. * * Ragel is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Ragel is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Ragel; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "ragel.h" #include "csfgoto.h" #include "redfsm.h" #include "gendata.h" #include "bstmap.h" std::ostream &CSharpFGotoCodeGen::EXEC_ACTIONS() { /* Loop the actions. */ for ( GenActionTableMap::Iter redAct = redFsm->actionMap; redAct.lte(); redAct++ ) { if ( redAct->numTransRefs > 0 ) { /* We are at the start of a glob, write the case. */ out << "f" << redAct->actListId << ":\n"; /* Write each action in the list of action items. */ for ( GenActionTable::Iter item = redAct->key; item.lte(); item++ ) ACTION( out, item->value, 0, false ); out << "\tgoto _again;\n"; } } return out; } /* Write out the function switch. This switch is keyed on the values * of the func index. */ std::ostream &CSharpFGotoCodeGen::TO_STATE_ACTION_SWITCH() { /* Loop the actions. */ for ( GenActionTableMap::Iter redAct = redFsm->actionMap; redAct.lte(); redAct++ ) { if ( redAct->numToStateRefs > 0 ) { /* Write the entry label. */ out << "\tcase " << redAct->actListId+1 << ":\n"; /* Write each action in the list of action items. */ for ( GenActionTable::Iter item = redAct->key; item.lte(); item++ ) ACTION( out, item->value, 0, false ); out << "\tbreak;\n"; } } genLineDirective( out ); return out; } /* Write out the function switch. This switch is keyed on the values * of the func index. */ std::ostream &CSharpFGotoCodeGen::FROM_STATE_ACTION_SWITCH() { /* Loop the actions. */ for ( GenActionTableMap::Iter redAct = redFsm->actionMap; redAct.lte(); redAct++ ) { if ( redAct->numFromStateRefs > 0 ) { /* Write the entry label. */ out << "\tcase " << redAct->actListId+1 << ":\n"; /* Write each action in the list of action items. */ for ( GenActionTable::Iter item = redAct->key; item.lte(); item++ ) ACTION( out, item->value, 0, false ); out << "\tbreak;\n"; } } genLineDirective( out ); return out; } std::ostream &CSharpFGotoCodeGen::EOF_ACTION_SWITCH() { /* Loop the actions. */ for ( GenActionTableMap::Iter redAct = redFsm->actionMap; redAct.lte(); redAct++ ) { if ( redAct->numEofRefs > 0 ) { /* Write the entry label. */ out << "\tcase " << redAct->actListId+1 << ":\n"; /* Write each action in the list of action items. */ for ( GenActionTable::Iter item = redAct->key; item.lte(); item++ ) ACTION( out, item->value, 0, true ); out << "\tbreak;\n"; } } genLineDirective( out ); return out; } std::ostream &CSharpFGotoCodeGen::FINISH_CASES() { for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { /* States that are final and have an out action need a case. */ if ( st->eofAction != 0 ) { /* Write the case label. */ out << "\t\tcase " << st->id << ": "; /* Jump to the func. */ out << "goto f" << st->eofAction->actListId << ";\n"; } } return out; } unsigned int CSharpFGotoCodeGen::TO_STATE_ACTION( RedStateAp *state ) { int act = 0; if ( state->toStateAction != 0 ) act = state->toStateAction->actListId+1; return act; } unsigned int CSharpFGotoCodeGen::FROM_STATE_ACTION( RedStateAp *state ) { int act = 0; if ( state->fromStateAction != 0 ) act = state->fromStateAction->actListId+1; return act; } unsigned int CSharpFGotoCodeGen::EOF_ACTION( RedStateAp *state ) { int act = 0; if ( state->eofAction != 0 ) act = state->eofAction->actListId+1; return act; } void CSharpFGotoCodeGen::writeData() { if ( redFsm->anyToStateActions() ) { OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActionLoc), TSA() ); TO_STATE_ACTIONS(); CLOSE_ARRAY() << "\n"; } if ( redFsm->anyFromStateActions() ) { OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActionLoc), FSA() ); FROM_STATE_ACTIONS(); CLOSE_ARRAY() << "\n"; } if ( redFsm->anyEofActions() ) { OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActionLoc), EA() ); EOF_ACTIONS(); CLOSE_ARRAY() << "\n"; } STATE_IDS(); } void CSharpFGotoCodeGen::writeExec() { testEofUsed = false; outLabelUsed = false; out << " {\n"; if ( redFsm->anyRegCurStateRef() ) out << " int _ps = 0;\n"; if ( redFsm->anyConditions() ) out << " " << WIDE_ALPH_TYPE() << " _widec;\n"; if ( !noEnd ) { testEofUsed = true; out << " if ( " << P() << " == " << PE() << " )\n" " goto _test_eof;\n"; } if ( redFsm->errState != 0 ) { outLabelUsed = true; out << " if ( " << vCS() << " == " << redFsm->errState->id << " )\n" " goto _out;\n"; } out << "_resume:\n"; if ( redFsm->anyFromStateActions() ) { out << " switch ( " << FSA() << "[" << vCS() << "] ) {\n"; FROM_STATE_ACTION_SWITCH(); SWITCH_DEFAULT() << " }\n" "\n"; } out << " switch ( " << vCS() << " ) {\n"; STATE_GOTOS(); SWITCH_DEFAULT() << " }\n" "\n"; TRANSITIONS() << "\n"; if ( redFsm->anyRegActions() ) EXEC_ACTIONS() << "\n"; out << "_again:\n"; if ( redFsm->anyToStateActions() ) { out << " switch ( " << TSA() << "[" << vCS() << "] ) {\n"; TO_STATE_ACTION_SWITCH(); SWITCH_DEFAULT() << " }\n" "\n"; } if ( redFsm->errState != 0 ) { outLabelUsed = true; out << " if ( " << vCS() << " == " << redFsm->errState->id << " )\n" " goto _out;\n"; } if ( !noEnd ) { out << " if ( ++" << P() << " != " << PE() << " )\n" " goto _resume;\n"; } else { out << " " << P() << " += 1;\n" " goto _resume;\n"; } if ( testEofUsed ) out << " _test_eof: {}\n"; if ( redFsm->anyEofTrans() || redFsm->anyEofActions() ) { out << " if ( " << P() << " == " << vEOF() << " )\n" " {\n"; if ( redFsm->anyEofTrans() ) { out << " switch ( " << vCS() << " ) {\n"; for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { if ( st->eofTrans != 0 ) out << " case " << st->id << ": goto tr" << st->eofTrans->id << ";\n"; } SWITCH_DEFAULT() << " }\n"; } if ( redFsm->anyEofActions() ) { out << " switch ( " << EA() << "[" << vCS() << "] ) {\n"; EOF_ACTION_SWITCH(); SWITCH_DEFAULT() << " }\n"; } out << " }\n" "\n"; } if ( outLabelUsed ) out << " _out: {}\n"; out << " }\n"; } ragel-6.8/ragel/goflat.cpp0000664000175000017500000004452312106050031012452 00000000000000/* * Copyright 2004-2006 Adrian Thurston * 2004 Erich Ocean * 2005 Alan West */ /* This file is part of Ragel. * * Ragel is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Ragel is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Ragel; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "ragel.h" #include "goflat.h" #include "redfsm.h" #include "gendata.h" using std::endl; std::ostream &GoFlatCodeGen::TO_STATE_ACTION( RedStateAp *state ) { int act = 0; if ( state->toStateAction != 0 ) act = state->toStateAction->location+1; out << act; return out; } std::ostream &GoFlatCodeGen::FROM_STATE_ACTION( RedStateAp *state ) { int act = 0; if ( state->fromStateAction != 0 ) act = state->fromStateAction->location+1; out << act; return out; } std::ostream &GoFlatCodeGen::EOF_ACTION( RedStateAp *state ) { int act = 0; if ( state->eofAction != 0 ) act = state->eofAction->location+1; out << act; return out; } std::ostream &GoFlatCodeGen::TRANS_ACTION( RedTransAp *trans ) { /* If there are actions, emit them. Otherwise emit zero. */ int act = 0; if ( trans->action != 0 ) act = trans->action->location+1; out << act; return out; } std::ostream &GoFlatCodeGen::TO_STATE_ACTION_SWITCH( int level ) { /* Walk the list of functions, printing the cases. */ for ( GenActionList::Iter act = actionList; act.lte(); act++ ) { /* Write out referenced actions. */ if ( act->numToStateRefs > 0 ) { /* Write the case label, the action and the case break */ out << TABS(level) << "case " << act->actionId << ":" << endl; ACTION( out, act, 0, false, false ); } } genLineDirective( out ); return out; } std::ostream &GoFlatCodeGen::FROM_STATE_ACTION_SWITCH( int level ) { /* Walk the list of functions, printing the cases. */ for ( GenActionList::Iter act = actionList; act.lte(); act++ ) { /* Write out referenced actions. */ if ( act->numFromStateRefs > 0 ) { /* Write the case label, the action and the case break */ out << TABS(level) << "case " << act->actionId << ":" << endl; ACTION( out, act, 0, false, false ); } } genLineDirective( out ); return out; } std::ostream &GoFlatCodeGen::EOF_ACTION_SWITCH( int level ) { /* Walk the list of functions, printing the cases. */ for ( GenActionList::Iter act = actionList; act.lte(); act++ ) { /* Write out referenced actions. */ if ( act->numEofRefs > 0 ) { /* Write the case label, the action and the case break */ out << TABS(level) << "case " << act->actionId << ":" << endl; ACTION( out, act, 0, true, false ); } } genLineDirective( out ); return out; } std::ostream &GoFlatCodeGen::ACTION_SWITCH( int level ) { /* Walk the list of functions, printing the cases. */ for ( GenActionList::Iter act = actionList; act.lte(); act++ ) { /* Write out referenced actions. */ if ( act->numTransRefs > 0 ) { /* Write the case label, the action and the case break */ out << TABS(level) << "case " << act->actionId << ":" << endl; ACTION( out, act, 0, false, false ); } } genLineDirective( out ); return out; } std::ostream &GoFlatCodeGen::FLAT_INDEX_OFFSET() { out << " "; int totalStateNum = 0, curIndOffset = 0; for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { /* Write the index offset. */ out << curIndOffset << ", "; if ( !st.last() ) { if ( ++totalStateNum % IALL == 0 ) out << endl << " "; } /* Move the index offset ahead. */ if ( st->transList != 0 ) curIndOffset += keyOps->span( st->lowKey, st->highKey ); if ( st->defTrans != 0 ) curIndOffset += 1; } out << endl; return out; } std::ostream &GoFlatCodeGen::KEY_SPANS() { out << " "; int totalStateNum = 0; for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { /* Write singles length. */ unsigned long long span = 0; if ( st->transList != 0 ) span = keyOps->span( st->lowKey, st->highKey ); out << span << ", "; if ( !st.last() ) { if ( ++totalStateNum % IALL == 0 ) out << endl << " "; } } out << endl; return out; } std::ostream &GoFlatCodeGen::TO_STATE_ACTIONS() { out << " "; int totalStateNum = 0; for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { /* Write any eof action. */ TO_STATE_ACTION(st); out << ", "; if ( !st.last() ) { if ( ++totalStateNum % IALL == 0 ) out << endl << " "; } } out << endl; return out; } std::ostream &GoFlatCodeGen::FROM_STATE_ACTIONS() { out << " "; int totalStateNum = 0; for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { /* Write any eof action. */ FROM_STATE_ACTION(st); out << ", "; if ( !st.last() ) { if ( ++totalStateNum % IALL == 0 ) out << endl << " "; } } out << endl; return out; } std::ostream &GoFlatCodeGen::EOF_ACTIONS() { out << " "; int totalStateNum = 0; for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { /* Write any eof action. */ EOF_ACTION(st); out << ", "; if ( !st.last() ) { if ( ++totalStateNum % IALL == 0 ) out << endl << " "; } } out << endl; return out; } std::ostream &GoFlatCodeGen::EOF_TRANS() { out << " "; int totalStateNum = 0; for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { /* Write any eof action. */ long trans = 0; if ( st->eofTrans != 0 ) { assert( st->eofTrans->pos >= 0 ); trans = st->eofTrans->pos+1; } out << trans << ", "; if ( !st.last() ) { if ( ++totalStateNum % IALL == 0 ) out << endl << " "; } } out << endl; return out; } std::ostream &GoFlatCodeGen::COND_KEYS() { out << " "; int totalStateNum = 0; for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { /* Emit just cond low key and cond high key. */ out << KEY( st->condLowKey ) << ", "; out << KEY( st->condHighKey ) << ", "; if ( !st.last() ) { if ( ++totalStateNum % IALL == 0 ) out << endl << " "; } } out << endl; return out; } std::ostream &GoFlatCodeGen::COND_KEY_SPANS() { out << " "; int totalStateNum = 0; for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { /* Write singles length. */ unsigned long long span = 0; if ( st->condList != 0 ) span = keyOps->span( st->condLowKey, st->condHighKey ); out << span << ", "; if ( !st.last() ) { if ( ++totalStateNum % IALL == 0 ) out << endl << " "; } } out << endl; return out; } std::ostream &GoFlatCodeGen::CONDS() { out << " "; int totalStateNum = 0; for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { if ( st->condList != 0 ) { /* Walk the singles. */ unsigned long long span = keyOps->span( st->condLowKey, st->condHighKey ); for ( unsigned long long pos = 0; pos < span; pos++ ) { if ( st->condList[pos] != 0 ) out << st->condList[pos]->condSpaceId + 1 << ", "; else out << "0, "; if ( !st.last() ) { if ( ++totalStateNum % IALL == 0 ) out << endl << " "; } } } } out << endl; return out; } std::ostream &GoFlatCodeGen::COND_INDEX_OFFSET() { out << " "; int totalStateNum = 0; int curIndOffset = 0; for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { /* Write the index offset. */ out << curIndOffset << ", "; if ( !st.last() ) { if ( ++totalStateNum % IALL == 0 ) out << endl << " "; } /* Move the index offset ahead. */ if ( st->condList != 0 ) curIndOffset += keyOps->span( st->condLowKey, st->condHighKey ); } out << endl; return out; } std::ostream &GoFlatCodeGen::KEYS() { out << " "; int totalStateNum = 0; for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { /* Emit just low key and high key. */ out << KEY( st->lowKey ) << ", "; out << KEY( st->highKey ) << ", "; if ( !st.last() ) { if ( ++totalStateNum % IALL == 0 ) out << endl << " "; } } out << endl; return out; } std::ostream &GoFlatCodeGen::INDICIES() { out << " "; int totalStateNum = 0; for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { if ( st->transList != 0 ) { /* Walk the singles. */ unsigned long long span = keyOps->span( st->lowKey, st->highKey ); for ( unsigned long long pos = 0; pos < span; pos++ ) { out << st->transList[pos]->id << ", "; if ( ++totalStateNum % IALL == 0 ) out << endl << " "; } } /* The state's default index goes next. */ if ( st->defTrans != 0 ) { out << st->defTrans->id << ", "; if ( ++totalStateNum % IALL == 0 ) out << endl << " "; } } out << endl; return out; } std::ostream &GoFlatCodeGen::TRANS_TARGS() { /* Transitions must be written ordered by their id. */ RedTransAp **transPtrs = new RedTransAp*[redFsm->transSet.length()]; for ( TransApSet::Iter trans = redFsm->transSet; trans.lte(); trans++ ) transPtrs[trans->id] = trans; /* Keep a count of the num of items in the array written. */ out << " "; int totalStates = 0; for ( int t = 0; t < redFsm->transSet.length(); t++ ) { /* Save the position. Needed for eofTargs. */ RedTransAp *trans = transPtrs[t]; trans->pos = t; /* Write out the target state. */ out << trans->targ->id << ", "; if ( t < redFsm->transSet.length()-1 ) { if ( ++totalStates % IALL == 0 ) out << endl << " "; } } out << endl; delete[] transPtrs; return out; } std::ostream &GoFlatCodeGen::TRANS_ACTIONS() { /* Transitions must be written ordered by their id. */ RedTransAp **transPtrs = new RedTransAp*[redFsm->transSet.length()]; for ( TransApSet::Iter trans = redFsm->transSet; trans.lte(); trans++ ) transPtrs[trans->id] = trans; /* Keep a count of the num of items in the array written. */ out << " "; int totalAct = 0; for ( int t = 0; t < redFsm->transSet.length(); t++ ) { /* Write the function for the transition. */ RedTransAp *trans = transPtrs[t]; TRANS_ACTION( trans ); out << ", "; if ( t < redFsm->transSet.length()-1 ) { if ( ++totalAct % IALL == 0 ) out << endl << " "; } } out << endl; delete[] transPtrs; return out; } void GoFlatCodeGen::LOCATE_TRANS() { out << " _keys = " << CAST(INT(), vCS() + " << 1") << endl << " _inds = " << CAST(INT(), IO() + "[" + vCS() + "]") << endl << endl << " _slen = " << CAST(INT(), SP() + "[" + vCS() + "]") << endl << " if _slen > 0 && " << K() << "[_keys] <= " << GET_WIDE_KEY() << " && " << GET_WIDE_KEY() << " <= " << K() << "[_keys + 1]" << " {" << endl << " _trans = " << CAST(INT(), I() + "[_inds + " + CAST(INT(), GET_WIDE_KEY() + " - " + K() + "[_keys]") + "]") << endl << " } else {" << endl << " _trans = " << CAST(INT(), I() + "[_inds + _slen]") << endl << " }" << endl << endl; } void GoFlatCodeGen::writeData() { /* If there are any transtion functions then output the array. If there * are none, don't bother emitting an empty array that won't be used. */ if ( redFsm->anyActions() ) { OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActArrItem), A() ); ACTIONS_ARRAY(); CLOSE_ARRAY() << endl; } if ( redFsm->anyConditions() ) { OPEN_ARRAY( WIDE_ALPH_TYPE(), CK() ); COND_KEYS(); CLOSE_ARRAY() << endl; OPEN_ARRAY( ARRAY_TYPE(redFsm->maxCondSpan), CSP() ); COND_KEY_SPANS(); CLOSE_ARRAY() << endl; OPEN_ARRAY( ARRAY_TYPE(redFsm->maxCond), C() ); CONDS(); CLOSE_ARRAY() << endl; OPEN_ARRAY( ARRAY_TYPE(redFsm->maxCondIndexOffset), CO() ); COND_INDEX_OFFSET(); CLOSE_ARRAY() << endl; } OPEN_ARRAY( WIDE_ALPH_TYPE(), K() ); KEYS(); CLOSE_ARRAY() << endl; OPEN_ARRAY( ARRAY_TYPE(redFsm->maxSpan), SP() ); KEY_SPANS(); CLOSE_ARRAY() << endl; OPEN_ARRAY( ARRAY_TYPE(redFsm->maxFlatIndexOffset), IO() ); FLAT_INDEX_OFFSET(); CLOSE_ARRAY() << endl; OPEN_ARRAY( ARRAY_TYPE(redFsm->maxIndex), I() ); INDICIES(); CLOSE_ARRAY() << endl; OPEN_ARRAY( ARRAY_TYPE(redFsm->maxState), TT() ); TRANS_TARGS(); CLOSE_ARRAY() << endl; if ( redFsm->anyActions() ) { OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActionLoc), TA() ); TRANS_ACTIONS(); CLOSE_ARRAY() << endl; } if ( redFsm->anyToStateActions() ) { OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActionLoc), TSA() ); TO_STATE_ACTIONS(); CLOSE_ARRAY() << endl; } if ( redFsm->anyFromStateActions() ) { OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActionLoc), FSA() ); FROM_STATE_ACTIONS(); CLOSE_ARRAY() << endl; } if ( redFsm->anyEofActions() ) { OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActionLoc), EA() ); EOF_ACTIONS(); CLOSE_ARRAY() << endl; } if ( redFsm->anyEofTrans() ) { OPEN_ARRAY( ARRAY_TYPE(redFsm->maxIndexOffset+1), ET() ); EOF_TRANS(); CLOSE_ARRAY() << endl; } STATE_IDS(); } void GoFlatCodeGen::COND_TRANSLATE() { out << " _widec = " << CAST(WIDE_ALPH_TYPE(), GET_KEY()) << endl; out << " _keys = " << CAST(INT(), vCS() + " << 1") << endl << " _conds = " << CAST(INT(), CO() + "[" + vCS() + "]") << endl << endl << " _slen = " << CAST(INT(), CSP() + "[" + vCS() + "]") << endl << " if _slen > 0 && " << CK() << "[_keys]" << " <= " << GET_WIDE_KEY() << " && " << GET_WIDE_KEY() << " <= " << CK() << "[_keys + 1] {" << endl << " _cond = " << CAST(INT(), C() + "[_conds + " + CAST(INT(), GET_WIDE_KEY() + " - " + CK() + "[_keys]") + "]") << endl << " } else {" << endl << " _cond = 0" << endl << " }" << endl << endl; out << " switch _cond {" << endl; for ( CondSpaceList::Iter csi = condSpaceList; csi.lte(); csi++ ) { GenCondSpace *condSpace = csi; out << " case " << condSpace->condSpaceId + 1 << ":" << endl; out << TABS(2) << "_widec = " << KEY(condSpace->baseKey) << " + (" << CAST(WIDE_ALPH_TYPE(), GET_KEY()) << " - " << KEY(keyOps->minKey) << ")" << endl; for ( GenCondSet::Iter csi = condSpace->condSet; csi.lte(); csi++ ) { out << TABS(2) << "if "; CONDITION( out, *csi ); Size condValOffset = ((1 << csi.pos()) * keyOps->alphSize()); out << " {" << endl << " _widec += " << condValOffset << endl << " }" << endl; } } out << " }" << endl; } void GoFlatCodeGen::writeExec() { testEofUsed = false; outLabelUsed = false; out << " {" << endl << " var _slen " << INT() << endl; if ( redFsm->anyRegCurStateRef() ) out << " var _ps " << INT() << endl; out << " var _trans " << INT() << endl; if ( redFsm->anyConditions() ) out << " var _cond " << INT() << endl; if ( redFsm->anyToStateActions() || redFsm->anyRegActions() || redFsm->anyFromStateActions() ) { out << " var _acts " << INT() << endl << " var _nacts " << UINT() << endl; } out << " var _keys " << INT() << endl << " var _inds " << INT() << endl; if ( redFsm->anyConditions() ) { out << " var _conds " << INT() << endl << " var _widec " << WIDE_ALPH_TYPE() << endl; } out << endl; if ( !noEnd ) { testEofUsed = true; out << " if " << P() << " == " << PE() << " {" << endl << " goto _test_eof" << endl << " }" << endl; } if ( redFsm->errState != 0 ) { outLabelUsed = true; out << " if " << vCS() << " == " << redFsm->errState->id << " {" << endl << " goto _out" << endl << " }" << endl; } out << "_resume:" << endl; if ( redFsm->anyFromStateActions() ) { out << " _acts = " << CAST(INT(), FSA() + "[" + vCS() + "]") << endl << " _nacts = " << CAST(UINT(), A() + "[_acts]") << "; _acts++" << endl << " for ; _nacts > 0; _nacts-- {" << endl << " _acts++" << endl << " switch " << A() << "[_acts - 1]" << " {" << endl; FROM_STATE_ACTION_SWITCH(2); out << " }" << endl << " }" << endl << endl; } if ( redFsm->anyConditions() ) COND_TRANSLATE(); LOCATE_TRANS(); if ( redFsm->anyEofTrans() ) out << "_eof_trans:" << endl; if ( redFsm->anyRegCurStateRef() ) out << " _ps = " << vCS() << endl; out << " " << vCS() << " = " << CAST(INT(), TT() + "[_trans]") << endl << endl; if ( redFsm->anyRegActions() ) { out << " if " << TA() << "[_trans] == 0 {" << endl << " goto _again" << endl << " }" << endl << endl << " _acts = " << CAST(INT(), TA() + "[_trans]") << endl << " _nacts = " << CAST(UINT(), A() + "[_acts]") << "; _acts++" << endl << " for ; _nacts > 0; _nacts-- {" << endl << " _acts++" << endl << " switch " << A() << "[_acts - 1]" << " {" << endl; ACTION_SWITCH(2); out << " }" << endl << " }" << endl << endl; } if ( redFsm->anyRegActions() || redFsm->anyActionGotos() || redFsm->anyActionCalls() || redFsm->anyActionRets() ) out << "_again:" << endl; if ( redFsm->anyToStateActions() ) { out << " _acts = " << CAST(INT(), TSA() + "[" + vCS() + "]") << endl << " _nacts = " << CAST(UINT(), A() + "[_acts]") << "; _acts++" << endl << " for ; _nacts > 0; _nacts-- {" << endl << " _acts++" << endl << " switch " << A() << "[_acts - 1]" << " {" << endl; TO_STATE_ACTION_SWITCH(2); out << " }" << endl << " }" << endl << endl; } if ( redFsm->errState != 0 ) { outLabelUsed = true; out << " if " << vCS() << " == " << redFsm->errState->id << " {" << endl << " goto _out" << endl << " }" << endl; } if ( !noEnd ) { out << " if " << P() << "++; " << P() << " != " << PE() << " {" << endl << " goto _resume" << endl << " }" << endl; } else { out << " " << P() << "++" << endl << " goto _resume" << endl; } if ( testEofUsed ) out << " _test_eof: {}" << endl; if ( redFsm->anyEofTrans() || redFsm->anyEofActions() ) { out << " if " << P() << " == " << vEOF() << " {" << endl; if ( redFsm->anyEofTrans() ) { out << " if " << ET() << "[" << vCS() << "] > 0 {" << endl << " _trans = " << CAST(INT(), ET() + "[" + vCS() + "] - 1") << endl << " goto _eof_trans" << endl << " }" << endl; } if ( redFsm->anyEofActions() ) { out << " __acts := " << CAST(INT(), EA() + "[" + vCS() + "]") << endl << " __nacts := " << CAST(UINT(), A() + "[__acts]") << "; __acts++" << endl << " for ; __nacts > 0; __nacts-- {" << endl << " __acts++" << endl << " switch " << A() << "[__acts - 1]" << " {" << endl; EOF_ACTION_SWITCH(3); out << " }" << endl << " }" << endl; } out << " }" << endl << endl; } if ( outLabelUsed ) out << " _out: {}" << endl; out << " }" << endl; } ragel-6.8/ragel/gofgoto.h0000664000175000017500000000305712106050031012304 00000000000000/* * Copyright 2001-2006 Adrian Thurston * 2004 Erich Ocean * 2005 Alan West */ /* This file is part of Ragel. * * Ragel is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Ragel is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Ragel; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef _GOFGOTO_H #define _GOFGOTO_H #include #include "gogoto.h" /* Forwards. */ struct CodeGenData; class GoFGotoCodeGen : public GoGotoCodeGen { public: GoFGotoCodeGen( ostream &out ) : GoGotoCodeGen(out) {} std::ostream &EXEC_ACTIONS(); std::ostream &TO_STATE_ACTION_SWITCH( int level ); std::ostream &FROM_STATE_ACTION_SWITCH( int level ); std::ostream &FINISH_CASES(); std::ostream &EOF_ACTION_SWITCH( int level ); unsigned int TO_STATE_ACTION( RedStateAp *state ); unsigned int FROM_STATE_ACTION( RedStateAp *state ); unsigned int EOF_ACTION( RedStateAp *state ); virtual void writeData(); virtual void writeExec(); }; #endif ragel-6.8/ragel/javacodegen.cpp0000664000175000017500000011710712106050031013443 00000000000000/* * Copyright 2006-2007 Adrian Thurston * 2007 Colin Fleming */ /* This file is part of Ragel. * * Ragel is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Ragel is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Ragel; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "ragel.h" #include "javacodegen.h" #include "redfsm.h" #include "gendata.h" #include #include /* Integer array line length. */ #define IALL 12 /* Static array initialization item count * (should be multiple of IALL). */ #define SAIIC 8184 #define _resume 1 #define _again 2 #define _eof_trans 3 #define _test_eof 4 #define _out 5 using std::setw; using std::ios; using std::ostringstream; using std::string; using std::cerr; using std::istream; using std::ifstream; using std::ostream; using std::ios; using std::cin; using std::cout; using std::cerr; using std::endl; void javaLineDirective( ostream &out, const char *fileName, int line ) { /* Write the preprocessor line info for to the input file. */ out << "// line " << line << " \""; for ( const char *pc = fileName; *pc != 0; pc++ ) { if ( *pc == '\\' ) out << "\\\\"; else out << *pc; } out << "\"\n"; } void JavaTabCodeGen::genLineDirective( ostream &out ) { std::streambuf *sbuf = out.rdbuf(); output_filter *filter = static_cast(sbuf); javaLineDirective( out, filter->fileName, filter->line + 1 ); } void JavaTabCodeGen::GOTO( ostream &ret, int gotoDest, bool inFinish ) { ret << "{" << vCS() << " = " << gotoDest << "; _goto_targ = " << _again << "; " << CTRL_FLOW() << "continue _goto;}"; } void JavaTabCodeGen::GOTO_EXPR( ostream &ret, GenInlineItem *ilItem, bool inFinish ) { ret << "{" << vCS() << " = ("; INLINE_LIST( ret, ilItem->children, 0, inFinish ); ret << "); _goto_targ = " << _again << "; " << CTRL_FLOW() << "continue _goto;}"; } void JavaTabCodeGen::CALL( ostream &ret, int callDest, int targState, bool inFinish ) { if ( prePushExpr != 0 ) { ret << "{"; INLINE_LIST( ret, prePushExpr, 0, false ); } ret << "{" << STACK() << "[" << TOP() << "++] = " << vCS() << "; " << vCS() << " = " << callDest << "; _goto_targ = " << _again << "; " << CTRL_FLOW() << "continue _goto;}"; if ( prePushExpr != 0 ) ret << "}"; } void JavaTabCodeGen::CALL_EXPR( ostream &ret, GenInlineItem *ilItem, int targState, bool inFinish ) { if ( prePushExpr != 0 ) { ret << "{"; INLINE_LIST( ret, prePushExpr, 0, false ); } ret << "{" << STACK() << "[" << TOP() << "++] = " << vCS() << "; " << vCS() << " = ("; INLINE_LIST( ret, ilItem->children, targState, inFinish ); ret << "); _goto_targ = " << _again << "; " << CTRL_FLOW() << "continue _goto;}"; if ( prePushExpr != 0 ) ret << "}"; } void JavaTabCodeGen::RET( ostream &ret, bool inFinish ) { ret << "{" << vCS() << " = " << STACK() << "[--" << TOP() << "];"; if ( postPopExpr != 0 ) { ret << "{"; INLINE_LIST( ret, postPopExpr, 0, false ); ret << "}"; } ret << "_goto_targ = " << _again << "; " << CTRL_FLOW() << "continue _goto;}"; } void JavaTabCodeGen::BREAK( ostream &ret, int targState ) { ret << "{ " << P() << " += 1; _goto_targ = " << _out << "; " << CTRL_FLOW() << " continue _goto;}"; } void JavaTabCodeGen::NEXT( ostream &ret, int nextDest, bool inFinish ) { ret << vCS() << " = " << nextDest << ";"; } void JavaTabCodeGen::NEXT_EXPR( ostream &ret, GenInlineItem *ilItem, bool inFinish ) { ret << vCS() << " = ("; INLINE_LIST( ret, ilItem->children, 0, inFinish ); ret << ");"; } void JavaTabCodeGen::EXEC( ostream &ret, GenInlineItem *item, int targState, int inFinish ) { /* The parser gives fexec two children. The double brackets are for D * code. If the inline list is a single word it will get interpreted as a * C-style cast by the D compiler. */ ret << "{" << P() << " = (("; INLINE_LIST( ret, item->children, targState, inFinish ); ret << "))-1;}"; } /* Write out an inline tree structure. Walks the list and possibly calls out * to virtual functions than handle language specific items in the tree. */ void JavaTabCodeGen::INLINE_LIST( ostream &ret, GenInlineList *inlineList, int targState, bool inFinish ) { for ( GenInlineList::Iter item = *inlineList; item.lte(); item++ ) { switch ( item->type ) { case GenInlineItem::Text: ret << item->data; break; case GenInlineItem::Goto: GOTO( ret, item->targState->id, inFinish ); break; case GenInlineItem::Call: CALL( ret, item->targState->id, targState, inFinish ); break; case GenInlineItem::Next: NEXT( ret, item->targState->id, inFinish ); break; case GenInlineItem::Ret: RET( ret, inFinish ); break; case GenInlineItem::PChar: ret << P(); break; case GenInlineItem::Char: ret << GET_KEY(); break; case GenInlineItem::Hold: ret << P() << "--;"; break; case GenInlineItem::Exec: EXEC( ret, item, targState, inFinish ); break; case GenInlineItem::Curs: ret << "(_ps)"; break; case GenInlineItem::Targs: ret << "(" << vCS() << ")"; break; case GenInlineItem::Entry: ret << item->targState->id; break; case GenInlineItem::GotoExpr: GOTO_EXPR( ret, item, inFinish ); break; case GenInlineItem::CallExpr: CALL_EXPR( ret, item, targState, inFinish ); break; case GenInlineItem::NextExpr: NEXT_EXPR( ret, item, inFinish ); break; case GenInlineItem::LmSwitch: LM_SWITCH( ret, item, targState, inFinish ); break; case GenInlineItem::LmSetActId: SET_ACT( ret, item ); break; case GenInlineItem::LmSetTokEnd: SET_TOKEND( ret, item ); break; case GenInlineItem::LmGetTokEnd: GET_TOKEND( ret, item ); break; case GenInlineItem::LmInitTokStart: INIT_TOKSTART( ret, item ); break; case GenInlineItem::LmInitAct: INIT_ACT( ret, item ); break; case GenInlineItem::LmSetTokStart: SET_TOKSTART( ret, item ); break; case GenInlineItem::SubAction: SUB_ACTION( ret, item, targState, inFinish ); break; case GenInlineItem::Break: BREAK( ret, targState ); break; } } } string JavaTabCodeGen::DATA_PREFIX() { if ( !noPrefix ) return FSM_NAME() + "_"; return ""; } /* Emit the alphabet data type. */ string JavaTabCodeGen::ALPH_TYPE() { string ret = keyOps->alphType->data1; if ( keyOps->alphType->data2 != 0 ) { ret += " "; ret += + keyOps->alphType->data2; } return ret; } /* Emit the alphabet data type. */ string JavaTabCodeGen::WIDE_ALPH_TYPE() { string ret; if ( redFsm->maxKey <= keyOps->maxKey ) ret = ALPH_TYPE(); else { long long maxKeyVal = redFsm->maxKey.getLongLong(); HostType *wideType = keyOps->typeSubsumes( keyOps->isSigned, maxKeyVal ); assert( wideType != 0 ); ret = wideType->data1; if ( wideType->data2 != 0 ) { ret += " "; ret += wideType->data2; } } return ret; } void JavaTabCodeGen::COND_TRANSLATE() { out << " _widec = " << GET_KEY() << ";\n" " _keys = " << CO() << "[" << vCS() << "]*2\n;" " _klen = " << CL() << "[" << vCS() << "];\n" " if ( _klen > 0 ) {\n" " int _lower = _keys\n;" " int _mid;\n" " int _upper = _keys + (_klen<<1) - 2;\n" " while (true) {\n" " if ( _upper < _lower )\n" " break;\n" "\n" " _mid = _lower + (((_upper-_lower) >> 1) & ~1);\n" " if ( " << GET_WIDE_KEY() << " < " << CK() << "[_mid] )\n" " _upper = _mid - 2;\n" " else if ( " << GET_WIDE_KEY() << " > " << CK() << "[_mid+1] )\n" " _lower = _mid + 2;\n" " else {\n" " switch ( " << C() << "[" << CO() << "[" << vCS() << "]" " + ((_mid - _keys)>>1)] ) {\n" ; for ( CondSpaceList::Iter csi = condSpaceList; csi.lte(); csi++ ) { GenCondSpace *condSpace = csi; out << " case " << condSpace->condSpaceId << ": {\n"; out << TABS(2) << "_widec = " << KEY(condSpace->baseKey) << " + (" << GET_KEY() << " - " << KEY(keyOps->minKey) << ");\n"; for ( GenCondSet::Iter csi = condSpace->condSet; csi.lte(); csi++ ) { out << TABS(2) << "if ( "; CONDITION( out, *csi ); Size condValOffset = ((1 << csi.pos()) * keyOps->alphSize()); out << " ) _widec += " << condValOffset << ";\n"; } out << " break;\n" " }\n"; } out << " }\n" " break;\n" " }\n" " }\n" " }\n" "\n"; } void JavaTabCodeGen::LOCATE_TRANS() { out << " _match: do {\n" " _keys = " << KO() << "[" << vCS() << "]" << ";\n" " _trans = " << IO() << "[" << vCS() << "];\n" " _klen = " << SL() << "[" << vCS() << "];\n" " if ( _klen > 0 ) {\n" " int _lower = _keys;\n" " int _mid;\n" " int _upper = _keys + _klen - 1;\n" " while (true) {\n" " if ( _upper < _lower )\n" " break;\n" "\n" " _mid = _lower + ((_upper-_lower) >> 1);\n" " if ( " << GET_WIDE_KEY() << " < " << K() << "[_mid] )\n" " _upper = _mid - 1;\n" " else if ( " << GET_WIDE_KEY() << " > " << K() << "[_mid] )\n" " _lower = _mid + 1;\n" " else {\n" " _trans += (_mid - _keys);\n" " break _match;\n" " }\n" " }\n" " _keys += _klen;\n" " _trans += _klen;\n" " }\n" "\n" " _klen = " << RL() << "[" << vCS() << "];\n" " if ( _klen > 0 ) {\n" " int _lower = _keys;\n" " int _mid;\n" " int _upper = _keys + (_klen<<1) - 2;\n" " while (true) {\n" " if ( _upper < _lower )\n" " break;\n" "\n" " _mid = _lower + (((_upper-_lower) >> 1) & ~1);\n" " if ( " << GET_WIDE_KEY() << " < " << K() << "[_mid] )\n" " _upper = _mid - 2;\n" " else if ( " << GET_WIDE_KEY() << " > " << K() << "[_mid+1] )\n" " _lower = _mid + 2;\n" " else {\n" " _trans += ((_mid - _keys)>>1);\n" " break _match;\n" " }\n" " }\n" " _trans += _klen;\n" " }\n" " } while (false);\n" "\n"; } /* Determine if we should use indicies or not. */ void JavaTabCodeGen::calcIndexSize() { int sizeWithInds = 0, sizeWithoutInds = 0; /* Calculate cost of using with indicies. */ for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { int totalIndex = st->outSingle.length() + st->outRange.length() + (st->defTrans == 0 ? 0 : 1); sizeWithInds += arrayTypeSize(redFsm->maxIndex) * totalIndex; } sizeWithInds += arrayTypeSize(redFsm->maxState) * redFsm->transSet.length(); if ( redFsm->anyActions() ) sizeWithInds += arrayTypeSize(redFsm->maxActionLoc) * redFsm->transSet.length(); /* Calculate the cost of not using indicies. */ for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { int totalIndex = st->outSingle.length() + st->outRange.length() + (st->defTrans == 0 ? 0 : 1); sizeWithoutInds += arrayTypeSize(redFsm->maxState) * totalIndex; if ( redFsm->anyActions() ) sizeWithoutInds += arrayTypeSize(redFsm->maxActionLoc) * totalIndex; } /* If using indicies reduces the size, use them. */ useIndicies = sizeWithInds < sizeWithoutInds; } int JavaTabCodeGen::TO_STATE_ACTION( RedStateAp *state ) { int act = 0; if ( state->toStateAction != 0 ) act = state->toStateAction->location+1; return act; } int JavaTabCodeGen::FROM_STATE_ACTION( RedStateAp *state ) { int act = 0; if ( state->fromStateAction != 0 ) act = state->fromStateAction->location+1; return act; } int JavaTabCodeGen::EOF_ACTION( RedStateAp *state ) { int act = 0; if ( state->eofAction != 0 ) act = state->eofAction->location+1; return act; } int JavaTabCodeGen::TRANS_ACTION( RedTransAp *trans ) { /* If there are actions, emit them. Otherwise emit zero. */ int act = 0; if ( trans->action != 0 ) act = trans->action->location+1; return act; } std::ostream &JavaTabCodeGen::TO_STATE_ACTION_SWITCH() { /* Walk the list of functions, printing the cases. */ for ( GenActionList::Iter act = actionList; act.lte(); act++ ) { /* Write out referenced actions. */ if ( act->numToStateRefs > 0 ) { /* Write the case label, the action and the case break. */ out << "\tcase " << act->actionId << ":\n"; ACTION( out, act, 0, false ); out << "\tbreak;\n"; } } genLineDirective( out ); return out; } std::ostream &JavaTabCodeGen::FROM_STATE_ACTION_SWITCH() { /* Walk the list of functions, printing the cases. */ for ( GenActionList::Iter act = actionList; act.lte(); act++ ) { /* Write out referenced actions. */ if ( act->numFromStateRefs > 0 ) { /* Write the case label, the action and the case break. */ out << "\tcase " << act->actionId << ":\n"; ACTION( out, act, 0, false ); out << "\tbreak;\n"; } } genLineDirective( out ); return out; } std::ostream &JavaTabCodeGen::EOF_ACTION_SWITCH() { /* Walk the list of functions, printing the cases. */ for ( GenActionList::Iter act = actionList; act.lte(); act++ ) { /* Write out referenced actions. */ if ( act->numEofRefs > 0 ) { /* Write the case label, the action and the case break. */ out << "\tcase " << act->actionId << ":\n"; ACTION( out, act, 0, true ); out << "\tbreak;\n"; } } genLineDirective( out ); return out; } std::ostream &JavaTabCodeGen::ACTION_SWITCH() { /* Walk the list of functions, printing the cases. */ for ( GenActionList::Iter act = actionList; act.lte(); act++ ) { /* Write out referenced actions. */ if ( act->numTransRefs > 0 ) { /* Write the case label, the action and the case break. */ out << "\tcase " << act->actionId << ":\n"; ACTION( out, act, 0, false ); out << "\tbreak;\n"; } } genLineDirective( out ); return out; } std::ostream &JavaTabCodeGen::COND_OFFSETS() { int curKeyOffset = 0; for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { /* Write the key offset. */ ARRAY_ITEM( INT(curKeyOffset), st.last() ); /* Move the key offset ahead. */ curKeyOffset += st->stateCondList.length(); } return out; } std::ostream &JavaTabCodeGen::KEY_OFFSETS() { int curKeyOffset = 0; for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { /* Write the key offset. */ ARRAY_ITEM( INT(curKeyOffset), st.last() ); /* Move the key offset ahead. */ curKeyOffset += st->outSingle.length() + st->outRange.length()*2; } return out; } std::ostream &JavaTabCodeGen::INDEX_OFFSETS() { int curIndOffset = 0; for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { /* Write the index offset. */ ARRAY_ITEM( INT(curIndOffset), st.last() ); /* Move the index offset ahead. */ curIndOffset += st->outSingle.length() + st->outRange.length(); if ( st->defTrans != 0 ) curIndOffset += 1; } return out; } std::ostream &JavaTabCodeGen::COND_LENS() { for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { /* Write singles length. */ ARRAY_ITEM( INT(st->stateCondList.length()), st.last() ); } return out; } std::ostream &JavaTabCodeGen::SINGLE_LENS() { for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { /* Write singles length. */ ARRAY_ITEM( INT(st->outSingle.length()), st.last() ); } return out; } std::ostream &JavaTabCodeGen::RANGE_LENS() { for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { /* Emit length of range index. */ ARRAY_ITEM( INT(st->outRange.length()), st.last() ); } return out; } std::ostream &JavaTabCodeGen::TO_STATE_ACTIONS() { for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { /* Write any eof action. */ ARRAY_ITEM( INT(TO_STATE_ACTION(st)), st.last() ); } return out; } std::ostream &JavaTabCodeGen::FROM_STATE_ACTIONS() { for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { /* Write any eof action. */ ARRAY_ITEM( INT(FROM_STATE_ACTION(st)), st.last() ); } return out; } std::ostream &JavaTabCodeGen::EOF_ACTIONS() { for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { /* Write any eof action. */ ARRAY_ITEM( INT(EOF_ACTION(st)), st.last() ); } return out; } std::ostream &JavaTabCodeGen::EOF_TRANS() { for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { /* Write any eof action. */ long trans = 0; if ( st->eofTrans != 0 ) { assert( st->eofTrans->pos >= 0 ); trans = st->eofTrans->pos+1; } /* Write any eof action. */ ARRAY_ITEM( INT(trans), st.last() ); } return out; } std::ostream &JavaTabCodeGen::COND_KEYS() { for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { /* Loop the state's transitions. */ for ( GenStateCondList::Iter sc = st->stateCondList; sc.lte(); sc++ ) { /* Lower key. */ ARRAY_ITEM( KEY( sc->lowKey ), false ); ARRAY_ITEM( KEY( sc->highKey ), false ); } } /* Output one last number so we don't have to figure out when the last * entry is and avoid writing a comma. */ ARRAY_ITEM( INT(0), true ); return out; } std::ostream &JavaTabCodeGen::COND_SPACES() { for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { /* Loop the state's transitions. */ for ( GenStateCondList::Iter sc = st->stateCondList; sc.lte(); sc++ ) { /* Cond Space id. */ ARRAY_ITEM( KEY( sc->condSpace->condSpaceId ), false ); } } /* Output one last number so we don't have to figure out when the last * entry is and avoid writing a comma. */ ARRAY_ITEM( INT(0), true ); return out; } std::ostream &JavaTabCodeGen::KEYS() { for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { /* Loop the singles. */ for ( RedTransList::Iter stel = st->outSingle; stel.lte(); stel++ ) { ARRAY_ITEM( KEY( stel->lowKey ), false ); } /* Loop the state's transitions. */ for ( RedTransList::Iter rtel = st->outRange; rtel.lte(); rtel++ ) { /* Lower key. */ ARRAY_ITEM( KEY( rtel->lowKey ), false ); /* Upper key. */ ARRAY_ITEM( KEY( rtel->highKey ), false ); } } /* Output one last number so we don't have to figure out when the last * entry is and avoid writing a comma. */ ARRAY_ITEM( INT(0), true ); return out; } std::ostream &JavaTabCodeGen::INDICIES() { for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { /* Walk the singles. */ for ( RedTransList::Iter stel = st->outSingle; stel.lte(); stel++ ) { ARRAY_ITEM( KEY( stel->value->id ), false ); } /* Walk the ranges. */ for ( RedTransList::Iter rtel = st->outRange; rtel.lte(); rtel++ ) { ARRAY_ITEM( KEY( rtel->value->id ), false ); } /* The state's default index goes next. */ if ( st->defTrans != 0 ) { ARRAY_ITEM( KEY( st->defTrans->id ), false ); } } /* Output one last number so we don't have to figure out when the last * entry is and avoid writing a comma. */ ARRAY_ITEM( INT(0), true ); return out; } std::ostream &JavaTabCodeGen::TRANS_TARGS() { int totalTrans = 0; for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { /* Walk the singles. */ for ( RedTransList::Iter stel = st->outSingle; stel.lte(); stel++ ) { RedTransAp *trans = stel->value; ARRAY_ITEM( KEY( trans->targ->id ), false ); totalTrans++; } /* Walk the ranges. */ for ( RedTransList::Iter rtel = st->outRange; rtel.lte(); rtel++ ) { RedTransAp *trans = rtel->value; ARRAY_ITEM( KEY( trans->targ->id ), false ); totalTrans++; } /* The state's default target state. */ if ( st->defTrans != 0 ) { RedTransAp *trans = st->defTrans; ARRAY_ITEM( KEY( trans->targ->id ), false ); totalTrans++; } } for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { if ( st->eofTrans != 0 ) { RedTransAp *trans = st->eofTrans; trans->pos = totalTrans++; ARRAY_ITEM( KEY( trans->targ->id ), false ); } } /* Output one last number so we don't have to figure out when the last * entry is and avoid writing a comma. */ ARRAY_ITEM( INT(0), true ); return out; } std::ostream &JavaTabCodeGen::TRANS_ACTIONS() { for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { /* Walk the singles. */ for ( RedTransList::Iter stel = st->outSingle; stel.lte(); stel++ ) { RedTransAp *trans = stel->value; ARRAY_ITEM( INT(TRANS_ACTION( trans )), false ); } /* Walk the ranges. */ for ( RedTransList::Iter rtel = st->outRange; rtel.lte(); rtel++ ) { RedTransAp *trans = rtel->value; ARRAY_ITEM( INT(TRANS_ACTION( trans )), false ); } /* The state's default index goes next. */ if ( st->defTrans != 0 ) { RedTransAp *trans = st->defTrans; ARRAY_ITEM( INT(TRANS_ACTION( trans )), false ); } } for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { if ( st->eofTrans != 0 ) { RedTransAp *trans = st->eofTrans; ARRAY_ITEM( INT(TRANS_ACTION( trans )), false ); } } /* Output one last number so we don't have to figure out when the last * entry is and avoid writing a comma. */ ARRAY_ITEM( INT(0), true ); return out; } std::ostream &JavaTabCodeGen::TRANS_TARGS_WI() { /* Transitions must be written ordered by their id. */ RedTransAp **transPtrs = new RedTransAp*[redFsm->transSet.length()]; for ( TransApSet::Iter trans = redFsm->transSet; trans.lte(); trans++ ) transPtrs[trans->id] = trans; /* Keep a count of the num of items in the array written. */ for ( int t = 0; t < redFsm->transSet.length(); t++ ) { /* Save the position. Needed for eofTargs. */ RedTransAp *trans = transPtrs[t]; trans->pos = t; /* Write out the target state. */ ARRAY_ITEM( INT(trans->targ->id), ( t >= redFsm->transSet.length()-1 ) ); } delete[] transPtrs; return out; } std::ostream &JavaTabCodeGen::TRANS_ACTIONS_WI() { /* Transitions must be written ordered by their id. */ RedTransAp **transPtrs = new RedTransAp*[redFsm->transSet.length()]; for ( TransApSet::Iter trans = redFsm->transSet; trans.lte(); trans++ ) transPtrs[trans->id] = trans; /* Keep a count of the num of items in the array written. */ for ( int t = 0; t < redFsm->transSet.length(); t++ ) { /* Write the function for the transition. */ RedTransAp *trans = transPtrs[t]; ARRAY_ITEM( INT(TRANS_ACTION( trans )), ( t >= redFsm->transSet.length()-1 ) ); } delete[] transPtrs; return out; } void JavaTabCodeGen::writeExports() { if ( exportList.length() > 0 ) { for ( ExportList::Iter ex = exportList; ex.lte(); ex++ ) { STATIC_VAR( ALPH_TYPE(), DATA_PREFIX() + "ex_" + ex->name ) << " = " << KEY(ex->key) << ";\n"; } out << "\n"; } } void JavaTabCodeGen::writeStart() { out << START_STATE_ID(); } void JavaTabCodeGen::writeFirstFinal() { out << FIRST_FINAL_STATE(); } void JavaTabCodeGen::writeError() { out << ERROR_STATE(); } void JavaTabCodeGen::writeData() { /* If there are any transtion functions then output the array. If there * are none, don't bother emitting an empty array that won't be used. */ if ( redFsm->anyActions() ) { OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActArrItem), A() ); ACTIONS_ARRAY(); CLOSE_ARRAY() << "\n"; } if ( redFsm->anyConditions() ) { OPEN_ARRAY( ARRAY_TYPE(redFsm->maxCondOffset), CO() ); COND_OFFSETS(); CLOSE_ARRAY() << "\n"; OPEN_ARRAY( ARRAY_TYPE(redFsm->maxCondLen), CL() ); COND_LENS(); CLOSE_ARRAY() << "\n"; OPEN_ARRAY( WIDE_ALPH_TYPE(), CK() ); COND_KEYS(); CLOSE_ARRAY() << "\n"; OPEN_ARRAY( ARRAY_TYPE(redFsm->maxCondSpaceId), C() ); COND_SPACES(); CLOSE_ARRAY() << "\n"; } OPEN_ARRAY( ARRAY_TYPE(redFsm->maxKeyOffset), KO() ); KEY_OFFSETS(); CLOSE_ARRAY() << "\n"; OPEN_ARRAY( WIDE_ALPH_TYPE(), K() ); KEYS(); CLOSE_ARRAY() << "\n"; OPEN_ARRAY( ARRAY_TYPE(redFsm->maxSingleLen), SL() ); SINGLE_LENS(); CLOSE_ARRAY() << "\n"; OPEN_ARRAY( ARRAY_TYPE(redFsm->maxRangeLen), RL() ); RANGE_LENS(); CLOSE_ARRAY() << "\n"; OPEN_ARRAY( ARRAY_TYPE(redFsm->maxIndexOffset), IO() ); INDEX_OFFSETS(); CLOSE_ARRAY() << "\n"; if ( useIndicies ) { OPEN_ARRAY( ARRAY_TYPE(redFsm->maxIndex), I() ); INDICIES(); CLOSE_ARRAY() << "\n"; OPEN_ARRAY( ARRAY_TYPE(redFsm->maxState), TT() ); TRANS_TARGS_WI(); CLOSE_ARRAY() << "\n"; if ( redFsm->anyActions() ) { OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActionLoc), TA() ); TRANS_ACTIONS_WI(); CLOSE_ARRAY() << "\n"; } } else { OPEN_ARRAY( ARRAY_TYPE(redFsm->maxState), TT() ); TRANS_TARGS(); CLOSE_ARRAY() << "\n"; if ( redFsm->anyActions() ) { OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActionLoc), TA() ); TRANS_ACTIONS(); CLOSE_ARRAY() << "\n"; } } if ( redFsm->anyToStateActions() ) { OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActionLoc), TSA() ); TO_STATE_ACTIONS(); CLOSE_ARRAY() << "\n"; } if ( redFsm->anyFromStateActions() ) { OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActionLoc), FSA() ); FROM_STATE_ACTIONS(); CLOSE_ARRAY() << "\n"; } if ( redFsm->anyEofActions() ) { OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActionLoc), EA() ); EOF_ACTIONS(); CLOSE_ARRAY() << "\n"; } if ( redFsm->anyEofTrans() ) { OPEN_ARRAY( ARRAY_TYPE(redFsm->maxIndexOffset+1), ET() ); EOF_TRANS(); CLOSE_ARRAY() << "\n"; } if ( redFsm->startState != 0 ) STATIC_VAR( "int", START() ) << " = " << START_STATE_ID() << ";\n"; if ( !noFinal ) STATIC_VAR( "int" , FIRST_FINAL() ) << " = " << FIRST_FINAL_STATE() << ";\n"; if ( !noError ) STATIC_VAR( "int", ERROR() ) << " = " << ERROR_STATE() << ";\n"; out << "\n"; if ( entryPointNames.length() > 0 ) { for ( EntryNameVect::Iter en = entryPointNames; en.lte(); en++ ) { STATIC_VAR( "int", DATA_PREFIX() + "en_" + *en ) << " = " << entryPointIds[en.pos()] << ";\n"; } out << "\n"; } } void JavaTabCodeGen::writeExec() { out << " {\n" " int _klen"; if ( redFsm->anyRegCurStateRef() ) out << ", _ps"; out << ";\n" " int _trans = 0;\n"; if ( redFsm->anyConditions() ) out << " int _widec;\n"; if ( redFsm->anyToStateActions() || redFsm->anyRegActions() || redFsm->anyFromStateActions() ) { out << " int _acts;\n" " int _nacts;\n"; } out << " int _keys;\n" " int _goto_targ = 0;\n" "\n"; out << " _goto: while (true) {\n" " switch ( _goto_targ ) {\n" " case 0:\n"; if ( !noEnd ) { out << " if ( " << P() << " == " << PE() << " ) {\n" " _goto_targ = " << _test_eof << ";\n" " continue _goto;\n" " }\n"; } if ( redFsm->errState != 0 ) { out << " if ( " << vCS() << " == " << redFsm->errState->id << " ) {\n" " _goto_targ = " << _out << ";\n" " continue _goto;\n" " }\n"; } out << "case " << _resume << ":\n"; if ( redFsm->anyFromStateActions() ) { out << " _acts = " << FSA() << "[" << vCS() << "]" << ";\n" " _nacts = " << CAST("int") << " " << A() << "[_acts++];\n" " while ( _nacts-- > 0 ) {\n" " switch ( " << A() << "[_acts++] ) {\n"; FROM_STATE_ACTION_SWITCH() << " }\n" " }\n" "\n"; } if ( redFsm->anyConditions() ) COND_TRANSLATE(); LOCATE_TRANS(); if ( useIndicies ) out << " _trans = " << I() << "[_trans];\n"; if ( redFsm->anyEofTrans() ) out << "case " << _eof_trans << ":\n"; if ( redFsm->anyRegCurStateRef() ) out << " _ps = " << vCS() << ";\n"; out << " " << vCS() << " = " << TT() << "[_trans];\n" "\n"; if ( redFsm->anyRegActions() ) { out << " if ( " << TA() << "[_trans] != 0 ) {\n" " _acts = " << TA() << "[_trans]" << ";\n" " _nacts = " << CAST("int") << " " << A() << "[_acts++];\n" " while ( _nacts-- > 0 )\n {\n" " switch ( " << A() << "[_acts++] )\n" " {\n"; ACTION_SWITCH() << " }\n" " }\n" " }\n" "\n"; } out << "case " << _again << ":\n"; if ( redFsm->anyToStateActions() ) { out << " _acts = " << TSA() << "[" << vCS() << "]" << ";\n" " _nacts = " << CAST("int") << " " << A() << "[_acts++];\n" " while ( _nacts-- > 0 ) {\n" " switch ( " << A() << "[_acts++] ) {\n"; TO_STATE_ACTION_SWITCH() << " }\n" " }\n" "\n"; } if ( redFsm->errState != 0 ) { out << " if ( " << vCS() << " == " << redFsm->errState->id << " ) {\n" " _goto_targ = " << _out << ";\n" " continue _goto;\n" " }\n"; } if ( !noEnd ) { out << " if ( ++" << P() << " != " << PE() << " ) {\n" " _goto_targ = " << _resume << ";\n" " continue _goto;\n" " }\n"; } else { out << " " << P() << " += 1;\n" " _goto_targ = " << _resume << ";\n" " continue _goto;\n"; } out << "case " << _test_eof << ":\n"; if ( redFsm->anyEofTrans() || redFsm->anyEofActions() ) { out << " if ( " << P() << " == " << vEOF() << " )\n" " {\n"; if ( redFsm->anyEofTrans() ) { out << " if ( " << ET() << "[" << vCS() << "] > 0 ) {\n" " _trans = " << ET() << "[" << vCS() << "] - 1;\n" " _goto_targ = " << _eof_trans << ";\n" " continue _goto;\n" " }\n"; } if ( redFsm->anyEofActions() ) { out << " int __acts = " << EA() << "[" << vCS() << "]" << ";\n" " int __nacts = " << CAST("int") << " " << A() << "[__acts++];\n" " while ( __nacts-- > 0 ) {\n" " switch ( " << A() << "[__acts++] ) {\n"; EOF_ACTION_SWITCH() << " }\n" " }\n"; } out << " }\n" "\n"; } out << "case " << _out << ":\n"; /* The switch and goto loop. */ out << " }\n"; out << " break; }\n"; /* The execute block. */ out << " }\n"; } std::ostream &JavaTabCodeGen::OPEN_ARRAY( string type, string name ) { array_type = type; array_name = name; item_count = 0; div_count = 1; out << "private static " << type << "[] init_" << name << "_0()\n" "{\n\t" "return new " << type << " [] {\n\t"; return out; } std::ostream &JavaTabCodeGen::ARRAY_ITEM( string item, bool last ) { item_count++; out << setw(5) << setiosflags(ios::right) << item; if ( !last ) { if ( item_count % SAIIC == 0 ) { out << "\n\t};\n};\n" "private static "<< array_type << "[] init_" << array_name << "_" << div_count << "()\n" "{\n\t" "return new " << array_type << " [] {\n\t"; div_count++; } else if (item_count % IALL == 0) { out << ",\n\t"; } else { out << ","; } } return out; } std::ostream &JavaTabCodeGen::CLOSE_ARRAY() { out << "\n\t};\n}\n\n"; if (item_count < SAIIC) { out << "private static final " << array_type << " " << array_name << "[] = init_" << array_name << "_0();\n\n"; } else { out << "private static final " << array_type << " [] combine_" << array_name << "() {\n\t" << array_type << " [] combined = new " << array_type << " [ " << item_count << " ];\n\t"; int block = 0; int full_blocks = item_count / SAIIC; for (;block < full_blocks; ++block) { out << "System.arraycopy ( init_" << array_name << "_" << block << "(), 0, combined, " << SAIIC * block << ", " << SAIIC << " );\n\t"; } if ( (item_count % SAIIC) > 0 ) { out << "System.arraycopy ( init_" << array_name << "_" << block << "(), 0, combined, " << SAIIC * block << ", " << (item_count % SAIIC) << " );\n\t"; } out << "return combined;\n}\n"; out << "private static final " << array_type << " [] " << array_name << " = combine_" << array_name << "();"; } return out; } std::ostream &JavaTabCodeGen::STATIC_VAR( string type, string name ) { out << "static final " << type << " " << name; return out; } string JavaTabCodeGen::ARR_OFF( string ptr, string offset ) { return ptr + " + " + offset; } string JavaTabCodeGen::CAST( string type ) { return "(" + type + ")"; } string JavaTabCodeGen::NULL_ITEM() { /* In java we use integers instead of pointers. */ return "-1"; } string JavaTabCodeGen::GET_KEY() { ostringstream ret; if ( getKeyExpr != 0 ) { /* Emit the user supplied method of retrieving the key. */ ret << "("; INLINE_LIST( ret, getKeyExpr, 0, false ); ret << ")"; } else { /* Expression for retrieving the key, use simple dereference. */ ret << DATA() << "[" << P() << "]"; } return ret.str(); } string JavaTabCodeGen::CTRL_FLOW() { return "if (true) "; } unsigned int JavaTabCodeGen::arrayTypeSize( unsigned long maxVal ) { long long maxValLL = (long long) maxVal; HostType *arrayType = keyOps->typeSubsumes( maxValLL ); assert( arrayType != 0 ); return arrayType->size; } string JavaTabCodeGen::ARRAY_TYPE( unsigned long maxVal ) { long long maxValLL = (long long) maxVal; HostType *arrayType = keyOps->typeSubsumes( maxValLL ); assert( arrayType != 0 ); string ret = arrayType->data1; if ( arrayType->data2 != 0 ) { ret += " "; ret += arrayType->data2; } return ret; } /* Write out the fsm name. */ string JavaTabCodeGen::FSM_NAME() { return fsmName; } /* Emit the offset of the start state as a decimal integer. */ string JavaTabCodeGen::START_STATE_ID() { ostringstream ret; ret << redFsm->startState->id; return ret.str(); }; /* Write out the array of actions. */ std::ostream &JavaTabCodeGen::ACTIONS_ARRAY() { ARRAY_ITEM( INT(0), false ); for ( GenActionTableMap::Iter act = redFsm->actionMap; act.lte(); act++ ) { /* Write out the length, which will never be the last character. */ ARRAY_ITEM( INT(act->key.length()), false ); for ( GenActionTable::Iter item = act->key; item.lte(); item++ ) ARRAY_ITEM( INT(item->value->actionId), (act.last() && item.last()) ); } return out; } string JavaTabCodeGen::ACCESS() { ostringstream ret; if ( accessExpr != 0 ) INLINE_LIST( ret, accessExpr, 0, false ); return ret.str(); } string JavaTabCodeGen::P() { ostringstream ret; if ( pExpr == 0 ) ret << "p"; else { ret << "("; INLINE_LIST( ret, pExpr, 0, false ); ret << ")"; } return ret.str(); } string JavaTabCodeGen::PE() { ostringstream ret; if ( peExpr == 0 ) ret << "pe"; else { ret << "("; INLINE_LIST( ret, peExpr, 0, false ); ret << ")"; } return ret.str(); } string JavaTabCodeGen::vEOF() { ostringstream ret; if ( eofExpr == 0 ) ret << "eof"; else { ret << "("; INLINE_LIST( ret, eofExpr, 0, false ); ret << ")"; } return ret.str(); } string JavaTabCodeGen::vCS() { ostringstream ret; if ( csExpr == 0 ) ret << ACCESS() << "cs"; else { /* Emit the user supplied method of retrieving the key. */ ret << "("; INLINE_LIST( ret, csExpr, 0, false ); ret << ")"; } return ret.str(); } string JavaTabCodeGen::TOP() { ostringstream ret; if ( topExpr == 0 ) ret << ACCESS() + "top"; else { ret << "("; INLINE_LIST( ret, topExpr, 0, false ); ret << ")"; } return ret.str(); } string JavaTabCodeGen::STACK() { ostringstream ret; if ( stackExpr == 0 ) ret << ACCESS() + "stack"; else { ret << "("; INLINE_LIST( ret, stackExpr, 0, false ); ret << ")"; } return ret.str(); } string JavaTabCodeGen::ACT() { ostringstream ret; if ( actExpr == 0 ) ret << ACCESS() + "act"; else { ret << "("; INLINE_LIST( ret, actExpr, 0, false ); ret << ")"; } return ret.str(); } string JavaTabCodeGen::TOKSTART() { ostringstream ret; if ( tokstartExpr == 0 ) ret << ACCESS() + "ts"; else { ret << "("; INLINE_LIST( ret, tokstartExpr, 0, false ); ret << ")"; } return ret.str(); } string JavaTabCodeGen::TOKEND() { ostringstream ret; if ( tokendExpr == 0 ) ret << ACCESS() + "te"; else { ret << "("; INLINE_LIST( ret, tokendExpr, 0, false ); ret << ")"; } return ret.str(); } string JavaTabCodeGen::DATA() { ostringstream ret; if ( dataExpr == 0 ) ret << ACCESS() + "data"; else { ret << "("; INLINE_LIST( ret, dataExpr, 0, false ); ret << ")"; } return ret.str(); } string JavaTabCodeGen::GET_WIDE_KEY() { if ( redFsm->anyConditions() ) return "_widec"; else return GET_KEY(); } string JavaTabCodeGen::GET_WIDE_KEY( RedStateAp *state ) { if ( state->stateCondList.length() > 0 ) return "_widec"; else return GET_KEY(); } /* Write out level number of tabs. Makes the nested binary search nice * looking. */ string JavaTabCodeGen::TABS( int level ) { string result; while ( level-- > 0 ) result += "\t"; return result; } string JavaTabCodeGen::KEY( Key key ) { ostringstream ret; if ( keyOps->isSigned || !hostLang->explicitUnsigned ) ret << key.getVal(); else ret << (unsigned long) key.getVal(); return ret.str(); } string JavaTabCodeGen::INT( int i ) { ostringstream ret; ret << i; return ret.str(); } void JavaTabCodeGen::LM_SWITCH( ostream &ret, GenInlineItem *item, int targState, int inFinish ) { ret << " switch( " << ACT() << " ) {\n"; for ( GenInlineList::Iter lma = *item->children; lma.lte(); lma++ ) { /* Write the case label, the action and the case break. */ if ( lma->lmId < 0 ) ret << " default:\n"; else ret << " case " << lma->lmId << ":\n"; /* Write the block and close it off. */ ret << " {"; INLINE_LIST( ret, lma->children, targState, inFinish ); ret << "}\n"; ret << " break;\n"; } ret << " }\n" "\t"; } void JavaTabCodeGen::SET_ACT( ostream &ret, GenInlineItem *item ) { ret << ACT() << " = " << item->lmId << ";"; } void JavaTabCodeGen::SET_TOKEND( ostream &ret, GenInlineItem *item ) { /* The tokend action sets tokend. */ ret << TOKEND() << " = " << P(); if ( item->offset != 0 ) out << "+" << item->offset; out << ";"; } void JavaTabCodeGen::GET_TOKEND( ostream &ret, GenInlineItem *item ) { ret << TOKEND(); } void JavaTabCodeGen::INIT_TOKSTART( ostream &ret, GenInlineItem *item ) { ret << TOKSTART() << " = " << NULL_ITEM() << ";"; } void JavaTabCodeGen::INIT_ACT( ostream &ret, GenInlineItem *item ) { ret << ACT() << " = 0;"; } void JavaTabCodeGen::SET_TOKSTART( ostream &ret, GenInlineItem *item ) { ret << TOKSTART() << " = " << P() << ";"; } void JavaTabCodeGen::SUB_ACTION( ostream &ret, GenInlineItem *item, int targState, bool inFinish ) { if ( item->children->length() > 0 ) { /* Write the block and close it off. */ ret << "{"; INLINE_LIST( ret, item->children, targState, inFinish ); ret << "}"; } } void JavaTabCodeGen::ACTION( ostream &ret, GenAction *action, int targState, bool inFinish ) { /* Write the preprocessor line info for going into the source file. */ javaLineDirective( ret, action->loc.fileName, action->loc.line ); /* Write the block and close it off. */ ret << "\t{"; INLINE_LIST( ret, action->inlineList, targState, inFinish ); ret << "}\n"; } void JavaTabCodeGen::CONDITION( ostream &ret, GenAction *condition ) { ret << "\n"; javaLineDirective( ret, condition->loc.fileName, condition->loc.line ); INLINE_LIST( ret, condition->inlineList, 0, false ); } string JavaTabCodeGen::ERROR_STATE() { ostringstream ret; if ( redFsm->errState != 0 ) ret << redFsm->errState->id; else ret << "-1"; return ret.str(); } string JavaTabCodeGen::FIRST_FINAL_STATE() { ostringstream ret; if ( redFsm->firstFinState != 0 ) ret << redFsm->firstFinState->id; else ret << redFsm->nextStateId; return ret.str(); } void JavaTabCodeGen::writeInit() { out << " {\n"; if ( !noCS ) out << "\t" << vCS() << " = " << START() << ";\n"; /* If there are any calls, then the stack top needs initialization. */ if ( redFsm->anyActionCalls() || redFsm->anyActionRets() ) out << "\t" << TOP() << " = 0;\n"; if ( hasLongestMatch ) { out << " " << TOKSTART() << " = " << NULL_ITEM() << ";\n" " " << TOKEND() << " = " << NULL_ITEM() << ";\n" " " << ACT() << " = 0;\n"; } out << " }\n"; } void JavaTabCodeGen::finishRagelDef() { /* The frontend will do this for us, but it may be a good idea to force it * if the intermediate file is edited. */ redFsm->sortByStateId(); /* Choose default transitions and the single transition. */ redFsm->chooseDefaultSpan(); /* Maybe do flat expand, otherwise choose single. */ redFsm->chooseSingle(); /* If any errors have occured in the input file then don't write anything. */ if ( gblErrorCount > 0 ) return; /* Anlayze Machine will find the final action reference counts, among * other things. We will use these in reporting the usage * of fsm directives in action code. */ analyzeMachine(); /* Determine if we should use indicies. */ calcIndexSize(); } ostream &JavaTabCodeGen::source_warning( const InputLoc &loc ) { cerr << sourceFileName << ":" << loc.line << ":" << loc.col << ": warning: "; return cerr; } ostream &JavaTabCodeGen::source_error( const InputLoc &loc ) { gblErrorCount += 1; assert( sourceFileName != 0 ); cerr << sourceFileName << ":" << loc.line << ":" << loc.col << ": "; return cerr; } ragel-6.8/ragel/mlflat.h0000664000175000017500000000551312106050031012116 00000000000000/* * Copyright 2004-2006 Adrian Thurston * 2004 Erich Ocean * 2005 Alan West */ /* This file is part of Ragel. * * Ragel is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Ragel is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Ragel; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef _MLFLAT_H #define _MLFLAT_H #include #include "mlcodegen.h" /* Forwards. */ //struct CodeGenData; //struct NameInst; //struct RedTransAp; //struct RedStateAp; /* * OCamlFlatCodeGen */ class OCamlFlatCodeGen : public OCamlCodeGen { public: OCamlFlatCodeGen( ostream &out ) : OCamlCodeGen(out) {} virtual ~OCamlFlatCodeGen() { } protected: std::ostream &TO_STATE_ACTION_SWITCH(); std::ostream &FROM_STATE_ACTION_SWITCH(); std::ostream &EOF_ACTION_SWITCH(); std::ostream &ACTION_SWITCH(); std::ostream &KEYS(); std::ostream &INDICIES(); std::ostream &FLAT_INDEX_OFFSET(); std::ostream &KEY_SPANS(); std::ostream &TO_STATE_ACTIONS(); std::ostream &FROM_STATE_ACTIONS(); std::ostream &EOF_ACTIONS(); std::ostream &EOF_TRANS(); std::ostream &TRANS_TARGS(); std::ostream &TRANS_ACTIONS(); void LOCATE_TRANS(); std::ostream &COND_INDEX_OFFSET(); void COND_TRANSLATE(); std::ostream &CONDS(); std::ostream &COND_KEYS(); std::ostream &COND_KEY_SPANS(); void GOTO( ostream &ret, int gotoDest, bool inFinish ); void CALL( ostream &ret, int callDest, int targState, bool inFinish ); void NEXT( ostream &ret, int nextDest, bool inFinish ); void GOTO_EXPR( ostream &ret, GenInlineItem *ilItem, bool inFinish ); void NEXT_EXPR( ostream &ret, GenInlineItem *ilItem, bool inFinish ); void CALL_EXPR( ostream &ret, GenInlineItem *ilItem, int targState, bool inFinish ); void CURS( ostream &ret, bool inFinish ); void TARGS( ostream &ret, bool inFinish, int targState ); void RET( ostream &ret, bool inFinish ); void BREAK( ostream &ret, int targState ); virtual std::ostream &TO_STATE_ACTION( RedStateAp *state ); virtual std::ostream &FROM_STATE_ACTION( RedStateAp *state ); virtual std::ostream &EOF_ACTION( RedStateAp *state ); virtual std::ostream &TRANS_ACTION( RedTransAp *trans ); virtual void writeData(); virtual void writeExec(); void initVarTypes(); string slenType, transType, indsType, condsType; }; #endif ragel-6.8/ragel/gotable.h0000664000175000017500000000452412106050031012255 00000000000000/* * Copyright 2001-2006 Adrian Thurston * 2004 Erich Ocean * 2005 Alan West */ /* This file is part of Ragel. * * Ragel is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Ragel is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Ragel; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef _GOTABLE_H #define _GOTABLE_H #include #include "gotablish.h" class GoTabCodeGen : public GoTablishCodeGen { public: GoTabCodeGen( ostream &out ) : GoTablishCodeGen(out) {} virtual ~GoTabCodeGen() { } virtual void writeData(); virtual void writeExec(); protected: std::ostream &TO_STATE_ACTION_SWITCH( int level ); std::ostream &FROM_STATE_ACTION_SWITCH( int level ); std::ostream &EOF_ACTION_SWITCH( int level ); std::ostream &ACTION_SWITCH( int level ); std::ostream &COND_KEYS(); std::ostream &COND_SPACES(); std::ostream &KEYS(); std::ostream &INDICIES(); std::ostream &COND_OFFSETS(); std::ostream &KEY_OFFSETS(); std::ostream &INDEX_OFFSETS(); std::ostream &COND_LENS(); std::ostream &SINGLE_LENS(); std::ostream &RANGE_LENS(); std::ostream &TO_STATE_ACTIONS(); std::ostream &FROM_STATE_ACTIONS(); std::ostream &EOF_ACTIONS(); std::ostream &EOF_TRANS(); std::ostream &TRANS_TARGS(); std::ostream &TRANS_ACTIONS(); std::ostream &TRANS_TARGS_WI(); std::ostream &TRANS_ACTIONS_WI(); void LOCATE_TRANS(); void COND_TRANSLATE(); virtual std::ostream &TO_STATE_ACTION( RedStateAp *state ); virtual std::ostream &FROM_STATE_ACTION( RedStateAp *state ); virtual std::ostream &EOF_ACTION( RedStateAp *state ); virtual std::ostream &TRANS_ACTION( RedTransAp *trans ); virtual void calcIndexSize(); }; #endif ragel-6.8/ragel/dotcodegen.cpp0000664000175000017500000002032412106050031013302 00000000000000/* * Copyright 2001-2007 Adrian Thurston */ /* This file is part of Ragel. * * Ragel is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Ragel is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Ragel; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "ragel.h" #include "dotcodegen.h" #include "gendata.h" using std::istream; using std::ifstream; using std::ostream; using std::ios; using std::cin; using std::cout; using std::cerr; using std::endl; /* Override this so that write statement processing is ignored */ void GraphvizDotGen::writeStatement( InputLoc &, int, char ** ) { } std::ostream &GraphvizDotGen::KEY( Key key ) { if ( displayPrintables && key.isPrintable() ) { // Output values as characters, ensuring we escape the quote (") character char cVal = (char) key.getVal(); switch ( cVal ) { case '"': case '\\': out << "'\\" << cVal << "'"; break; case '\a': out << "'\\\\a'"; break; case '\b': out << "'\\\\b'"; break; case '\t': out << "'\\\\t'"; break; case '\n': out << "'\\\\n'"; break; case '\v': out << "'\\\\v'"; break; case '\f': out << "'\\\\f'"; break; case '\r': out << "'\\\\r'"; break; case ' ': out << "SP"; break; default: out << "'" << cVal << "'"; break; } } else { if ( keyOps->isSigned ) out << key.getVal(); else out << (unsigned long) key.getVal(); } return out; } std::ostream &GraphvizDotGen::TRANS_ACTION( RedStateAp *fromState, RedTransAp *trans ) { int n = 0; RedAction *actions[3]; if ( fromState->fromStateAction != 0 ) actions[n++] = fromState->fromStateAction; if ( trans->action != 0 ) actions[n++] = trans->action; if ( trans->targ != 0 && trans->targ->toStateAction != 0 ) actions[n++] = trans->targ->toStateAction; if ( n > 0 ) out << " / "; /* Loop the existing actions and write out what's there. */ for ( int a = 0; a < n; a++ ) { for ( GenActionTable::Iter actIt = actions[a]->key.first(); actIt.lte(); actIt++ ) { GenAction *action = actIt->value; out << action->nameOrLoc(); if ( a < n-1 || !actIt.last() ) out << ", "; } } return out; } std::ostream &GraphvizDotGen::ACTION( RedAction *action ) { /* The action. */ out << " / "; for ( GenActionTable::Iter actIt = action->key.first(); actIt.lte(); actIt++ ) { GenAction *action = actIt->value; if ( action->name != 0 ) out << action->name; else out << action->loc.line << ":" << action->loc.col; if ( !actIt.last() ) out << ", "; } return out; } std::ostream &GraphvizDotGen::ONCHAR( Key lowKey, Key highKey ) { GenCondSpace *condSpace; if ( lowKey > keyOps->maxKey && (condSpace=findCondSpace(lowKey, highKey) ) ) { Key values = ( lowKey - condSpace->baseKey ) / keyOps->alphSize(); lowKey = keyOps->minKey + (lowKey - condSpace->baseKey - keyOps->alphSize() * values.getVal()); highKey = keyOps->minKey + (highKey - condSpace->baseKey - keyOps->alphSize() * values.getVal()); KEY( lowKey ); if ( lowKey != highKey ) { out << ".."; KEY( highKey ); } out << "("; for ( GenCondSet::Iter csi = condSpace->condSet; csi.lte(); csi++ ) { bool set = values & (1 << csi.pos()); if ( !set ) out << "!"; out << (*csi)->nameOrLoc(); if ( !csi.last() ) out << ", "; } out << ")"; } else { /* Output the key. Possibly a range. */ KEY( lowKey ); if ( highKey != lowKey ) { out << ".."; KEY( highKey ); } } return out; } void GraphvizDotGen::writeTransList( RedStateAp *state ) { /* Build the set of unique transitions out of this state. */ RedTransSet stTransSet; for ( RedTransList::Iter tel = state->outRange; tel.lte(); tel++ ) { /* If we haven't seen the transitions before, the move forward * emitting all the transitions on the same character. */ if ( stTransSet.insert( tel->value ) ) { /* Write out the from and to states. */ out << "\t" << state->id << " -> "; if ( tel->value->targ == 0 ) out << "err_" << state->id; else out << tel->value->targ->id; /* Begin the label. */ out << " [ label = \""; ONCHAR( tel->lowKey, tel->highKey ); /* Walk the transition list, finding the same. */ for ( RedTransList::Iter mtel = tel.next(); mtel.lte(); mtel++ ) { if ( mtel->value == tel->value ) { out << ", "; ONCHAR( mtel->lowKey, mtel->highKey ); } } /* Write the action and close the transition. */ TRANS_ACTION( state, tel->value ); out << "\" ];\n"; } } /* Write the default transition. */ if ( state->defTrans != 0 ) { /* Write out the from and to states. */ out << "\t" << state->id << " -> "; if ( state->defTrans->targ == 0 ) out << "err_" << state->id; else out << state->defTrans->targ->id; /* Begin the label. */ out << " [ label = \"DEF"; /* Write the action and close the transition. */ TRANS_ACTION( state, state->defTrans ); out << "\" ];\n"; } } void GraphvizDotGen::writeDotFile( ) { out << "digraph " << fsmName << " {\n" " rankdir=LR;\n"; /* Define the psuedo states. Transitions will be done after the states * have been defined as either final or not final. */ out << " node [ shape = point ];\n"; if ( redFsm->startState != 0 ) out << " ENTRY;\n"; /* Psuedo states for entry points in the entry map. */ for ( EntryIdVect::Iter en = entryPointIds; en.lte(); en++ ) { RedStateAp *state = allStates + *en; out << " en_" << state->id << ";\n"; } /* Psuedo states for final states with eof actions. */ for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { if ( st->eofTrans != 0 && st->eofTrans->action != 0 ) out << " eof_" << st->id << ";\n"; if ( st->eofAction != 0 ) out << " eof_" << st->id << ";\n"; } out << " node [ shape = circle, height = 0.2 ];\n"; /* Psuedo states for states whose default actions go to error. */ for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { bool needsErr = false; if ( st->defTrans != 0 && st->defTrans->targ == 0 ) needsErr = true; else { for ( RedTransList::Iter tel = st->outRange; tel.lte(); tel++ ) { if ( tel->value->targ == 0 ) { needsErr = true; break; } } } if ( needsErr ) out << " err_" << st->id << " [ label=\"\"];\n"; } /* Attributes common to all nodes, plus double circle for final states. */ out << " node [ fixedsize = true, height = 0.65, shape = doublecircle ];\n"; /* List Final states. */ for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { if ( st->isFinal ) out << " " << st->id << ";\n"; } /* List transitions. */ out << " node [ shape = circle ];\n"; /* Walk the states. */ for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) writeTransList( st ); /* Transitions into the start state. */ if ( redFsm->startState != 0 ) out << " ENTRY -> " << redFsm->startState->id << " [ label = \"IN\" ];\n"; /* Transitions into the entry points. */ for ( EntryIdVect::Iter en = entryPointIds; en.lte(); en++ ) { RedStateAp *state = allStates + *en; char *name = entryPointNames[en.pos()]; out << " en_" << state->id << " -> " << state->id << " [ label = \"" << name << "\" ];\n"; } /* Out action transitions. */ for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { if ( st->eofTrans != 0 && st->eofTrans->action != 0 ) { out << " " << st->id << " -> eof_" << st->id << " [ label = \"EOF"; ACTION( st->eofTrans->action ) << "\" ];\n"; } if ( st->eofAction != 0 ) { out << " " << st->id << " -> eof_" << st->id << " [ label = \"EOF"; ACTION( st->eofAction ) << "\" ];\n"; } } out << "}\n"; } void GraphvizDotGen::finishRagelDef() { /* For dot file generation we want to pick default transitions. */ redFsm->chooseDefaultSpan(); } ragel-6.8/ragel/rbxgoto.cpp0000664000175000017500000005306512106050031012663 00000000000000/* * Copyright 2007 Victor Hugo Borja * 2006-2007 Adrian Thurston */ /* This file is part of Ragel. * * Ragel is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Ragel is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Ragel; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #include "rbxgoto.h" #include "ragel.h" #include "redfsm.h" #include "bstmap.h" #include "gendata.h" using std::ostream; using std::string; inline string label(string a, int i) { return a + itoa(i); } ostream &RbxGotoCodeGen::rbxLabel(ostream &out, string label) { out << "Rubinius.asm { @labels[:_" << FSM_NAME() << "_" << label << "].set! }\n"; return out; } ostream &RbxGotoCodeGen::rbxGoto(ostream &out, string label) { out << "Rubinius.asm { goto @labels[:_" << FSM_NAME() << "_" << label << "] }\n"; return out; } /* Emit the goto to take for a given transition. */ std::ostream &RbxGotoCodeGen::TRANS_GOTO( RedTransAp *trans, int level ) { out << TABS(level); return rbxGoto(out, label("tr",trans->id)); } std::ostream &RbxGotoCodeGen::TO_STATE_ACTION_SWITCH() { /* Walk the list of functions, printing the cases. */ for ( GenActionList::Iter act = actionList; act.lte(); act++ ) { /* Write out referenced actions. */ if ( act->numToStateRefs > 0 ) { /* Write the case label, the action and the case break. */ out << "\twhen " << act->actionId << " then\n"; ACTION( out, act, 0, false ); } } genLineDirective( out ); return out; } std::ostream &RbxGotoCodeGen::FROM_STATE_ACTION_SWITCH() { /* Walk the list of functions, printing the cases. */ for ( GenActionList::Iter act = actionList; act.lte(); act++ ) { /* Write out referenced actions. */ if ( act->numFromStateRefs > 0 ) { /* Write the case label, the action and the case break. */ out << "\twhen " << act->actionId << " then\n"; ACTION( out, act, 0, false ); } } genLineDirective( out ); return out; } std::ostream &RbxGotoCodeGen::EOF_ACTION_SWITCH() { /* Walk the list of functions, printing the cases. */ for ( GenActionList::Iter act = actionList; act.lte(); act++ ) { /* Write out referenced actions. */ if ( act->numEofRefs > 0 ) { /* Write the case label, the action and the case break. */ out << "\twhen " << act->actionId << " then\n"; ACTION( out, act, 0, true ); } } genLineDirective( out ); return out; } std::ostream &RbxGotoCodeGen::ACTION_SWITCH() { /* Walk the list of functions, printing the cases. */ for ( GenActionList::Iter act = actionList; act.lte(); act++ ) { /* Write out referenced actions. */ if ( act->numTransRefs > 0 ) { /* Write the case label, the action and the case break. */ out << "\twhen " << act->actionId << " then\n"; ACTION( out, act, 0, false ); } } genLineDirective( out ); return out; } void RbxGotoCodeGen::GOTO_HEADER( RedStateAp *state ) { /* Label the state. */ out << "when " << state->id << " then\n"; } void RbxGotoCodeGen::emitSingleSwitch( RedStateAp *state ) { /* Load up the singles. */ int numSingles = state->outSingle.length(); RedTransEl *data = state->outSingle.data; if ( numSingles == 1 ) { /* If there is a single single key then write it out as an if. */ out << "\tif " << GET_WIDE_KEY(state) << " == " << KEY(data[0].lowKey) << " \n\t\t"; /* Virtual function for writing the target of the transition. */ TRANS_GOTO(data[0].value, 0) << "\n"; out << "end\n"; } else if ( numSingles > 1 ) { /* Write out single keys in a switch if there is more than one. */ out << "\tcase " << GET_WIDE_KEY(state) << "\n"; /* Write out the single indicies. */ for ( int j = 0; j < numSingles; j++ ) { out << "\t\twhen " << KEY(data[j].lowKey) << " then\n"; TRANS_GOTO(data[j].value, 0) << "\n"; } /* Close off the transition switch. */ out << "\tend\n"; } } void RbxGotoCodeGen::emitRangeBSearch( RedStateAp *state, int level, int low, int high ) { /* Get the mid position, staying on the lower end of the range. */ int mid = (low + high) >> 1; RedTransEl *data = state->outRange.data; /* Determine if we need to look higher or lower. */ bool anyLower = mid > low; bool anyHigher = mid < high; /* Determine if the keys at mid are the limits of the alphabet. */ bool limitLow = data[mid].lowKey == keyOps->minKey; bool limitHigh = data[mid].highKey == keyOps->maxKey; if ( anyLower && anyHigher ) { /* Can go lower and higher than mid. */ out << TABS(level) << "if " << GET_WIDE_KEY(state) << " < " << KEY(data[mid].lowKey) << " \n"; emitRangeBSearch( state, level+1, low, mid-1 ); out << TABS(level) << "elsif " << GET_WIDE_KEY(state) << " > " << KEY(data[mid].highKey) << " \n"; emitRangeBSearch( state, level+1, mid+1, high ); out << TABS(level) << "else\n"; TRANS_GOTO(data[mid].value, level+1) << "\n"; out << TABS(level) << "end\n"; } else if ( anyLower && !anyHigher ) { /* Can go lower than mid but not higher. */ out << TABS(level) << "if " << GET_WIDE_KEY(state) << " < " << KEY(data[mid].lowKey) << " then\n"; emitRangeBSearch( state, level+1, low, mid-1 ); /* if the higher is the highest in the alphabet then there is no * sense testing it. */ if ( limitHigh ) { out << TABS(level) << "else\n"; TRANS_GOTO(data[mid].value, level+1) << "\n"; } else { out << TABS(level) << "elsif" << GET_WIDE_KEY(state) << " <= " << KEY(data[mid].highKey) << " )\n"; TRANS_GOTO(data[mid].value, level+1) << "\n"; } out << TABS(level) << "end\n"; } else if ( !anyLower && anyHigher ) { /* Can go higher than mid but not lower. */ out << TABS(level) << "if " << GET_WIDE_KEY(state) << " > " << KEY(data[mid].highKey) << " \n"; emitRangeBSearch( state, level+1, mid+1, high ); /* If the lower end is the lowest in the alphabet then there is no * sense testing it. */ if ( limitLow ) { out << TABS(level) << "else\n"; TRANS_GOTO(data[mid].value, level+1) << "\n"; } else { out << TABS(level) << "elsif " << GET_WIDE_KEY(state) << " >= " << KEY(data[mid].lowKey) << " then\n"; TRANS_GOTO(data[mid].value, level+1) << "\n"; } out << TABS(level) << "end\n"; } else { /* Cannot go higher or lower than mid. It's mid or bust. What * tests to do depends on limits of alphabet. */ if ( !limitLow && !limitHigh ) { out << TABS(level) << "if " << KEY(data[mid].lowKey) << " <= " << GET_WIDE_KEY(state) << " && " << GET_WIDE_KEY(state) << " <= " << KEY(data[mid].highKey) << " \n"; TRANS_GOTO(data[mid].value, level+1) << "\n"; out << TABS(level) << "end\n"; } else if ( limitLow && !limitHigh ) { out << TABS(level) << "if " << GET_WIDE_KEY(state) << " <= " << KEY(data[mid].highKey) << " \n"; TRANS_GOTO(data[mid].value, level+1) << "\n"; out << TABS(level) << "end\n"; } else if ( !limitLow && limitHigh ) { out << TABS(level) << "if " << KEY(data[mid].lowKey) << " <= " << GET_WIDE_KEY(state) << " \n"; TRANS_GOTO(data[mid].value, level+1) << "\n"; out << TABS(level) << "end\n"; } else { /* Both high and low are at the limit. No tests to do. */ TRANS_GOTO(data[mid].value, level+1) << "\n"; } } } void RbxGotoCodeGen::STATE_GOTO_ERROR() { /* Label the state and bail immediately. */ outLabelUsed = true; RedStateAp *state = redFsm->errState; out << "when " << state->id << " then\n"; rbxGoto(out << " ", "_out") << "\n"; } void RbxGotoCodeGen::COND_TRANSLATE( GenStateCond *stateCond, int level ) { GenCondSpace *condSpace = stateCond->condSpace; out << TABS(level) << "_widec = " << KEY(condSpace->baseKey) << " + (" << GET_KEY() << " - " << KEY(keyOps->minKey) << ");\n"; for ( GenCondSet::Iter csi = condSpace->condSet; csi.lte(); csi++ ) { out << TABS(level) << "if "; CONDITION( out, *csi ); Size condValOffset = ((1 << csi.pos()) * keyOps->alphSize()); out << "\n _widec += " << condValOffset << ";\n end"; } } void RbxGotoCodeGen::emitCondBSearch( RedStateAp *state, int level, int low, int high ) { /* Get the mid position, staying on the lower end of the range. */ int mid = (low + high) >> 1; GenStateCond **data = state->stateCondVect.data; /* Determine if we need to look higher or lower. */ bool anyLower = mid > low; bool anyHigher = mid < high; /* Determine if the keys at mid are the limits of the alphabet. */ bool limitLow = data[mid]->lowKey == keyOps->minKey; bool limitHigh = data[mid]->highKey == keyOps->maxKey; if ( anyLower && anyHigher ) { /* Can go lower and higher than mid. */ out << TABS(level) << "if " << GET_KEY() << " < " << KEY(data[mid]->lowKey) << " \n"; emitCondBSearch( state, level+1, low, mid-1 ); out << TABS(level) << "elsif " << GET_KEY() << " > " << KEY(data[mid]->highKey) << " \n"; emitCondBSearch( state, level+1, mid+1, high ); out << TABS(level) << "else\n"; COND_TRANSLATE(data[mid], level+1); out << TABS(level) << "end\n"; } else if ( anyLower && !anyHigher ) { /* Can go lower than mid but not higher. */ out << TABS(level) << "if " << GET_KEY() << " < " << KEY(data[mid]->lowKey) << " \n"; emitCondBSearch( state, level+1, low, mid-1 ); /* if the higher is the highest in the alphabet then there is no * sense testing it. */ if ( limitHigh ) { out << TABS(level) << "else\n"; COND_TRANSLATE(data[mid], level+1); } else { out << TABS(level) << "elsif " << GET_KEY() << " <= " << KEY(data[mid]->highKey) << " then\n"; COND_TRANSLATE(data[mid], level+1); } out << TABS(level) << "end\n"; } else if ( !anyLower && anyHigher ) { /* Can go higher than mid but not lower. */ out << TABS(level) << "if " << GET_KEY() << " > " << KEY(data[mid]->highKey) << " \n"; emitCondBSearch( state, level+1, mid+1, high ); /* If the lower end is the lowest in the alphabet then there is no * sense testing it. */ if ( limitLow ) { out << TABS(level) << "else\n"; COND_TRANSLATE(data[mid], level+1); } else { out << TABS(level) << "elsif " << GET_KEY() << " >= " << KEY(data[mid]->lowKey) << " then\n"; COND_TRANSLATE(data[mid], level+1); } out << TABS(level) << "end\n"; } else { /* Cannot go higher or lower than mid. It's mid or bust. What * tests to do depends on limits of alphabet. */ if ( !limitLow && !limitHigh ) { out << TABS(level) << "if " << KEY(data[mid]->lowKey) << " <= " << GET_KEY() << " && " << GET_KEY() << " <= " << KEY(data[mid]->highKey) << " then\n"; COND_TRANSLATE(data[mid], level+1); out << TABS(level) << "end\n"; } else if ( limitLow && !limitHigh ) { out << TABS(level) << "if " << GET_KEY() << " <= " << KEY(data[mid]->highKey) << " then\n"; COND_TRANSLATE(data[mid], level+1); out << TABS(level) << "end\n"; } else if ( !limitLow && limitHigh ) { out << TABS(level) << "if " << KEY(data[mid]->lowKey) << " <= " << GET_KEY() << " then\n"; COND_TRANSLATE(data[mid], level+1); out << TABS(level) << "end\n"; } else { /* Both high and low are at the limit. No tests to do. */ COND_TRANSLATE(data[mid], level); } } } std::ostream &RbxGotoCodeGen::STATE_GOTOS() { for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { if ( st == redFsm->errState ) STATE_GOTO_ERROR(); else { /* Writing code above state gotos. */ GOTO_HEADER( st ); if ( st->stateCondVect.length() > 0 ) { out << " _widec = " << GET_KEY() << ";\n"; emitCondBSearch( st, 1, 0, st->stateCondVect.length() - 1 ); } /* Try singles. */ if ( st->outSingle.length() > 0 ) emitSingleSwitch( st ); /* Default case is to binary search for the ranges, if that fails then */ if ( st->outRange.length() > 0 ) emitRangeBSearch( st, 1, 0, st->outRange.length() - 1 ); /* Write the default transition. */ TRANS_GOTO( st->defTrans, 1 ) << "\n"; } } return out; } std::ostream &RbxGotoCodeGen::TRANSITIONS() { /* Emit any transitions that have functions and that go to * this state. */ for ( TransApSet::Iter trans = redFsm->transSet; trans.lte(); trans++ ) { /* Write the label for the transition so it can be jumped to. */ rbxLabel(out << " ", label("tr", trans->id)) << "\n"; /* Destination state. */ if ( trans->action != 0 && trans->action->anyCurStateRef() ) out << "_ps = " << vCS() << "'n"; out << vCS() << " = " << trans->targ->id << "\n"; if ( trans->action != 0 ) { /* Write out the transition func. */ rbxGoto(out, label("f", trans->action->actListId)) << "\n"; } else { /* No code to execute, just loop around. */ rbxGoto(out, "_again") << "\n"; } } return out; } std::ostream &RbxGotoCodeGen::EXEC_FUNCS() { /* Make labels that set acts and jump to execFuncs. Loop func indicies. */ for ( GenActionTableMap::Iter redAct = redFsm->actionMap; redAct.lte(); redAct++ ) { if ( redAct->numTransRefs > 0 ) { rbxLabel(out, label("f", redAct->actListId)) << "\n" << "_acts = " << itoa( redAct->location+1 ) << "\n"; rbxGoto(out, "execFuncs") << "\n"; } } rbxLabel(out, "execFuncs") << "\n" " _nacts = " << A() << "[_acts]\n" " _acts += 1\n" " while ( _nacts > 0 ) \n" " _nacts -= 1\n" " _acts += 1\n" " case ( "<< A() << "[_acts-1] ) \n"; ACTION_SWITCH(); out << " end\n" " end \n"; rbxGoto(out, "_again"); return out; } int RbxGotoCodeGen::TO_STATE_ACTION( RedStateAp *state ) { int act = 0; if ( state->toStateAction != 0 ) act = state->toStateAction->location+1; return act; } int RbxGotoCodeGen::FROM_STATE_ACTION( RedStateAp *state ) { int act = 0; if ( state->fromStateAction != 0 ) act = state->fromStateAction->location+1; return act; } int RbxGotoCodeGen::EOF_ACTION( RedStateAp *state ) { int act = 0; if ( state->eofAction != 0 ) act = state->eofAction->location+1; return act; } std::ostream &RbxGotoCodeGen::TO_STATE_ACTIONS() { /* Take one off for the psuedo start state. */ int numStates = redFsm->stateList.length(); unsigned int *vals = new unsigned int[numStates]; memset( vals, 0, sizeof(unsigned int)*numStates ); for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) vals[st->id] = TO_STATE_ACTION(st); out << "\t"; for ( int st = 0; st < redFsm->nextStateId; st++ ) { /* Write any eof action. */ out << vals[st]; if ( st < numStates-1 ) { out << ", "; if ( (st+1) % IALL == 0 ) out << "\n\t"; } } out << "\n"; delete[] vals; return out; } std::ostream &RbxGotoCodeGen::FROM_STATE_ACTIONS() { /* Take one off for the psuedo start state. */ int numStates = redFsm->stateList.length(); unsigned int *vals = new unsigned int[numStates]; memset( vals, 0, sizeof(unsigned int)*numStates ); for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) vals[st->id] = FROM_STATE_ACTION(st); out << "\t"; for ( int st = 0; st < redFsm->nextStateId; st++ ) { /* Write any eof action. */ out << vals[st]; if ( st < numStates-1 ) { out << ", "; if ( (st+1) % IALL == 0 ) out << "\n\t"; } } out << "\n"; delete[] vals; return out; } std::ostream &RbxGotoCodeGen::EOF_ACTIONS() { /* Take one off for the psuedo start state. */ int numStates = redFsm->stateList.length(); unsigned int *vals = new unsigned int[numStates]; memset( vals, 0, sizeof(unsigned int)*numStates ); for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) vals[st->id] = EOF_ACTION(st); out << "\t"; for ( int st = 0; st < redFsm->nextStateId; st++ ) { /* Write any eof action. */ out << vals[st]; if ( st < numStates-1 ) { out << ", "; if ( (st+1) % IALL == 0 ) out << "\n\t"; } } out << "\n"; delete[] vals; return out; } std::ostream &RbxGotoCodeGen::FINISH_CASES() { for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { /* States that are final and have an out action need a case. */ if ( st->eofAction != 0 ) { /* Write the case label. */ out << "\t\twhen " << st->id << " then\n"; /* Write the goto func. */ rbxGoto(out, label("f", st->eofAction->actListId)) << "\n"; } } return out; } void RbxGotoCodeGen::GOTO( ostream &ret, int gotoDest, bool inFinish ) { ret << "begin\n" << vCS() << " = " << gotoDest << " "; rbxGoto(ret, "_again") << "\nend\n"; } void RbxGotoCodeGen::GOTO_EXPR( ostream &ret, GenInlineItem *ilItem, bool inFinish ) { ret << "begin\n" << vCS() << " = ("; INLINE_LIST( ret, ilItem->children, 0, inFinish ); ret << ")"; rbxGoto(ret, "_again") << "\nend\n"; } void RbxGotoCodeGen::CURS( ostream &ret, bool inFinish ) { ret << "(_ps)"; } void RbxGotoCodeGen::TARGS( ostream &ret, bool inFinish, int targState ) { ret << "(" << vCS() << ")"; } void RbxGotoCodeGen::NEXT( ostream &ret, int nextDest, bool inFinish ) { ret << vCS() << " = " << nextDest << ";"; } void RbxGotoCodeGen::NEXT_EXPR( ostream &ret, GenInlineItem *ilItem, bool inFinish ) { ret << vCS() << " = ("; INLINE_LIST( ret, ilItem->children, 0, inFinish ); ret << ");"; } void RbxGotoCodeGen::CALL( ostream &ret, int callDest, int targState, bool inFinish ) { if ( prePushExpr != 0 ) { ret << "{"; INLINE_LIST( ret, prePushExpr, 0, false ); } ret << "begin\n" << STACK() << "[" << TOP() << "++] = " << vCS() << "; " << vCS() << " = " << callDest << "; "; rbxGoto(ret, "_again") << "\nend\n"; if ( prePushExpr != 0 ) ret << "}"; } void RbxGotoCodeGen::CALL_EXPR( ostream &ret, GenInlineItem *ilItem, int targState, bool inFinish ) { if ( prePushExpr != 0 ) { ret << "{"; INLINE_LIST( ret, prePushExpr, 0, false ); } ret << "begin\n" << STACK() << "[" << TOP() << "++] = " << vCS() << "; " << vCS() << " = ("; INLINE_LIST( ret, ilItem->children, targState, inFinish ); ret << "); "; rbxGoto(ret, "_again") << "\nend\n"; if ( prePushExpr != 0 ) ret << "}"; } void RbxGotoCodeGen::RET( ostream &ret, bool inFinish ) { ret << "begin\n" << vCS() << " = " << STACK() << "[--" << TOP() << "]; " ; if ( postPopExpr != 0 ) { ret << "{"; INLINE_LIST( ret, postPopExpr, 0, false ); ret << "}"; } rbxGoto(ret, "_again") << "\nend\n"; } void RbxGotoCodeGen::BREAK( ostream &ret, int targState ) { outLabelUsed = true; out << " begin\n" " " << P() << " += 1\n" " " << rbxGoto(ret, "_out") << "\n" " end\n"; } void RbxGotoCodeGen::writeData() { if ( redFsm->anyActions() ) { OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActArrItem), A() ); ACTIONS_ARRAY(); CLOSE_ARRAY() << "\n"; } if ( redFsm->anyToStateActions() ) { OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActionLoc), TSA() ); TO_STATE_ACTIONS(); CLOSE_ARRAY() << "\n"; } if ( redFsm->anyFromStateActions() ) { OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActionLoc), FSA() ); FROM_STATE_ACTIONS(); CLOSE_ARRAY() << "\n"; } if ( redFsm->anyEofActions() ) { OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActionLoc), EA() ); EOF_ACTIONS(); CLOSE_ARRAY() << "\n"; } STATE_IDS(); } void RbxGotoCodeGen::writeExec() { outLabelUsed = false; out << " begin\n"; out << " Rubinius.asm { @labels = Hash.new { |h,k| h[k] = new_label } }\n"; if ( redFsm->anyRegCurStateRef() ) out << " _ps = 0;\n"; if ( redFsm->anyToStateActions() || redFsm->anyRegActions() || redFsm->anyFromStateActions() ) { out << " _acts, _nacts = nil\n"; } if ( redFsm->anyConditions() ) out << " _widec = nil\n"; out << "\n"; if ( !noEnd ) { outLabelUsed = true; out << " if ( " << P() << " == " << PE() << " )\n"; rbxGoto(out << " ", "_out") << "\n" << " end\n"; } if ( redFsm->errState != 0 ) { outLabelUsed = true; out << " if ( " << vCS() << " == " << redFsm->errState->id << " )\n"; rbxGoto(out << " ", "_out") << "\n" << " end\n"; } rbxLabel(out, "_resume") << "\n"; if ( redFsm->anyFromStateActions() ) { out << " _acts = " << ARR_OFF( A(), FSA() + "[" + vCS() + "]" ) << ";\n" " _nacts = " << " *_acts++;\n" " while ( _nacts-- > 0 ) {\n" " switch ( *_acts++ ) {\n"; FROM_STATE_ACTION_SWITCH(); out << " }\n" " }\n" "\n"; } out << " case ( " << vCS() << " )\n"; STATE_GOTOS(); out << " end # case\n" "\n"; TRANSITIONS() << "\n"; if ( redFsm->anyRegActions() ) EXEC_FUNCS() << "\n"; rbxLabel(out, "_again") << "\n"; if ( redFsm->anyToStateActions() ) { out << " _acts = " << ARR_OFF( A(), TSA() + "[" + vCS() + "]" ) << ";\n" " _nacts = " << " *_acts++;\n" " while ( _nacts-- > 0 ) {\n" " switch ( *_acts++ ) {\n"; TO_STATE_ACTION_SWITCH(); out << " }\n" " }\n" "\n"; } if ( redFsm->errState != 0 ) { outLabelUsed = true; out << " if ( " << vCS() << " == " << redFsm->errState->id << " )\n"; rbxGoto(out << " ", "_out") << "\n" << " end" << "\n"; } if ( !noEnd ) { out << " " << P() << " += 1\n" " if ( " << P() << " != " << PE() << " )\n"; rbxGoto(out << " ", "_resume") << "\n" << " end" << "\n"; } else { out << " " << P() << " += 1;\n"; rbxGoto(out << " ", "_resume") << "\n"; } if ( outLabelUsed ) rbxLabel(out, "_out") << "\n"; out << " end\n"; } void RbxGotoCodeGen::writeEOF() { if ( redFsm->anyEofActions() ) { out << " {\n" " _acts = " << ARR_OFF( A(), EA() + "[" + vCS() + "]" ) << ";\n" " " << " _nacts = " << " *_acts++;\n" " while ( _nacts-- > 0 ) {\n" " switch ( *_acts++ ) {\n"; EOF_ACTION_SWITCH(); out << " }\n" " }\n" " }\n" "\n"; } } /* * Local Variables: * mode: c++ * indent-tabs-mode: 1 * c-file-style: "bsd" * End: */ ragel-6.8/ragel/main.cpp0000664000175000017500000003365512106050031012126 00000000000000/* * Copyright 2001-2007 Adrian Thurston */ /* This file is part of Ragel. * * Ragel is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Ragel is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Ragel; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #include #include #include #include #include #include #include #include #include #include #ifdef _WIN32 #include #include #include #include #include #if _MSC_VER #define S_IRUSR _S_IREAD #define S_IWUSR _S_IWRITE #endif #endif /* Parsing. */ #include "ragel.h" #include "rlscan.h" /* Parameters and output. */ #include "pcheck.h" #include "vector.h" #include "version.h" #include "common.h" #include "inputdata.h" using std::istream; using std::ostream; using std::ifstream; using std::ofstream; using std::cin; using std::cout; using std::cerr; using std::endl; using std::ios; using std::streamsize; /* Controls minimization. */ MinimizeLevel minimizeLevel = MinimizePartition2; MinimizeOpt minimizeOpt = MinimizeMostOps; /* Graphviz dot file generation. */ const char *machineSpec = 0, *machineName = 0; bool machineSpecFound = false; bool wantDupsRemoved = true; bool printStatistics = false; bool generateXML = false; bool generateDot = false; /* Target language and output style. */ CodeStyle codeStyle = GenTables; int numSplitPartitions = 0; bool noLineDirectives = false; bool displayPrintables = false; /* Target ruby impl */ RubyImplEnum rubyImpl = MRI; /* Print a summary of the options. */ void usage() { cout << "usage: ragel [options] file\n" "general:\n" " -h, -H, -?, --help Print this usage and exit\n" " -v, --version Print version information and exit\n" " -o Write output to \n" " -s Print some statistics on stderr\n" " -d Do not remove duplicates from action lists\n" " -I Add to the list of directories to search\n" " for included an imported files\n" "error reporting format:\n" " --error-format=gnu file:line:column: message (default)\n" " --error-format=msvc file(line,column): message\n" "fsm minimization:\n" " -n Do not perform minimization\n" " -m Minimize at the end of the compilation\n" " -l Minimize after most operations (default)\n" " -e Minimize after every operation\n" "visualization:\n" " -x Run the frontend only: emit XML intermediate format\n" " -V Generate a dot file for Graphviz\n" " -p Display printable characters on labels\n" " -S FSM specification to output (for graphviz output)\n" " -M Machine definition/instantiation to output (for graphviz output)\n" "host language:\n" " -C The host language is C, C++, Obj-C or Obj-C++ (default)\n" " -D The host language is D\n" " -Z The host language is Go\n" " -J The host language is Java\n" " -R The host language is Ruby\n" " -A The host language is C#\n" " -O The host language is OCaml\n" "line directives: (C/D/Ruby/C#)\n" " -L Inhibit writing of #line directives\n" "code style: (C/D/Java/Ruby/C#)\n" " -T0 Table driven FSM (default)\n" "code style: (C/D/Ruby/C#)\n" " -T1 Faster table driven FSM\n" " -F0 Flat table driven FSM\n" " -F1 Faster flat table-driven FSM\n" "code style: (C/D/C#)\n" " -G0 Goto-driven FSM\n" " -G1 Faster goto-driven FSM\n" "code style: (C/D)\n" " -G2 Really fast goto-driven FSM\n" " -P N-Way Split really fast goto-driven FSM\n" ; exit(0); } /* Print version information and exit. */ void version() { cout << "Ragel State Machine Compiler version " VERSION << " " PUBDATE << endl << "Copyright (c) 2001-2009 by Adrian Thurston" << endl; exit(0); } /* Error reporting format. */ ErrorFormat errorFormat = ErrorFormatGNU; InputLoc makeInputLoc( const char *fileName, int line, int col) { InputLoc loc = { fileName, line, col }; return loc; } ostream &operator<<( ostream &out, const InputLoc &loc ) { assert( loc.fileName != 0 ); switch ( errorFormat ) { case ErrorFormatMSVC: out << loc.fileName << "(" << loc.line; if ( loc.col ) out << "," << loc.col; out << ")"; break; default: out << loc.fileName << ":" << loc.line; if ( loc.col ) out << ":" << loc.col; break; } return out; } /* Total error count. */ int gblErrorCount = 0; /* Print the opening to a warning in the input, then return the error ostream. */ ostream &warning( const InputLoc &loc ) { cerr << loc << ": warning: "; return cerr; } /* Print the opening to a program error, then return the error stream. */ ostream &error() { gblErrorCount += 1; cerr << PROGNAME ": "; return cerr; } ostream &error( const InputLoc &loc ) { gblErrorCount += 1; cerr << loc << ": "; return cerr; } void escapeLineDirectivePath( std::ostream &out, char *path ) { for ( char *pc = path; *pc != 0; pc++ ) { if ( *pc == '\\' ) out << "\\\\"; else out << *pc; } } void processArgs( int argc, const char **argv, InputData &id ) { ParamCheck pc("xo:dnmleabjkS:M:I:CDEJZRAOvHh?-:sT:F:G:P:LpV", argc, argv); /* FIXME: Need to check code styles VS langauge. */ while ( pc.check() ) { switch ( pc.state ) { case ParamCheck::match: switch ( pc.parameter ) { case 'V': generateDot = true; break; case 'x': generateXML = true; break; /* Output. */ case 'o': if ( *pc.paramArg == 0 ) error() << "a zero length output file name was given" << endl; else if ( id.outputFileName != 0 ) error() << "more than one output file name was given" << endl; else { /* Ok, remember the output file name. */ id.outputFileName = pc.paramArg; } break; /* Flag for turning off duplicate action removal. */ case 'd': wantDupsRemoved = false; break; /* Minimization, mostly hidden options. */ case 'n': minimizeOpt = MinimizeNone; break; case 'm': minimizeOpt = MinimizeEnd; break; case 'l': minimizeOpt = MinimizeMostOps; break; case 'e': minimizeOpt = MinimizeEveryOp; break; case 'a': minimizeLevel = MinimizeApprox; break; case 'b': minimizeLevel = MinimizeStable; break; case 'j': minimizeLevel = MinimizePartition1; break; case 'k': minimizeLevel = MinimizePartition2; break; /* Machine spec. */ case 'S': if ( *pc.paramArg == 0 ) error() << "please specify an argument to -S" << endl; else if ( machineSpec != 0 ) error() << "more than one -S argument was given" << endl; else { /* Ok, remember the path to the machine to generate. */ machineSpec = pc.paramArg; } break; /* Machine path. */ case 'M': if ( *pc.paramArg == 0 ) error() << "please specify an argument to -M" << endl; else if ( machineName != 0 ) error() << "more than one -M argument was given" << endl; else { /* Ok, remember the machine name to generate. */ machineName = pc.paramArg; } break; case 'I': if ( *pc.paramArg == 0 ) error() << "please specify an argument to -I" << endl; else { id.includePaths.append( pc.paramArg ); } break; /* Host language types. */ case 'C': hostLang = &hostLangC; break; case 'D': hostLang = &hostLangD; break; case 'E': hostLang = &hostLangD2; break; case 'Z': hostLang = &hostLangGo; break; case 'J': hostLang = &hostLangJava; break; case 'R': hostLang = &hostLangRuby; break; case 'A': hostLang = &hostLangCSharp; break; case 'O': hostLang = &hostLangOCaml; break; /* Version and help. */ case 'v': version(); break; case 'H': case 'h': case '?': usage(); break; case 's': printStatistics = true; break; case '-': { char *arg = strdup( pc.paramArg ); char *eq = strchr( arg, '=' ); if ( eq != 0 ) *eq++ = 0; if ( strcmp( arg, "help" ) == 0 ) usage(); else if ( strcmp( arg, "version" ) == 0 ) version(); else if ( strcmp( arg, "error-format" ) == 0 ) { if ( eq == 0 ) error() << "expecting '=value' for error-format" << endl; else if ( strcmp( eq, "gnu" ) == 0 ) errorFormat = ErrorFormatGNU; else if ( strcmp( eq, "msvc" ) == 0 ) errorFormat = ErrorFormatMSVC; else error() << "invalid value for error-format" << endl; } else if ( strcmp( arg, "rbx" ) == 0 ) rubyImpl = Rubinius; else { error() << "--" << pc.paramArg << " is an invalid argument" << endl; } free( arg ); break; } /* Passthrough args. */ case 'T': if ( pc.paramArg[0] == '0' ) codeStyle = GenTables; else if ( pc.paramArg[0] == '1' ) codeStyle = GenFTables; else { error() << "-T" << pc.paramArg[0] << " is an invalid argument" << endl; exit(1); } break; case 'F': if ( pc.paramArg[0] == '0' ) codeStyle = GenFlat; else if ( pc.paramArg[0] == '1' ) codeStyle = GenFFlat; else { error() << "-F" << pc.paramArg[0] << " is an invalid argument" << endl; exit(1); } break; case 'G': if ( pc.paramArg[0] == '0' ) codeStyle = GenGoto; else if ( pc.paramArg[0] == '1' ) codeStyle = GenFGoto; else if ( pc.paramArg[0] == '2' ) codeStyle = GenIpGoto; else { error() << "-G" << pc.paramArg[0] << " is an invalid argument" << endl; exit(1); } break; case 'P': codeStyle = GenSplit; numSplitPartitions = atoi( pc.paramArg ); break; case 'p': displayPrintables = true; break; case 'L': noLineDirectives = true; break; } break; case ParamCheck::invalid: error() << "-" << pc.parameter << " is an invalid argument" << endl; break; case ParamCheck::noparam: /* It is interpreted as an input file. */ if ( *pc.curArg == 0 ) error() << "a zero length input file name was given" << endl; else if ( id.inputFileName != 0 ) error() << "more than one input file name was given" << endl; else { /* OK, Remember the filename. */ id.inputFileName = pc.curArg; } break; } } } void process( InputData &id ) { /* Open the input file for reading. */ assert( id.inputFileName != 0 ); ifstream *inFile = new ifstream( id.inputFileName ); if ( ! inFile->is_open() ) error() << "could not open " << id.inputFileName << " for reading" << endp; /* Used for just a few things. */ std::ostringstream hostData; /* Make the first input item. */ InputItem *firstInputItem = new InputItem; firstInputItem->type = InputItem::HostData; firstInputItem->loc.fileName = id.inputFileName; firstInputItem->loc.line = 1; firstInputItem->loc.col = 1; id.inputItems.append( firstInputItem ); Scanner scanner( id, id.inputFileName, *inFile, 0, 0, 0, false ); scanner.do_scan(); /* Finished, final check for errors.. */ if ( gblErrorCount > 0 ) exit(1); /* Now send EOF to all parsers. */ id.terminateAllParsers(); /* Bail on above error. */ if ( gblErrorCount > 0 ) exit(1); /* Locate the backend program */ /* Compiles machines. */ id.prepareMachineGen(); if ( gblErrorCount > 0 ) exit(1); id.makeOutputStream(); /* Generates the reduced machine, which we use to write output. */ if ( !generateXML ) { id.generateReduced(); if ( gblErrorCount > 0 ) exit(1); } id.verifyWritesHaveData(); if ( gblErrorCount > 0 ) exit(1); /* * From this point on we should not be reporting any errors. */ id.openOutput(); id.writeOutput(); /* Close the input and the intermediate file. */ delete inFile; /* If writing to a file, delete the ostream, causing it to flush. * Standard out is flushed automatically. */ if ( id.outputFileName != 0 ) { delete id.outStream; delete id.outFilter; } assert( gblErrorCount == 0 ); } char *makeIntermedTemplate( const char *baseFileName ) { char *result = 0; const char *templ = "ragel-XXXXXX.xml"; const char *lastSlash = strrchr( baseFileName, '/' ); if ( lastSlash == 0 ) { result = new char[strlen(templ)+1]; strcpy( result, templ ); } else { int baseLen = lastSlash - baseFileName + 1; result = new char[baseLen + strlen(templ) + 1]; memcpy( result, baseFileName, baseLen ); strcpy( result+baseLen, templ ); } return result; }; /* Main, process args and call yyparse to start scanning input. */ int main( int argc, const char **argv ) { InputData id; processArgs( argc, argv, id ); /* Require an input file. If we use standard in then we won't have a file * name on which to base the output. */ if ( id.inputFileName == 0 ) error() << "no input file given" << endl; /* Bail on argument processing errors. */ if ( gblErrorCount > 0 ) exit(1); /* Make sure we are not writing to the same file as the input file. */ if ( id.inputFileName != 0 && id.outputFileName != 0 && strcmp( id.inputFileName, id.outputFileName ) == 0 ) { error() << "output file \"" << id.outputFileName << "\" is the same as the input file" << endp; } process( id ); return 0; } ragel-6.8/ragel/cdcodegen.h0000664000175000017500000002017112106050031012547 00000000000000/* * Copyright 2001-2006 Adrian Thurston * 2004 Erich Ocean * 2005 Alan West */ /* This file is part of Ragel. * * Ragel is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Ragel is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Ragel; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef _CDCODEGEN_H #define _CDCODEGEN_H #include #include #include #include "common.h" #include "gendata.h" using std::string; using std::ostream; /* Integer array line length. */ #define IALL 8 /* Forwards. */ struct RedFsmAp; struct RedStateAp; struct CodeGenData; struct GenAction; struct NameInst; struct GenInlineItem; struct GenInlineList; struct RedAction; struct LongestMatch; struct LongestMatchPart; string itoa( int i ); /* * class FsmCodeGen */ class FsmCodeGen : public CodeGenData { public: FsmCodeGen( ostream &out ); virtual ~FsmCodeGen() {} virtual void finishRagelDef(); virtual void writeInit(); virtual void writeStart(); virtual void writeFirstFinal(); virtual void writeError(); protected: string FSM_NAME(); string START_STATE_ID(); ostream &ACTIONS_ARRAY(); string GET_WIDE_KEY(); string GET_WIDE_KEY( RedStateAp *state ); string TABS( int level ); string KEY( Key key ); string WIDE_KEY( RedStateAp *state, Key key ); string LDIR_PATH( char *path ); virtual void ACTION( ostream &ret, GenAction *action, int targState, bool inFinish, bool csForced ); void CONDITION( ostream &ret, GenAction *condition ); string ALPH_TYPE(); string WIDE_ALPH_TYPE(); string ARRAY_TYPE( unsigned long maxVal ); bool isAlphTypeSigned(); bool isWideAlphTypeSigned(); virtual string ARR_OFF( string ptr, string offset ) = 0; virtual string CAST( string type ) = 0; virtual string UINT() = 0; virtual string NULL_ITEM() = 0; virtual string POINTER() = 0; virtual string GET_KEY(); virtual ostream &SWITCH_DEFAULT() = 0; string P(); string PE(); string vEOF(); string ACCESS(); string vCS(); string STACK(); string TOP(); string TOKSTART(); string TOKEND(); string ACT(); string DATA_PREFIX(); string PM() { return "_" + DATA_PREFIX() + "partition_map"; } string C() { return "_" + DATA_PREFIX() + "cond_spaces"; } string CK() { return "_" + DATA_PREFIX() + "cond_keys"; } string K() { return "_" + DATA_PREFIX() + "trans_keys"; } string I() { return "_" + DATA_PREFIX() + "indicies"; } string CO() { return "_" + DATA_PREFIX() + "cond_offsets"; } string KO() { return "_" + DATA_PREFIX() + "key_offsets"; } string IO() { return "_" + DATA_PREFIX() + "index_offsets"; } string CL() { return "_" + DATA_PREFIX() + "cond_lengths"; } string SL() { return "_" + DATA_PREFIX() + "single_lengths"; } string RL() { return "_" + DATA_PREFIX() + "range_lengths"; } string A() { return "_" + DATA_PREFIX() + "actions"; } string TA() { return "_" + DATA_PREFIX() + "trans_actions"; } string TT() { return "_" + DATA_PREFIX() + "trans_targs"; } string TSA() { return "_" + DATA_PREFIX() + "to_state_actions"; } string FSA() { return "_" + DATA_PREFIX() + "from_state_actions"; } string EA() { return "_" + DATA_PREFIX() + "eof_actions"; } string ET() { return "_" + DATA_PREFIX() + "eof_trans"; } string SP() { return "_" + DATA_PREFIX() + "key_spans"; } string CSP() { return "_" + DATA_PREFIX() + "cond_key_spans"; } string START() { return DATA_PREFIX() + "start"; } string ERROR() { return DATA_PREFIX() + "error"; } string FIRST_FINAL() { return DATA_PREFIX() + "first_final"; } string CTXDATA() { return DATA_PREFIX() + "ctxdata"; } void INLINE_LIST( ostream &ret, GenInlineList *inlineList, int targState, bool inFinish, bool csForced ); virtual void GOTO( ostream &ret, int gotoDest, bool inFinish ) = 0; virtual void CALL( ostream &ret, int callDest, int targState, bool inFinish ) = 0; virtual void NEXT( ostream &ret, int nextDest, bool inFinish ) = 0; virtual void GOTO_EXPR( ostream &ret, GenInlineItem *ilItem, bool inFinish ) = 0; virtual void NEXT_EXPR( ostream &ret, GenInlineItem *ilItem, bool inFinish ) = 0; virtual void CALL_EXPR( ostream &ret, GenInlineItem *ilItem, int targState, bool inFinish ) = 0; virtual void RET( ostream &ret, bool inFinish ) = 0; virtual void BREAK( ostream &ret, int targState, bool csForced ) = 0; virtual void CURS( ostream &ret, bool inFinish ) = 0; virtual void TARGS( ostream &ret, bool inFinish, int targState ) = 0; void EXEC( ostream &ret, GenInlineItem *item, int targState, int inFinish ); void LM_SWITCH( ostream &ret, GenInlineItem *item, int targState, int inFinish, bool csForced ); void SET_ACT( ostream &ret, GenInlineItem *item ); void INIT_TOKSTART( ostream &ret, GenInlineItem *item ); void INIT_ACT( ostream &ret, GenInlineItem *item ); void SET_TOKSTART( ostream &ret, GenInlineItem *item ); void SET_TOKEND( ostream &ret, GenInlineItem *item ); void GET_TOKEND( ostream &ret, GenInlineItem *item ); virtual void SUB_ACTION( ostream &ret, GenInlineItem *item, int targState, bool inFinish, bool csForced ); void STATE_IDS(); string ERROR_STATE(); string FIRST_FINAL_STATE(); virtual string PTR_CONST() = 0; virtual string PTR_CONST_END() = 0; virtual ostream &OPEN_ARRAY( string type, string name ) = 0; virtual ostream &CLOSE_ARRAY() = 0; virtual ostream &STATIC_VAR( string type, string name ) = 0; virtual string CTRL_FLOW() = 0; ostream &source_warning(const InputLoc &loc); ostream &source_error(const InputLoc &loc); unsigned int arrayTypeSize( unsigned long maxVal ); bool outLabelUsed; bool testEofUsed; bool againLabelUsed; bool useIndicies; void genLineDirective( ostream &out ); public: /* Determine if we should use indicies. */ virtual void calcIndexSize() {} }; class CCodeGen : virtual public FsmCodeGen { public: CCodeGen( ostream &out ) : FsmCodeGen(out) {} virtual string NULL_ITEM(); virtual string POINTER(); virtual ostream &SWITCH_DEFAULT(); virtual ostream &OPEN_ARRAY( string type, string name ); virtual ostream &CLOSE_ARRAY(); virtual ostream &STATIC_VAR( string type, string name ); virtual string ARR_OFF( string ptr, string offset ); virtual string CAST( string type ); virtual string UINT(); virtual string PTR_CONST(); virtual string PTR_CONST_END(); virtual string CTRL_FLOW(); virtual void writeExports(); }; class DCodeGen : virtual public FsmCodeGen { public: DCodeGen( ostream &out ) : FsmCodeGen(out) {} virtual string NULL_ITEM(); virtual string POINTER(); virtual ostream &SWITCH_DEFAULT(); virtual ostream &OPEN_ARRAY( string type, string name ); virtual ostream &CLOSE_ARRAY(); virtual ostream &STATIC_VAR( string type, string name ); virtual string ARR_OFF( string ptr, string offset ); virtual string CAST( string type ); virtual string UINT(); virtual string PTR_CONST(); virtual string PTR_CONST_END(); virtual string CTRL_FLOW(); virtual void writeExports(); }; class D2CodeGen : virtual public FsmCodeGen { public: D2CodeGen( ostream &out ) : FsmCodeGen(out) {} virtual string NULL_ITEM(); virtual string POINTER(); virtual ostream &SWITCH_DEFAULT(); virtual ostream &OPEN_ARRAY( string type, string name ); virtual ostream &CLOSE_ARRAY(); virtual ostream &STATIC_VAR( string type, string name ); virtual string ARR_OFF( string ptr, string offset ); virtual string CAST( string type ); virtual string UINT(); virtual string PTR_CONST(); virtual string PTR_CONST_END(); virtual string CTRL_FLOW(); virtual void writeExports(); virtual void SUB_ACTION( ostream &ret, GenInlineItem *item, int targState, bool inFinish, bool csForced ); virtual void ACTION( ostream &ret, GenAction *action, int targState, bool inFinish, bool csForced ); }; #endif ragel-6.8/ragel/parsetree.h0000664000175000017500000004261412106050031012634 00000000000000/* * Copyright 2001-2006 Adrian Thurston */ /* This file is part of Ragel. * * Ragel is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Ragel is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Ragel; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef _PARSETREE_H #define _PARSETREE_H #include "ragel.h" #include "avlmap.h" #include "bstmap.h" #include "vector.h" #include "dlist.h" struct NameInst; /* Types of builtin machines. */ enum BuiltinMachine { BT_Any, BT_Ascii, BT_Extend, BT_Alpha, BT_Digit, BT_Alnum, BT_Lower, BT_Upper, BT_Cntrl, BT_Graph, BT_Print, BT_Punct, BT_Space, BT_Xdigit, BT_Lambda, BT_Empty }; struct ParseData; /* Leaf type. */ struct Literal; /* Tree nodes. */ struct Term; struct FactorWithAug; struct FactorWithRep; struct FactorWithNeg; struct Factor; struct Expression; struct Join; struct MachineDef; struct LongestMatch; struct LongestMatchPart; struct LmPartList; struct Range; struct LengthDef; /* Type of augmentation. Describes locations in the machine. */ enum AugType { /* Transition actions/priorities. */ at_start, at_all, at_finish, at_leave, /* Global error actions. */ at_start_gbl_error, at_all_gbl_error, at_final_gbl_error, at_not_start_gbl_error, at_not_final_gbl_error, at_middle_gbl_error, /* Local error actions. */ at_start_local_error, at_all_local_error, at_final_local_error, at_not_start_local_error, at_not_final_local_error, at_middle_local_error, /* To State Action embedding. */ at_start_to_state, at_all_to_state, at_final_to_state, at_not_start_to_state, at_not_final_to_state, at_middle_to_state, /* From State Action embedding. */ at_start_from_state, at_all_from_state, at_final_from_state, at_not_start_from_state, at_not_final_from_state, at_middle_from_state, /* EOF Action embedding. */ at_start_eof, at_all_eof, at_final_eof, at_not_start_eof, at_not_final_eof, at_middle_eof }; /* IMPORTANT: These must follow the same order as the state augs in AugType * since we will be using this to compose AugType. */ enum StateAugType { sat_start = 0, sat_all, sat_final, sat_not_start, sat_not_final, sat_middle }; struct Action; struct PriorDesc; struct RegExpr; struct ReItem; struct ReOrBlock; struct ReOrItem; struct ExplicitMachine; struct InlineItem; struct InlineList; /* Reference to a named state. */ typedef Vector NameRef; typedef Vector NameRefList; typedef Vector NameTargList; /* Structure for storing location of epsilon transitons. */ struct EpsilonLink { EpsilonLink( const InputLoc &loc, NameRef &target ) : loc(loc), target(target) { } InputLoc loc; NameRef target; }; struct Label { Label( const InputLoc &loc, char *data ) : loc(loc), data(data) { } InputLoc loc; char *data; }; /* Structrue represents an action assigned to some FactorWithAug node. The * factor with aug will keep an array of these. */ struct ParserAction { ParserAction( const InputLoc &loc, AugType type, int localErrKey, Action *action ) : loc(loc), type(type), localErrKey(localErrKey), action(action) { } InputLoc loc; AugType type; int localErrKey; Action *action; }; struct ConditionTest { ConditionTest( const InputLoc &loc, AugType type, Action *action, bool sense ) : loc(loc), type(type), action(action), sense(sense) { } InputLoc loc; AugType type; Action *action; bool sense; }; struct Token { char *data; int length; InputLoc loc; void append( const Token &other ); void set( const char *str, int len ); }; char *prepareLitString( const InputLoc &loc, const char *src, long length, long &resLen, bool &caseInsensitive ); /* Store the value and type of a priority augmentation. */ struct PriorityAug { PriorityAug( AugType type, int priorKey, int priorValue ) : type(type), priorKey(priorKey), priorValue(priorValue) { } AugType type; int priorKey; int priorValue; }; /* * A Variable Definition */ struct VarDef { VarDef( const char *name, MachineDef *machineDef ) : name(name), machineDef(machineDef), isExport(false) { } /* Parse tree traversal. */ FsmAp *walk( ParseData *pd ); void makeNameTree( const InputLoc &loc, ParseData *pd ); void resolveNameRefs( ParseData *pd ); const char *name; MachineDef *machineDef; bool isExport; }; /* * LongestMatch * * Wherever possible the item match will execute on the character. If not * possible the item match will execute on a lookahead character and either * hold the current char (if one away) or backup. * * How to handle the problem of backing up over a buffer break? * * Don't want to use pending out transitions for embedding item match because * the role of item match action is different: it may sometimes match on the * final transition, or may match on a lookahead character. * * Don't want to invent a new operator just for this. So just trail action * after machine, this means we can only use literal actions. * * The item action may * * What states of the machine will be final. The item actions that wrap around * on the last character will go straight to the start state. * * Some transitions will be lookahead transitions, they will hold the current * character. Crossing them with regular transitions must be restricted * because it does not make sense. The transition cannot simultaneously hold * and consume the current character. */ struct LongestMatchPart { LongestMatchPart( Join *join, Action *action, InputLoc &semiLoc, int longestMatchId ) : join(join), action(action), semiLoc(semiLoc), longestMatchId(longestMatchId), inLmSelect(false) { } InputLoc getLoc(); Join *join; Action *action; InputLoc semiLoc; Action *setActId; Action *actOnLast; Action *actOnNext; Action *actLagBehind; int longestMatchId; bool inLmSelect; LongestMatch *longestMatch; LongestMatchPart *prev, *next; }; /* Declare a new type so that ptreetypes.h need not include dlist.h. */ struct LmPartList : DList {}; struct LongestMatch { /* Construct with a list of joins */ LongestMatch( const InputLoc &loc, LmPartList *longestMatchList ) : loc(loc), longestMatchList(longestMatchList), name(0), lmSwitchHandlesError(false) { } /* Tree traversal. */ FsmAp *walk( ParseData *pd ); void makeNameTree( ParseData *pd ); void resolveNameRefs( ParseData *pd ); void transferScannerLeavingActions( FsmAp *graph ); void runLongestMatch( ParseData *pd, FsmAp *graph ); Action *newAction( ParseData *pd, const InputLoc &loc, const char *name, InlineList *inlineList ); void makeActions( ParseData *pd ); void findName( ParseData *pd ); void restart( FsmAp *graph, TransAp *trans ); InputLoc loc; LmPartList *longestMatchList; const char *name; Action *lmActSelect; bool lmSwitchHandlesError; LongestMatch *next, *prev; }; /* List of Expressions. */ typedef DList ExprList; struct MachineDef { enum Type { JoinType, LongestMatchType, LengthDefType }; MachineDef( Join *join ) : join(join), longestMatch(0), lengthDef(0), type(JoinType) {} MachineDef( LongestMatch *longestMatch ) : join(0), longestMatch(longestMatch), lengthDef(0), type(LongestMatchType) {} MachineDef( LengthDef *lengthDef ) : join(0), longestMatch(0), lengthDef(lengthDef), type(LengthDefType) {} FsmAp *walk( ParseData *pd ); void makeNameTree( ParseData *pd ); void resolveNameRefs( ParseData *pd ); Join *join; LongestMatch *longestMatch; LengthDef *lengthDef; Type type; }; /* * Join */ struct Join { /* Construct with the first expression. */ Join( Expression *expr ); Join( const InputLoc &loc, Expression *expr ); /* Tree traversal. */ FsmAp *walk( ParseData *pd ); FsmAp *walkJoin( ParseData *pd ); void makeNameTree( ParseData *pd ); void resolveNameRefs( ParseData *pd ); /* Data. */ InputLoc loc; ExprList exprList; }; /* * Expression */ struct Expression { enum Type { OrType, IntersectType, SubtractType, StrongSubtractType, TermType, BuiltinType }; /* Construct with an expression on the left and a term on the right. */ Expression( Expression *expression, Term *term, Type type ) : expression(expression), term(term), builtin(builtin), type(type), prev(this), next(this) { } /* Construct with only a term. */ Expression( Term *term ) : expression(0), term(term), builtin(builtin), type(TermType) , prev(this), next(this) { } /* Construct with a builtin type. */ Expression( BuiltinMachine builtin ) : expression(0), term(0), builtin(builtin), type(BuiltinType), prev(this), next(this) { } ~Expression(); /* Tree traversal. */ FsmAp *walk( ParseData *pd, bool lastInSeq = true ); void makeNameTree( ParseData *pd ); void resolveNameRefs( ParseData *pd ); /* Node data. */ Expression *expression; Term *term; BuiltinMachine builtin; Type type; Expression *prev, *next; }; /* * Term */ struct Term { enum Type { ConcatType, RightStartType, RightFinishType, LeftType, FactorWithAugType }; Term( Term *term, FactorWithAug *factorWithAug ) : term(term), factorWithAug(factorWithAug), type(ConcatType) { } Term( Term *term, FactorWithAug *factorWithAug, Type type ) : term(term), factorWithAug(factorWithAug), type(type) { } Term( FactorWithAug *factorWithAug ) : term(0), factorWithAug(factorWithAug), type(FactorWithAugType) { } ~Term(); FsmAp *walk( ParseData *pd, bool lastInSeq = true ); void makeNameTree( ParseData *pd ); void resolveNameRefs( ParseData *pd ); Term *term; FactorWithAug *factorWithAug; Type type; /* Priority descriptor for RightFinish type. */ PriorDesc priorDescs[2]; }; /* Third level of precedence. Augmenting nodes with actions and priorities. */ struct FactorWithAug { FactorWithAug( FactorWithRep *factorWithRep ) : priorDescs(0), factorWithRep(factorWithRep) { } ~FactorWithAug(); /* Tree traversal. */ FsmAp *walk( ParseData *pd ); void makeNameTree( ParseData *pd ); void resolveNameRefs( ParseData *pd ); void assignActions( ParseData *pd, FsmAp *graph, int *actionOrd ); void assignPriorities( FsmAp *graph, int *priorOrd ); void assignConditions( FsmAp *graph ); /* Actions and priorities assigned to the factor node. */ Vector actions; Vector priorityAugs; PriorDesc *priorDescs; Vector
\n" ); fgoto main; } }; '\n' { if ( single_line ) { write( "
\n" ); fgoto main; } }; # Word word { write( "" ); write( ts, te-ts ); write( "\n" ); }; # Decimal integer. integer { write( "" ); write( ts, te-ts ); write( "\n" ); }; # Hexidecimal integer. hex { write( "" ); write( ts, te-ts ); write( "\n" ); }; # Consume comments. '#' [^\n]* '\n'; # Single literal string. "'" ( [^'\\] | /\\./ )* "'" { write( "" ); escapeXML( ts, te-ts ); write( "\n" ); }; # Double literal string. '"' ( [^"\\] | /\\./ )* '"' { write( "" ); escapeXML( ts, te-ts ); write( "\n" ); }; # Or literal. '[' ( [^\]\\] | /\\./ )* ']' { write( "" ); escapeXML( ts, te-ts ); write( "\n" ); }; # Regex Literal. '/' ( [^/\\] | /\\./ ) * '/' { write( "" ); escapeXML( ts, te-ts ); write( "\n" ); }; # Open an inline block '{' { inline_depth = 1; write( "{" ); fgoto ilscan; }; punct { write( "" ); escapeXML( fc ); write( "\n" ); }; default; *|; # # Outside code. # main := |* "'" ( [^'\\] | /\\./ )* "'" => emit; '"' ( [^"\\] | /\\./ )* '"' => emit; '/*' { escapeXML( ts, te-ts ); fcall c_comment; }; '//' [^\n]* '\n' => emit; '%%{' { write( "
\n" ); single_line = false; fgoto rlscan; }; '%%' { write( "
\n" ); single_line = true; fgoto rlscan; }; default { escapeXML( *ts ); }; # EOF. EOF; *|; }%% %% write data nofinal; #define BUFSIZE 2048 int main() { std::ios::sync_with_stdio(false); int cs, act; char *ts, *te; int stack[1], top; static char inbuf[BUFSIZE]; bool single_line = false; int inline_depth = 0; %% write init; bool done = false; int have = 0; while ( !done ) { /* How much space is in the buffer? */ int space = BUFSIZE - have; if ( space == 0 ) { /* Buffer is full. */ cerr << "TOKEN TOO BIG" << endl; exit(1); } /* Read in a block. */ char *p = inbuf + have; cin.read( p, space ); int len = cin.gcount(); char *pe = p + len; char *eof = 0; /* Check for EOF. */ if ( len == 0 ) { eof = pe; done = true; } %% write exec; if ( cs == RagelScan_error ) { /* Machine failed before finding a token. */ cerr << "PARSE ERROR" << endl; exit(1); } if ( ts == 0 ) have = 0; else { /* There is a prefix to preserve, shift it over. */ have = pe - ts; memmove( inbuf, ts, have ); te = inbuf + (te-ts); ts = inbuf; } } return 0; } ragel-6.8/examples/concurrent.cpp0000664000175000017500000003520412106311500014101 00000000000000 #line 1 "concurrent.rl" /* * Show off concurrent abilities. */ #include #include #include using namespace std; #define BUFSIZE 2048 struct Concurrent { int cur_char; int start_word; int start_comment; int start_literal; int cs; int init( ); int execute( const char *data, int len, bool isEof ); int finish( ); }; #line 75 "concurrent.rl" #line 35 "concurrent.cpp" static const int Concurrent_start = 0; static const int Concurrent_first_final = 0; static const int Concurrent_error = -1; static const int Concurrent_en_main = 0; #line 78 "concurrent.rl" int Concurrent::init( ) { #line 48 "concurrent.cpp" { cs = Concurrent_start; } #line 82 "concurrent.rl" cur_char = 0; return 1; } int Concurrent::execute( const char *data, int len, bool isEof ) { const char *p = data; const char *pe = data + len; const char *eof = isEof ? pe : 0; #line 65 "concurrent.cpp" { if ( p == pe ) goto _test_eof; switch ( cs ) { tr1: #line 30 "concurrent.rl" { cur_char += 1; } goto st0; tr5: #line 30 "concurrent.rl" { cur_char += 1; } #line 37 "concurrent.rl" { cout << "word: " << start_word << " " << cur_char-1 << endl; } goto st0; tr19: #line 30 "concurrent.rl" { cur_char += 1; } #line 37 "concurrent.rl" { cout << "word: " << start_word << " " << cur_char-1 << endl; } #line 53 "concurrent.rl" { cout << "literal: " << start_literal << " " << cur_char-1 << endl; } goto st0; tr46: #line 30 "concurrent.rl" { cur_char += 1; } #line 37 "concurrent.rl" { cout << "word: " << start_word << " " << cur_char-1 << endl; } #line 45 "concurrent.rl" { cout << "comment: " << start_comment << " " << cur_char-1 << endl; } goto st0; st0: if ( ++p == pe ) goto _test_eof0; case 0: #line 124 "concurrent.cpp" switch( (*p) ) { case 32: goto tr1; case 39: goto tr2; case 47: goto tr3; } if ( 9 <= (*p) && (*p) <= 13 ) goto tr1; goto tr0; tr0: #line 30 "concurrent.rl" { cur_char += 1; } #line 34 "concurrent.rl" { start_word = cur_char; } goto st1; tr4: #line 30 "concurrent.rl" { cur_char += 1; } goto st1; tr18: #line 30 "concurrent.rl" { cur_char += 1; } #line 53 "concurrent.rl" { cout << "literal: " << start_literal << " " << cur_char-1 << endl; } goto st1; tr45: #line 30 "concurrent.rl" { cur_char += 1; } #line 45 "concurrent.rl" { cout << "comment: " << start_comment << " " << cur_char-1 << endl; } goto st1; st1: if ( ++p == pe ) goto _test_eof1; case 1: #line 175 "concurrent.cpp" switch( (*p) ) { case 32: goto tr5; case 39: goto tr6; case 47: goto tr7; } if ( 9 <= (*p) && (*p) <= 13 ) goto tr5; goto tr4; tr13: #line 30 "concurrent.rl" { cur_char += 1; } #line 34 "concurrent.rl" { start_word = cur_char; } goto st2; tr8: #line 30 "concurrent.rl" { cur_char += 1; } goto st2; tr2: #line 30 "concurrent.rl" { cur_char += 1; } #line 34 "concurrent.rl" { start_word = cur_char; } #line 50 "concurrent.rl" { start_literal = cur_char; } goto st2; tr6: #line 30 "concurrent.rl" { cur_char += 1; } #line 50 "concurrent.rl" { start_literal = cur_char; } goto st2; tr20: #line 30 "concurrent.rl" { cur_char += 1; } #line 53 "concurrent.rl" { cout << "literal: " << start_literal << " " << cur_char-1 << endl; } #line 50 "concurrent.rl" { start_literal = cur_char; } goto st2; tr50: #line 30 "concurrent.rl" { cur_char += 1; } #line 45 "concurrent.rl" { cout << "comment: " << start_comment << " " << cur_char-1 << endl; } goto st2; tr47: #line 30 "concurrent.rl" { cur_char += 1; } #line 45 "concurrent.rl" { cout << "comment: " << start_comment << " " << cur_char-1 << endl; } #line 50 "concurrent.rl" { start_literal = cur_char; } goto st2; st2: if ( ++p == pe ) goto _test_eof2; case 2: #line 269 "concurrent.cpp" switch( (*p) ) { case 32: goto tr9; case 39: goto tr10; case 47: goto tr11; case 92: goto tr12; } if ( 9 <= (*p) && (*p) <= 13 ) goto tr9; goto tr8; tr14: #line 30 "concurrent.rl" { cur_char += 1; } goto st3; tr9: #line 30 "concurrent.rl" { cur_char += 1; } #line 37 "concurrent.rl" { cout << "word: " << start_word << " " << cur_char-1 << endl; } goto st3; tr51: #line 30 "concurrent.rl" { cur_char += 1; } #line 37 "concurrent.rl" { cout << "word: " << start_word << " " << cur_char-1 << endl; } #line 45 "concurrent.rl" { cout << "comment: " << start_comment << " " << cur_char-1 << endl; } goto st3; st3: if ( ++p == pe ) goto _test_eof3; case 3: #line 316 "concurrent.cpp" switch( (*p) ) { case 32: goto tr14; case 39: goto tr15; case 47: goto tr16; case 92: goto tr17; } if ( 9 <= (*p) && (*p) <= 13 ) goto tr14; goto tr13; tr15: #line 30 "concurrent.rl" { cur_char += 1; } #line 34 "concurrent.rl" { start_word = cur_char; } goto st4; tr10: #line 30 "concurrent.rl" { cur_char += 1; } goto st4; tr52: #line 30 "concurrent.rl" { cur_char += 1; } #line 45 "concurrent.rl" { cout << "comment: " << start_comment << " " << cur_char-1 << endl; } goto st4; st4: if ( ++p == pe ) goto _test_eof4; case 4: #line 357 "concurrent.cpp" switch( (*p) ) { case 32: goto tr19; case 39: goto tr20; case 47: goto tr21; } if ( 9 <= (*p) && (*p) <= 13 ) goto tr19; goto tr18; tr3: #line 30 "concurrent.rl" { cur_char += 1; } #line 34 "concurrent.rl" { start_word = cur_char; } #line 42 "concurrent.rl" { start_comment = cur_char; } goto st5; tr7: #line 30 "concurrent.rl" { cur_char += 1; } #line 42 "concurrent.rl" { start_comment = cur_char; } goto st5; tr21: #line 30 "concurrent.rl" { cur_char += 1; } #line 42 "concurrent.rl" { start_comment = cur_char; } #line 53 "concurrent.rl" { cout << "literal: " << start_literal << " " << cur_char-1 << endl; } goto st5; tr48: #line 30 "concurrent.rl" { cur_char += 1; } #line 45 "concurrent.rl" { cout << "comment: " << start_comment << " " << cur_char-1 << endl; } #line 42 "concurrent.rl" { start_comment = cur_char; } goto st5; st5: if ( ++p == pe ) goto _test_eof5; case 5: #line 424 "concurrent.cpp" switch( (*p) ) { case 32: goto tr5; case 39: goto tr6; case 42: goto tr22; case 47: goto tr7; } if ( 9 <= (*p) && (*p) <= 13 ) goto tr5; goto tr4; tr26: #line 30 "concurrent.rl" { cur_char += 1; } #line 34 "concurrent.rl" { start_word = cur_char; } goto st6; tr22: #line 30 "concurrent.rl" { cur_char += 1; } goto st6; tr40: #line 30 "concurrent.rl" { cur_char += 1; } #line 53 "concurrent.rl" { cout << "literal: " << start_literal << " " << cur_char-1 << endl; } goto st6; st6: if ( ++p == pe ) goto _test_eof6; case 6: #line 465 "concurrent.cpp" switch( (*p) ) { case 32: goto tr23; case 39: goto tr24; case 42: goto tr25; } if ( 9 <= (*p) && (*p) <= 13 ) goto tr23; goto tr22; tr27: #line 30 "concurrent.rl" { cur_char += 1; } goto st7; tr23: #line 30 "concurrent.rl" { cur_char += 1; } #line 37 "concurrent.rl" { cout << "word: " << start_word << " " << cur_char-1 << endl; } goto st7; tr41: #line 30 "concurrent.rl" { cur_char += 1; } #line 37 "concurrent.rl" { cout << "word: " << start_word << " " << cur_char-1 << endl; } #line 53 "concurrent.rl" { cout << "literal: " << start_literal << " " << cur_char-1 << endl; } goto st7; st7: if ( ++p == pe ) goto _test_eof7; case 7: #line 511 "concurrent.cpp" switch( (*p) ) { case 32: goto tr27; case 39: goto tr28; case 42: goto tr29; } if ( 9 <= (*p) && (*p) <= 13 ) goto tr27; goto tr26; tr35: #line 30 "concurrent.rl" { cur_char += 1; } #line 34 "concurrent.rl" { start_word = cur_char; } goto st8; tr30: #line 30 "concurrent.rl" { cur_char += 1; } goto st8; tr28: #line 30 "concurrent.rl" { cur_char += 1; } #line 34 "concurrent.rl" { start_word = cur_char; } #line 50 "concurrent.rl" { start_literal = cur_char; } goto st8; tr24: #line 30 "concurrent.rl" { cur_char += 1; } #line 50 "concurrent.rl" { start_literal = cur_char; } goto st8; tr42: #line 30 "concurrent.rl" { cur_char += 1; } #line 53 "concurrent.rl" { cout << "literal: " << start_literal << " " << cur_char-1 << endl; } #line 50 "concurrent.rl" { start_literal = cur_char; } goto st8; st8: if ( ++p == pe ) goto _test_eof8; case 8: #line 579 "concurrent.cpp" switch( (*p) ) { case 32: goto tr31; case 39: goto tr32; case 42: goto tr33; case 92: goto tr34; } if ( 9 <= (*p) && (*p) <= 13 ) goto tr31; goto tr30; tr36: #line 30 "concurrent.rl" { cur_char += 1; } goto st9; tr31: #line 30 "concurrent.rl" { cur_char += 1; } #line 37 "concurrent.rl" { cout << "word: " << start_word << " " << cur_char-1 << endl; } goto st9; st9: if ( ++p == pe ) goto _test_eof9; case 9: #line 610 "concurrent.cpp" switch( (*p) ) { case 32: goto tr36; case 39: goto tr37; case 42: goto tr38; case 92: goto tr39; } if ( 9 <= (*p) && (*p) <= 13 ) goto tr36; goto tr35; tr37: #line 30 "concurrent.rl" { cur_char += 1; } #line 34 "concurrent.rl" { start_word = cur_char; } goto st10; tr32: #line 30 "concurrent.rl" { cur_char += 1; } goto st10; st10: if ( ++p == pe ) goto _test_eof10; case 10: #line 640 "concurrent.cpp" switch( (*p) ) { case 32: goto tr41; case 39: goto tr42; case 42: goto tr43; } if ( 9 <= (*p) && (*p) <= 13 ) goto tr41; goto tr40; tr29: #line 30 "concurrent.rl" { cur_char += 1; } #line 34 "concurrent.rl" { start_word = cur_char; } goto st11; tr25: #line 30 "concurrent.rl" { cur_char += 1; } goto st11; tr43: #line 30 "concurrent.rl" { cur_char += 1; } #line 53 "concurrent.rl" { cout << "literal: " << start_literal << " " << cur_char-1 << endl; } goto st11; st11: if ( ++p == pe ) goto _test_eof11; case 11: #line 680 "concurrent.cpp" switch( (*p) ) { case 32: goto tr23; case 39: goto tr24; case 42: goto tr25; case 47: goto tr44; } if ( 9 <= (*p) && (*p) <= 13 ) goto tr23; goto tr22; tr44: #line 30 "concurrent.rl" { cur_char += 1; } goto st12; st12: if ( ++p == pe ) goto _test_eof12; case 12: #line 700 "concurrent.cpp" switch( (*p) ) { case 32: goto tr46; case 39: goto tr47; case 47: goto tr48; } if ( 9 <= (*p) && (*p) <= 13 ) goto tr46; goto tr45; tr38: #line 30 "concurrent.rl" { cur_char += 1; } #line 34 "concurrent.rl" { start_word = cur_char; } goto st13; tr33: #line 30 "concurrent.rl" { cur_char += 1; } goto st13; st13: if ( ++p == pe ) goto _test_eof13; case 13: #line 729 "concurrent.cpp" switch( (*p) ) { case 32: goto tr31; case 39: goto tr32; case 42: goto tr33; case 47: goto tr49; case 92: goto tr34; } if ( 9 <= (*p) && (*p) <= 13 ) goto tr31; goto tr30; tr49: #line 30 "concurrent.rl" { cur_char += 1; } goto st14; st14: if ( ++p == pe ) goto _test_eof14; case 14: #line 750 "concurrent.cpp" switch( (*p) ) { case 32: goto tr51; case 39: goto tr52; case 47: goto tr53; case 92: goto tr54; } if ( 9 <= (*p) && (*p) <= 13 ) goto tr51; goto tr50; tr16: #line 30 "concurrent.rl" { cur_char += 1; } #line 34 "concurrent.rl" { start_word = cur_char; } #line 42 "concurrent.rl" { start_comment = cur_char; } goto st15; tr11: #line 30 "concurrent.rl" { cur_char += 1; } #line 42 "concurrent.rl" { start_comment = cur_char; } goto st15; tr53: #line 30 "concurrent.rl" { cur_char += 1; } #line 45 "concurrent.rl" { cout << "comment: " << start_comment << " " << cur_char-1 << endl; } #line 42 "concurrent.rl" { start_comment = cur_char; } goto st15; st15: if ( ++p == pe ) goto _test_eof15; case 15: #line 803 "concurrent.cpp" switch( (*p) ) { case 32: goto tr9; case 39: goto tr10; case 42: goto tr30; case 47: goto tr11; case 92: goto tr12; } if ( 9 <= (*p) && (*p) <= 13 ) goto tr9; goto tr8; tr17: #line 30 "concurrent.rl" { cur_char += 1; } #line 34 "concurrent.rl" { start_word = cur_char; } goto st16; tr12: #line 30 "concurrent.rl" { cur_char += 1; } goto st16; tr54: #line 30 "concurrent.rl" { cur_char += 1; } #line 45 "concurrent.rl" { cout << "comment: " << start_comment << " " << cur_char-1 << endl; } goto st16; st16: if ( ++p == pe ) goto _test_eof16; case 16: #line 845 "concurrent.cpp" switch( (*p) ) { case 32: goto tr9; case 47: goto tr11; } if ( 9 <= (*p) && (*p) <= 13 ) goto tr9; goto tr8; tr39: #line 30 "concurrent.rl" { cur_char += 1; } #line 34 "concurrent.rl" { start_word = cur_char; } goto st17; tr34: #line 30 "concurrent.rl" { cur_char += 1; } goto st17; st17: if ( ++p == pe ) goto _test_eof17; case 17: #line 873 "concurrent.cpp" switch( (*p) ) { case 32: goto tr31; case 42: goto tr33; } if ( 9 <= (*p) && (*p) <= 13 ) goto tr31; goto tr30; } _test_eof0: cs = 0; goto _test_eof; _test_eof1: cs = 1; goto _test_eof; _test_eof2: cs = 2; goto _test_eof; _test_eof3: cs = 3; goto _test_eof; _test_eof4: cs = 4; goto _test_eof; _test_eof5: cs = 5; goto _test_eof; _test_eof6: cs = 6; goto _test_eof; _test_eof7: cs = 7; goto _test_eof; _test_eof8: cs = 8; goto _test_eof; _test_eof9: cs = 9; goto _test_eof; _test_eof10: cs = 10; goto _test_eof; _test_eof11: cs = 11; goto _test_eof; _test_eof12: cs = 12; goto _test_eof; _test_eof13: cs = 13; goto _test_eof; _test_eof14: cs = 14; goto _test_eof; _test_eof15: cs = 15; goto _test_eof; _test_eof16: cs = 16; goto _test_eof; _test_eof17: cs = 17; goto _test_eof; _test_eof: {} if ( p == eof ) { switch ( cs ) { case 1: case 2: case 5: case 6: case 8: case 11: case 13: case 15: case 16: case 17: #line 37 "concurrent.rl" { cout << "word: " << start_word << " " << cur_char-1 << endl; } break; case 12: case 14: #line 37 "concurrent.rl" { cout << "word: " << start_word << " " << cur_char-1 << endl; } #line 45 "concurrent.rl" { cout << "comment: " << start_comment << " " << cur_char-1 << endl; } break; case 4: case 10: #line 37 "concurrent.rl" { cout << "word: " << start_word << " " << cur_char-1 << endl; } #line 53 "concurrent.rl" { cout << "literal: " << start_literal << " " << cur_char-1 << endl; } break; #line 947 "concurrent.cpp" } } } #line 93 "concurrent.rl" if ( cs == Concurrent_error ) return -1; if ( cs >= Concurrent_first_final ) return 1; return 0; } int Concurrent::finish( ) { if ( cs == Concurrent_error ) return -1; if ( cs >= Concurrent_first_final ) return 1; return 0; } Concurrent concurrent; char buf[BUFSIZE]; int main() { concurrent.init(); while ( 1 ) { int len = fread( buf, 1, BUFSIZE, stdin ); concurrent.execute( buf, len, len != BUFSIZE ); if ( len != BUFSIZE ) break; } if ( concurrent.finish() <= 0 ) cerr << "concurrent: error parsing input" << endl; return 0; } ragel-6.8/examples/mailbox.rl0000664000175000017500000001045312043335171013216 00000000000000/* * Parses unix mail boxes into headers and bodies. */ #include #include #include #include using namespace std; #define BUFSIZE 2048 /* A growable buffer for collecting headers. */ struct Buffer { Buffer() : data(0), allocated(0), length(0) { } ~Buffer() { empty(); } void append( char p ) { if ( ++length > allocated ) upAllocate( length*2 ); data[length-1] = p; } void clear() { length = 0; } void upAllocate( int len ); void empty(); char *data; int allocated; int length; }; struct MailboxScanner { Buffer headName; Buffer headContent; int cs, top, stack[1]; int init( ); int execute( const char *data, int len, bool isEof ); int finish( ); }; %%{ machine MailboxScanner; # Buffer the header names. action bufHeadName { headName.append(fc); } # Prints a blank line after the end of the headers of each message. action blankLine { cout << endl; } # Helpers we will use in matching the date section of the from line. day = /[A-Z][a-z][a-z]/; month = /[A-Z][a-z][a-z]/; year = /[0-9][0-9][0-9][0-9]/; time = /[0-9][0-9]:[0-9][0-9]/ . ( /:[0-9][0-9]/ | '' ); letterZone = /[A-Z][A-Z][A-Z]/; numZone = /[+\-][0-9][0-9][0-9][0-9]/; zone = letterZone | numZone; dayNum = /[0-9 ][0-9]/; # These are the different formats of the date minus an obscure # type that has a funny string 'remote from xxx' on the end. Taken # from c-client in the imap-2000 distribution. date = day . ' ' . month . ' ' . dayNum . ' ' . time . ' ' . ( year | year . ' ' . zone | zone . ' ' . year ); # From lines separate messages. We will exclude fromLine from a message # body line. This will cause us to stay in message line up until an # entirely correct from line is matched. fromLine = 'From ' . (any-'\n')* . ' ' . date . '\n'; # The types of characters that can be used as a header name. hchar = print - [ :]; # Simply eat up an uninteresting header. Return at the first non-ws # character following a newline. consumeHeader := ( [^\n] | '\n' [ \t] | '\n' [^ \t] @{fhold; fret;} )*; action hchar {headContent.append(fc);} action hspace {headContent.append(' ');} action hfinish { headContent.append(0); cout << headContent.data << endl; headContent.clear(); fhold; fret; } # Display the contents of a header as it is consumed. Collapses line # continuations to a single space. printHeader := ( [^\n] @hchar | ( '\n' ( [ \t]+ '\n' )* [ \t]+ ) %hspace )** $!hfinish; action onHeader { headName.append(0); if ( strcmp( headName.data, "From" ) == 0 || strcmp( headName.data, "To" ) == 0 || strcmp( headName.data, "Subject" ) == 0 ) { /* Print the header name, then jump to a machine the will display * the contents. */ cout << headName.data << ":"; headName.clear(); fcall printHeader; } headName.clear(); fcall consumeHeader; } header = hchar+ $bufHeadName ':' @onHeader; # Exclude fromLine from a messageLine, otherwise when encountering a # fromLine we will be simultaneously matching the old message and a new # message. messageLine = ( [^\n]* '\n' - fromLine ); # An entire message. message = ( fromLine . header* . '\n' @blankLine . messageLine* ); # File is a series of messages. main := message*; }%% %% write data; int MailboxScanner::init( ) { %% write init; return 1; } int MailboxScanner::execute( const char *data, int len, bool isEof ) { const char *p = data; const char *pe = data + len; const char *eof = isEof ? pe : 0; %% write exec; if ( cs == MailboxScanner_error ) return -1; if ( cs >= MailboxScanner_first_final ) return 1; return 0; } int MailboxScanner::finish( ) { if ( cs == MailboxScanner_error ) return -1; if ( cs >= MailboxScanner_first_final ) return 1; return 0; } void Buffer::empty() { if ( data != 0 ) { free( data ); data = 0; length = 0; allocated = 0; } } void Buffer::upAllocate( int len ) { if ( data == 0 ) data = (char*) malloc( len ); else data = (char*) realloc( data, len ); allocated = len; } MailboxScanner mailbox; char buf[BUFSIZE]; int main() { mailbox.init(); while ( 1 ) { int len = fread( buf, 1, BUFSIZE, stdin ); mailbox.execute( buf, len, len != BUFSIZE ); if ( len != BUFSIZE ) break; } if ( mailbox.finish() <= 0 ) cerr << "mailbox: error parsing input" << endl; return 0; } ragel-6.8/examples/format.rl0000664000175000017500000000716512043335171013061 00000000000000/* * Partial printf implementation. */ #define BUFLEN 1024 #include typedef void (*WriteFunc)( char *data, int len ); struct format { char buf[BUFLEN+1]; int buflen; WriteFunc write; int flags; int width; int prec; int cs; }; void do_conv( struct format *fsm, char c ) { printf( "flags: %x\n", fsm->flags ); printf( "width: %i\n", fsm->width ); printf( "prec: %i\n", fsm->prec ); printf( "conv: %c\n", c ); printf( "\n" ); } #define FL_HASH 0x01 #define FL_ZERO 0x02 #define FL_DASH 0x04 #define FL_SPACE 0x08 #define FL_PLUS 0x10 #define FL_HAS_WIDTH 0x0100 #define FL_WIDTH_ARG 0x0200 #define FL_HAS_PREC 0x0400 #define FL_PREC_ARG 0x0800 #define FL_LEN_H 0x010000 #define FL_LEN_HH 0x020000 #define FL_LEN_L 0x040000 #define FL_LEN_LL 0x080000 %%{ machine format; access fsm->; action clear { fsm->flags = 0; fsm->width = 0; fsm->prec = 0; } # A non-zero number. nznum = [1-9] [0-9]*; # Width action width_num { fsm->width = 10 * fsm->width + (fc-'0'); } action width_arg { fsm->flags |= FL_WIDTH_ARG; } action width { fsm->flags |= FL_HAS_WIDTH; } width = ( ( nznum $width_num | '*' @width_arg ) %width )?; # Precision action prec_num { fsm->prec = 10 * fsm->prec + (fc-'0'); } action prec_arg { fsm->flags |= FL_PREC_ARG; } action prec { fsm->flags |= FL_HAS_PREC; } precision = ( '.' ( digit* $prec_num %prec | '*' @prec_arg ) )?; # Flags action flags_hash { fsm->flags |= FL_HASH; } action flags_zero { fsm->flags |= FL_ZERO; } action flags_dash { fsm->flags |= FL_DASH; } action flags_space { fsm->flags |= FL_SPACE; } action flags_plus { fsm->flags |= FL_PLUS; } flags = ( '#' @flags_hash | '0' @flags_zero | '-' @flags_dash | ' ' @flags_space | '+' @flags_plus )*; action length_h { fsm->flags |= FL_LEN_H; } action length_l { fsm->flags |= FL_LEN_L; } action length_hh { fsm->flags |= FL_LEN_HH; } action length_ll { fsm->flags |= FL_LEN_LL; } # Must use leaving transitions on 'h' and 'l' because they are # prefixes for 'hh' and 'll'. length = ( 'h' %length_h | 'l' %length_l | 'hh' @length_hh | 'll' @length_ll )?; action conversion { do_conv( fsm, fc ); } conversion = [diouxXcsp] @conversion; fmt_spec = '%' @clear flags width precision length conversion; action emit { if ( fsm->buflen == BUFLEN ) { fsm->write( fsm->buf, fsm->buflen ); fsm->buflen = 0; } fsm->buf[fsm->buflen++] = fc; } action finish_ok { if ( fsm->buflen > 0 ) fsm->write( fsm->buf, fsm->buflen ); } action finish_err { printf("EOF IN FORMAT\n"); } action err_char { printf("ERROR ON CHAR: 0x%x\n", fc ); } main := ( [^%] @emit | '%%' @emit | fmt_spec )* @/finish_err %/finish_ok $!err_char; }%% %% write data; void format_init( struct format *fsm ) { fsm->buflen = 0; %% write init; } void format_execute( struct format *fsm, const char *data, int len, int isEof ) { const char *p = data; const char *pe = data + len; const char *eof = isEof ? pe : 0; %% write exec; } int format_finish( struct format *fsm ) { if ( fsm->cs == format_error ) return -1; if ( fsm->cs >= format_first_final ) return 1; return 0; } #define INPUT_BUFSIZE 2048 struct format fsm; char buf[INPUT_BUFSIZE]; void write(char *data, int len ) { fwrite( data, 1, len, stdout ); } int main() { fsm.write = write; format_init( &fsm ); while ( 1 ) { int len = fread( buf, 1, INPUT_BUFSIZE, stdin ); int eof = len != INPUT_BUFSIZE; format_execute( &fsm, buf, len, eof ); if ( eof ) break; } if ( format_finish( &fsm ) <= 0 ) printf("FAIL\n"); return 0; } ragel-6.8/examples/statechart.rl0000664000175000017500000000333212043335171013723 00000000000000/* * Demonstrate the use of labels, the epsilon operator, and the join operator * for creating machines using the named state and transition list paradigm. * This implementes the same machine as the atoi example. */ #include #include #include #include using namespace std; struct StateChart { bool neg; int val; int cs; int init( ); int execute( const char *data, int len ); int finish( ); }; %%{ machine StateChart; action begin { neg = false; val = 0; } action see_neg { neg = true; } action add_digit { val = val * 10 + (fc - '0'); } action finish { if ( neg ) val = -1 * val; } atoi = ( start: ( '-' @see_neg ->om_num | '+' ->om_num | [0-9] @add_digit ->more_nums ), # One or more nums. om_num: ( [0-9] @add_digit ->more_nums ), # Zero ore more nums. more_nums: ( [0-9] @add_digit ->more_nums | '' -> final ) ) >begin %finish; main := ( atoi '\n' @{ cout << val << endl; } )*; }%% %% write data; int StateChart::init( ) { neg = false; val = false; %% write init; return 1; } int StateChart::execute( const char *data, int len ) { const char *p = data; const char *pe = data + len; %% write exec; if ( cs == StateChart_error ) return -1; if ( cs >= StateChart_first_final ) return 1; return 0; } int StateChart::finish( ) { if ( cs == StateChart_error ) return -1; if ( cs >= StateChart_first_final ) return 1; return 0; } #define BUFSIZE 1024 int main() { char buf[BUFSIZE]; StateChart atoi; atoi.init(); while ( fgets( buf, sizeof(buf), stdin ) != 0 ) { atoi.execute( buf, strlen(buf) ); } if ( atoi.finish() <= 0 ) cerr << "statechart: error: parsing input" << endl; return 0; } ragel-6.8/examples/gotocallret.rl0000664000175000017500000000415012043335171014077 00000000000000/* * Demonstrate the use of goto, call and return. This machine expects either a * lower case char or a digit as a command then a space followed by the command * arg. If the command is a char, then the arg must be an a string of chars. * If the command is a digit, then the arg must be a string of digits. This * choice is determined by action code, rather than though transition * desitinations. */ #include #include #include #include using namespace std; struct GotoCallRet { char comm; int cs, top, stack[32]; int init( ); int execute( const char *data, int len, bool isEof ); int finish( ); }; %%{ machine GotoCallRet; # Error machine, consumes to end of # line, then starts the main line over. garble_line := ( (any-'\n')*'\n' ) >{cout << "error: garbling line" << endl;} @{fgoto main;}; # Look for a string of alphas or of digits, # on anything else, hold the character and return. alp_comm := alpha+ $!{fhold;fret;}; dig_comm := digit+ $!{fhold;fret;}; # Choose which to machine to call into based on the command. action comm_arg { if ( comm >= 'a' ) fcall alp_comm; else fcall dig_comm; } # Specifies command string. Note that the arg is left out. command = ( [a-z0-9] @{comm = fc;} ' ' @comm_arg '\n' ) @{cout << "correct command" << endl;}; # Any number of commands. If there is an # error anywhere, garble the line. main := command* $!{fhold;fgoto garble_line;}; }%% %% write data; int GotoCallRet::init( ) { %% write init; return 1; } int GotoCallRet::execute( const char *data, int len, bool isEof ) { const char *p = data; const char *pe = data + len; const char *eof = isEof ? pe : 0; %% write exec; if ( cs == GotoCallRet_error ) return -1; if ( cs >= GotoCallRet_first_final ) return 1; return 0; } #define BUFSIZE 1024 int main() { char buf[BUFSIZE]; GotoCallRet gcr; gcr.init(); while ( fgets( buf, sizeof(buf), stdin ) != 0 ) gcr.execute( buf, strlen(buf), false ); gcr.execute( 0, 0, true ); if ( gcr.cs < GotoCallRet_first_final ) cerr << "gotocallret: error: parsing input" << endl; return 0; } ragel-6.8/examples/awkemu.rl0000664000175000017500000000432212043335171013052 00000000000000/* * Perform the basic line parsing of input performed by awk. */ #include #include #include #include %%{ machine awkemu; action start_word { ws[nwords] = fpc; } action end_word { we[nwords++] = fpc; } action start_line { nwords = 0; ls = fpc; } action end_line { printf("endline(%i): ", nwords ); fwrite( ls, 1, p - ls, stdout ); printf("\n"); for ( i = 0; i < nwords; i++ ) { printf(" word: "); fwrite( ws[i], 1, we[i] - ws[i], stdout ); printf("\n"); } } # Words in a line. word = ^[ \t\n]+; # The whitespace separating words in a line. whitespace = [ \t]; # The components in a line to break up. Either a word or a single char of # whitespace. On the word capture characters. blineElements = word >start_word %end_word | whitespace; # Star the break line elements. Just be careful to decrement the leaving # priority as we don't want multiple character identifiers to be treated as # multiple single char identifiers. line = ( blineElements** '\n' ) >start_line @end_line; # Any number of lines. main := line*; }%% %% write data noerror nofinal; #define MAXWORDS 256 #define BUFSIZE 4096 char buf[BUFSIZE]; int main() { int i, nwords = 0; char *ls = 0; char *ws[MAXWORDS]; char *we[MAXWORDS]; int cs; int have = 0; %% write init; while ( 1 ) { char *p, *pe, *data = buf + have; int len, space = BUFSIZE - have; /* fprintf( stderr, "space: %i\n", space ); */ if ( space == 0 ) { fprintf(stderr, "buffer out of space\n"); exit(1); } len = fread( data, 1, space, stdin ); /* fprintf( stderr, "len: %i\n", len ); */ if ( len == 0 ) break; /* Find the last newline by searching backwards. This is where * we will stop processing on this iteration. */ p = buf; pe = buf + have + len - 1; while ( *pe != '\n' && pe >= buf ) pe--; pe += 1; /* fprintf( stderr, "running on: %i\n", pe - p ); */ %% write exec; /* How much is still in the buffer. */ have = data + len - pe; if ( have > 0 ) memmove( buf, pe, have ); /* fprintf(stderr, "have: %i\n", have ); */ if ( len < space ) break; } if ( have > 0 ) fprintf(stderr, "input not newline terminated\n"); return 0; } ragel-6.8/examples/mailbox.cpp0000664000175000017500000006640112106311500013355 00000000000000 #line 1 "mailbox.rl" /* * Parses unix mail boxes into headers and bodies. */ #include #include #include #include using namespace std; #define BUFSIZE 2048 /* A growable buffer for collecting headers. */ struct Buffer { Buffer() : data(0), allocated(0), length(0) { } ~Buffer() { empty(); } void append( char p ) { if ( ++length > allocated ) upAllocate( length*2 ); data[length-1] = p; } void clear() { length = 0; } void upAllocate( int len ); void empty(); char *data; int allocated; int length; }; struct MailboxScanner { Buffer headName; Buffer headContent; int cs, top, stack[1]; int init( ); int execute( const char *data, int len, bool isEof ); int finish( ); }; #line 137 "mailbox.rl" #line 56 "mailbox.cpp" static const int MailboxScanner_start = 100; static const int MailboxScanner_first_final = 100; static const int MailboxScanner_error = 0; static const int MailboxScanner_en_consumeHeader = 102; static const int MailboxScanner_en_printHeader = 103; static const int MailboxScanner_en_main = 100; #line 140 "mailbox.rl" int MailboxScanner::init( ) { #line 71 "mailbox.cpp" { cs = MailboxScanner_start; top = 0; } #line 144 "mailbox.rl" return 1; } int MailboxScanner::execute( const char *data, int len, bool isEof ) { const char *p = data; const char *pe = data + len; const char *eof = isEof ? pe : 0; #line 88 "mailbox.cpp" { if ( p == pe ) goto _test_eof; goto _resume; _again: switch ( cs ) { case 100: goto st100; case 0: goto st0; case 1: goto st1; case 2: goto st2; case 3: goto st3; case 4: goto st4; case 5: goto st5; case 6: goto st6; case 7: goto st7; case 8: goto st8; case 9: goto st9; case 10: goto st10; case 11: goto st11; case 12: goto st12; case 13: goto st13; case 14: goto st14; case 15: goto st15; case 16: goto st16; case 17: goto st17; case 18: goto st18; case 19: goto st19; case 20: goto st20; case 21: goto st21; case 22: goto st22; case 23: goto st23; case 24: goto st24; case 25: goto st25; case 26: goto st26; case 27: goto st27; case 28: goto st28; case 29: goto st29; case 30: goto st30; case 31: goto st31; case 32: goto st32; case 33: goto st33; case 34: goto st34; case 101: goto st101; case 35: goto st35; case 36: goto st36; case 37: goto st37; case 38: goto st38; case 39: goto st39; case 40: goto st40; case 41: goto st41; case 42: goto st42; case 43: goto st43; case 44: goto st44; case 45: goto st45; case 46: goto st46; case 47: goto st47; case 48: goto st48; case 49: goto st49; case 50: goto st50; case 51: goto st51; case 52: goto st52; case 53: goto st53; case 54: goto st54; case 55: goto st55; case 56: goto st56; case 57: goto st57; case 58: goto st58; case 59: goto st59; case 60: goto st60; case 61: goto st61; case 62: goto st62; case 63: goto st63; case 64: goto st64; case 65: goto st65; case 66: goto st66; case 67: goto st67; case 68: goto st68; case 69: goto st69; case 70: goto st70; case 71: goto st71; case 72: goto st72; case 73: goto st73; case 74: goto st74; case 75: goto st75; case 76: goto st76; case 77: goto st77; case 78: goto st78; case 79: goto st79; case 80: goto st80; case 81: goto st81; case 82: goto st82; case 83: goto st83; case 84: goto st84; case 85: goto st85; case 86: goto st86; case 87: goto st87; case 88: goto st88; case 89: goto st89; case 90: goto st90; case 91: goto st91; case 92: goto st92; case 93: goto st93; case 94: goto st94; case 95: goto st95; case 96: goto st96; case 97: goto st97; case 102: goto st102; case 98: goto st98; case 103: goto st103; case 99: goto st99; case 104: goto st104; default: break; } if ( ++p == pe ) goto _test_eof; _resume: switch ( cs ) { st100: if ( ++p == pe ) goto _test_eof100; case 100: if ( (*p) == 70 ) goto st1; goto st0; tr101: #line 92 "mailbox.rl" { headContent.append(0); cout << headContent.data << endl; headContent.clear(); p--; {cs = stack[--top];goto _again;} } goto st0; #line 226 "mailbox.cpp" st0: cs = 0; goto _out; st1: if ( ++p == pe ) goto _test_eof1; case 1: if ( (*p) == 114 ) goto st2; goto st0; st2: if ( ++p == pe ) goto _test_eof2; case 2: if ( (*p) == 111 ) goto st3; goto st0; st3: if ( ++p == pe ) goto _test_eof3; case 3: if ( (*p) == 109 ) goto st4; goto st0; st4: if ( ++p == pe ) goto _test_eof4; case 4: if ( (*p) == 32 ) goto st5; goto st0; st5: if ( ++p == pe ) goto _test_eof5; case 5: switch( (*p) ) { case 10: goto st0; case 32: goto st6; } goto st5; st6: if ( ++p == pe ) goto _test_eof6; case 6: switch( (*p) ) { case 10: goto st0; case 32: goto st6; } if ( 65 <= (*p) && (*p) <= 90 ) goto st7; goto st5; st7: if ( ++p == pe ) goto _test_eof7; case 7: switch( (*p) ) { case 10: goto st0; case 32: goto st6; } if ( 97 <= (*p) && (*p) <= 122 ) goto st8; goto st5; st8: if ( ++p == pe ) goto _test_eof8; case 8: switch( (*p) ) { case 10: goto st0; case 32: goto st6; } if ( 97 <= (*p) && (*p) <= 122 ) goto st9; goto st5; st9: if ( ++p == pe ) goto _test_eof9; case 9: switch( (*p) ) { case 10: goto st0; case 32: goto st10; } goto st5; st10: if ( ++p == pe ) goto _test_eof10; case 10: switch( (*p) ) { case 10: goto st0; case 32: goto st6; } if ( 65 <= (*p) && (*p) <= 90 ) goto st11; goto st5; st11: if ( ++p == pe ) goto _test_eof11; case 11: switch( (*p) ) { case 10: goto st0; case 32: goto st6; } if ( 97 <= (*p) && (*p) <= 122 ) goto st12; goto st5; st12: if ( ++p == pe ) goto _test_eof12; case 12: switch( (*p) ) { case 10: goto st0; case 32: goto st6; } if ( 97 <= (*p) && (*p) <= 122 ) goto st13; goto st5; st13: if ( ++p == pe ) goto _test_eof13; case 13: switch( (*p) ) { case 10: goto st0; case 32: goto st14; } goto st5; st14: if ( ++p == pe ) goto _test_eof14; case 14: switch( (*p) ) { case 10: goto st0; case 32: goto st15; } if ( (*p) > 57 ) { if ( 65 <= (*p) && (*p) <= 90 ) goto st11; } else if ( (*p) >= 48 ) goto st97; goto st5; st15: if ( ++p == pe ) goto _test_eof15; case 15: switch( (*p) ) { case 10: goto st0; case 32: goto st6; } if ( (*p) > 57 ) { if ( 65 <= (*p) && (*p) <= 90 ) goto st7; } else if ( (*p) >= 48 ) goto st16; goto st5; st16: if ( ++p == pe ) goto _test_eof16; case 16: switch( (*p) ) { case 10: goto st0; case 32: goto st17; } goto st5; st17: if ( ++p == pe ) goto _test_eof17; case 17: switch( (*p) ) { case 10: goto st0; case 32: goto st6; } if ( (*p) > 57 ) { if ( 65 <= (*p) && (*p) <= 90 ) goto st7; } else if ( (*p) >= 48 ) goto st18; goto st5; st18: if ( ++p == pe ) goto _test_eof18; case 18: switch( (*p) ) { case 10: goto st0; case 32: goto st6; } if ( 48 <= (*p) && (*p) <= 57 ) goto st19; goto st5; st19: if ( ++p == pe ) goto _test_eof19; case 19: switch( (*p) ) { case 10: goto st0; case 32: goto st6; case 58: goto st20; } goto st5; st20: if ( ++p == pe ) goto _test_eof20; case 20: switch( (*p) ) { case 10: goto st0; case 32: goto st6; } if ( 48 <= (*p) && (*p) <= 57 ) goto st21; goto st5; st21: if ( ++p == pe ) goto _test_eof21; case 21: switch( (*p) ) { case 10: goto st0; case 32: goto st6; } if ( 48 <= (*p) && (*p) <= 57 ) goto st22; goto st5; st22: if ( ++p == pe ) goto _test_eof22; case 22: switch( (*p) ) { case 10: goto st0; case 32: goto st23; case 58: goto st94; } goto st5; st23: if ( ++p == pe ) goto _test_eof23; case 23: switch( (*p) ) { case 10: goto st0; case 32: goto st6; case 43: goto st24; case 45: goto st24; } if ( (*p) > 57 ) { if ( 65 <= (*p) && (*p) <= 90 ) goto st92; } else if ( (*p) >= 48 ) goto st84; goto st5; st24: if ( ++p == pe ) goto _test_eof24; case 24: switch( (*p) ) { case 10: goto st0; case 32: goto st6; } if ( 48 <= (*p) && (*p) <= 57 ) goto st25; goto st5; st25: if ( ++p == pe ) goto _test_eof25; case 25: switch( (*p) ) { case 10: goto st0; case 32: goto st6; } if ( 48 <= (*p) && (*p) <= 57 ) goto st26; goto st5; st26: if ( ++p == pe ) goto _test_eof26; case 26: switch( (*p) ) { case 10: goto st0; case 32: goto st6; } if ( 48 <= (*p) && (*p) <= 57 ) goto st27; goto st5; st27: if ( ++p == pe ) goto _test_eof27; case 27: switch( (*p) ) { case 10: goto st0; case 32: goto st6; } if ( 48 <= (*p) && (*p) <= 57 ) goto st28; goto st5; st28: if ( ++p == pe ) goto _test_eof28; case 28: switch( (*p) ) { case 10: goto st0; case 32: goto st29; } goto st5; st29: if ( ++p == pe ) goto _test_eof29; case 29: switch( (*p) ) { case 10: goto st0; case 32: goto st6; } if ( (*p) > 57 ) { if ( 65 <= (*p) && (*p) <= 90 ) goto st7; } else if ( (*p) >= 48 ) goto st30; goto st5; st30: if ( ++p == pe ) goto _test_eof30; case 30: switch( (*p) ) { case 10: goto st0; case 32: goto st6; } if ( 48 <= (*p) && (*p) <= 57 ) goto st31; goto st5; st31: if ( ++p == pe ) goto _test_eof31; case 31: switch( (*p) ) { case 10: goto st0; case 32: goto st6; } if ( 48 <= (*p) && (*p) <= 57 ) goto st32; goto st5; st32: if ( ++p == pe ) goto _test_eof32; case 32: switch( (*p) ) { case 10: goto st0; case 32: goto st6; } if ( 48 <= (*p) && (*p) <= 57 ) goto st33; goto st5; st33: if ( ++p == pe ) goto _test_eof33; case 33: switch( (*p) ) { case 10: goto st34; case 32: goto st6; } goto st5; tr88: #line 108 "mailbox.rl" { headName.append(0); if ( strcmp( headName.data, "From" ) == 0 || strcmp( headName.data, "To" ) == 0 || strcmp( headName.data, "Subject" ) == 0 ) { /* Print the header name, then jump to a machine the will display * the contents. */ cout << headName.data << ":"; headName.clear(); {stack[top++] = 34; goto st103;} } headName.clear(); {stack[top++] = 34; goto st102;} } goto st34; st34: if ( ++p == pe ) goto _test_eof34; case 34: #line 603 "mailbox.cpp" if ( (*p) == 10 ) goto tr38; if ( (*p) > 57 ) { if ( 59 <= (*p) && (*p) <= 126 ) goto tr39; } else if ( (*p) >= 33 ) goto tr39; goto st0; tr38: #line 55 "mailbox.rl" { cout << endl; } goto st101; st101: if ( ++p == pe ) goto _test_eof101; case 101: #line 620 "mailbox.cpp" switch( (*p) ) { case 10: goto st101; case 70: goto st36; } goto st35; st35: if ( ++p == pe ) goto _test_eof35; case 35: if ( (*p) == 10 ) goto st101; goto st35; st36: if ( ++p == pe ) goto _test_eof36; case 36: switch( (*p) ) { case 10: goto st101; case 114: goto st37; } goto st35; st37: if ( ++p == pe ) goto _test_eof37; case 37: switch( (*p) ) { case 10: goto st101; case 111: goto st38; } goto st35; st38: if ( ++p == pe ) goto _test_eof38; case 38: switch( (*p) ) { case 10: goto st101; case 109: goto st39; } goto st35; st39: if ( ++p == pe ) goto _test_eof39; case 39: switch( (*p) ) { case 10: goto st101; case 32: goto st40; } goto st35; st40: if ( ++p == pe ) goto _test_eof40; case 40: switch( (*p) ) { case 10: goto st101; case 32: goto st41; } goto st40; st41: if ( ++p == pe ) goto _test_eof41; case 41: switch( (*p) ) { case 10: goto st101; case 32: goto st41; } if ( 65 <= (*p) && (*p) <= 90 ) goto st42; goto st40; st42: if ( ++p == pe ) goto _test_eof42; case 42: switch( (*p) ) { case 10: goto st101; case 32: goto st41; } if ( 97 <= (*p) && (*p) <= 122 ) goto st43; goto st40; st43: if ( ++p == pe ) goto _test_eof43; case 43: switch( (*p) ) { case 10: goto st101; case 32: goto st41; } if ( 97 <= (*p) && (*p) <= 122 ) goto st44; goto st40; st44: if ( ++p == pe ) goto _test_eof44; case 44: switch( (*p) ) { case 10: goto st101; case 32: goto st45; } goto st40; st45: if ( ++p == pe ) goto _test_eof45; case 45: switch( (*p) ) { case 10: goto st101; case 32: goto st41; } if ( 65 <= (*p) && (*p) <= 90 ) goto st46; goto st40; st46: if ( ++p == pe ) goto _test_eof46; case 46: switch( (*p) ) { case 10: goto st101; case 32: goto st41; } if ( 97 <= (*p) && (*p) <= 122 ) goto st47; goto st40; st47: if ( ++p == pe ) goto _test_eof47; case 47: switch( (*p) ) { case 10: goto st101; case 32: goto st41; } if ( 97 <= (*p) && (*p) <= 122 ) goto st48; goto st40; st48: if ( ++p == pe ) goto _test_eof48; case 48: switch( (*p) ) { case 10: goto st101; case 32: goto st49; } goto st40; st49: if ( ++p == pe ) goto _test_eof49; case 49: switch( (*p) ) { case 10: goto st101; case 32: goto st50; } if ( (*p) > 57 ) { if ( 65 <= (*p) && (*p) <= 90 ) goto st46; } else if ( (*p) >= 48 ) goto st82; goto st40; st50: if ( ++p == pe ) goto _test_eof50; case 50: switch( (*p) ) { case 10: goto st101; case 32: goto st41; } if ( (*p) > 57 ) { if ( 65 <= (*p) && (*p) <= 90 ) goto st42; } else if ( (*p) >= 48 ) goto st51; goto st40; st51: if ( ++p == pe ) goto _test_eof51; case 51: switch( (*p) ) { case 10: goto st101; case 32: goto st52; } goto st40; st52: if ( ++p == pe ) goto _test_eof52; case 52: switch( (*p) ) { case 10: goto st101; case 32: goto st41; } if ( (*p) > 57 ) { if ( 65 <= (*p) && (*p) <= 90 ) goto st42; } else if ( (*p) >= 48 ) goto st53; goto st40; st53: if ( ++p == pe ) goto _test_eof53; case 53: switch( (*p) ) { case 10: goto st101; case 32: goto st41; } if ( 48 <= (*p) && (*p) <= 57 ) goto st54; goto st40; st54: if ( ++p == pe ) goto _test_eof54; case 54: switch( (*p) ) { case 10: goto st101; case 32: goto st41; case 58: goto st55; } goto st40; st55: if ( ++p == pe ) goto _test_eof55; case 55: switch( (*p) ) { case 10: goto st101; case 32: goto st41; } if ( 48 <= (*p) && (*p) <= 57 ) goto st56; goto st40; st56: if ( ++p == pe ) goto _test_eof56; case 56: switch( (*p) ) { case 10: goto st101; case 32: goto st41; } if ( 48 <= (*p) && (*p) <= 57 ) goto st57; goto st40; st57: if ( ++p == pe ) goto _test_eof57; case 57: switch( (*p) ) { case 10: goto st101; case 32: goto st58; case 58: goto st79; } goto st40; st58: if ( ++p == pe ) goto _test_eof58; case 58: switch( (*p) ) { case 10: goto st101; case 32: goto st41; case 43: goto st59; case 45: goto st59; } if ( (*p) > 57 ) { if ( 65 <= (*p) && (*p) <= 90 ) goto st77; } else if ( (*p) >= 48 ) goto st69; goto st40; st59: if ( ++p == pe ) goto _test_eof59; case 59: switch( (*p) ) { case 10: goto st101; case 32: goto st41; } if ( 48 <= (*p) && (*p) <= 57 ) goto st60; goto st40; st60: if ( ++p == pe ) goto _test_eof60; case 60: switch( (*p) ) { case 10: goto st101; case 32: goto st41; } if ( 48 <= (*p) && (*p) <= 57 ) goto st61; goto st40; st61: if ( ++p == pe ) goto _test_eof61; case 61: switch( (*p) ) { case 10: goto st101; case 32: goto st41; } if ( 48 <= (*p) && (*p) <= 57 ) goto st62; goto st40; st62: if ( ++p == pe ) goto _test_eof62; case 62: switch( (*p) ) { case 10: goto st101; case 32: goto st41; } if ( 48 <= (*p) && (*p) <= 57 ) goto st63; goto st40; st63: if ( ++p == pe ) goto _test_eof63; case 63: switch( (*p) ) { case 10: goto st101; case 32: goto st64; } goto st40; st64: if ( ++p == pe ) goto _test_eof64; case 64: switch( (*p) ) { case 10: goto st101; case 32: goto st41; } if ( (*p) > 57 ) { if ( 65 <= (*p) && (*p) <= 90 ) goto st42; } else if ( (*p) >= 48 ) goto st65; goto st40; st65: if ( ++p == pe ) goto _test_eof65; case 65: switch( (*p) ) { case 10: goto st101; case 32: goto st41; } if ( 48 <= (*p) && (*p) <= 57 ) goto st66; goto st40; st66: if ( ++p == pe ) goto _test_eof66; case 66: switch( (*p) ) { case 10: goto st101; case 32: goto st41; } if ( 48 <= (*p) && (*p) <= 57 ) goto st67; goto st40; st67: if ( ++p == pe ) goto _test_eof67; case 67: switch( (*p) ) { case 10: goto st101; case 32: goto st41; } if ( 48 <= (*p) && (*p) <= 57 ) goto st68; goto st40; st68: if ( ++p == pe ) goto _test_eof68; case 68: switch( (*p) ) { case 10: goto st34; case 32: goto st41; } goto st40; st69: if ( ++p == pe ) goto _test_eof69; case 69: switch( (*p) ) { case 10: goto st101; case 32: goto st41; } if ( 48 <= (*p) && (*p) <= 57 ) goto st70; goto st40; st70: if ( ++p == pe ) goto _test_eof70; case 70: switch( (*p) ) { case 10: goto st101; case 32: goto st41; } if ( 48 <= (*p) && (*p) <= 57 ) goto st71; goto st40; st71: if ( ++p == pe ) goto _test_eof71; case 71: switch( (*p) ) { case 10: goto st101; case 32: goto st41; } if ( 48 <= (*p) && (*p) <= 57 ) goto st72; goto st40; st72: if ( ++p == pe ) goto _test_eof72; case 72: switch( (*p) ) { case 10: goto st34; case 32: goto st73; } goto st40; st73: if ( ++p == pe ) goto _test_eof73; case 73: switch( (*p) ) { case 10: goto st101; case 32: goto st41; case 43: goto st74; case 45: goto st74; } if ( 65 <= (*p) && (*p) <= 90 ) goto st75; goto st40; st74: if ( ++p == pe ) goto _test_eof74; case 74: switch( (*p) ) { case 10: goto st101; case 32: goto st41; } if ( 48 <= (*p) && (*p) <= 57 ) goto st65; goto st40; st75: if ( ++p == pe ) goto _test_eof75; case 75: switch( (*p) ) { case 10: goto st101; case 32: goto st41; } if ( (*p) > 90 ) { if ( 97 <= (*p) && (*p) <= 122 ) goto st43; } else if ( (*p) >= 65 ) goto st76; goto st40; st76: if ( ++p == pe ) goto _test_eof76; case 76: switch( (*p) ) { case 10: goto st101; case 32: goto st41; } if ( 65 <= (*p) && (*p) <= 90 ) goto st68; goto st40; st77: if ( ++p == pe ) goto _test_eof77; case 77: switch( (*p) ) { case 10: goto st101; case 32: goto st41; } if ( (*p) > 90 ) { if ( 97 <= (*p) && (*p) <= 122 ) goto st43; } else if ( (*p) >= 65 ) goto st78; goto st40; st78: if ( ++p == pe ) goto _test_eof78; case 78: switch( (*p) ) { case 10: goto st101; case 32: goto st41; } if ( 65 <= (*p) && (*p) <= 90 ) goto st63; goto st40; st79: if ( ++p == pe ) goto _test_eof79; case 79: switch( (*p) ) { case 10: goto st101; case 32: goto st41; } if ( 48 <= (*p) && (*p) <= 57 ) goto st80; goto st40; st80: if ( ++p == pe ) goto _test_eof80; case 80: switch( (*p) ) { case 10: goto st101; case 32: goto st41; } if ( 48 <= (*p) && (*p) <= 57 ) goto st81; goto st40; st81: if ( ++p == pe ) goto _test_eof81; case 81: switch( (*p) ) { case 10: goto st101; case 32: goto st58; } goto st40; st82: if ( ++p == pe ) goto _test_eof82; case 82: switch( (*p) ) { case 10: goto st101; case 32: goto st41; } if ( 48 <= (*p) && (*p) <= 57 ) goto st51; goto st40; tr39: #line 52 "mailbox.rl" { headName.append((*p)); } goto st83; st83: if ( ++p == pe ) goto _test_eof83; case 83: #line 1157 "mailbox.cpp" if ( (*p) == 58 ) goto tr88; if ( 33 <= (*p) && (*p) <= 126 ) goto tr39; goto st0; st84: if ( ++p == pe ) goto _test_eof84; case 84: switch( (*p) ) { case 10: goto st0; case 32: goto st6; } if ( 48 <= (*p) && (*p) <= 57 ) goto st85; goto st5; st85: if ( ++p == pe ) goto _test_eof85; case 85: switch( (*p) ) { case 10: goto st0; case 32: goto st6; } if ( 48 <= (*p) && (*p) <= 57 ) goto st86; goto st5; st86: if ( ++p == pe ) goto _test_eof86; case 86: switch( (*p) ) { case 10: goto st0; case 32: goto st6; } if ( 48 <= (*p) && (*p) <= 57 ) goto st87; goto st5; st87: if ( ++p == pe ) goto _test_eof87; case 87: switch( (*p) ) { case 10: goto st34; case 32: goto st88; } goto st5; st88: if ( ++p == pe ) goto _test_eof88; case 88: switch( (*p) ) { case 10: goto st0; case 32: goto st6; case 43: goto st89; case 45: goto st89; } if ( 65 <= (*p) && (*p) <= 90 ) goto st90; goto st5; st89: if ( ++p == pe ) goto _test_eof89; case 89: switch( (*p) ) { case 10: goto st0; case 32: goto st6; } if ( 48 <= (*p) && (*p) <= 57 ) goto st30; goto st5; st90: if ( ++p == pe ) goto _test_eof90; case 90: switch( (*p) ) { case 10: goto st0; case 32: goto st6; } if ( (*p) > 90 ) { if ( 97 <= (*p) && (*p) <= 122 ) goto st8; } else if ( (*p) >= 65 ) goto st91; goto st5; st91: if ( ++p == pe ) goto _test_eof91; case 91: switch( (*p) ) { case 10: goto st0; case 32: goto st6; } if ( 65 <= (*p) && (*p) <= 90 ) goto st33; goto st5; st92: if ( ++p == pe ) goto _test_eof92; case 92: switch( (*p) ) { case 10: goto st0; case 32: goto st6; } if ( (*p) > 90 ) { if ( 97 <= (*p) && (*p) <= 122 ) goto st8; } else if ( (*p) >= 65 ) goto st93; goto st5; st93: if ( ++p == pe ) goto _test_eof93; case 93: switch( (*p) ) { case 10: goto st0; case 32: goto st6; } if ( 65 <= (*p) && (*p) <= 90 ) goto st28; goto st5; st94: if ( ++p == pe ) goto _test_eof94; case 94: switch( (*p) ) { case 10: goto st0; case 32: goto st6; } if ( 48 <= (*p) && (*p) <= 57 ) goto st95; goto st5; st95: if ( ++p == pe ) goto _test_eof95; case 95: switch( (*p) ) { case 10: goto st0; case 32: goto st6; } if ( 48 <= (*p) && (*p) <= 57 ) goto st96; goto st5; st96: if ( ++p == pe ) goto _test_eof96; case 96: switch( (*p) ) { case 10: goto st0; case 32: goto st23; } goto st5; st97: if ( ++p == pe ) goto _test_eof97; case 97: switch( (*p) ) { case 10: goto st0; case 32: goto st6; } if ( 48 <= (*p) && (*p) <= 57 ) goto st16; goto st5; tr99: #line 86 "mailbox.rl" {p--; {cs = stack[--top];goto _again;}} goto st102; st102: if ( ++p == pe ) goto _test_eof102; case 102: #line 1329 "mailbox.cpp" if ( (*p) == 10 ) goto st98; goto st102; st98: if ( ++p == pe ) goto _test_eof98; case 98: switch( (*p) ) { case 9: goto st102; case 32: goto st102; } goto tr99; tr106: #line 89 "mailbox.rl" {headContent.append((*p));} goto st103; tr108: #line 90 "mailbox.rl" {headContent.append(' ');} #line 89 "mailbox.rl" {headContent.append((*p));} goto st103; st103: if ( ++p == pe ) goto _test_eof103; case 103: #line 1356 "mailbox.cpp" if ( (*p) == 10 ) goto st99; goto tr106; st99: if ( ++p == pe ) goto _test_eof99; case 99: switch( (*p) ) { case 9: goto st104; case 32: goto st104; } goto tr101; st104: if ( ++p == pe ) goto _test_eof104; case 104: switch( (*p) ) { case 9: goto st104; case 10: goto st99; case 32: goto st104; } goto tr108; } _test_eof100: cs = 100; goto _test_eof; _test_eof1: cs = 1; goto _test_eof; _test_eof2: cs = 2; goto _test_eof; _test_eof3: cs = 3; goto _test_eof; _test_eof4: cs = 4; goto _test_eof; _test_eof5: cs = 5; goto _test_eof; _test_eof6: cs = 6; goto _test_eof; _test_eof7: cs = 7; goto _test_eof; _test_eof8: cs = 8; goto _test_eof; _test_eof9: cs = 9; goto _test_eof; _test_eof10: cs = 10; goto _test_eof; _test_eof11: cs = 11; goto _test_eof; _test_eof12: cs = 12; goto _test_eof; _test_eof13: cs = 13; goto _test_eof; _test_eof14: cs = 14; goto _test_eof; _test_eof15: cs = 15; goto _test_eof; _test_eof16: cs = 16; goto _test_eof; _test_eof17: cs = 17; goto _test_eof; _test_eof18: cs = 18; goto _test_eof; _test_eof19: cs = 19; goto _test_eof; _test_eof20: cs = 20; goto _test_eof; _test_eof21: cs = 21; goto _test_eof; _test_eof22: cs = 22; goto _test_eof; _test_eof23: cs = 23; goto _test_eof; _test_eof24: cs = 24; goto _test_eof; _test_eof25: cs = 25; goto _test_eof; _test_eof26: cs = 26; goto _test_eof; _test_eof27: cs = 27; goto _test_eof; _test_eof28: cs = 28; goto _test_eof; _test_eof29: cs = 29; goto _test_eof; _test_eof30: cs = 30; goto _test_eof; _test_eof31: cs = 31; goto _test_eof; _test_eof32: cs = 32; goto _test_eof; _test_eof33: cs = 33; goto _test_eof; _test_eof34: cs = 34; goto _test_eof; _test_eof101: cs = 101; goto _test_eof; _test_eof35: cs = 35; goto _test_eof; _test_eof36: cs = 36; goto _test_eof; _test_eof37: cs = 37; goto _test_eof; _test_eof38: cs = 38; goto _test_eof; _test_eof39: cs = 39; goto _test_eof; _test_eof40: cs = 40; goto _test_eof; _test_eof41: cs = 41; goto _test_eof; _test_eof42: cs = 42; goto _test_eof; _test_eof43: cs = 43; goto _test_eof; _test_eof44: cs = 44; goto _test_eof; _test_eof45: cs = 45; goto _test_eof; _test_eof46: cs = 46; goto _test_eof; _test_eof47: cs = 47; goto _test_eof; _test_eof48: cs = 48; goto _test_eof; _test_eof49: cs = 49; goto _test_eof; _test_eof50: cs = 50; goto _test_eof; _test_eof51: cs = 51; goto _test_eof; _test_eof52: cs = 52; goto _test_eof; _test_eof53: cs = 53; goto _test_eof; _test_eof54: cs = 54; goto _test_eof; _test_eof55: cs = 55; goto _test_eof; _test_eof56: cs = 56; goto _test_eof; _test_eof57: cs = 57; goto _test_eof; _test_eof58: cs = 58; goto _test_eof; _test_eof59: cs = 59; goto _test_eof; _test_eof60: cs = 60; goto _test_eof; _test_eof61: cs = 61; goto _test_eof; _test_eof62: cs = 62; goto _test_eof; _test_eof63: cs = 63; goto _test_eof; _test_eof64: cs = 64; goto _test_eof; _test_eof65: cs = 65; goto _test_eof; _test_eof66: cs = 66; goto _test_eof; _test_eof67: cs = 67; goto _test_eof; _test_eof68: cs = 68; goto _test_eof; _test_eof69: cs = 69; goto _test_eof; _test_eof70: cs = 70; goto _test_eof; _test_eof71: cs = 71; goto _test_eof; _test_eof72: cs = 72; goto _test_eof; _test_eof73: cs = 73; goto _test_eof; _test_eof74: cs = 74; goto _test_eof; _test_eof75: cs = 75; goto _test_eof; _test_eof76: cs = 76; goto _test_eof; _test_eof77: cs = 77; goto _test_eof; _test_eof78: cs = 78; goto _test_eof; _test_eof79: cs = 79; goto _test_eof; _test_eof80: cs = 80; goto _test_eof; _test_eof81: cs = 81; goto _test_eof; _test_eof82: cs = 82; goto _test_eof; _test_eof83: cs = 83; goto _test_eof; _test_eof84: cs = 84; goto _test_eof; _test_eof85: cs = 85; goto _test_eof; _test_eof86: cs = 86; goto _test_eof; _test_eof87: cs = 87; goto _test_eof; _test_eof88: cs = 88; goto _test_eof; _test_eof89: cs = 89; goto _test_eof; _test_eof90: cs = 90; goto _test_eof; _test_eof91: cs = 91; goto _test_eof; _test_eof92: cs = 92; goto _test_eof; _test_eof93: cs = 93; goto _test_eof; _test_eof94: cs = 94; goto _test_eof; _test_eof95: cs = 95; goto _test_eof; _test_eof96: cs = 96; goto _test_eof; _test_eof97: cs = 97; goto _test_eof; _test_eof102: cs = 102; goto _test_eof; _test_eof98: cs = 98; goto _test_eof; _test_eof103: cs = 103; goto _test_eof; _test_eof99: cs = 99; goto _test_eof; _test_eof104: cs = 104; goto _test_eof; _test_eof: {} if ( p == eof ) { switch ( cs ) { case 104: #line 90 "mailbox.rl" {headContent.append(' ');} break; case 99: #line 92 "mailbox.rl" { headContent.append(0); cout << headContent.data << endl; headContent.clear(); p--; {cs = stack[--top];goto _again;} } break; #line 1503 "mailbox.cpp" } } _out: {} } #line 154 "mailbox.rl" if ( cs == MailboxScanner_error ) return -1; if ( cs >= MailboxScanner_first_final ) return 1; return 0; } int MailboxScanner::finish( ) { if ( cs == MailboxScanner_error ) return -1; if ( cs >= MailboxScanner_first_final ) return 1; return 0; } void Buffer::empty() { if ( data != 0 ) { free( data ); data = 0; length = 0; allocated = 0; } } void Buffer::upAllocate( int len ) { if ( data == 0 ) data = (char*) malloc( len ); else data = (char*) realloc( data, len ); allocated = len; } MailboxScanner mailbox; char buf[BUFSIZE]; int main() { mailbox.init(); while ( 1 ) { int len = fread( buf, 1, BUFSIZE, stdin ); mailbox.execute( buf, len, len != BUFSIZE ); if ( len != BUFSIZE ) break; } if ( mailbox.finish() <= 0 ) cerr << "mailbox: error parsing input" << endl; return 0; } ragel-6.8/examples/pullscan.rl0000664000175000017500000000521012043335171013377 00000000000000#include #include #include #define BUFSIZE 4096 typedef struct _Scanner { /* Scanner state. */ int cs; int act; int have; int curline; char *ts; char *te; char *p; char *pe; char *eof; FILE *file; int done; /* Token data */ char *data; int len; int value; char buf[BUFSIZE]; } Scanner; %%{ machine Scanner; write data; }%% void scan_init( Scanner *s, FILE *file ) { memset (s, '\0', sizeof(Scanner)); s->curline = 1; s->file = file; s->eof = 0; %% write init; } #define TK_NO_TOKEN (-1) #define TK_ERR 128 #define TK_EOF 129 #define TK_Identifier 130 #define TK_Number 131 #define TK_String 132 #define ret_tok( _tok ) token = _tok; s->data = s->ts int scan( Scanner *s ) { int token = TK_NO_TOKEN; int space, readlen; while ( 1 ) { if ( s->p == s->pe ) { printf("scanner: need more data\n"); if ( s->ts == 0 ) s->have = 0; else { /* There is data that needs to be shifted over. */ printf("scanner: buffer broken mid token\n"); s->have = s->pe - s->ts; memmove( s->buf, s->ts, s->have ); s->te -= (s->ts-s->buf); s->ts = s->buf; } s->p = s->buf + s->have; space = BUFSIZE - s->have; if ( space == 0 ) { /* We filled up the buffer trying to scan a token. */ printf("scanner: out of buffer space\n"); return TK_ERR; } if ( s->done ) { printf("scanner: end of file\n"); s->p[0] = 0; readlen = 1; } else { readlen = fread( s->p, 1, space, s->file ); if ( readlen < space ) s->done = 1; } s->pe = s->p + readlen; } %%{ machine Scanner; access s->; variable p s->p; variable pe s->pe; variable eof s->eof; main := |* # Identifiers ( [a-zA-Z_] [a-zA-Z0-9_]* ) => { ret_tok( TK_Identifier ); fbreak; }; # Whitespace [ \t\n]; '"' ( [^\\"] | '\\' any ) * '"' => { ret_tok( TK_String ); fbreak; }; # Number digit+ => { ret_tok( TK_Number ); fbreak; }; # EOF 0 => { ret_tok( TK_EOF ); fbreak; }; # Anything else any => { ret_tok( *s->p ); fbreak; }; *|; write exec; }%% if ( s->cs == Scanner_error ) return TK_ERR; if ( token != TK_NO_TOKEN ) { s->len = s->p - s->data; return token; } } } int main (int argc, char** argv) { Scanner ss; int tok; scan_init(&ss, stdin); while ( 1 ) { tok = scan (&ss); if ( tok == TK_EOF ) { printf ("parser: EOF\n"); break; } else if ( tok == TK_ERR ) { printf ("parser: ERR\n"); break; } else { printf ("parser: %d \"", tok); fwrite ( ss.data, 1, ss.len, stdout ); printf ("\"\n" ); } } return 0; } ragel-6.8/examples/awkemu.c0000664000175000017500000000642512106311500012653 00000000000000 #line 1 "awkemu.rl" /* * Perform the basic line parsing of input performed by awk. */ #include #include #include #include #line 55 "awkemu.rl" #line 18 "awkemu.c" static const int awkemu_start = 2; static const int awkemu_en_main = 2; #line 58 "awkemu.rl" #define MAXWORDS 256 #define BUFSIZE 4096 char buf[BUFSIZE]; int main() { int i, nwords = 0; char *ls = 0; char *ws[MAXWORDS]; char *we[MAXWORDS]; int cs; int have = 0; #line 41 "awkemu.c" { cs = awkemu_start; } #line 74 "awkemu.rl" while ( 1 ) { char *p, *pe, *data = buf + have; int len, space = BUFSIZE - have; /* fprintf( stderr, "space: %i\n", space ); */ if ( space == 0 ) { fprintf(stderr, "buffer out of space\n"); exit(1); } len = fread( data, 1, space, stdin ); /* fprintf( stderr, "len: %i\n", len ); */ if ( len == 0 ) break; /* Find the last newline by searching backwards. This is where * we will stop processing on this iteration. */ p = buf; pe = buf + have + len - 1; while ( *pe != '\n' && pe >= buf ) pe--; pe += 1; /* fprintf( stderr, "running on: %i\n", pe - p ); */ #line 74 "awkemu.c" { if ( p == pe ) goto _test_eof; switch ( cs ) { tr2: #line 17 "awkemu.rl" { we[nwords++] = p; } #line 26 "awkemu.rl" { printf("endline(%i): ", nwords ); fwrite( ls, 1, p - ls, stdout ); printf("\n"); for ( i = 0; i < nwords; i++ ) { printf(" word: "); fwrite( ws[i], 1, we[i] - ws[i], stdout ); printf("\n"); } } goto st2; tr5: #line 26 "awkemu.rl" { printf("endline(%i): ", nwords ); fwrite( ls, 1, p - ls, stdout ); printf("\n"); for ( i = 0; i < nwords; i++ ) { printf(" word: "); fwrite( ws[i], 1, we[i] - ws[i], stdout ); printf("\n"); } } goto st2; tr8: #line 21 "awkemu.rl" { nwords = 0; ls = p; } #line 26 "awkemu.rl" { printf("endline(%i): ", nwords ); fwrite( ls, 1, p - ls, stdout ); printf("\n"); for ( i = 0; i < nwords; i++ ) { printf(" word: "); fwrite( ws[i], 1, we[i] - ws[i], stdout ); printf("\n"); } } goto st2; st2: if ( ++p == pe ) goto _test_eof2; case 2: #line 135 "awkemu.c" switch( (*p) ) { case 9: goto tr7; case 10: goto tr8; case 32: goto tr7; } goto tr6; tr3: #line 13 "awkemu.rl" { ws[nwords] = p; } goto st0; tr6: #line 21 "awkemu.rl" { nwords = 0; ls = p; } #line 13 "awkemu.rl" { ws[nwords] = p; } goto st0; st0: if ( ++p == pe ) goto _test_eof0; case 0: #line 163 "awkemu.c" switch( (*p) ) { case 9: goto tr1; case 10: goto tr2; case 32: goto tr1; } goto st0; tr1: #line 17 "awkemu.rl" { we[nwords++] = p; } goto st1; tr7: #line 21 "awkemu.rl" { nwords = 0; ls = p; } goto st1; st1: if ( ++p == pe ) goto _test_eof1; case 1: #line 187 "awkemu.c" switch( (*p) ) { case 9: goto st1; case 10: goto tr5; case 32: goto st1; } goto tr3; } _test_eof2: cs = 2; goto _test_eof; _test_eof0: cs = 0; goto _test_eof; _test_eof1: cs = 1; goto _test_eof; _test_eof: {} } #line 101 "awkemu.rl" /* How much is still in the buffer. */ have = data + len - pe; if ( have > 0 ) memmove( buf, pe, have ); /* fprintf(stderr, "have: %i\n", have ); */ if ( len < space ) break; } if ( have > 0 ) fprintf(stderr, "input not newline terminated\n"); return 0; } ragel-6.8/examples/params.rl0000664000175000017500000000346112043335171013047 00000000000000/* * Parse command line arguments. */ #include #include #define BUFLEN 1024 struct params { char buffer[BUFLEN+1]; int buflen; int cs; }; %%{ machine params; access fsm->; # A buffer to collect argurments # Append to the buffer. action append { if ( fsm->buflen < BUFLEN ) fsm->buffer[fsm->buflen++] = fc; } # Terminate a buffer. action term { if ( fsm->buflen < BUFLEN ) fsm->buffer[fsm->buflen++] = 0; } # Clear out the buffer action clear { fsm->buflen = 0; } action help { printf("help\n"); } action version { printf("version\n"); } action output { printf("output: \"%s\"\n", fsm->buffer); } action spec { printf("spec: \"%s\"\n", fsm->buffer); } action mach { printf("machine: \"%s\"\n", fsm->buffer); } # Helpers that collect strings string = [^\0]+ >clear $append %term; # Different arguments. help = ( '-h' | '-H' | '-?' | '--help' ) 0 @help; version = ( '-v' | '--version' ) 0 @version; output = '-o' 0? string 0 @output; spec = '-S' 0? string 0 @spec; mach = '-M' 0? string 0 @mach; main := ( help | version | output | spec | mach )*; }%% %% write data; void params_init( struct params *fsm ) { fsm->buflen = 0; %% write init; } void params_execute( struct params *fsm, const char *data, int len ) { const char *p = data; const char *pe = data + len; %% write exec; } int params_finish( struct params *fsm ) { if ( fsm->cs == params_error ) return -1; if ( fsm->cs >= params_first_final ) return 1; return 0; } #define BUFSIZE 2048 int main( int argc, char **argv ) { int a; struct params params; params_init( ¶ms ); for ( a = 1; a < argc; a++ ) params_execute( ¶ms, argv[a], strlen(argv[a])+1 ); if ( params_finish( ¶ms ) != 1 ) fprintf( stderr, "params: error processing arguments\n" ); return 0; } ragel-6.8/examples/rlscan.cpp0000664000175000017500000004240412106311500013201 00000000000000 #line 1 "rlscan.rl" /* * Lexes Ragel input files. */ #include #include #include #include using namespace std; void escapeXML( char *data ) { while ( *data != 0 ) { switch ( *data ) { case '<': cout << "<"; break; case '>': cout << ">"; break; case '&': cout << "&"; break; default: cout << *data; break; } data += 1; } } void escapeXML( char c ) { switch ( c ) { case '<': cout << "<"; break; case '>': cout << ">"; break; case '&': cout << "&"; break; default: cout << c; break; } } void escapeXML( char *data, int len ) { for ( char *end = data + len; data != end; data++ ) { switch ( *data ) { case '<': cout << "<"; break; case '>': cout << ">"; break; case '&': cout << "&"; break; default: cout << *data; break; } } } inline void write( const char *data ) { cout << data; } inline void write( char c ) { cout << c; } inline void write( char *data, int len ) { cout.write( data, len ); } #line 237 "rlscan.rl" #line 71 "rlscan.cpp" static const int RagelScan_start = 24; static const int RagelScan_error = 0; static const int RagelScan_en_c_comment = 6; static const int RagelScan_en_ilscan = 31; static const int RagelScan_en_rlscan = 35; static const int RagelScan_en_main = 24; #line 240 "rlscan.rl" #define BUFSIZE 2048 int main() { std::ios::sync_with_stdio(false); int cs, act; char *ts, *te; int stack[1], top; static char inbuf[BUFSIZE]; bool single_line = false; int inline_depth = 0; #line 98 "rlscan.cpp" { cs = RagelScan_start; top = 0; ts = 0; te = 0; act = 0; } #line 256 "rlscan.rl" bool done = false; int have = 0; while ( !done ) { /* How much space is in the buffer? */ int space = BUFSIZE - have; if ( space == 0 ) { /* Buffer is full. */ cerr << "TOKEN TOO BIG" << endl; exit(1); } /* Read in a block. */ char *p = inbuf + have; cin.read( p, space ); int len = cin.gcount(); char *pe = p + len; char *eof = 0; /* Check for EOF. */ if ( len == 0 ) { eof = pe; done = true; } #line 134 "rlscan.cpp" { if ( p == pe ) goto _test_eof; goto _resume; _again: switch ( cs ) { case 24: goto st24; case 25: goto st25; case 1: goto st1; case 2: goto st2; case 26: goto st26; case 27: goto st27; case 28: goto st28; case 3: goto st3; case 4: goto st4; case 29: goto st29; case 5: goto st5; case 6: goto st6; case 0: goto st0; case 7: goto st7; case 30: goto st30; case 31: goto st31; case 32: goto st32; case 8: goto st8; case 9: goto st9; case 33: goto st33; case 10: goto st10; case 11: goto st11; case 34: goto st34; case 12: goto st12; case 35: goto st35; case 36: goto st36; case 13: goto st13; case 14: goto st14; case 37: goto st37; case 15: goto st15; case 38: goto st38; case 16: goto st16; case 17: goto st17; case 39: goto st39; case 18: goto st18; case 19: goto st19; case 40: goto st40; case 41: goto st41; case 20: goto st20; case 42: goto st42; case 43: goto st43; case 44: goto st44; case 21: goto st21; case 22: goto st22; case 45: goto st45; case 23: goto st23; default: break; } if ( ++p == pe ) goto _test_eof; _resume: switch ( cs ) { tr0: #line 230 "rlscan.rl" {{p = ((te))-1;}{ escapeXML( *ts ); }} goto st24; tr2: #line 79 "rlscan.rl" {te = p+1;{ escapeXML( ts, te-ts ); }} goto st24; tr5: #line 79 "rlscan.rl" {te = p+1;{ escapeXML( ts, te-ts ); }} goto st24; tr8: #line 79 "rlscan.rl" {te = p+1;{ escapeXML( ts, te-ts ); }} goto st24; tr40: #line 230 "rlscan.rl" {te = p+1;{ escapeXML( *ts ); }} goto st24; tr41: #line 235 "rlscan.rl" {te = p+1;} goto st24; tr46: #line 230 "rlscan.rl" {te = p;p--;{ escapeXML( *ts ); }} goto st24; tr48: #line 224 "rlscan.rl" {te = p;p--;{ write( "
\n" ); single_line = true; {goto st35;} }} goto st24; tr49: #line 218 "rlscan.rl" {te = p+1;{ write( "
\n" ); single_line = false; {goto st35;} }} goto st24; tr50: #line 211 "rlscan.rl" {te = p+1;{ escapeXML( ts, te-ts ); {stack[top++] = 24; goto st6;} }} goto st24; st24: #line 1 "NONE" {ts = 0;} if ( ++p == pe ) goto _test_eof24; case 24: #line 1 "NONE" {ts = p;} #line 267 "rlscan.cpp" switch( (*p) ) { case 0: goto tr41; case 34: goto tr42; case 37: goto st26; case 39: goto tr44; case 47: goto tr45; } goto tr40; tr42: #line 1 "NONE" {te = p+1;} goto st25; st25: if ( ++p == pe ) goto _test_eof25; case 25: #line 284 "rlscan.cpp" switch( (*p) ) { case 34: goto tr2; case 92: goto st2; } goto st1; st1: if ( ++p == pe ) goto _test_eof1; case 1: switch( (*p) ) { case 34: goto tr2; case 92: goto st2; } goto st1; st2: if ( ++p == pe ) goto _test_eof2; case 2: goto st1; st26: if ( ++p == pe ) goto _test_eof26; case 26: if ( (*p) == 37 ) goto st27; goto tr46; st27: if ( ++p == pe ) goto _test_eof27; case 27: if ( (*p) == 123 ) goto tr49; goto tr48; tr44: #line 1 "NONE" {te = p+1;} goto st28; st28: if ( ++p == pe ) goto _test_eof28; case 28: #line 326 "rlscan.cpp" switch( (*p) ) { case 39: goto tr5; case 92: goto st4; } goto st3; st3: if ( ++p == pe ) goto _test_eof3; case 3: switch( (*p) ) { case 39: goto tr5; case 92: goto st4; } goto st3; st4: if ( ++p == pe ) goto _test_eof4; case 4: goto st3; tr45: #line 1 "NONE" {te = p+1;} goto st29; st29: if ( ++p == pe ) goto _test_eof29; case 29: #line 354 "rlscan.cpp" switch( (*p) ) { case 42: goto tr50; case 47: goto st5; } goto tr46; st5: if ( ++p == pe ) goto _test_eof5; case 5: if ( (*p) == 10 ) goto tr8; goto st5; tr9: #line 76 "rlscan.rl" { escapeXML( (*p) ); } goto st6; st6: #line 1 "NONE" {ts = 0;} if ( ++p == pe ) goto _test_eof6; case 6: #line 377 "rlscan.cpp" switch( (*p) ) { case 0: goto st0; case 42: goto tr11; } goto tr9; st0: cs = 0; goto _out; tr11: #line 76 "rlscan.rl" { escapeXML( (*p) ); } goto st7; st7: if ( ++p == pe ) goto _test_eof7; case 7: #line 394 "rlscan.cpp" switch( (*p) ) { case 0: goto st0; case 42: goto tr11; case 47: goto tr12; } goto tr9; tr12: #line 76 "rlscan.rl" { escapeXML( (*p) ); } #line 77 "rlscan.rl" { {cs = stack[--top];goto _again;} } goto st30; st30: if ( ++p == pe ) goto _test_eof30; case 30: #line 411 "rlscan.cpp" goto st0; tr13: #line 112 "rlscan.rl" {{p = ((te))-1;}{ escapeXML( *ts ); }} goto st31; tr15: #line 79 "rlscan.rl" {te = p+1;{ escapeXML( ts, te-ts ); }} goto st31; tr18: #line 79 "rlscan.rl" {te = p+1;{ escapeXML( ts, te-ts ); }} goto st31; tr21: #line 79 "rlscan.rl" {te = p+1;{ escapeXML( ts, te-ts ); }} goto st31; tr51: #line 112 "rlscan.rl" {te = p+1;{ escapeXML( *ts ); }} goto st31; tr55: #line 97 "rlscan.rl" {te = p+1;{ write( '{' ); inline_depth += 1; }} goto st31; tr56: #line 102 "rlscan.rl" {te = p+1;{ write( '}' ); /* If dropping down to the last } then return * to ragel code. */ if ( --inline_depth == 0 ) { write( "\n" ); {goto st35;} } }} goto st31; tr57: #line 112 "rlscan.rl" {te = p;p--;{ escapeXML( *ts ); }} goto st31; tr58: #line 91 "rlscan.rl" {te = p+1;{ write( "/*" ); {stack[top++] = 31; goto st6;} }} goto st31; st31: #line 1 "NONE" {ts = 0;} if ( ++p == pe ) goto _test_eof31; case 31: #line 1 "NONE" {ts = p;} #line 477 "rlscan.cpp" switch( (*p) ) { case 0: goto st0; case 34: goto tr52; case 39: goto tr53; case 47: goto tr54; case 123: goto tr55; case 125: goto tr56; } goto tr51; tr52: #line 1 "NONE" {te = p+1;} goto st32; st32: if ( ++p == pe ) goto _test_eof32; case 32: #line 495 "rlscan.cpp" switch( (*p) ) { case 34: goto tr15; case 92: goto st9; } goto st8; st8: if ( ++p == pe ) goto _test_eof8; case 8: switch( (*p) ) { case 34: goto tr15; case 92: goto st9; } goto st8; st9: if ( ++p == pe ) goto _test_eof9; case 9: goto st8; tr53: #line 1 "NONE" {te = p+1;} goto st33; st33: if ( ++p == pe ) goto _test_eof33; case 33: #line 523 "rlscan.cpp" switch( (*p) ) { case 39: goto tr18; case 92: goto st11; } goto st10; st10: if ( ++p == pe ) goto _test_eof10; case 10: switch( (*p) ) { case 39: goto tr18; case 92: goto st11; } goto st10; st11: if ( ++p == pe ) goto _test_eof11; case 11: goto st10; tr54: #line 1 "NONE" {te = p+1;} goto st34; st34: if ( ++p == pe ) goto _test_eof34; case 34: #line 551 "rlscan.cpp" switch( (*p) ) { case 42: goto tr58; case 47: goto st12; } goto tr57; st12: if ( ++p == pe ) goto _test_eof12; case 12: if ( (*p) == 10 ) goto tr21; goto st12; tr22: #line 193 "rlscan.rl" {{p = ((te))-1;}{ write( "" ); escapeXML( (*p) ); write( "\n" ); }} goto st35; tr24: #line 166 "rlscan.rl" {te = p+1;{ write( "" ); escapeXML( ts, te-ts ); write( "\n" ); }} goto st35; tr27: #line 156 "rlscan.rl" {te = p+1;} goto st35; tr29: #line 159 "rlscan.rl" {te = p+1;{ write( "" ); escapeXML( ts, te-ts ); write( "\n" ); }} goto st35; tr32: #line 180 "rlscan.rl" {te = p+1;{ write( "" ); escapeXML( ts, te-ts ); write( "\n" ); }} goto st35; tr34: #line 142 "rlscan.rl" {{p = ((te))-1;}{ write( "" ); write( ts, te-ts ); write( "\n" ); }} goto st35; tr38: #line 173 "rlscan.rl" {te = p+1;{ write( "" ); escapeXML( ts, te-ts ); write( "\n" ); }} goto st35; tr39: #line 120 "rlscan.rl" {te = p+1;{ if ( !single_line ) { write( "
\n" ); {goto st24;} } }} goto st35; tr59: #line 199 "rlscan.rl" {te = p+1;} goto st35; tr60: #line 127 "rlscan.rl" {te = p+1;{ if ( single_line ) { write( "
\n" ); {goto st24;} } }} goto st35; tr61: #line 193 "rlscan.rl" {te = p+1;{ write( "" ); escapeXML( (*p) ); write( "\n" ); }} goto st35; tr70: #line 187 "rlscan.rl" {te = p+1;{ inline_depth = 1; write( "{" ); {goto st31;} }} goto st35; tr72: #line 193 "rlscan.rl" {te = p;p--;{ write( "" ); escapeXML( (*p) ); write( "\n" ); }} goto st35; tr73: #line 142 "rlscan.rl" {te = p;p--;{ write( "" ); write( ts, te-ts ); write( "\n" ); }} goto st35; tr75: #line 149 "rlscan.rl" {te = p;p--;{ write( "" ); write( ts, te-ts ); write( "\n" ); }} goto st35; tr76: #line 135 "rlscan.rl" {te = p;p--;{ write( "" ); write( ts, te-ts ); write( "\n" ); }} goto st35; st35: #line 1 "NONE" {ts = 0;} if ( ++p == pe ) goto _test_eof35; case 35: #line 1 "NONE" {ts = p;} #line 694 "rlscan.cpp" switch( (*p) ) { case 0: goto st0; case 10: goto tr60; case 34: goto tr62; case 35: goto tr63; case 39: goto tr64; case 47: goto tr65; case 48: goto tr66; case 91: goto tr69; case 95: goto st43; case 123: goto tr70; case 125: goto tr71; } if ( (*p) < 65 ) { if ( (*p) < 49 ) { if ( 33 <= (*p) && (*p) <= 46 ) goto tr61; } else if ( (*p) > 57 ) { if ( 58 <= (*p) && (*p) <= 64 ) goto tr61; } else goto st41; } else if ( (*p) > 90 ) { if ( (*p) < 97 ) { if ( 92 <= (*p) && (*p) <= 96 ) goto tr61; } else if ( (*p) > 122 ) { if ( 124 <= (*p) && (*p) <= 126 ) goto tr61; } else goto st43; } else goto st43; goto tr59; tr62: #line 1 "NONE" {te = p+1;} goto st36; st36: if ( ++p == pe ) goto _test_eof36; case 36: #line 737 "rlscan.cpp" switch( (*p) ) { case 34: goto tr24; case 92: goto st14; } goto st13; st13: if ( ++p == pe ) goto _test_eof13; case 13: switch( (*p) ) { case 34: goto tr24; case 92: goto st14; } goto st13; st14: if ( ++p == pe ) goto _test_eof14; case 14: goto st13; tr63: #line 1 "NONE" {te = p+1;} goto st37; st37: if ( ++p == pe ) goto _test_eof37; case 37: #line 765 "rlscan.cpp" if ( (*p) == 10 ) goto tr27; goto st15; st15: if ( ++p == pe ) goto _test_eof15; case 15: if ( (*p) == 10 ) goto tr27; goto st15; tr64: #line 1 "NONE" {te = p+1;} goto st38; st38: if ( ++p == pe ) goto _test_eof38; case 38: #line 784 "rlscan.cpp" switch( (*p) ) { case 39: goto tr29; case 92: goto st17; } goto st16; st16: if ( ++p == pe ) goto _test_eof16; case 16: switch( (*p) ) { case 39: goto tr29; case 92: goto st17; } goto st16; st17: if ( ++p == pe ) goto _test_eof17; case 17: goto st16; tr65: #line 1 "NONE" {te = p+1;} goto st39; st39: if ( ++p == pe ) goto _test_eof39; case 39: #line 812 "rlscan.cpp" switch( (*p) ) { case 47: goto tr32; case 92: goto st19; } goto st18; st18: if ( ++p == pe ) goto _test_eof18; case 18: switch( (*p) ) { case 47: goto tr32; case 92: goto st19; } goto st18; st19: if ( ++p == pe ) goto _test_eof19; case 19: goto st18; tr66: #line 1 "NONE" {te = p+1;} goto st40; st40: if ( ++p == pe ) goto _test_eof40; case 40: #line 840 "rlscan.cpp" if ( (*p) == 120 ) goto st20; if ( 48 <= (*p) && (*p) <= 57 ) goto st41; goto tr73; st41: if ( ++p == pe ) goto _test_eof41; case 41: if ( 48 <= (*p) && (*p) <= 57 ) goto st41; goto tr73; st20: if ( ++p == pe ) goto _test_eof20; case 20: if ( (*p) < 65 ) { if ( 48 <= (*p) && (*p) <= 57 ) goto st42; } else if ( (*p) > 70 ) { if ( 97 <= (*p) && (*p) <= 102 ) goto st42; } else goto st42; goto tr34; st42: if ( ++p == pe ) goto _test_eof42; case 42: if ( (*p) < 65 ) { if ( 48 <= (*p) && (*p) <= 57 ) goto st42; } else if ( (*p) > 70 ) { if ( 97 <= (*p) && (*p) <= 102 ) goto st42; } else goto st42; goto tr75; st43: if ( ++p == pe ) goto _test_eof43; case 43: if ( (*p) == 95 ) goto st43; if ( (*p) < 65 ) { if ( 48 <= (*p) && (*p) <= 57 ) goto st43; } else if ( (*p) > 90 ) { if ( 97 <= (*p) && (*p) <= 122 ) goto st43; } else goto st43; goto tr76; tr69: #line 1 "NONE" {te = p+1;} goto st44; st44: if ( ++p == pe ) goto _test_eof44; case 44: #line 902 "rlscan.cpp" switch( (*p) ) { case 92: goto st22; case 93: goto tr38; } goto st21; st21: if ( ++p == pe ) goto _test_eof21; case 21: switch( (*p) ) { case 92: goto st22; case 93: goto tr38; } goto st21; st22: if ( ++p == pe ) goto _test_eof22; case 22: goto st21; tr71: #line 1 "NONE" {te = p+1;} goto st45; st45: if ( ++p == pe ) goto _test_eof45; case 45: #line 930 "rlscan.cpp" if ( (*p) == 37 ) goto st23; goto tr72; st23: if ( ++p == pe ) goto _test_eof23; case 23: if ( (*p) == 37 ) goto tr39; goto tr22; } _test_eof24: cs = 24; goto _test_eof; _test_eof25: cs = 25; goto _test_eof; _test_eof1: cs = 1; goto _test_eof; _test_eof2: cs = 2; goto _test_eof; _test_eof26: cs = 26; goto _test_eof; _test_eof27: cs = 27; goto _test_eof; _test_eof28: cs = 28; goto _test_eof; _test_eof3: cs = 3; goto _test_eof; _test_eof4: cs = 4; goto _test_eof; _test_eof29: cs = 29; goto _test_eof; _test_eof5: cs = 5; goto _test_eof; _test_eof6: cs = 6; goto _test_eof; _test_eof7: cs = 7; goto _test_eof; _test_eof30: cs = 30; goto _test_eof; _test_eof31: cs = 31; goto _test_eof; _test_eof32: cs = 32; goto _test_eof; _test_eof8: cs = 8; goto _test_eof; _test_eof9: cs = 9; goto _test_eof; _test_eof33: cs = 33; goto _test_eof; _test_eof10: cs = 10; goto _test_eof; _test_eof11: cs = 11; goto _test_eof; _test_eof34: cs = 34; goto _test_eof; _test_eof12: cs = 12; goto _test_eof; _test_eof35: cs = 35; goto _test_eof; _test_eof36: cs = 36; goto _test_eof; _test_eof13: cs = 13; goto _test_eof; _test_eof14: cs = 14; goto _test_eof; _test_eof37: cs = 37; goto _test_eof; _test_eof15: cs = 15; goto _test_eof; _test_eof38: cs = 38; goto _test_eof; _test_eof16: cs = 16; goto _test_eof; _test_eof17: cs = 17; goto _test_eof; _test_eof39: cs = 39; goto _test_eof; _test_eof18: cs = 18; goto _test_eof; _test_eof19: cs = 19; goto _test_eof; _test_eof40: cs = 40; goto _test_eof; _test_eof41: cs = 41; goto _test_eof; _test_eof20: cs = 20; goto _test_eof; _test_eof42: cs = 42; goto _test_eof; _test_eof43: cs = 43; goto _test_eof; _test_eof44: cs = 44; goto _test_eof; _test_eof21: cs = 21; goto _test_eof; _test_eof22: cs = 22; goto _test_eof; _test_eof45: cs = 45; goto _test_eof; _test_eof23: cs = 23; goto _test_eof; _test_eof: {} if ( p == eof ) { switch ( cs ) { case 25: goto tr46; case 1: goto tr0; case 2: goto tr0; case 26: goto tr46; case 27: goto tr48; case 28: goto tr46; case 3: goto tr0; case 4: goto tr0; case 29: goto tr46; case 5: goto tr0; case 32: goto tr57; case 8: goto tr13; case 9: goto tr13; case 33: goto tr57; case 10: goto tr13; case 11: goto tr13; case 34: goto tr57; case 12: goto tr13; case 36: goto tr72; case 13: goto tr22; case 14: goto tr22; case 37: goto tr72; case 15: goto tr22; case 38: goto tr72; case 16: goto tr22; case 17: goto tr22; case 39: goto tr72; case 18: goto tr22; case 19: goto tr22; case 40: goto tr73; case 41: goto tr73; case 20: goto tr34; case 42: goto tr75; case 43: goto tr76; case 44: goto tr72; case 21: goto tr22; case 22: goto tr22; case 45: goto tr72; case 23: goto tr22; } } _out: {} } #line 282 "rlscan.rl" if ( cs == RagelScan_error ) { /* Machine failed before finding a token. */ cerr << "PARSE ERROR" << endl; exit(1); } if ( ts == 0 ) have = 0; else { /* There is a prefix to preserve, shift it over. */ have = pe - ts; memmove( inbuf, ts, have ); te = inbuf + (te-ts); ts = inbuf; } } return 0; } ragel-6.8/examples/pullscan.c0000664000175000017500000001240312106311500013174 00000000000000 #line 1 "pullscan.rl" #include #include #include #define BUFSIZE 4096 typedef struct _Scanner { /* Scanner state. */ int cs; int act; int have; int curline; char *ts; char *te; char *p; char *pe; char *eof; FILE *file; int done; /* Token data */ char *data; int len; int value; char buf[BUFSIZE]; } Scanner; #line 34 "pullscan.c" static const int Scanner_start = 2; static const int Scanner_first_final = 2; static const int Scanner_error = -1; static const int Scanner_en_main = 2; #line 33 "pullscan.rl" void scan_init( Scanner *s, FILE *file ) { memset (s, '\0', sizeof(Scanner)); s->curline = 1; s->file = file; s->eof = 0; #line 52 "pullscan.c" { s->cs = Scanner_start; s->ts = 0; s->te = 0; s->act = 0; } #line 42 "pullscan.rl" } #define TK_NO_TOKEN (-1) #define TK_ERR 128 #define TK_EOF 129 #define TK_Identifier 130 #define TK_Number 131 #define TK_String 132 #define ret_tok( _tok ) token = _tok; s->data = s->ts int scan( Scanner *s ) { int token = TK_NO_TOKEN; int space, readlen; while ( 1 ) { if ( s->p == s->pe ) { printf("scanner: need more data\n"); if ( s->ts == 0 ) s->have = 0; else { /* There is data that needs to be shifted over. */ printf("scanner: buffer broken mid token\n"); s->have = s->pe - s->ts; memmove( s->buf, s->ts, s->have ); s->te -= (s->ts-s->buf); s->ts = s->buf; } s->p = s->buf + s->have; space = BUFSIZE - s->have; if ( space == 0 ) { /* We filled up the buffer trying to scan a token. */ printf("scanner: out of buffer space\n"); return TK_ERR; } if ( s->done ) { printf("scanner: end of file\n"); s->p[0] = 0; readlen = 1; } else { readlen = fread( s->p, 1, space, s->file ); if ( readlen < space ) s->done = 1; } s->pe = s->p + readlen; } #line 116 "pullscan.c" { if ( ( s->p) == ( s->pe) ) goto _test_eof; switch ( s->cs ) { tr0: #line 125 "pullscan.rl" {{( s->p) = (( s->te))-1;}{ ret_tok( *s->p ); {( s->p)++; s->cs = 2; goto _out;} }} goto st2; tr2: #line 113 "pullscan.rl" { s->te = ( s->p)+1;{ ret_tok( TK_String ); {( s->p)++; s->cs = 2; goto _out;} }} goto st2; tr4: #line 125 "pullscan.rl" { s->te = ( s->p)+1;{ ret_tok( *s->p ); {( s->p)++; s->cs = 2; goto _out;} }} goto st2; tr5: #line 121 "pullscan.rl" { s->te = ( s->p)+1;{ ret_tok( TK_EOF ); {( s->p)++; s->cs = 2; goto _out;} }} goto st2; tr6: #line 110 "pullscan.rl" { s->te = ( s->p)+1;} goto st2; tr10: #line 125 "pullscan.rl" { s->te = ( s->p);( s->p)--;{ ret_tok( *s->p ); {( s->p)++; s->cs = 2; goto _out;} }} goto st2; tr11: #line 117 "pullscan.rl" { s->te = ( s->p);( s->p)--;{ ret_tok( TK_Number ); {( s->p)++; s->cs = 2; goto _out;} }} goto st2; tr12: #line 107 "pullscan.rl" { s->te = ( s->p);( s->p)--;{ ret_tok( TK_Identifier ); {( s->p)++; s->cs = 2; goto _out;} }} goto st2; st2: #line 1 "NONE" { s->ts = 0;} if ( ++( s->p) == ( s->pe) ) goto _test_eof2; case 2: #line 1 "NONE" { s->ts = ( s->p);} #line 162 "pullscan.c" switch( (*( s->p)) ) { case 0: goto tr5; case 32: goto tr6; case 34: goto tr7; case 95: goto st5; } if ( (*( s->p)) < 48 ) { if ( 9 <= (*( s->p)) && (*( s->p)) <= 10 ) goto tr6; } else if ( (*( s->p)) > 57 ) { if ( (*( s->p)) > 90 ) { if ( 97 <= (*( s->p)) && (*( s->p)) <= 122 ) goto st5; } else if ( (*( s->p)) >= 65 ) goto st5; } else goto st4; goto tr4; tr7: #line 1 "NONE" { s->te = ( s->p)+1;} goto st3; st3: if ( ++( s->p) == ( s->pe) ) goto _test_eof3; case 3: #line 189 "pullscan.c" switch( (*( s->p)) ) { case 34: goto tr2; case 92: goto st1; } goto st0; st0: if ( ++( s->p) == ( s->pe) ) goto _test_eof0; case 0: switch( (*( s->p)) ) { case 34: goto tr2; case 92: goto st1; } goto st0; st1: if ( ++( s->p) == ( s->pe) ) goto _test_eof1; case 1: goto st0; st4: if ( ++( s->p) == ( s->pe) ) goto _test_eof4; case 4: if ( 48 <= (*( s->p)) && (*( s->p)) <= 57 ) goto st4; goto tr11; st5: if ( ++( s->p) == ( s->pe) ) goto _test_eof5; case 5: if ( (*( s->p)) == 95 ) goto st5; if ( (*( s->p)) < 65 ) { if ( 48 <= (*( s->p)) && (*( s->p)) <= 57 ) goto st5; } else if ( (*( s->p)) > 90 ) { if ( 97 <= (*( s->p)) && (*( s->p)) <= 122 ) goto st5; } else goto st5; goto tr12; } _test_eof2: s->cs = 2; goto _test_eof; _test_eof3: s->cs = 3; goto _test_eof; _test_eof0: s->cs = 0; goto _test_eof; _test_eof1: s->cs = 1; goto _test_eof; _test_eof4: s->cs = 4; goto _test_eof; _test_eof5: s->cs = 5; goto _test_eof; _test_eof: {} if ( ( s->p) == ( s->eof) ) { switch ( s->cs ) { case 3: goto tr10; case 0: goto tr0; case 1: goto tr0; case 4: goto tr11; case 5: goto tr12; } } _out: {} } #line 130 "pullscan.rl" if ( s->cs == Scanner_error ) return TK_ERR; if ( token != TK_NO_TOKEN ) { s->len = s->p - s->data; return token; } } } int main (int argc, char** argv) { Scanner ss; int tok; scan_init(&ss, stdin); while ( 1 ) { tok = scan (&ss); if ( tok == TK_EOF ) { printf ("parser: EOF\n"); break; } else if ( tok == TK_ERR ) { printf ("parser: ERR\n"); break; } else { printf ("parser: %d \"", tok); fwrite ( ss.data, 1, ss.len, stdout ); printf ("\"\n" ); } } return 0; } ragel-6.8/examples/clang.c0000664000175000017500000001650512106311500012446 00000000000000 #line 1 "clang.rl" /* * A mini C-like language scanner. */ #include #include #include #line 91 "clang.rl" #line 17 "clang.c" static const int clang_start = 10; static const int clang_error = 0; static const int clang_en_c_comment = 8; static const int clang_en_main = 10; #line 94 "clang.rl" #define BUFSIZE 128 void scanner() { static char buf[BUFSIZE]; int cs, act, have = 0, curline = 1; char *ts, *te = 0; int done = 0; #line 37 "clang.c" { cs = clang_start; ts = 0; te = 0; act = 0; } #line 105 "clang.rl" while ( !done ) { char *p = buf + have, *pe, *eof = 0; int len, space = BUFSIZE - have; if ( space == 0 ) { /* We've used up the entire buffer storing an already-parsed token * prefix that must be preserved. */ fprintf(stderr, "OUT OF BUFFER SPACE\n" ); exit(1); } len = fread( p, 1, space, stdin ); pe = p + len; /* Check if this is the end of file. */ if ( len < space ) { eof = pe; done = 1; } #line 68 "clang.c" { if ( p == pe ) goto _test_eof; switch ( cs ) { tr2: #line 50 "clang.rl" {te = p+1;{ printf( "double_lit(%i): ", curline ); fwrite( ts, 1, te-ts, stdout ); printf("\n"); }} goto st10; tr6: #line 42 "clang.rl" {te = p+1;{ printf( "single_lit(%i): ", curline ); fwrite( ts, 1, te-ts, stdout ); printf("\n"); }} goto st10; tr8: #line 28 "clang.rl" {{p = ((te))-1;}{ printf( "symbol(%i): %c\n", curline, ts[0] ); }} goto st10; tr10: #line 12 "clang.rl" {curline += 1;} #line 62 "clang.rl" {te = p+1;} goto st10; tr11: #line 68 "clang.rl" {{p = ((te))-1;}{ printf( "int(%i): ", curline ); fwrite( ts, 1, te-ts, stdout ); printf("\n"); }} goto st10; tr18: #line 57 "clang.rl" {te = p+1;} goto st10; tr19: #line 12 "clang.rl" {curline += 1;} #line 57 "clang.rl" {te = p+1;} goto st10; tr20: #line 28 "clang.rl" {te = p+1;{ printf( "symbol(%i): %c\n", curline, ts[0] ); }} goto st10; tr25: #line 28 "clang.rl" {te = p;p--;{ printf( "symbol(%i): %c\n", curline, ts[0] ); }} goto st10; tr26: #line 64 "clang.rl" {te = p+1;{ {goto st8;} }} goto st10; tr27: #line 68 "clang.rl" {te = p;p--;{ printf( "int(%i): ", curline ); fwrite( ts, 1, te-ts, stdout ); printf("\n"); }} goto st10; tr30: #line 76 "clang.rl" {te = p;p--;{ printf( "float(%i): ", curline ); fwrite( ts, 1, te-ts, stdout ); printf("\n"); }} goto st10; tr31: #line 84 "clang.rl" {te = p;p--;{ printf( "hex(%i): ", curline ); fwrite( ts, 1, te-ts, stdout ); printf("\n"); }} goto st10; tr32: #line 34 "clang.rl" {te = p;p--;{ printf( "ident(%i): ", curline ); fwrite( ts, 1, te-ts, stdout ); printf("\n"); }} goto st10; st10: #line 1 "NONE" {ts = 0;} if ( ++p == pe ) goto _test_eof10; case 10: #line 1 "NONE" {ts = p;} #line 176 "clang.c" switch( (*p) ) { case 10: goto tr19; case 34: goto st1; case 39: goto st3; case 47: goto tr21; case 48: goto tr22; case 95: goto st16; } if ( (*p) < 65 ) { if ( (*p) < 49 ) { if ( 33 <= (*p) && (*p) <= 46 ) goto tr20; } else if ( (*p) > 57 ) { if ( 58 <= (*p) && (*p) <= 64 ) goto tr20; } else goto tr23; } else if ( (*p) > 90 ) { if ( (*p) < 97 ) { if ( 91 <= (*p) && (*p) <= 96 ) goto tr20; } else if ( (*p) > 122 ) { if ( 123 <= (*p) && (*p) <= 126 ) goto tr20; } else goto st16; } else goto st16; goto tr18; tr1: #line 12 "clang.rl" {curline += 1;} goto st1; st1: if ( ++p == pe ) goto _test_eof1; case 1: #line 214 "clang.c" switch( (*p) ) { case 10: goto tr1; case 34: goto tr2; case 92: goto st2; } goto st1; st2: if ( ++p == pe ) goto _test_eof2; case 2: if ( (*p) == 10 ) goto tr1; goto st1; tr5: #line 12 "clang.rl" {curline += 1;} goto st3; st3: if ( ++p == pe ) goto _test_eof3; case 3: #line 236 "clang.c" switch( (*p) ) { case 10: goto tr5; case 39: goto tr6; case 92: goto st4; } goto st3; st4: if ( ++p == pe ) goto _test_eof4; case 4: if ( (*p) == 10 ) goto tr5; goto st3; tr21: #line 1 "NONE" {te = p+1;} goto st11; st11: if ( ++p == pe ) goto _test_eof11; case 11: #line 258 "clang.c" switch( (*p) ) { case 42: goto tr26; case 47: goto st5; } goto tr25; st5: if ( ++p == pe ) goto _test_eof5; case 5: if ( (*p) == 10 ) goto tr10; goto st5; tr22: #line 1 "NONE" {te = p+1;} goto st12; st12: if ( ++p == pe ) goto _test_eof12; case 12: #line 279 "clang.c" switch( (*p) ) { case 46: goto st6; case 120: goto st7; } if ( 48 <= (*p) && (*p) <= 57 ) goto tr23; goto tr27; st6: if ( ++p == pe ) goto _test_eof6; case 6: if ( 48 <= (*p) && (*p) <= 57 ) goto st13; goto tr11; st13: if ( ++p == pe ) goto _test_eof13; case 13: if ( 48 <= (*p) && (*p) <= 57 ) goto st13; goto tr30; tr23: #line 1 "NONE" {te = p+1;} goto st14; st14: if ( ++p == pe ) goto _test_eof14; case 14: #line 309 "clang.c" if ( (*p) == 46 ) goto st6; if ( 48 <= (*p) && (*p) <= 57 ) goto tr23; goto tr27; st7: if ( ++p == pe ) goto _test_eof7; case 7: if ( (*p) < 65 ) { if ( 48 <= (*p) && (*p) <= 57 ) goto st15; } else if ( (*p) > 70 ) { if ( 97 <= (*p) && (*p) <= 102 ) goto st15; } else goto st15; goto tr11; st15: if ( ++p == pe ) goto _test_eof15; case 15: if ( (*p) < 65 ) { if ( 48 <= (*p) && (*p) <= 57 ) goto st15; } else if ( (*p) > 70 ) { if ( 97 <= (*p) && (*p) <= 102 ) goto st15; } else goto st15; goto tr31; st16: if ( ++p == pe ) goto _test_eof16; case 16: if ( (*p) == 95 ) goto st16; if ( (*p) < 65 ) { if ( 48 <= (*p) && (*p) <= 57 ) goto st16; } else if ( (*p) > 90 ) { if ( 97 <= (*p) && (*p) <= 122 ) goto st16; } else goto st16; goto tr32; tr15: #line 12 "clang.rl" {curline += 1;} goto st8; st8: #line 1 "NONE" {ts = 0;} if ( ++p == pe ) goto _test_eof8; case 8: #line 366 "clang.c" switch( (*p) ) { case 10: goto tr15; case 42: goto st9; } goto st8; st9: if ( ++p == pe ) goto _test_eof9; case 9: switch( (*p) ) { case 10: goto tr15; case 42: goto st9; case 47: goto tr17; } goto st8; tr17: #line 16 "clang.rl" {{goto st10;}} goto st17; st17: if ( ++p == pe ) goto _test_eof17; case 17: #line 390 "clang.c" goto st0; st0: cs = 0; goto _out; } _test_eof10: cs = 10; goto _test_eof; _test_eof1: cs = 1; goto _test_eof; _test_eof2: cs = 2; goto _test_eof; _test_eof3: cs = 3; goto _test_eof; _test_eof4: cs = 4; goto _test_eof; _test_eof11: cs = 11; goto _test_eof; _test_eof5: cs = 5; goto _test_eof; _test_eof12: cs = 12; goto _test_eof; _test_eof6: cs = 6; goto _test_eof; _test_eof13: cs = 13; goto _test_eof; _test_eof14: cs = 14; goto _test_eof; _test_eof7: cs = 7; goto _test_eof; _test_eof15: cs = 15; goto _test_eof; _test_eof16: cs = 16; goto _test_eof; _test_eof8: cs = 8; goto _test_eof; _test_eof9: cs = 9; goto _test_eof; _test_eof17: cs = 17; goto _test_eof; _test_eof: {} if ( p == eof ) { switch ( cs ) { case 11: goto tr25; case 5: goto tr8; case 12: goto tr27; case 6: goto tr11; case 13: goto tr30; case 14: goto tr27; case 7: goto tr11; case 15: goto tr31; case 16: goto tr32; } } _out: {} } #line 127 "clang.rl" if ( cs == clang_error ) { fprintf(stderr, "PARSE ERROR\n" ); break; } if ( ts == 0 ) have = 0; else { /* There is a prefix to preserve, shift it over. */ have = pe - ts; memmove( buf, ts, have ); te = buf + (te-ts); ts = buf; } } } int main() { scanner(); return 0; } ragel-6.8/examples/cppscan.cpp0000664000175000017500000003771312106311500013355 00000000000000 #line 1 "cppscan.rl" /* * A C++ scanner. Uses the longest match construction. * << <= <<= >> >= >>= are left out since angle brackets are used in templates. */ #include #include #include #define TK_Dlit 256 #define TK_Slit 257 #define TK_Float 258 #define TK_Id 259 #define TK_NameSep 260 #define TK_Arrow 261 #define TK_PlusPlus 262 #define TK_MinusMinus 263 #define TK_ArrowStar 264 #define TK_DotStar 265 #define TK_ShiftLeft 266 #define TK_ShiftRight 267 #define TK_IntegerDecimal 268 #define TK_IntegerOctal 269 #define TK_IntegerHex 270 #define TK_EqualsEquals 271 #define TK_NotEquals 272 #define TK_AndAnd 273 #define TK_OrOr 274 #define TK_MultAssign 275 #define TK_DivAssign 276 #define TK_PercentAssign 277 #define TK_PlusAssign 278 #define TK_MinusAssign 279 #define TK_AmpAssign 280 #define TK_CaretAssign 281 #define TK_BarAssign 282 #define TK_DotDotDot 283 #define TK_Whitespace 284 #define TK_Comment 285 #define BUFSIZE 16384 /* EOF char used to flush out that last token. This should be a whitespace * token. */ #define LAST_CHAR 0 using std::cerr; using std::cout; using std::cin; using std::endl; static char buf[BUFSIZE]; static int line = 1, col = 1; static char *ts, *te; static int act, have = 0; static int cs; #line 63 "cppscan.cpp" static const int Scanner_start = 12; static const int Scanner_error = 0; static const int Scanner_en_c_comment = 10; static const int Scanner_en_main = 12; #line 132 "cppscan.rl" void token( int tok ) { char *data = ts; int len = te - ts; cout << '<' << tok << "> "; cout.write( data, len ); cout << '\n'; /* Count newlines and columns. This code is here mainly for having some * code in the token routine when commenting out the above output during * performance testing. */ for ( int i = 0; i < len; i ++ ) { if ( data[i] == '\n' ) { line += 1; col = 1; } else { col += 1; } } } int main() { std::ios::sync_with_stdio(false); #line 102 "cppscan.cpp" { cs = Scanner_start; ts = 0; te = 0; act = 0; } #line 162 "cppscan.rl" /* Do the first read. */ bool done = false; while ( !done ) { char *p = buf + have; int space = BUFSIZE - have; if ( space == 0 ) { /* We filled up the buffer trying to scan a token. */ cerr << "OUT OF BUFFER SPACE" << endl; exit(1); } cin.read( p, space ); int len = cin.gcount(); char *pe = p + len; char *eof = 0; /* If we see eof then append the EOF char. */ if ( cin.eof() ) { eof = pe; done = true; } #line 136 "cppscan.cpp" { if ( p == pe ) goto _test_eof; switch ( cs ) { tr0: #line 1 "NONE" { switch( act ) { case 0: {{goto st0;}} break; case 3: {{p = ((te))-1;}token( TK_Id );} break; case 4: {{p = ((te))-1;}token( TK_Float );} break; case 5: {{p = ((te))-1;}token( TK_IntegerDecimal );} break; case 6: {{p = ((te))-1;}token( TK_IntegerOctal );} break; } } goto st12; tr2: #line 78 "cppscan.rl" {te = p+1;{token( TK_Dlit );}} goto st12; tr5: #line 76 "cppscan.rl" {te = p+1;{token( TK_Slit );}} goto st12; tr7: #line 124 "cppscan.rl" {{p = ((te))-1;}{token( ts[0] );}} goto st12; tr8: #line 121 "cppscan.rl" {te = p+1;{token( TK_DotDotDot );}} goto st12; tr12: #line 128 "cppscan.rl" {te = p+1;} goto st12; tr13: #line 90 "cppscan.rl" {{p = ((te))-1;}{token( TK_IntegerDecimal );}} goto st12; tr20: #line 124 "cppscan.rl" {te = p+1;{token( ts[0] );}} goto st12; tr36: #line 129 "cppscan.rl" {te = p;p--;} goto st12; tr37: #line 124 "cppscan.rl" {te = p;p--;{token( ts[0] );}} goto st12; tr38: #line 103 "cppscan.rl" {te = p+1;{token( TK_NotEquals );}} goto st12; tr39: #line 108 "cppscan.rl" {te = p+1;{token( TK_PercentAssign );}} goto st12; tr40: #line 104 "cppscan.rl" {te = p+1;{token( TK_AndAnd );}} goto st12; tr41: #line 111 "cppscan.rl" {te = p+1;{token( TK_AmpAssign );}} goto st12; tr42: #line 106 "cppscan.rl" {te = p+1;{token( TK_MultAssign );}} goto st12; tr43: #line 114 "cppscan.rl" {te = p+1;{token( TK_PlusPlus );}} goto st12; tr44: #line 109 "cppscan.rl" {te = p+1;{token( TK_PlusAssign );}} goto st12; tr45: #line 115 "cppscan.rl" {te = p+1;{token( TK_MinusMinus );}} goto st12; tr46: #line 110 "cppscan.rl" {te = p+1;{token( TK_MinusAssign );}} goto st12; tr48: #line 116 "cppscan.rl" {te = p;p--;{token( TK_Arrow );}} goto st12; tr49: #line 117 "cppscan.rl" {te = p+1;{token( TK_ArrowStar );}} goto st12; tr50: #line 118 "cppscan.rl" {te = p+1;{token( TK_DotStar );}} goto st12; tr53: #line 86 "cppscan.rl" {te = p;p--;{token( TK_Float );}} goto st12; tr55: #line 86 "cppscan.rl" {te = p+1;{token( TK_Float );}} goto st12; tr56: #line 127 "cppscan.rl" {te = p+1;{ {goto st10;} }} goto st12; tr57: #line 107 "cppscan.rl" {te = p+1;{token( TK_DivAssign );}} goto st12; tr58: #line 90 "cppscan.rl" {te = p;p--;{token( TK_IntegerDecimal );}} goto st12; tr62: #line 94 "cppscan.rl" {te = p;p--;{token( TK_IntegerOctal );}} goto st12; tr64: #line 94 "cppscan.rl" {te = p+1;{token( TK_IntegerOctal );}} goto st12; tr66: #line 90 "cppscan.rl" {te = p+1;{token( TK_IntegerDecimal );}} goto st12; tr67: #line 98 "cppscan.rl" {te = p;p--;{token( TK_IntegerHex );}} goto st12; tr69: #line 98 "cppscan.rl" {te = p+1;{token( TK_IntegerHex );}} goto st12; tr70: #line 101 "cppscan.rl" {te = p+1;{token( TK_NameSep );}} goto st12; tr71: #line 102 "cppscan.rl" {te = p+1;{token( TK_EqualsEquals );}} goto st12; tr72: #line 82 "cppscan.rl" {te = p;p--;{token( TK_Id );}} goto st12; tr73: #line 112 "cppscan.rl" {te = p+1;{token( TK_CaretAssign );}} goto st12; tr74: #line 113 "cppscan.rl" {te = p+1;{token( TK_BarAssign );}} goto st12; tr75: #line 105 "cppscan.rl" {te = p+1;{token( TK_OrOr );}} goto st12; st12: #line 1 "NONE" {ts = 0;} #line 1 "NONE" {act = 0;} if ( ++p == pe ) goto _test_eof12; case 12: #line 1 "NONE" {ts = p;} #line 321 "cppscan.cpp" switch( (*p) ) { case 33: goto st14; case 34: goto st1; case 37: goto st15; case 38: goto st16; case 39: goto st3; case 42: goto st17; case 43: goto st18; case 45: goto st19; case 46: goto tr26; case 47: goto tr27; case 48: goto tr28; case 58: goto st33; case 61: goto st34; case 76: goto tr33; case 94: goto st37; case 95: goto st35; case 124: goto st38; } if ( (*p) < 65 ) { if ( (*p) < 49 ) { if ( 35 <= (*p) && (*p) <= 44 ) goto tr20; } else if ( (*p) > 57 ) { if ( 59 <= (*p) && (*p) <= 64 ) goto tr20; } else goto tr29; } else if ( (*p) > 90 ) { if ( (*p) < 97 ) { if ( 91 <= (*p) && (*p) <= 96 ) goto tr20; } else if ( (*p) > 122 ) { if ( 123 <= (*p) && (*p) <= 126 ) goto tr20; } else goto st35; } else goto st35; goto st13; st13: if ( ++p == pe ) goto _test_eof13; case 13: if ( 33 <= (*p) && (*p) <= 126 ) goto tr36; goto st13; st14: if ( ++p == pe ) goto _test_eof14; case 14: if ( (*p) == 61 ) goto tr38; goto tr37; st1: if ( ++p == pe ) goto _test_eof1; case 1: switch( (*p) ) { case 10: goto tr0; case 34: goto tr2; case 92: goto st2; } goto st1; st2: if ( ++p == pe ) goto _test_eof2; case 2: goto st1; st15: if ( ++p == pe ) goto _test_eof15; case 15: if ( (*p) == 61 ) goto tr39; goto tr37; st16: if ( ++p == pe ) goto _test_eof16; case 16: switch( (*p) ) { case 38: goto tr40; case 61: goto tr41; } goto tr37; st3: if ( ++p == pe ) goto _test_eof3; case 3: switch( (*p) ) { case 10: goto tr0; case 39: goto tr5; case 92: goto st4; } goto st3; st4: if ( ++p == pe ) goto _test_eof4; case 4: goto st3; st17: if ( ++p == pe ) goto _test_eof17; case 17: if ( (*p) == 61 ) goto tr42; goto tr37; st18: if ( ++p == pe ) goto _test_eof18; case 18: switch( (*p) ) { case 43: goto tr43; case 61: goto tr44; } goto tr37; st19: if ( ++p == pe ) goto _test_eof19; case 19: switch( (*p) ) { case 45: goto tr45; case 61: goto tr46; case 62: goto st20; } goto tr37; st20: if ( ++p == pe ) goto _test_eof20; case 20: if ( (*p) == 42 ) goto tr49; goto tr48; tr26: #line 1 "NONE" {te = p+1;} goto st21; st21: if ( ++p == pe ) goto _test_eof21; case 21: #line 463 "cppscan.cpp" switch( (*p) ) { case 42: goto tr50; case 46: goto st5; } if ( 48 <= (*p) && (*p) <= 57 ) goto tr52; goto tr37; st5: if ( ++p == pe ) goto _test_eof5; case 5: if ( (*p) == 46 ) goto tr8; goto tr7; tr52: #line 1 "NONE" {te = p+1;} #line 86 "cppscan.rl" {act = 4;} goto st22; st22: if ( ++p == pe ) goto _test_eof22; case 22: #line 488 "cppscan.cpp" switch( (*p) ) { case 69: goto st6; case 70: goto tr55; case 76: goto tr55; case 101: goto st6; case 102: goto tr55; case 108: goto tr55; } if ( 48 <= (*p) && (*p) <= 57 ) goto tr52; goto tr53; st6: if ( ++p == pe ) goto _test_eof6; case 6: switch( (*p) ) { case 43: goto st7; case 45: goto st7; } if ( 48 <= (*p) && (*p) <= 57 ) goto st23; goto tr0; st7: if ( ++p == pe ) goto _test_eof7; case 7: if ( 48 <= (*p) && (*p) <= 57 ) goto st23; goto tr0; st23: if ( ++p == pe ) goto _test_eof23; case 23: switch( (*p) ) { case 70: goto tr55; case 76: goto tr55; case 102: goto tr55; case 108: goto tr55; } if ( 48 <= (*p) && (*p) <= 57 ) goto st23; goto tr53; tr27: #line 1 "NONE" {te = p+1;} goto st24; st24: if ( ++p == pe ) goto _test_eof24; case 24: #line 539 "cppscan.cpp" switch( (*p) ) { case 42: goto tr56; case 47: goto st8; case 61: goto tr57; } goto tr37; st8: if ( ++p == pe ) goto _test_eof8; case 8: if ( (*p) == 10 ) goto tr12; goto st8; tr28: #line 1 "NONE" {te = p+1;} #line 90 "cppscan.rl" {act = 5;} goto st25; st25: if ( ++p == pe ) goto _test_eof25; case 25: #line 563 "cppscan.cpp" switch( (*p) ) { case 46: goto tr52; case 69: goto st6; case 76: goto st28; case 85: goto st28; case 101: goto st6; case 108: goto st28; case 117: goto st28; case 120: goto st9; } if ( 48 <= (*p) && (*p) <= 57 ) goto tr59; goto tr58; tr59: #line 1 "NONE" {te = p+1;} #line 94 "cppscan.rl" {act = 6;} goto st26; st26: if ( ++p == pe ) goto _test_eof26; case 26: #line 587 "cppscan.cpp" switch( (*p) ) { case 46: goto tr52; case 69: goto st6; case 76: goto st27; case 85: goto st27; case 101: goto st6; case 108: goto st27; case 117: goto st27; } if ( 48 <= (*p) && (*p) <= 57 ) goto tr59; goto tr62; st27: if ( ++p == pe ) goto _test_eof27; case 27: switch( (*p) ) { case 76: goto tr64; case 85: goto tr64; case 108: goto tr64; case 117: goto tr64; } goto tr62; st28: if ( ++p == pe ) goto _test_eof28; case 28: switch( (*p) ) { case 76: goto st29; case 85: goto st29; case 108: goto st29; case 117: goto st29; } goto tr58; st29: if ( ++p == pe ) goto _test_eof29; case 29: switch( (*p) ) { case 76: goto tr66; case 85: goto tr66; case 108: goto tr66; case 117: goto tr66; } goto tr58; st9: if ( ++p == pe ) goto _test_eof9; case 9: if ( (*p) < 65 ) { if ( 48 <= (*p) && (*p) <= 57 ) goto st30; } else if ( (*p) > 70 ) { if ( 97 <= (*p) && (*p) <= 102 ) goto st30; } else goto st30; goto tr13; st30: if ( ++p == pe ) goto _test_eof30; case 30: switch( (*p) ) { case 76: goto st31; case 85: goto st31; case 108: goto st31; case 117: goto st31; } if ( (*p) < 65 ) { if ( 48 <= (*p) && (*p) <= 57 ) goto st30; } else if ( (*p) > 70 ) { if ( 97 <= (*p) && (*p) <= 102 ) goto st30; } else goto st30; goto tr67; st31: if ( ++p == pe ) goto _test_eof31; case 31: switch( (*p) ) { case 76: goto tr69; case 85: goto tr69; case 108: goto tr69; case 117: goto tr69; } goto tr67; tr29: #line 1 "NONE" {te = p+1;} #line 90 "cppscan.rl" {act = 5;} goto st32; st32: if ( ++p == pe ) goto _test_eof32; case 32: #line 686 "cppscan.cpp" switch( (*p) ) { case 46: goto tr52; case 69: goto st6; case 76: goto st28; case 85: goto st28; case 101: goto st6; case 108: goto st28; case 117: goto st28; } if ( 48 <= (*p) && (*p) <= 57 ) goto tr29; goto tr58; st33: if ( ++p == pe ) goto _test_eof33; case 33: if ( (*p) == 58 ) goto tr70; goto tr37; st34: if ( ++p == pe ) goto _test_eof34; case 34: if ( (*p) == 61 ) goto tr71; goto tr37; st35: if ( ++p == pe ) goto _test_eof35; case 35: if ( (*p) == 95 ) goto st35; if ( (*p) < 65 ) { if ( 48 <= (*p) && (*p) <= 57 ) goto st35; } else if ( (*p) > 90 ) { if ( 97 <= (*p) && (*p) <= 122 ) goto st35; } else goto st35; goto tr72; tr33: #line 1 "NONE" {te = p+1;} #line 82 "cppscan.rl" {act = 3;} goto st36; st36: if ( ++p == pe ) goto _test_eof36; case 36: #line 738 "cppscan.cpp" switch( (*p) ) { case 34: goto st1; case 39: goto st3; case 95: goto st35; } if ( (*p) < 65 ) { if ( 48 <= (*p) && (*p) <= 57 ) goto st35; } else if ( (*p) > 90 ) { if ( 97 <= (*p) && (*p) <= 122 ) goto st35; } else goto st35; goto tr72; st37: if ( ++p == pe ) goto _test_eof37; case 37: if ( (*p) == 61 ) goto tr73; goto tr37; st38: if ( ++p == pe ) goto _test_eof38; case 38: switch( (*p) ) { case 61: goto tr74; case 124: goto tr75; } goto tr37; st10: #line 1 "NONE" {ts = 0;} if ( ++p == pe ) goto _test_eof10; case 10: #line 775 "cppscan.cpp" if ( (*p) == 42 ) goto st11; goto st10; st11: if ( ++p == pe ) goto _test_eof11; case 11: switch( (*p) ) { case 42: goto st11; case 47: goto tr17; } goto st10; tr17: #line 70 "cppscan.rl" { {goto st12;} } goto st39; st39: if ( ++p == pe ) goto _test_eof39; case 39: #line 796 "cppscan.cpp" goto st0; st0: cs = 0; goto _out; } _test_eof12: cs = 12; goto _test_eof; _test_eof13: cs = 13; goto _test_eof; _test_eof14: cs = 14; goto _test_eof; _test_eof1: cs = 1; goto _test_eof; _test_eof2: cs = 2; goto _test_eof; _test_eof15: cs = 15; goto _test_eof; _test_eof16: cs = 16; goto _test_eof; _test_eof3: cs = 3; goto _test_eof; _test_eof4: cs = 4; goto _test_eof; _test_eof17: cs = 17; goto _test_eof; _test_eof18: cs = 18; goto _test_eof; _test_eof19: cs = 19; goto _test_eof; _test_eof20: cs = 20; goto _test_eof; _test_eof21: cs = 21; goto _test_eof; _test_eof5: cs = 5; goto _test_eof; _test_eof22: cs = 22; goto _test_eof; _test_eof6: cs = 6; goto _test_eof; _test_eof7: cs = 7; goto _test_eof; _test_eof23: cs = 23; goto _test_eof; _test_eof24: cs = 24; goto _test_eof; _test_eof8: cs = 8; goto _test_eof; _test_eof25: cs = 25; goto _test_eof; _test_eof26: cs = 26; goto _test_eof; _test_eof27: cs = 27; goto _test_eof; _test_eof28: cs = 28; goto _test_eof; _test_eof29: cs = 29; goto _test_eof; _test_eof9: cs = 9; goto _test_eof; _test_eof30: cs = 30; goto _test_eof; _test_eof31: cs = 31; goto _test_eof; _test_eof32: cs = 32; goto _test_eof; _test_eof33: cs = 33; goto _test_eof; _test_eof34: cs = 34; goto _test_eof; _test_eof35: cs = 35; goto _test_eof; _test_eof36: cs = 36; goto _test_eof; _test_eof37: cs = 37; goto _test_eof; _test_eof38: cs = 38; goto _test_eof; _test_eof10: cs = 10; goto _test_eof; _test_eof11: cs = 11; goto _test_eof; _test_eof39: cs = 39; goto _test_eof; _test_eof: {} if ( p == eof ) { switch ( cs ) { case 13: goto tr36; case 14: goto tr37; case 1: goto tr0; case 2: goto tr0; case 15: goto tr37; case 16: goto tr37; case 3: goto tr0; case 4: goto tr0; case 17: goto tr37; case 18: goto tr37; case 19: goto tr37; case 20: goto tr48; case 21: goto tr37; case 5: goto tr7; case 22: goto tr53; case 6: goto tr0; case 7: goto tr0; case 23: goto tr53; case 24: goto tr37; case 8: goto tr7; case 25: goto tr58; case 26: goto tr62; case 27: goto tr62; case 28: goto tr58; case 29: goto tr58; case 9: goto tr13; case 30: goto tr67; case 31: goto tr67; case 32: goto tr58; case 33: goto tr37; case 34: goto tr37; case 35: goto tr72; case 36: goto tr72; case 37: goto tr37; case 38: goto tr37; } } _out: {} } #line 187 "cppscan.rl" /* Check if we failed. */ if ( cs == Scanner_error ) { /* Machine failed before finding a token. */ cerr << "PARSE ERROR" << endl; exit(1); } /* Now set up the prefix. */ if ( ts == 0 ) have = 0; else { /* There is data that needs to be shifted over. */ have = pe - ts; memmove( buf, ts, have ); te -= (ts-buf); ts = buf; } } return 0; } ragel-6.8/examples/atoi.cpp0000664000175000017500000000320012106311500012642 00000000000000 #line 1 "atoi.rl" /* * Convert a string to an integer. */ #include #include #include #line 13 "atoi.cpp" static const int atoi_start = 1; static const int atoi_first_final = 4; static const int atoi_error = 0; static const int atoi_en_main = 1; #line 12 "atoi.rl" long long atoi( char *str ) { char *p = str, *pe = str + strlen( str ); int cs; long long val = 0; bool neg = false; #line 32 "atoi.cpp" { cs = atoi_start; } #line 37 "atoi.cpp" { if ( p == pe ) goto _test_eof; switch ( cs ) { case 1: switch( (*p) ) { case 43: goto st2; case 45: goto tr2; } if ( 48 <= (*p) && (*p) <= 57 ) goto tr3; goto st0; st0: cs = 0; goto _out; tr2: #line 22 "atoi.rl" { neg = true; } goto st2; st2: if ( ++p == pe ) goto _test_eof2; case 2: #line 64 "atoi.cpp" if ( 48 <= (*p) && (*p) <= 57 ) goto tr3; goto st0; tr3: #line 26 "atoi.rl" { val = val * 10 + ((*p) - '0'); } goto st3; st3: if ( ++p == pe ) goto _test_eof3; case 3: #line 78 "atoi.cpp" if ( (*p) == 10 ) goto st4; if ( 48 <= (*p) && (*p) <= 57 ) goto tr3; goto st0; st4: if ( ++p == pe ) goto _test_eof4; case 4: goto st0; } _test_eof2: cs = 2; goto _test_eof; _test_eof3: cs = 3; goto _test_eof; _test_eof4: cs = 4; goto _test_eof; _test_eof: {} _out: {} } #line 37 "atoi.rl" if ( neg ) val = -1 * val; if ( cs < atoi_first_final ) fprintf( stderr, "atoi: there was an error\n" ); return val; }; #define BUFSIZE 1024 int main() { char buf[BUFSIZE]; while ( fgets( buf, sizeof(buf), stdin ) != 0 ) { long long value = atoi( buf ); printf( "%lld\n", value ); } return 0; } ragel-6.8/examples/format.c0000664000175000017500000002251112106311500012644 00000000000000 #line 1 "format.rl" /* * Partial printf implementation. */ #define BUFLEN 1024 #include typedef void (*WriteFunc)( char *data, int len ); struct format { char buf[BUFLEN+1]; int buflen; WriteFunc write; int flags; int width; int prec; int cs; }; void do_conv( struct format *fsm, char c ) { printf( "flags: %x\n", fsm->flags ); printf( "width: %i\n", fsm->width ); printf( "prec: %i\n", fsm->prec ); printf( "conv: %c\n", c ); printf( "\n" ); } #define FL_HASH 0x01 #define FL_ZERO 0x02 #define FL_DASH 0x04 #define FL_SPACE 0x08 #define FL_PLUS 0x10 #define FL_HAS_WIDTH 0x0100 #define FL_WIDTH_ARG 0x0200 #define FL_HAS_PREC 0x0400 #define FL_PREC_ARG 0x0800 #define FL_LEN_H 0x010000 #define FL_LEN_HH 0x020000 #define FL_LEN_L 0x040000 #define FL_LEN_LL 0x080000 #line 137 "format.rl" #line 55 "format.c" static const int format_start = 11; static const int format_first_final = 11; static const int format_error = 0; static const int format_en_main = 11; #line 140 "format.rl" void format_init( struct format *fsm ) { fsm->buflen = 0; #line 69 "format.c" { fsm->cs = format_start; } #line 145 "format.rl" } void format_execute( struct format *fsm, const char *data, int len, int isEof ) { const char *p = data; const char *pe = data + len; const char *eof = isEof ? pe : 0; #line 84 "format.c" { if ( p == pe ) goto _test_eof; switch ( fsm->cs ) { tr3: #line 113 "format.rl" { if ( fsm->buflen == BUFLEN ) { fsm->write( fsm->buf, fsm->buflen ); fsm->buflen = 0; } fsm->buf[fsm->buflen++] = (*p); } goto st11; tr10: #line 99 "format.rl" { do_conv( fsm, (*p) ); } goto st11; tr14: #line 63 "format.rl" { fsm->flags |= FL_HAS_WIDTH; } #line 99 "format.rl" { do_conv( fsm, (*p) ); } goto st11; tr19: #line 69 "format.rl" { fsm->flags |= FL_HAS_PREC; } #line 99 "format.rl" { do_conv( fsm, (*p) ); } goto st11; tr22: #line 86 "format.rl" { fsm->flags |= FL_LEN_H; } #line 99 "format.rl" { do_conv( fsm, (*p) ); } goto st11; tr24: #line 87 "format.rl" { fsm->flags |= FL_LEN_L; } #line 99 "format.rl" { do_conv( fsm, (*p) ); } goto st11; st11: if ( ++p == pe ) goto _test_eof11; case 11: #line 142 "format.c" if ( (*p) == 37 ) goto tr26; goto tr3; tr26: #line 51 "format.rl" { fsm->flags = 0; fsm->width = 0; fsm->prec = 0; } goto st1; st1: if ( ++p == pe ) goto _test_eof1; case 1: #line 158 "format.c" switch( (*p) ) { case 32: goto tr1; case 35: goto tr2; case 37: goto tr3; case 42: goto tr4; case 43: goto tr5; case 45: goto tr6; case 46: goto st4; case 48: goto tr8; case 88: goto tr10; case 104: goto st6; case 105: goto tr10; case 108: goto st8; case 115: goto tr10; case 117: goto tr10; case 120: goto tr10; } if ( (*p) < 99 ) { if ( 49 <= (*p) && (*p) <= 57 ) goto tr9; } else if ( (*p) > 100 ) { if ( 111 <= (*p) && (*p) <= 112 ) goto tr10; } else goto tr10; goto tr0; tr0: #line 128 "format.rl" { printf("ERROR ON CHAR: 0x%x\n", (*p) ); } goto st0; #line 191 "format.c" st0: fsm->cs = 0; goto _out; tr1: #line 76 "format.rl" { fsm->flags |= FL_SPACE; } goto st2; tr2: #line 73 "format.rl" { fsm->flags |= FL_HASH; } goto st2; tr5: #line 77 "format.rl" { fsm->flags |= FL_PLUS; } goto st2; tr6: #line 75 "format.rl" { fsm->flags |= FL_DASH; } goto st2; tr8: #line 74 "format.rl" { fsm->flags |= FL_ZERO; } goto st2; st2: if ( ++p == pe ) goto _test_eof2; case 2: #line 219 "format.c" switch( (*p) ) { case 32: goto tr1; case 35: goto tr2; case 42: goto tr4; case 43: goto tr5; case 45: goto tr6; case 46: goto st4; case 48: goto tr8; case 88: goto tr10; case 104: goto st6; case 105: goto tr10; case 108: goto st8; case 115: goto tr10; case 117: goto tr10; case 120: goto tr10; } if ( (*p) < 99 ) { if ( 49 <= (*p) && (*p) <= 57 ) goto tr9; } else if ( (*p) > 100 ) { if ( 111 <= (*p) && (*p) <= 112 ) goto tr10; } else goto tr10; goto tr0; tr4: #line 62 "format.rl" { fsm->flags |= FL_WIDTH_ARG; } goto st3; st3: if ( ++p == pe ) goto _test_eof3; case 3: #line 253 "format.c" switch( (*p) ) { case 46: goto tr13; case 88: goto tr14; case 104: goto tr15; case 105: goto tr14; case 108: goto tr16; case 115: goto tr14; case 117: goto tr14; case 120: goto tr14; } if ( (*p) > 100 ) { if ( 111 <= (*p) && (*p) <= 112 ) goto tr14; } else if ( (*p) >= 99 ) goto tr14; goto tr0; tr13: #line 63 "format.rl" { fsm->flags |= FL_HAS_WIDTH; } goto st4; st4: if ( ++p == pe ) goto _test_eof4; case 4: #line 278 "format.c" switch( (*p) ) { case 42: goto tr17; case 88: goto tr19; case 104: goto tr20; case 105: goto tr19; case 108: goto tr21; case 115: goto tr19; case 117: goto tr19; case 120: goto tr19; } if ( (*p) < 99 ) { if ( 48 <= (*p) && (*p) <= 57 ) goto tr18; } else if ( (*p) > 100 ) { if ( 111 <= (*p) && (*p) <= 112 ) goto tr19; } else goto tr19; goto tr0; tr17: #line 68 "format.rl" { fsm->flags |= FL_PREC_ARG; } goto st5; st5: if ( ++p == pe ) goto _test_eof5; case 5: #line 306 "format.c" switch( (*p) ) { case 88: goto tr10; case 104: goto st6; case 105: goto tr10; case 108: goto st8; case 115: goto tr10; case 117: goto tr10; case 120: goto tr10; } if ( (*p) > 100 ) { if ( 111 <= (*p) && (*p) <= 112 ) goto tr10; } else if ( (*p) >= 99 ) goto tr10; goto tr0; tr15: #line 63 "format.rl" { fsm->flags |= FL_HAS_WIDTH; } goto st6; tr20: #line 69 "format.rl" { fsm->flags |= FL_HAS_PREC; } goto st6; st6: if ( ++p == pe ) goto _test_eof6; case 6: #line 334 "format.c" switch( (*p) ) { case 88: goto tr22; case 104: goto tr23; case 105: goto tr22; case 115: goto tr22; case 117: goto tr22; case 120: goto tr22; } if ( (*p) > 100 ) { if ( 111 <= (*p) && (*p) <= 112 ) goto tr22; } else if ( (*p) >= 99 ) goto tr22; goto tr0; tr23: #line 88 "format.rl" { fsm->flags |= FL_LEN_HH; } goto st7; tr25: #line 89 "format.rl" { fsm->flags |= FL_LEN_LL; } goto st7; st7: if ( ++p == pe ) goto _test_eof7; case 7: #line 361 "format.c" switch( (*p) ) { case 88: goto tr10; case 105: goto tr10; case 115: goto tr10; case 117: goto tr10; case 120: goto tr10; } if ( (*p) > 100 ) { if ( 111 <= (*p) && (*p) <= 112 ) goto tr10; } else if ( (*p) >= 99 ) goto tr10; goto tr0; tr16: #line 63 "format.rl" { fsm->flags |= FL_HAS_WIDTH; } goto st8; tr21: #line 69 "format.rl" { fsm->flags |= FL_HAS_PREC; } goto st8; st8: if ( ++p == pe ) goto _test_eof8; case 8: #line 387 "format.c" switch( (*p) ) { case 88: goto tr24; case 105: goto tr24; case 108: goto tr25; case 115: goto tr24; case 117: goto tr24; case 120: goto tr24; } if ( (*p) > 100 ) { if ( 111 <= (*p) && (*p) <= 112 ) goto tr24; } else if ( (*p) >= 99 ) goto tr24; goto tr0; tr18: #line 67 "format.rl" { fsm->prec = 10 * fsm->prec + ((*p)-'0'); } goto st9; st9: if ( ++p == pe ) goto _test_eof9; case 9: #line 410 "format.c" switch( (*p) ) { case 88: goto tr19; case 104: goto tr20; case 105: goto tr19; case 108: goto tr21; case 115: goto tr19; case 117: goto tr19; case 120: goto tr19; } if ( (*p) < 99 ) { if ( 48 <= (*p) && (*p) <= 57 ) goto tr18; } else if ( (*p) > 100 ) { if ( 111 <= (*p) && (*p) <= 112 ) goto tr19; } else goto tr19; goto tr0; tr9: #line 61 "format.rl" { fsm->width = 10 * fsm->width + ((*p)-'0'); } goto st10; st10: if ( ++p == pe ) goto _test_eof10; case 10: #line 437 "format.c" switch( (*p) ) { case 46: goto tr13; case 88: goto tr14; case 104: goto tr15; case 105: goto tr14; case 108: goto tr16; case 115: goto tr14; case 117: goto tr14; case 120: goto tr14; } if ( (*p) < 99 ) { if ( 48 <= (*p) && (*p) <= 57 ) goto tr9; } else if ( (*p) > 100 ) { if ( 111 <= (*p) && (*p) <= 112 ) goto tr14; } else goto tr14; goto tr0; } _test_eof11: fsm->cs = 11; goto _test_eof; _test_eof1: fsm->cs = 1; goto _test_eof; _test_eof2: fsm->cs = 2; goto _test_eof; _test_eof3: fsm->cs = 3; goto _test_eof; _test_eof4: fsm->cs = 4; goto _test_eof; _test_eof5: fsm->cs = 5; goto _test_eof; _test_eof6: fsm->cs = 6; goto _test_eof; _test_eof7: fsm->cs = 7; goto _test_eof; _test_eof8: fsm->cs = 8; goto _test_eof; _test_eof9: fsm->cs = 9; goto _test_eof; _test_eof10: fsm->cs = 10; goto _test_eof; _test_eof: {} if ( p == eof ) { switch ( fsm->cs ) { case 11: #line 121 "format.rl" { if ( fsm->buflen > 0 ) fsm->write( fsm->buf, fsm->buflen ); } break; case 1: case 2: case 3: case 4: case 5: case 6: case 7: case 8: case 9: case 10: #line 125 "format.rl" { printf("EOF IN FORMAT\n"); } #line 128 "format.rl" { printf("ERROR ON CHAR: 0x%x\n", (*p) ); } break; #line 500 "format.c" } } _out: {} } #line 154 "format.rl" } int format_finish( struct format *fsm ) { if ( fsm->cs == format_error ) return -1; if ( fsm->cs >= format_first_final ) return 1; return 0; } #define INPUT_BUFSIZE 2048 struct format fsm; char buf[INPUT_BUFSIZE]; void write(char *data, int len ) { fwrite( data, 1, len, stdout ); } int main() { fsm.write = write; format_init( &fsm ); while ( 1 ) { int len = fread( buf, 1, INPUT_BUFSIZE, stdin ); int eof = len != INPUT_BUFSIZE; format_execute( &fsm, buf, len, eof ); if ( eof ) break; } if ( format_finish( &fsm ) <= 0 ) printf("FAIL\n"); return 0; } ragel-6.8/examples/Makefile.in0000664000175000017500000005011612106313353013267 00000000000000# Makefile.in generated by automake 1.11.3 from Makefile.am. # @configure_input@ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, # 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software # Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ # # Copyright 2002-2009 Adrian Thurston # # This file is part of Ragel. # # Ragel is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # Ragel is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Ragel; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA VPATH = @srcdir@ pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : noinst_PROGRAMS = atoi$(EXEEXT) awkemu$(EXEEXT) clang$(EXEEXT) \ concurrent$(EXEEXT) cppscan$(EXEEXT) format$(EXEEXT) \ gotocallret$(EXEEXT) mailbox$(EXEEXT) params$(EXEEXT) \ pullscan$(EXEEXT) rlscan$(EXEEXT) statechart$(EXEEXT) subdir = examples DIST_COMMON = README $(srcdir)/Makefile.am $(srcdir)/Makefile.in ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/configure.in am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/ragel/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = PROGRAMS = $(noinst_PROGRAMS) am_atoi_OBJECTS = atoi.$(OBJEXT) atoi_OBJECTS = $(am_atoi_OBJECTS) atoi_LDADD = $(LDADD) am_awkemu_OBJECTS = awkemu.$(OBJEXT) awkemu_OBJECTS = $(am_awkemu_OBJECTS) awkemu_LDADD = $(LDADD) am_clang_OBJECTS = clang.$(OBJEXT) clang_OBJECTS = $(am_clang_OBJECTS) clang_LDADD = $(LDADD) am_concurrent_OBJECTS = concurrent.$(OBJEXT) concurrent_OBJECTS = $(am_concurrent_OBJECTS) concurrent_LDADD = $(LDADD) am_cppscan_OBJECTS = cppscan.$(OBJEXT) cppscan_OBJECTS = $(am_cppscan_OBJECTS) cppscan_LDADD = $(LDADD) am_format_OBJECTS = format.$(OBJEXT) format_OBJECTS = $(am_format_OBJECTS) format_LDADD = $(LDADD) am_gotocallret_OBJECTS = gotocallret.$(OBJEXT) gotocallret_OBJECTS = $(am_gotocallret_OBJECTS) gotocallret_LDADD = $(LDADD) am_mailbox_OBJECTS = mailbox.$(OBJEXT) mailbox_OBJECTS = $(am_mailbox_OBJECTS) mailbox_LDADD = $(LDADD) am_params_OBJECTS = params.$(OBJEXT) params_OBJECTS = $(am_params_OBJECTS) params_LDADD = $(LDADD) am_pullscan_OBJECTS = pullscan.$(OBJEXT) pullscan_OBJECTS = $(am_pullscan_OBJECTS) pullscan_LDADD = $(LDADD) am_rlscan_OBJECTS = rlscan.$(OBJEXT) rlscan_OBJECTS = $(am_rlscan_OBJECTS) rlscan_LDADD = $(LDADD) am_statechart_OBJECTS = statechart.$(OBJEXT) statechart_OBJECTS = $(am_statechart_OBJECTS) statechart_LDADD = $(LDADD) DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/ragel depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) CCLD = $(CC) LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) CXXLD = $(CXX) CXXLINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) \ -o $@ SOURCES = $(atoi_SOURCES) $(awkemu_SOURCES) $(clang_SOURCES) \ $(concurrent_SOURCES) $(cppscan_SOURCES) $(format_SOURCES) \ $(gotocallret_SOURCES) $(mailbox_SOURCES) $(params_SOURCES) \ $(pullscan_SOURCES) $(rlscan_SOURCES) $(statechart_SOURCES) DIST_SOURCES = $(atoi_SOURCES) $(awkemu_SOURCES) $(clang_SOURCES) \ $(concurrent_SOURCES) $(cppscan_SOURCES) $(format_SOURCES) \ $(gotocallret_SOURCES) $(mailbox_SOURCES) $(params_SOURCES) \ $(pullscan_SOURCES) $(rlscan_SOURCES) $(statechart_SOURCES) ETAGS = etags CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EXEEXT = @EXEEXT@ FIG2DEV = @FIG2DEV@ GDC = @GDC@ GMCS = @GMCS@ GOBIN = @GOBIN@ GOBJC = @GOBJC@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ JAVAC = @JAVAC@ KELBT = @KELBT@ LDFLAGS = @LDFLAGS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LTLIBOBJS = @LTLIBOBJS@ MAKEINFO = @MAKEINFO@ MKDIR_P = @MKDIR_P@ OBJEXT = @OBJEXT@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PDFLATEX = @PDFLATEX@ PUBDATE = @PUBDATE@ RAGEL = ../ragel/ragel RANLIB = @RANLIB@ RUBY = @RUBY@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ TXL = @TXL@ VERSION = @VERSION@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build_alias = @build_alias@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host_alias = @host_alias@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ FLEX = flex RE2C = re2c EXTRA_DIST = \ gotocallret.rl pullscan.rl concurrent.rl rlscan.rl statechart.rl \ params.rl clang.rl cppscan.rl format.rl awkemu.rl mailbox.rl atoi.rl gotocallret_SOURCES = gotocallret.cpp pullscan_SOURCES = pullscan.c concurrent_SOURCES = concurrent.cpp rlscan_SOURCES = rlscan.cpp statechart_SOURCES = statechart.cpp params_SOURCES = params.c clang_SOURCES = clang.c cppscan_SOURCES = cppscan.cpp format_SOURCES = format.c awkemu_SOURCES = awkemu.c mailbox_SOURCES = mailbox.cpp atoi_SOURCES = atoi.cpp all: all-am .SUFFIXES: .SUFFIXES: .c .cpp .o .obj $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign examples/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign examples/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): clean-noinstPROGRAMS: -test -z "$(noinst_PROGRAMS)" || rm -f $(noinst_PROGRAMS) atoi$(EXEEXT): $(atoi_OBJECTS) $(atoi_DEPENDENCIES) $(EXTRA_atoi_DEPENDENCIES) @rm -f atoi$(EXEEXT) $(CXXLINK) $(atoi_OBJECTS) $(atoi_LDADD) $(LIBS) awkemu$(EXEEXT): $(awkemu_OBJECTS) $(awkemu_DEPENDENCIES) $(EXTRA_awkemu_DEPENDENCIES) @rm -f awkemu$(EXEEXT) $(LINK) $(awkemu_OBJECTS) $(awkemu_LDADD) $(LIBS) clang$(EXEEXT): $(clang_OBJECTS) $(clang_DEPENDENCIES) $(EXTRA_clang_DEPENDENCIES) @rm -f clang$(EXEEXT) $(LINK) $(clang_OBJECTS) $(clang_LDADD) $(LIBS) concurrent$(EXEEXT): $(concurrent_OBJECTS) $(concurrent_DEPENDENCIES) $(EXTRA_concurrent_DEPENDENCIES) @rm -f concurrent$(EXEEXT) $(CXXLINK) $(concurrent_OBJECTS) $(concurrent_LDADD) $(LIBS) cppscan$(EXEEXT): $(cppscan_OBJECTS) $(cppscan_DEPENDENCIES) $(EXTRA_cppscan_DEPENDENCIES) @rm -f cppscan$(EXEEXT) $(CXXLINK) $(cppscan_OBJECTS) $(cppscan_LDADD) $(LIBS) format$(EXEEXT): $(format_OBJECTS) $(format_DEPENDENCIES) $(EXTRA_format_DEPENDENCIES) @rm -f format$(EXEEXT) $(LINK) $(format_OBJECTS) $(format_LDADD) $(LIBS) gotocallret$(EXEEXT): $(gotocallret_OBJECTS) $(gotocallret_DEPENDENCIES) $(EXTRA_gotocallret_DEPENDENCIES) @rm -f gotocallret$(EXEEXT) $(CXXLINK) $(gotocallret_OBJECTS) $(gotocallret_LDADD) $(LIBS) mailbox$(EXEEXT): $(mailbox_OBJECTS) $(mailbox_DEPENDENCIES) $(EXTRA_mailbox_DEPENDENCIES) @rm -f mailbox$(EXEEXT) $(CXXLINK) $(mailbox_OBJECTS) $(mailbox_LDADD) $(LIBS) params$(EXEEXT): $(params_OBJECTS) $(params_DEPENDENCIES) $(EXTRA_params_DEPENDENCIES) @rm -f params$(EXEEXT) $(LINK) $(params_OBJECTS) $(params_LDADD) $(LIBS) pullscan$(EXEEXT): $(pullscan_OBJECTS) $(pullscan_DEPENDENCIES) $(EXTRA_pullscan_DEPENDENCIES) @rm -f pullscan$(EXEEXT) $(LINK) $(pullscan_OBJECTS) $(pullscan_LDADD) $(LIBS) rlscan$(EXEEXT): $(rlscan_OBJECTS) $(rlscan_DEPENDENCIES) $(EXTRA_rlscan_DEPENDENCIES) @rm -f rlscan$(EXEEXT) $(CXXLINK) $(rlscan_OBJECTS) $(rlscan_LDADD) $(LIBS) statechart$(EXEEXT): $(statechart_OBJECTS) $(statechart_DEPENDENCIES) $(EXTRA_statechart_DEPENDENCIES) @rm -f statechart$(EXEEXT) $(CXXLINK) $(statechart_OBJECTS) $(statechart_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/atoi.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/awkemu.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/clang.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/concurrent.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cppscan.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/format.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gotocallret.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mailbox.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/params.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pullscan.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rlscan.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/statechart.Po@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(COMPILE) -c $< .c.obj: @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` .cpp.o: @am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ $< .cpp.obj: @am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ mkid -fID $$unique tags: TAGS TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) set x; \ here=`pwd`; \ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: CTAGS CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(PROGRAMS) installdirs: install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-noinstPROGRAMS mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: .MAKE: install-am install-strip .PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ clean-noinstPROGRAMS ctags distclean distclean-compile \ distclean-generic distclean-tags distdir dvi dvi-am html \ html-am info info-am install install-am install-data \ install-data-am install-dvi install-dvi-am install-exec \ install-exec-am install-html install-html-am install-info \ install-info-am install-man install-pdf install-pdf-am \ install-ps install-ps-am install-strip installcheck \ installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-compile \ mostlyclean-generic pdf pdf-am ps ps-am tags uninstall \ uninstall-am gotocallret.cpp: gotocallret.rl $(RAGEL) -G2 -o gotocallret.cpp gotocallret.rl pullscan.c: pullscan.rl $(RAGEL) $(RAGEL) -G2 -o $@ pullscan.rl concurrent.cpp: concurrent.rl $(RAGEL) $(RAGEL) -G2 -o concurrent.cpp concurrent.rl rlscan.cpp: rlscan.rl $(RAGEL) -G2 -o rlscan.cpp rlscan.rl statechart.cpp: statechart.rl $(RAGEL) -G2 -o statechart.cpp statechart.rl params.c: params.rl $(RAGEL) -G2 -o params.c params.rl clang.c: clang.rl $(RAGEL) -G2 -o clang.c clang.rl cppscan.cpp: cppscan.rl $(RAGEL) -G2 -o $@ cppscan.rl format.c: format.rl $(RAGEL) -G2 -o format.c format.rl awkemu.c: awkemu.rl $(RAGEL) -G2 -o awkemu.c awkemu.rl mailbox.cpp: mailbox.rl $(RAGEL) -G2 -o mailbox.cpp mailbox.rl atoi.cpp: atoi.rl $(RAGEL) -G2 -o atoi.cpp atoi.rl ### lex-cppscan.cpp: cppscan.lex $(FLEX) -f -o $@ $< re2c-cppscan.cpp: cppscan.rec $(RE2C) -s $< > $@ example.cpp: example.rec $(RE2C) -s $< > $@ # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: ragel-6.8/examples/concurrent.rl0000664000175000017500000000425312043335171013746 00000000000000/* * Show off concurrent abilities. */ #include #include #include using namespace std; #define BUFSIZE 2048 struct Concurrent { int cur_char; int start_word; int start_comment; int start_literal; int cs; int init( ); int execute( const char *data, int len, bool isEof ); int finish( ); }; %%{ machine Concurrent; action next_char { cur_char += 1; } action start_word { start_word = cur_char; } action end_word { cout << "word: " << start_word << " " << cur_char-1 << endl; } action start_comment { start_comment = cur_char; } action end_comment { cout << "comment: " << start_comment << " " << cur_char-1 << endl; } action start_literal { start_literal = cur_char; } action end_literal { cout << "literal: " << start_literal << " " << cur_char-1 << endl; } # Count characters. chars = ( any @next_char )*; # Words are non-whitespace. word = ( any-space )+ >start_word %end_word; words = ( ( word | space ) $1 %0 )*; # Finds C style comments. comment = ( '/*' any* :>> '*/' ) >start_comment %end_comment; comments = ( comment | any )**; # Finds single quoted strings. literalChar = ( any - ['\\] ) | ( '\\' . any ); literal = ('\'' literalChar* '\'' ) >start_literal %end_literal; literals = ( ( literal | (any-'\'') ) $1 %0 )*; main := chars | words | comments | literals; }%% %% write data; int Concurrent::init( ) { %% write init; cur_char = 0; return 1; } int Concurrent::execute( const char *data, int len, bool isEof ) { const char *p = data; const char *pe = data + len; const char *eof = isEof ? pe : 0; %% write exec; if ( cs == Concurrent_error ) return -1; if ( cs >= Concurrent_first_final ) return 1; return 0; } int Concurrent::finish( ) { if ( cs == Concurrent_error ) return -1; if ( cs >= Concurrent_first_final ) return 1; return 0; } Concurrent concurrent; char buf[BUFSIZE]; int main() { concurrent.init(); while ( 1 ) { int len = fread( buf, 1, BUFSIZE, stdin ); concurrent.execute( buf, len, len != BUFSIZE ); if ( len != BUFSIZE ) break; } if ( concurrent.finish() <= 0 ) cerr << "concurrent: error parsing input" << endl; return 0; } ragel-6.8/examples/gotocallret.cpp0000664000175000017500000001173512106311500014241 00000000000000 #line 1 "gotocallret.rl" /* * Demonstrate the use of goto, call and return. This machine expects either a * lower case char or a digit as a command then a space followed by the command * arg. If the command is a char, then the arg must be an a string of chars. * If the command is a digit, then the arg must be a string of digits. This * choice is determined by action code, rather than though transition * desitinations. */ #include #include #include #include using namespace std; struct GotoCallRet { char comm; int cs, top, stack[32]; int init( ); int execute( const char *data, int len, bool isEof ); int finish( ); }; #line 57 "gotocallret.rl" #line 35 "gotocallret.cpp" static const int GotoCallRet_start = 7; static const int GotoCallRet_first_final = 7; static const int GotoCallRet_error = 0; static const int GotoCallRet_en_garble_line = 3; static const int GotoCallRet_en_alp_comm = 5; static const int GotoCallRet_en_dig_comm = 6; static const int GotoCallRet_en_main = 7; #line 60 "gotocallret.rl" int GotoCallRet::init( ) { #line 51 "gotocallret.cpp" { cs = GotoCallRet_start; top = 0; } #line 64 "gotocallret.rl" return 1; } int GotoCallRet::execute( const char *data, int len, bool isEof ) { const char *p = data; const char *pe = data + len; const char *eof = isEof ? pe : 0; #line 68 "gotocallret.cpp" { if ( p == pe ) goto _test_eof; goto _resume; _again: switch ( cs ) { case 7: goto st7; case 0: goto st0; case 1: goto st1; case 2: goto st2; case 3: goto st3; case 4: goto st4; case 8: goto st8; case 5: goto st5; case 9: goto st9; case 6: goto st6; case 10: goto st10; default: break; } if ( ++p == pe ) goto _test_eof; _resume: switch ( cs ) { tr2: #line 52 "gotocallret.rl" {cout << "correct command" << endl;} goto st7; st7: if ( ++p == pe ) goto _test_eof7; case 7: #line 103 "gotocallret.cpp" if ( (*p) > 57 ) { if ( 97 <= (*p) && (*p) <= 122 ) goto tr11; } else if ( (*p) >= 48 ) goto tr11; goto tr0; tr0: #line 56 "gotocallret.rl" {p--;{goto st3;}} goto st0; tr7: #line 38 "gotocallret.rl" {p--;{cs = stack[--top];goto _again;}} goto st0; tr9: #line 39 "gotocallret.rl" {p--;{cs = stack[--top];goto _again;}} goto st0; #line 122 "gotocallret.cpp" st0: cs = 0; goto _out; tr11: #line 51 "gotocallret.rl" {comm = (*p);} goto st1; st1: if ( ++p == pe ) goto _test_eof1; case 1: #line 134 "gotocallret.cpp" if ( (*p) == 32 ) goto tr1; goto tr0; tr1: #line 42 "gotocallret.rl" { if ( comm >= 'a' ) {stack[top++] = 2; goto st5;} else {stack[top++] = 2; goto st6;} } goto st2; st2: if ( ++p == pe ) goto _test_eof2; case 2: #line 151 "gotocallret.cpp" if ( (*p) == 10 ) goto tr2; goto tr0; st3: if ( ++p == pe ) goto _test_eof3; case 3: if ( (*p) == 10 ) goto tr4; goto tr3; tr3: #line 34 "gotocallret.rl" {cout << "error: garbling line" << endl;} goto st4; st4: if ( ++p == pe ) goto _test_eof4; case 4: #line 170 "gotocallret.cpp" if ( (*p) == 10 ) goto tr6; goto st4; tr4: #line 34 "gotocallret.rl" {cout << "error: garbling line" << endl;} #line 34 "gotocallret.rl" {{goto st7;}} goto st8; tr6: #line 34 "gotocallret.rl" {{goto st7;}} goto st8; st8: if ( ++p == pe ) goto _test_eof8; case 8: #line 188 "gotocallret.cpp" goto st0; st5: if ( ++p == pe ) goto _test_eof5; case 5: if ( (*p) > 90 ) { if ( 97 <= (*p) && (*p) <= 122 ) goto st9; } else if ( (*p) >= 65 ) goto st9; goto tr7; st9: if ( ++p == pe ) goto _test_eof9; case 9: if ( (*p) > 90 ) { if ( 97 <= (*p) && (*p) <= 122 ) goto st9; } else if ( (*p) >= 65 ) goto st9; goto tr7; st6: if ( ++p == pe ) goto _test_eof6; case 6: if ( 48 <= (*p) && (*p) <= 57 ) goto st10; goto tr9; st10: if ( ++p == pe ) goto _test_eof10; case 10: if ( 48 <= (*p) && (*p) <= 57 ) goto st10; goto tr9; } _test_eof7: cs = 7; goto _test_eof; _test_eof1: cs = 1; goto _test_eof; _test_eof2: cs = 2; goto _test_eof; _test_eof3: cs = 3; goto _test_eof; _test_eof4: cs = 4; goto _test_eof; _test_eof8: cs = 8; goto _test_eof; _test_eof5: cs = 5; goto _test_eof; _test_eof9: cs = 9; goto _test_eof; _test_eof6: cs = 6; goto _test_eof; _test_eof10: cs = 10; goto _test_eof; _test_eof: {} if ( p == eof ) { switch ( cs ) { case 5: #line 38 "gotocallret.rl" {p--;{cs = stack[--top];goto _again;}} break; case 6: #line 39 "gotocallret.rl" {p--;{cs = stack[--top];goto _again;}} break; case 1: case 2: #line 56 "gotocallret.rl" {p--;{goto st3;}} break; #line 253 "gotocallret.cpp" } } _out: {} } #line 74 "gotocallret.rl" if ( cs == GotoCallRet_error ) return -1; if ( cs >= GotoCallRet_first_final ) return 1; return 0; } #define BUFSIZE 1024 int main() { char buf[BUFSIZE]; GotoCallRet gcr; gcr.init(); while ( fgets( buf, sizeof(buf), stdin ) != 0 ) gcr.execute( buf, strlen(buf), false ); gcr.execute( 0, 0, true ); if ( gcr.cs < GotoCallRet_first_final ) cerr << "gotocallret: error: parsing input" << endl; return 0; } ragel-6.8/examples/clang.rl0000664000175000017500000000623212043335171012647 00000000000000/* * A mini C-like language scanner. */ #include #include #include %%{ machine clang; newline = '\n' @{curline += 1;}; any_count_line = any | newline; # Consume a C comment. c_comment := any_count_line* :>> '*/' @{fgoto main;}; main := |* # Alpha numberic characters or underscore. alnum_u = alnum | '_'; # Alpha charactres or underscore. alpha_u = alpha | '_'; # Symbols. Upon entering clear the buffer. On all transitions # buffer a character. Upon leaving dump the symbol. ( punct - [_'"] ) { printf( "symbol(%i): %c\n", curline, ts[0] ); }; # Identifier. Upon entering clear the buffer. On all transitions # buffer a character. Upon leaving, dump the identifier. alpha_u alnum_u* { printf( "ident(%i): ", curline ); fwrite( ts, 1, te-ts, stdout ); printf("\n"); }; # Single Quote. sliteralChar = [^'\\] | newline | ( '\\' . any_count_line ); '\'' . sliteralChar* . '\'' { printf( "single_lit(%i): ", curline ); fwrite( ts, 1, te-ts, stdout ); printf("\n"); }; # Double Quote. dliteralChar = [^"\\] | newline | ( '\\' any_count_line ); '"' . dliteralChar* . '"' { printf( "double_lit(%i): ", curline ); fwrite( ts, 1, te-ts, stdout ); printf("\n"); }; # Whitespace is standard ws, newlines and control codes. any_count_line - 0x21..0x7e; # Describe both c style comments and c++ style comments. The # priority bump on tne terminator of the comments brings us # out of the extend* which matches everything. '//' [^\n]* newline; '/*' { fgoto c_comment; }; # Match an integer. We don't bother clearing the buf or filling it. # The float machine overlaps with int and it will do it. digit+ { printf( "int(%i): ", curline ); fwrite( ts, 1, te-ts, stdout ); printf("\n"); }; # Match a float. Upon entering the machine clear the buf, buffer # characters on every trans and dump the float upon leaving. digit+ '.' digit+ { printf( "float(%i): ", curline ); fwrite( ts, 1, te-ts, stdout ); printf("\n"); }; # Match a hex. Upon entering the hex part, clear the buf, buffer characters # on every trans and dump the hex on leaving transitions. '0x' xdigit+ { printf( "hex(%i): ", curline ); fwrite( ts, 1, te-ts, stdout ); printf("\n"); }; *|; }%% %% write data nofinal; #define BUFSIZE 128 void scanner() { static char buf[BUFSIZE]; int cs, act, have = 0, curline = 1; char *ts, *te = 0; int done = 0; %% write init; while ( !done ) { char *p = buf + have, *pe, *eof = 0; int len, space = BUFSIZE - have; if ( space == 0 ) { /* We've used up the entire buffer storing an already-parsed token * prefix that must be preserved. */ fprintf(stderr, "OUT OF BUFFER SPACE\n" ); exit(1); } len = fread( p, 1, space, stdin ); pe = p + len; /* Check if this is the end of file. */ if ( len < space ) { eof = pe; done = 1; } %% write exec; if ( cs == clang_error ) { fprintf(stderr, "PARSE ERROR\n" ); break; } if ( ts == 0 ) have = 0; else { /* There is a prefix to preserve, shift it over. */ have = pe - ts; memmove( buf, ts, have ); te = buf + (te-ts); ts = buf; } } } int main() { scanner(); return 0; } ragel-6.8/examples/statechart.cpp0000664000175000017500000000537512106311500014067 00000000000000 #line 1 "statechart.rl" /* * Demonstrate the use of labels, the epsilon operator, and the join operator * for creating machines using the named state and transition list paradigm. * This implementes the same machine as the atoi example. */ #include #include #include #include using namespace std; struct StateChart { bool neg; int val; int cs; int init( ); int execute( const char *data, int len ); int finish( ); }; #line 66 "statechart.rl" #line 33 "statechart.cpp" static const int StateChart_start = 3; static const int StateChart_first_final = 3; static const int StateChart_error = 0; static const int StateChart_en_main = 3; #line 69 "statechart.rl" int StateChart::init( ) { neg = false; val = false; #line 48 "statechart.cpp" { cs = StateChart_start; } #line 75 "statechart.rl" return 1; } int StateChart::execute( const char *data, int len ) { const char *p = data; const char *pe = data + len; #line 63 "statechart.cpp" { if ( p == pe ) goto _test_eof; switch ( cs ) { tr2: #line 41 "statechart.rl" { if ( neg ) val = -1 * val; } #line 65 "statechart.rl" { cout << val << endl; } goto st3; st3: if ( ++p == pe ) goto _test_eof3; case 3: #line 82 "statechart.cpp" switch( (*p) ) { case 43: goto tr3; case 45: goto tr4; } if ( 48 <= (*p) && (*p) <= 57 ) goto tr5; goto st0; st0: cs = 0; goto _out; tr3: #line 28 "statechart.rl" { neg = false; val = 0; } goto st1; tr4: #line 28 "statechart.rl" { neg = false; val = 0; } #line 33 "statechart.rl" { neg = true; } goto st1; st1: if ( ++p == pe ) goto _test_eof1; case 1: #line 115 "statechart.cpp" if ( 48 <= (*p) && (*p) <= 57 ) goto tr0; goto st0; tr0: #line 37 "statechart.rl" { val = val * 10 + ((*p) - '0'); } goto st2; tr5: #line 28 "statechart.rl" { neg = false; val = 0; } #line 37 "statechart.rl" { val = val * 10 + ((*p) - '0'); } goto st2; st2: if ( ++p == pe ) goto _test_eof2; case 2: #line 140 "statechart.cpp" if ( (*p) == 10 ) goto tr2; if ( 48 <= (*p) && (*p) <= 57 ) goto tr0; goto st0; } _test_eof3: cs = 3; goto _test_eof; _test_eof1: cs = 1; goto _test_eof; _test_eof2: cs = 2; goto _test_eof; _test_eof: {} _out: {} } #line 84 "statechart.rl" if ( cs == StateChart_error ) return -1; if ( cs >= StateChart_first_final ) return 1; return 0; } int StateChart::finish( ) { if ( cs == StateChart_error ) return -1; if ( cs >= StateChart_first_final ) return 1; return 0; } #define BUFSIZE 1024 int main() { char buf[BUFSIZE]; StateChart atoi; atoi.init(); while ( fgets( buf, sizeof(buf), stdin ) != 0 ) { atoi.execute( buf, strlen(buf) ); } if ( atoi.finish() <= 0 ) cerr << "statechart: error: parsing input" << endl; return 0; } ragel-6.8/examples/README0000664000175000017500000000346012043335171012104 00000000000000 Ragel State Machine Compiler -- Examples ======================================== atoi -- Converts a string to an integer. awkemu -- Perfoms the basic parsing that the awk program perfoms on input. The awk equivalent to awkemu is in awkemu/awkequiv.awk clang -- A scanner for a simple C like language. It breaks input up into words, numbers, strings and symbols and strips out whitespace and comments. It is a suitable template for writing a parser that finds a sequence of tokens. concurrent -- Demonstrates the ability of ragel to produce parsers that perform independent tasks concurrently. cppscan -- A C++ scanner that uses the longest match scanning method. This example differs from other examples of scanning. Each run of the state machine matches one token. This method results in a smaller state machine since the final kleene star is omitted and therefore every state does not need to get all the transitions of the start state. format -- Partial printf implementation. gotocallret -- Demonstrate the use of fgoto, fcall and fret. mailbox -- Parses unix mailbox files. It breaks files into messages, and messages into headers and body. It demonstrates Ragel's ability to make parsers for structured file formats. params -- Parses command line arguements. rlscan -- Lexes Ragel input files. statechart -- Demonstrate the use of labels, the epsilon operator, and the join operator for creating machines using the named state and transition list paradigm. This implementes the same machine as the atoi example. ragel-6.8/configure.in0000664000175000017500000000727412106313333011722 00000000000000dnl dnl Copyright 2001-2009 Adrian Thurston dnl dnl This file is part of Ragel. dnl dnl Ragel is free software; you can redistribute it and/or modify dnl it under the terms of the GNU General Public License as published by dnl the Free Software Foundation; either version 2 of the License, or dnl (at your option) any later version. dnl dnl Ragel is distributed in the hope that it will be useful, dnl but WITHOUT ANY WARRANTY; without even the implied warranty of dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the dnl GNU General Public License for more details. dnl dnl You should have received a copy of the GNU General Public License dnl along with Ragel; if not, write to the Free Software dnl Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA AC_INIT(ragel, 6.8) PUBDATE="Feb 2013" AM_INIT_AUTOMAKE([foreign]) AC_SUBST(PUBDATE) AC_CONFIG_HEADER(ragel/config.h) dnl Choose defaults for the build_parsers and build_manual vars. If the dist dnl file is present in the root then default to no, otherwise go for it. AC_CHECK_FILES( $srcdir/DIST, [ . $srcdir/DIST; ], [ build_parsers=yes; build_manual=yes; ] ) dnl dnl Enable arg to explicitly control the building of the manual dnl AC_ARG_ENABLE(manual, [ --enable-manual do we want to build the manual?], [ if test "x$enableval" = "xyes"; then build_manual=yes; else build_manual=no; fi ], ) dnl Set to true if the build system should generate parsers from ragel and kelbt dnl sources. Set to false if generated files are included and not to be built dnl (production). AM_CONDITIONAL(BUILD_PARSERS, [test "x$build_parsers" = "xyes"]) dnl Set to true if the manual should be built. AM_CONDITIONAL(BUILD_MANUAL, [test "x$build_manual" = "xyes"]) dnl Checks for programs. AC_PROG_CC AC_PROG_CXX AC_CHECK_TOOL(AR, ar) AC_PROG_RANLIB dnl Set test on c++ compiler. AC_LANG_CPLUSPLUS dnl Check for definition of MAKE. AC_PROG_MAKE_SET # Checks to carry out if we are building parsers. if test "x$build_parsers" = "xyes"; then AC_CHECK_PROG(RAGEL, ragel, ragel) if test -z "$RAGEL"; then echo echo "error: ragel is required to build the parsers" echo exit 1 fi AC_CHECK_PROG(KELBT, kelbt, kelbt) if test -z "$KELBT"; then echo echo "error: kelbt is required to build the parsers" echo exit 1 fi fi # Checks to carry out if we are building the manual. if test "x$build_manual" = "xyes"; then AC_CHECK_PROG(FIG2DEV, fig2dev, fig2dev) if test -z "$FIG2DEV"; then echo echo "error: fig2dev is required to build the manual (maybe use --disable-manual)" echo exit 1 fi AC_CHECK_PROG(PDFLATEX, pdflatex, pdflatex) if test -z "$PDFLATEX"; then echo echo "error: pdflatex is required to build the manual (maybe use --disable-manual)" echo exit 1 fi fi dnl Check for the D compiler AC_CHECK_PROG(GDC, gdc, gdc) dnl Check for the Objective-C compiler AC_MSG_CHECKING([for the Objective-C compiler]) cat > conftest.m </dev/null; then GOBJC="gcc -x objective-c" AC_MSG_RESULT([yes]) else AC_MSG_RESULT([no]) fi AC_SUBST(GOBJC) dnl Check for the Java compiler. AC_CHECK_PROG(JAVAC, javac, javac) dnl Check for TXL. AC_CHECK_PROG(TXL, txl, txl) dnl Check for Ruby. AC_CHECK_PROG(RUBY, ruby, ruby) dnl Check for the C# compiler. AC_CHECK_PROG(GMCS, gmcs, gmcs) dnl Check for the Go compiler. AC_CHECK_PROG(GOBIN, go, go build) dnl write output files AC_OUTPUT( [ Makefile ragel/Makefile aapl/Makefile doc/Makefile doc/ragel.1 contrib/Makefile test/Makefile test/runtests examples/Makefile ], [chmod +x test/runtests] ) echo "configuration of ragel complete" ragel-6.8/COPYING0000664000175000017500000004326012043335171010443 00000000000000 GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Library General Public License instead of this License. ragel-6.8/Makefile.in0000664000175000017500000006035212106313353011454 00000000000000# Makefile.in generated by automake 1.11.3 from Makefile.am. # @configure_input@ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, # 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software # Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : subdir = . DIST_COMMON = README $(am__configure_deps) $(dist_doc_DATA) \ $(srcdir)/Makefile.am $(srcdir)/Makefile.in \ $(top_srcdir)/configure AUTHORS COPYING ChangeLog TODO depcomp \ install-sh missing ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/configure.in am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \ configure.lineno config.status.lineno mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/ragel/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = SOURCES = DIST_SOURCES = RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \ html-recursive info-recursive install-data-recursive \ install-dvi-recursive install-exec-recursive \ install-html-recursive install-info-recursive \ install-pdf-recursive install-ps-recursive install-recursive \ installcheck-recursive installdirs-recursive pdf-recursive \ ps-recursive uninstall-recursive am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } am__installdirs = "$(DESTDIR)$(docdir)" DATA = $(dist_doc_DATA) RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ distclean-recursive maintainer-clean-recursive AM_RECURSIVE_TARGETS = $(RECURSIVE_TARGETS:-recursive=) \ $(RECURSIVE_CLEAN_TARGETS:-recursive=) tags TAGS ctags CTAGS \ distdir dist dist-all distcheck ETAGS = etags CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) distdir = $(PACKAGE)-$(VERSION) top_distdir = $(distdir) am__remove_distdir = \ if test -d "$(distdir)"; then \ find "$(distdir)" -type d ! -perm -200 -exec chmod u+w {} ';' \ && rm -rf "$(distdir)" \ || { sleep 5 && rm -rf "$(distdir)"; }; \ else :; fi am__relativize = \ dir0=`pwd`; \ sed_first='s,^\([^/]*\)/.*$$,\1,'; \ sed_rest='s,^[^/]*/*,,'; \ sed_last='s,^.*/\([^/]*\)$$,\1,'; \ sed_butlast='s,/*[^/]*$$,,'; \ while test -n "$$dir1"; do \ first=`echo "$$dir1" | sed -e "$$sed_first"`; \ if test "$$first" != "."; then \ if test "$$first" = ".."; then \ dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ else \ first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ if test "$$first2" = "$$first"; then \ dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ else \ dir2="../$$dir2"; \ fi; \ dir0="$$dir0"/"$$first"; \ fi; \ fi; \ dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ done; \ reldir="$$dir2" DIST_ARCHIVES = $(distdir).tar.gz GZIP_ENV = --best distuninstallcheck_listfiles = find . -type f -print am__distuninstallcheck_listfiles = $(distuninstallcheck_listfiles) \ | sed 's|^\./|$(prefix)/|' | grep -v '$(infodir)/dir$$' distcleancheck_listfiles = find . -type f -print ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EXEEXT = @EXEEXT@ FIG2DEV = @FIG2DEV@ GDC = @GDC@ GMCS = @GMCS@ GOBIN = @GOBIN@ GOBJC = @GOBJC@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ JAVAC = @JAVAC@ KELBT = @KELBT@ LDFLAGS = @LDFLAGS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LTLIBOBJS = @LTLIBOBJS@ MAKEINFO = @MAKEINFO@ MKDIR_P = @MKDIR_P@ OBJEXT = @OBJEXT@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PDFLATEX = @PDFLATEX@ PUBDATE = @PUBDATE@ RAGEL = @RAGEL@ RANLIB = @RANLIB@ RUBY = @RUBY@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ TXL = @TXL@ VERSION = @VERSION@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build_alias = @build_alias@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host_alias = @host_alias@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ SUBDIRS = ragel doc DIST_SUBDIRS = $(SUBDIRS) aapl contrib examples test dist_doc_DATA = CREDITS ChangeLog EXTRA_DIST = ragel.vim all: all-recursive .SUFFIXES: am--refresh: Makefile @: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ echo ' cd $(srcdir) && $(AUTOMAKE) --foreign'; \ $(am__cd) $(srcdir) && $(AUTOMAKE) --foreign \ && exit 0; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ echo ' $(SHELL) ./config.status'; \ $(SHELL) ./config.status;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) $(SHELL) ./config.status --recheck $(top_srcdir)/configure: $(am__configure_deps) $(am__cd) $(srcdir) && $(AUTOCONF) $(ACLOCAL_M4): $(am__aclocal_m4_deps) $(am__cd) $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS) $(am__aclocal_m4_deps): install-dist_docDATA: $(dist_doc_DATA) @$(NORMAL_INSTALL) test -z "$(docdir)" || $(MKDIR_P) "$(DESTDIR)$(docdir)" @list='$(dist_doc_DATA)'; test -n "$(docdir)" || list=; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(docdir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(docdir)" || exit $$?; \ done uninstall-dist_docDATA: @$(NORMAL_UNINSTALL) @list='$(dist_doc_DATA)'; test -n "$(docdir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(docdir)'; $(am__uninstall_files_from_dir) # This directory's subdirectories are mostly independent; you can cd # into them and run `make' without going through this Makefile. # To change the values of `make' variables: instead of editing Makefiles, # (1) if the variable is set in `config.status', edit `config.status' # (which will cause the Makefiles to be regenerated when you run `make'); # (2) otherwise, pass the desired values on the `make' command line. $(RECURSIVE_TARGETS): @fail= failcom='exit 1'; \ for f in x $$MAKEFLAGS; do \ case $$f in \ *=* | --[!k]*);; \ *k*) failcom='fail=yes';; \ esac; \ done; \ dot_seen=no; \ target=`echo $@ | sed s/-recursive//`; \ list='$(SUBDIRS)'; for subdir in $$list; do \ echo "Making $$target in $$subdir"; \ if test "$$subdir" = "."; then \ dot_seen=yes; \ local_target="$$target-am"; \ else \ local_target="$$target"; \ fi; \ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ || eval $$failcom; \ done; \ if test "$$dot_seen" = "no"; then \ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ fi; test -z "$$fail" $(RECURSIVE_CLEAN_TARGETS): @fail= failcom='exit 1'; \ for f in x $$MAKEFLAGS; do \ case $$f in \ *=* | --[!k]*);; \ *k*) failcom='fail=yes';; \ esac; \ done; \ dot_seen=no; \ case "$@" in \ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ *) list='$(SUBDIRS)' ;; \ esac; \ rev=''; for subdir in $$list; do \ if test "$$subdir" = "."; then :; else \ rev="$$subdir $$rev"; \ fi; \ done; \ rev="$$rev ."; \ target=`echo $@ | sed s/-recursive//`; \ for subdir in $$rev; do \ echo "Making $$target in $$subdir"; \ if test "$$subdir" = "."; then \ local_target="$$target-am"; \ else \ local_target="$$target"; \ fi; \ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ || eval $$failcom; \ done && test -z "$$fail" tags-recursive: list='$(SUBDIRS)'; for subdir in $$list; do \ test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \ done ctags-recursive: list='$(SUBDIRS)'; for subdir in $$list; do \ test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \ done ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ mkid -fID $$unique tags: TAGS TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) set x; \ here=`pwd`; \ if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ include_option=--etags-include; \ empty_fix=.; \ else \ include_option=--include; \ empty_fix=; \ fi; \ list='$(SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ test ! -f $$subdir/TAGS || \ set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ fi; \ done; \ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: CTAGS CTAGS: ctags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) $(am__remove_distdir) test -d "$(distdir)" || mkdir "$(distdir)" @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ test -d "$(distdir)/$$subdir" \ || $(MKDIR_P) "$(distdir)/$$subdir" \ || exit 1; \ fi; \ done @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ $(am__relativize); \ new_distdir=$$reldir; \ dir1=$$subdir; dir2="$(top_distdir)"; \ $(am__relativize); \ new_top_distdir=$$reldir; \ echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ ($(am__cd) $$subdir && \ $(MAKE) $(AM_MAKEFLAGS) \ top_distdir="$$new_top_distdir" \ distdir="$$new_distdir" \ am__remove_distdir=: \ am__skip_length_check=: \ am__skip_mode_fix=: \ distdir) \ || exit 1; \ fi; \ done $(MAKE) $(AM_MAKEFLAGS) \ top_distdir="$(top_distdir)" distdir="$(distdir)" \ dist-hook -test -n "$(am__skip_mode_fix)" \ || find "$(distdir)" -type d ! -perm -755 \ -exec chmod u+rwx,go+rx {} \; -o \ ! -type d ! -perm -444 -links 1 -exec chmod a+r {} \; -o \ ! -type d ! -perm -400 -exec chmod a+r {} \; -o \ ! -type d ! -perm -444 -exec $(install_sh) -c -m a+r {} {} \; \ || chmod -R a+r "$(distdir)" dist-gzip: distdir tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz $(am__remove_distdir) dist-bzip2: distdir tardir=$(distdir) && $(am__tar) | BZIP2=$${BZIP2--9} bzip2 -c >$(distdir).tar.bz2 $(am__remove_distdir) dist-lzip: distdir tardir=$(distdir) && $(am__tar) | lzip -c $${LZIP_OPT--9} >$(distdir).tar.lz $(am__remove_distdir) dist-lzma: distdir tardir=$(distdir) && $(am__tar) | lzma -9 -c >$(distdir).tar.lzma $(am__remove_distdir) dist-xz: distdir tardir=$(distdir) && $(am__tar) | XZ_OPT=$${XZ_OPT--e} xz -c >$(distdir).tar.xz $(am__remove_distdir) dist-tarZ: distdir tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z $(am__remove_distdir) dist-shar: distdir shar $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).shar.gz $(am__remove_distdir) dist-zip: distdir -rm -f $(distdir).zip zip -rq $(distdir).zip $(distdir) $(am__remove_distdir) dist dist-all: distdir tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz $(am__remove_distdir) # This target untars the dist file and tries a VPATH configuration. Then # it guarantees that the distribution is self-contained by making another # tarfile. distcheck: dist case '$(DIST_ARCHIVES)' in \ *.tar.gz*) \ GZIP=$(GZIP_ENV) gzip -dc $(distdir).tar.gz | $(am__untar) ;;\ *.tar.bz2*) \ bzip2 -dc $(distdir).tar.bz2 | $(am__untar) ;;\ *.tar.lzma*) \ lzma -dc $(distdir).tar.lzma | $(am__untar) ;;\ *.tar.lz*) \ lzip -dc $(distdir).tar.lz | $(am__untar) ;;\ *.tar.xz*) \ xz -dc $(distdir).tar.xz | $(am__untar) ;;\ *.tar.Z*) \ uncompress -c $(distdir).tar.Z | $(am__untar) ;;\ *.shar.gz*) \ GZIP=$(GZIP_ENV) gzip -dc $(distdir).shar.gz | unshar ;;\ *.zip*) \ unzip $(distdir).zip ;;\ esac chmod -R a-w $(distdir); chmod a+w $(distdir) mkdir $(distdir)/_build mkdir $(distdir)/_inst chmod a-w $(distdir) test -d $(distdir)/_build || exit 0; \ dc_install_base=`$(am__cd) $(distdir)/_inst && pwd | sed -e 's,^[^:\\/]:[\\/],/,'` \ && dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \ && am__cwd=`pwd` \ && $(am__cd) $(distdir)/_build \ && ../configure --srcdir=.. --prefix="$$dc_install_base" \ $(AM_DISTCHECK_CONFIGURE_FLAGS) \ $(DISTCHECK_CONFIGURE_FLAGS) \ && $(MAKE) $(AM_MAKEFLAGS) \ && $(MAKE) $(AM_MAKEFLAGS) dvi \ && $(MAKE) $(AM_MAKEFLAGS) check \ && $(MAKE) $(AM_MAKEFLAGS) install \ && $(MAKE) $(AM_MAKEFLAGS) installcheck \ && $(MAKE) $(AM_MAKEFLAGS) uninstall \ && $(MAKE) $(AM_MAKEFLAGS) distuninstallcheck_dir="$$dc_install_base" \ distuninstallcheck \ && chmod -R a-w "$$dc_install_base" \ && ({ \ (cd ../.. && umask 077 && mkdir "$$dc_destdir") \ && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" install \ && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" uninstall \ && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" \ distuninstallcheck_dir="$$dc_destdir" distuninstallcheck; \ } || { rm -rf "$$dc_destdir"; exit 1; }) \ && rm -rf "$$dc_destdir" \ && $(MAKE) $(AM_MAKEFLAGS) dist \ && rm -rf $(DIST_ARCHIVES) \ && $(MAKE) $(AM_MAKEFLAGS) distcleancheck \ && cd "$$am__cwd" \ || exit 1 $(am__remove_distdir) @(echo "$(distdir) archives ready for distribution: "; \ list='$(DIST_ARCHIVES)'; for i in $$list; do echo $$i; done) | \ sed -e 1h -e 1s/./=/g -e 1p -e 1x -e '$$p' -e '$$x' distuninstallcheck: @test -n '$(distuninstallcheck_dir)' || { \ echo 'ERROR: trying to run $@ with an empty' \ '$$(distuninstallcheck_dir)' >&2; \ exit 1; \ }; \ $(am__cd) '$(distuninstallcheck_dir)' || { \ echo 'ERROR: cannot chdir into $(distuninstallcheck_dir)' >&2; \ exit 1; \ }; \ test `$(am__distuninstallcheck_listfiles) | wc -l` -eq 0 \ || { echo "ERROR: files left after uninstall:" ; \ if test -n "$(DESTDIR)"; then \ echo " (check DESTDIR support)"; \ fi ; \ $(distuninstallcheck_listfiles) ; \ exit 1; } >&2 distcleancheck: distclean @if test '$(srcdir)' = . ; then \ echo "ERROR: distcleancheck can only run from a VPATH build" ; \ exit 1 ; \ fi @test `$(distcleancheck_listfiles) | wc -l` -eq 0 \ || { echo "ERROR: files left in build directory after distclean:" ; \ $(distcleancheck_listfiles) ; \ exit 1; } >&2 check-am: all-am check: check-recursive all-am: Makefile $(DATA) installdirs: installdirs-recursive installdirs-am: for dir in "$(DESTDIR)$(docdir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-recursive install-exec: install-exec-recursive install-data: install-data-recursive uninstall: uninstall-recursive install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-recursive install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-recursive clean-am: clean-generic mostlyclean-am distclean: distclean-recursive -rm -f $(am__CONFIG_DISTCLEAN_FILES) -rm -f Makefile distclean-am: clean-am distclean-generic distclean-tags dvi: dvi-recursive dvi-am: html: html-recursive html-am: info: info-recursive info-am: install-data-am: install-dist_docDATA install-dvi: install-dvi-recursive install-dvi-am: install-exec-am: install-html: install-html-recursive install-html-am: install-info: install-info-recursive install-info-am: install-man: install-pdf: install-pdf-recursive install-pdf-am: install-ps: install-ps-recursive install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-recursive -rm -f $(am__CONFIG_DISTCLEAN_FILES) -rm -rf $(top_srcdir)/autom4te.cache -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-recursive mostlyclean-am: mostlyclean-generic pdf: pdf-recursive pdf-am: ps: ps-recursive ps-am: uninstall-am: uninstall-dist_docDATA .MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) ctags-recursive \ install-am install-strip tags-recursive .PHONY: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) CTAGS GTAGS \ all all-am am--refresh check check-am clean clean-generic \ ctags ctags-recursive dist dist-all dist-bzip2 dist-gzip \ dist-hook dist-lzip dist-lzma dist-shar dist-tarZ dist-xz \ dist-zip distcheck distclean distclean-generic distclean-tags \ distcleancheck distdir distuninstallcheck dvi dvi-am html \ html-am info info-am install install-am install-data \ install-data-am install-dist_docDATA install-dvi \ install-dvi-am install-exec install-exec-am install-html \ install-html-am install-info install-info-am install-man \ install-pdf install-pdf-am install-ps install-ps-am \ install-strip installcheck installcheck-am installdirs \ installdirs-am maintainer-clean maintainer-clean-generic \ mostlyclean mostlyclean-generic pdf pdf-am ps ps-am tags \ tags-recursive uninstall uninstall-am uninstall-dist_docDATA # This file is checked for by the configure script and its existence causes the # parsers and the manual to not be built when the distribution is built. dist-hook: ( \ echo "#!/bin/sh"; \ echo ""; \ echo "# Change to yes to enable building of parsers or manual. Reconfigure"; \ echo "# afterwards."; \ echo "build_parsers=no;"; \ echo "build_manual=no;"; \ ) > $(distdir)/DIST # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: ragel-6.8/ChangeLog0000664000175000017500000026500512106313322011157 00000000000000Ragel 6.8 - Feb 11, 2013 ======================== -The -G2 code generator for Go1 was rewritten. Table, flat and switch-based code generators were added. (Anton Ageev) -The CXXFLAGS variable is not longer set in the configure script. Ragel 6.7 - May 22, 2011 ======================== -The C vim file now supports L,l on the end of literal numbers, other syntax highlighting fixes. -Added an explicit cast when modifying _trans to eliminate compiler warnings on Windows/VC++ -Fix for ruby 1.9 compatibility. -Fix for include directories (-I option) on Windows/VC++ -Can now rename data variable in C# code generator. -Fix for non-char alphtype in C# code generator. -Fix for signedness of wide char in C code generator. when comparing the wide type against a literal we need to pick the right signedness for the literal. -Fixed arithmetic overflow in generated C# code. The C# _acts and _nacts vars should not be typed based on the size of the array elements they point to. Fixes a bug reported by Attila Sztupák. -Made the -L option work for Ruby. -Enhanced ragel.m4 (from Diego). -Applied GO patch from Justine Tunney. -Applied D2 patch from Johannes Pfau. -Applied Ocaml patch from ygrek. Ragel 6.6 - Dec 2, 2009 ======================= -Applied a number of patches from Diego Elio 'Flameeyes' Pettenò. Should not be modifying the program's arguments. Problem raised by const correctness in gcc 4.4. Other const-correctness and include fixes provided. -Fixed improper allocation of checks in makeIncludePathChecks. -Fixed segfault when there are no machine instantiations. -Fixed wrong line directives. Line directives need to use the fileName stored in the InputLoc stuctures from the parse trees, not the root source file, otherwise actions in included files will have the wrong source file names associated with the text. -Made a number of build system improvements. We locate the DIST file using $srcdir and source it. It contains settings for build_parsers and build_manual. This allows the user of a dist to enable only one. -Added missing files to doc/Makefile.am and examples/Makefile.am. -Added checks for pdflatex and fig2dev is build_manual is on. -Use automake --foreign so we don't need to have INSTALL and NEWS present. -Ragel VIM syntax files should be specialized by host language. Updated the VIM syntax files. -Added examples to the dist. Added unicode2ragel.rb to EXTRA_DIST in contrib. -Moved unicode2ragel.rb to the contrib directory. Ragel 6.5 - May 18, 2009 ======================== -Fixed a bug in graphviz generation. Ragel crashed when using -V and -M and the specified machine referenced another machine that wasn't included in the build. -The name "CS" is in use on OpenSolaris, changed to vCS to ease compiling Ragel there. -Converted to automake. -REALLY fixed a bug that was intended to be fixed in 6.4: Fixed a problem reading hex numbers that have the high bit set when the alphabet is signed and we are on 64 bit. This was reported by _why. The fix was provided by Wialliam Morgan. The literal 0xffffffff was used for a fully set long when -1L should be used instead. A null patch (whitespace changes) must have gotten checked after I was testing with and without the critical one-line patch and I forgot to enable make sure it was enabled in the final checkin version. Ragel 6.4 - Mar 22, 2009 ======================== -Moved back to a single executable. The old intermediate format can still be generated using the -x option. Ragel was split into frontend and backend programs in version 5.0. This was done to encourage interoperability with other tools. Since then, ragel has been made to work with qfsm, with ragel producing the intermediate format and qfsm consuming it. However, there has been no use of Ragel as a consumer of state machine data, with Ragel used as a code generator for DFAs. This is not surprising given that much of the complexity of Ragel is in the frontend, where the regular language to DFA compilation happens. Since the full benefits of the split have not materialized, and the split increases the complexity for users, Ragel has been made once again into a single executable. -Applied a fix to the documentation Makefile from John D. Mitchell. -Use CXXFLAGS instead of CFLAGS for C++ compiling. Patch from Diego 'Flameeyes' Pettenò. -Added support for DESTDIR variable. Patch from Diego 'Flameeyes' Pettenò. -Added a script called unicode2ragel.rb for generating unicode machines to the examples directory. From Rakan El-Khalil. -Fixed a copy-paste error in the documentation that was reported by Jose Quinteiro. -Added three new write commands: write start; write first_final; write error; These generate a reference to the start, first final and error state. When there are many different machine specifications in one file it is easy to get the prefix for these wrong (especially when you do a lot of copy-pasting of boilerplate). The problem can be avoided by using write commands. -Fixed a problem reading hex numbers that have the high bit set when the alphabet is signed and we are on 64 bit. This was reported by _why. The fix was provided by Wialliam Morgan. The literal 0xffffffff was used for a fully set long when -1L should be used instead. Ragel 6.3 - Aug 29, 2008 ======================== -Fixed an assertion that is too strong. In the condition code we need to copy transitions that have non-empty lmActionTable arrays so we don't assert emptiness in the constructor. Lift out the assertion and copy the array in the constructor. -Fixed and improved multiple include prevention. We now track the entire include history of a parser state to prevent duplicates. -Fixed crash on failed lookup of goto/call/etc target. Ragel 6.2 - May 9, 2008 ======================= -Bug fix: The lm_switch actions needs to set p from tokend when there is no user action. -Bug fix: when not using indicies we can't use a transitions's id to identify the eof transition to take. Instead add the transition to the end of the transition list and store its position in a new var called pos. The pos var is then used as the index. -Bug fix: an fnext followed by an fbreak in -G2 was not working. The fbreak was not aware that the fnext causes the cs variable to be forced active. In this case fbreak does not need to save cs because it is already current. -Bug fix: need to compute the low and high character-space keys from the condition-trans overlap when computing an expansion. Can't use the range supplied from the condition overlap since they may not match. An incorrect machine that accepted 1(!cond1, !cond2) was generated for the following grammar. This bug was reported by Tim Chklovski. c = 2 @matched_c; sc1 = 1..2 when cond1; sc2 = 1..2 when cond2; main := sc1 | c | sc2; -Bug fix: error messages in start label analysis of join operations were causing assertion failures because location info was not set. Fixed by adding locations. -Include and import file searching now searches for the file name given based on the location of the current file, not ragel's current path. Additional search locations can be given using the -I option. -Rubinius code generation was updated to the latest Rubinius. Patch from Evan Phoenix. -Switched from strcasecmp to strcmp for testing long arguments. -Applied a patch from Andrei Polushin for setting the error message format. --error-format=gnu (default) --error-fromat=msvc -Now using the _WIN32 define instead of _WIN32. Other MSVC compilation improvments from Andrei Polushin. -Added the hyperref package to the manual. Ragel 6.1 - Mar 26, 2008 ======================== -Scanners now ensure that any leaving actions at the end of a pattern are executed. They are always executed before the pattern action. -Added an option -d for turning off the removal of duplicate actions from actions lists. -Need to unset the final state status of the start state in kleene star if it is set. It is possible to crash ragel when the warning is ignored. -In the dot file generation we need to print any actions that are in State::eofTrans. These come from scanners only. -Use @docdir@ for the docdir Makefile variable. -Check for ar and ranlib in the configure script. Ragel 6.0 - Jan 12, 2008 ======================== -Removed the 'noend' write option from examples/atoi.rl. This example is referenced a lot as a first example and as such it shouldn't contain a special purpose write option like 'noend'. -Introcuded the "eof" variable for indicating the end of file. The p variable is checked against eof when the processing loop reaches the end of a block. If p == eof at this time then the EOF actions are executed. The variable is required only when EOF actions have been emebedded. -The "write eof" command is no longer needed and was removed. -Scanners now use EOF actions to generate tokens. This eliminates the need to flush the last token. -Restructured the Java driver; a switch statement with fallthrough cases are now used to emulate gotos. -Ruby code generation was also restructured. Gotos are elmulated using a series of if tests. -Went back to 3.X semantics for >, % and error actions. The > operator also embeds a leaving action/priority into the start state if it is final. If EOF happens in a state with a leaving operator then the leaving action is executed. If EOF happens in a non-final state that has an error action, the error action is executed. -The "ragel" program now executes frontend and backend processes separately, connecting them with a temporary file in the current directory. Without the -x option the "ragel" program marshals arguments and calls the frontend and backend. With the -x option the "ragel" program acts as the frontend only. -Added name finding for executables. If any forward slash is found in argv0 then it is assumed that the path is explicit and the path to the backend executable should be derived from that. Whe check that location and also go up one then inside a directory of the same name in case we are executing from the source tree. If no forward slash is found it is assumed the file is being run from the installed location. The PREFIX supplied during configuration is used. -On windows GetModuleFileNameEx is used to find out where the the current process's binary is. That location is searched first. If that fails then we go up one directory and look for the executable inside a directory of the same name in case we are executing from the source tree. -Changed the -l option in rlgen-cd to -L because it is covered in the frontend. Added a passthrough in the frontend for the backend options. -Dot file generation can now be invoked using the -V option to ragel. We now require an input file. If standard in is used then we don't have a file name on which to base the output. -Able to build native windows executables using Cygwin+MinGW. -Patch from David Waite: Large arrays are now created by copying in the data from smaller arrays using System.arraycopy(). This eliminates the debug data associated with explicit initialization statements. It is also much easier on the java compiler which can run out of memory compiling very large machines. The downside is that it takes slightly longer to initialize static data at run time. -The fbreak statement now advances p. -In the :> :>> and <: operators it was possible for the priority assignment to be bypassed via the zero length string. In :> this was fixed automatically with the semantics change to the entering priority operator. If the start state is final it now embeds a leaving action into it, preventing persistance through the zero length string. In :>> and <: this was fixed explicitly. With <: the entering priority operator was used and with :> a special exception was added. Since it uses the finishing transition operator it also adds a leaving priority to the start state if it is final. -Ranlib is now run on the archives. Patch from Kenny MacDermid. -The case statement syntax in ruby code generation used a form depreciated in Ruby 1.9. Updated it. -Made a number of fixes that eliminate warnings in GCC 4.3. Mostly concern the now depreciate automatic conversion of string contsants to "char*" type. Other fixes include adding parenthesis around && within ||. -The "tokstart" and "tokend" variables were changed to "ts" and "te". Ragel 5.25 - Dec 24, 2007 ========================= -Fixed segfault reported by Ryan Phelps. Affected Java and Ruby code generation. The dataExpr variable was not initialized. -Fixed incorrect case label in test/runtests. Caused Objective-C tests to be ignored. -Added missing include to common.cpp. Ragel 5.24 - Sep 16, 2007 ========================= -Applied patch from Victor Hugo Borja . This patch implements -T1 -F0 -F1 and -G0 in the ruby code generator. Goto-driven code generation is experimental and requires rubinius asm directives (specify with --rbx option). These code generators pass all the ruby tests. -If the condition embedding code runs out of available characters in the keyspace an error message is emitted. -The first example that appeared in the manual used the special-purpose 'noend' write option. This caused confusion. Now a basic example appears first. -Added two new statements: prepush and postpop. These are code blocks that are written out during call and return statements. The prepush code is written immediately before pushing the current state to the state stack during a call. The postpop code is written immediately after popping the current state during return. These can be used to implement a dynamically resizable stack. Ragel 5.23 - Jul 24, 2007 ========================= -Eliminated the use of callcc as an alternative to goto. Instead, the named breaks implementation used in the Java code generator is imitated using control flow variables. -Improved the error message given when there is a write statement but no machine instantiations and hence no state machine. -Documentation improvements: updates to "Machine Instantiation", "Write Init" and "Write Exports" sectons. Added the "Variables Used by Ragel" section. -Renamed "Entering Actions" to "Starting Actions." -Other documentation updates. Ragel 5.22 - June 14, 2007 ========================== -Bug fix: need to isolate the start state of a scanner before setting the to-state and from-state actions which clear and set tokstart. This affected very simple scanners only. Most scanners have an isolated start state due to the pattern structure. -Bug fix: when -S or -M was given the ragel version number was not emitted, causing the backend to reject the intermediate format. From Tim Potter. -The p varialbe is now set up at the beginning of a scanner action, rather than at the end. This leaves scanner actions free to manipulate p and removes the need for the special holdTE and execTE (TE for tokend) versions of hold and exec. It also removes the need to set p = tokend-1 immediately before any control flow. We loose the ability to determine where in the input stream a scanner action is executed, however this information is of little use because it is primarily an artifact of the scanner implementation (sometimes the last char, other times later on). The gains of this change are consistency and simplicity. -The "data" variable (used in Java and Ruby code generation only) can now be overridden using the variable statement. Ragel 5.21 - May 9, 2007 ======================== -Fixed an inconsistency in the value of p following an error. In the C directly executable code (rlgen-cd -G2) p is left at the character where the error occurred, which is correct. In all other code generators it was left at the following character. This was fixed. Now in all code generators p is left at the character where the error occurred. -Bug fix: when fhold was used in scanner pattern actions which get executed on the last character of the pattern (pattern matches which do not require any lookahead), fhold was modifying p instead of tokend. This was fixed and the patact.rl test was modified to cover the case. -Fixed typos in the guide, improved the state action embedding operator section and added subsections on the variable, import, and export statements. -Implemented a better solution than the pri hack for resolving the '-' ambiguity: force a shortest match of term. -Fixed bugs in the binary searching for condition keys in both the Ruby and Java code generation. -Can now embed the negative sense of a condition. Added a language- independent test case for this feature and the necessary transformation support. -Added new condition embedding syntax: expr inwhen cond - The transitions into the machine (starting transitions). expr outwhen cond - The pending transitions out of the machine. -The argument to the variable statement which affects the name of the current state variable was changed from "curstate" to "cs" (the default name used for the current state) -Implemented the other variables names in the variable statement. Now all variables (p, pe, cs, top, stack, act, tokstart, tokend) can be renamed. -Parse errors in the intermediate XML file now cause the backend to exit immediately rather then forge on. The recovery infrastructure isn't there and segfaults are likely. -When no input is given to the backend program, it should not print an error message, it should just return a non-zero exit status. The assumption is that the frontend printed an error. -The version number is now included in the intermediate file. An error is emitted if there is a mismatch. -The alphabet type is now communicated from the frontend to the backend using a one-word internal name instead of an array offset. -The Ruby host language types had been just copied from Java. Reduced them to two basic types: char and int, both signed with the usual C sizes. Ragel 5.20 - Apr 7, 2007 ======================== -The cs variable is now always initialized, unless the "nocs" option is given to the write init command. If there is no main machine, cs is initialized to the entry point defined by the last machine instantiation. -A number of fixes were made to the Ruby code generator. -The frontend now scans ruby comments and regular expressions. -A transformation for Ruby was added to the language-independent test suite. The Ruby code generator passes on all the language-independent tests. -A new Ruby test and two language-independent tests were added. -Some portability fixes were made (Patches from Josef Goettgens and Aaron Campbell). -Fixed a make dependency bug which caused a problem for parallel building (Patch from Jeremy Hinegardner). Ragel 5.19 - Mar 14, 2007 ========================= -Added an import statement to ragel. This statement takes a literal string as an argument, interprets it as a file name, then scrapes the file for sequences of tokens that match the following forms. Tokens inside ragel sections are ignored. An example is in test/import1.rl name = number name = lit_string "define" name number "define" name lit_string -Added an export mechanism which writes defines for single character machines that have been tagged with the export keyword in their definition. Defines are used for C, ints for D, Java and Ruby. Examples of the export feature are in test/export*.rl. -All machine instantiations are now always generated, even if they are not referenced. In the backend, entry points for all instantiations are written out alongside start, error and first final states. -If the main machine is not present then do not emit an error. Generate the machine without a start state and do not initialize cs in the write init code. -Added an option -l to rlgen-cd which inhibits the writing of #line directives. -Added a new syntax for verbose embeddings. This adds parentheses: $from(action_name); Verbose embeddings without parentheses can make code difficult to read because they force a space in the middle of an action embedding. There is a tendency to associtate spaces with concatenation. Without syntax highlighting to make it clear that the embedding type is a keyword, the problem is especially bad. The danger is that a verbose embedding could be read as an embedding of the keyword representing the empbedding type. With parentheses, verbose embeddings read much more clearly. -Conditions now have a forced order when more than one is executed on a single character. Previously ordering relied on pointers, which caused results to vary by compiler. Ordering is now done using conditon action declaration order. This fixes the failure of cond4.rl which occured with g++ 4.1 and other compiler versions. -In the port from flex to ragel, the name separator :: in Ragel code was lost. Added it back. -In the examples directory switched from rlcodegen to rlgen-cd. Silenced a warning in statechart.rl. -In the root makefile the distclean target was fixed. It was calling clean in the subdirs. In docs, the clean target was not deleting the new manpages for the rlgen-* programs. Fixed. -Portability and other fixes from Josef Goettgens were applied. -The @datadir@ and @mandir@ variables are made use of in doc/Makefile.in for specifying where documentation should be installed. Patch from Marcus Rueckert. Ragel 5.18 - Feb 13, 2007 ========================= -There is now a 100% correspondence between state id numbers in the intermediate XML file, Graphviz dot files and generated code. This was achieved by moving code which determines if the error state is necessary into the frontend, and then assigning state numbers before writing out the intermediate file. -Backened class structure was reorganized to make it easier to add new code generators without having to also modify the existing code generators. -The C and D code generation executable was changed to rlgen-cd. -The Java code generation was split out into it's own exectuable (rlgen-java) to allow it to freely diverge from the C/D-based code generation. -The graphviz dot file generation was also split out to it's own executable (rlgen-dot). -The Ruby code generation patch from Victor Hugo Borja was added. This is highly experimental code and is not yet completely functional. It is in the executable rlgen-ruby. -The problem with large state machine machines in Java was fixed. This problem was discovered by Colin Fleming, who also contributed a patch. Rather than specify arrays as comma-separated lists of literals, array initialization is now done in a static function. This is the approach used by the Java compiler. Unlike the compiler Ragel is careful split large initilization functions. -The manual was expanded and reorganized somewhat. -Eliminated per-example directories in examples/. -Made some fixes to the pullscan.rl example. -In the frontend CR characters are now treated as whitespace. -Updated to the latest aapl. This completely eliminates the shallowCopy function. With that, a definitive memory leak is fixed. -Control codes with escape sequences are now printable characters (-p option). Also, the space character is now printed as SP. -Fixed the null dereference and consequential segfault which occurred when trying to create empty machines with [] and // and /a[]b/. -Fixed the segfault which occured when a machine reference failed. -Discontinuing ragel.spec. It is more appropriate for this to be written by package maintenance developers. Ragel 5.17 - Jan 28, 2007 ========================= -The scanners and parsers in both the frontend and backend programs were completely rewritten using Ragel and Kelbt. -The '%when condition' syntax was functioning like '$when condition'. This was fixed. -In the Vim syntax file fixes to the matching of embedding operators were made. Also, improvements to the sync patterns were made. -Added pullscan.rl to the examples directory. It is an example of doing pull-based scanning. Also, xmlscan.rl in rlcodegen is a pull scanner. -The introduction chapter of the manual was improved. The manually-drawn figures for the examples were replaced with graphviz-drawn figures. Ragel 5.16 - Nov 20, 2006 ========================= -Policy change: the fhold and fexec directives did not function correctly in scanner pattern actions. In this context manipulations of p may be lost or made invalid. In the previous version of Ragel they were banned because of this. Instead of banning these directives they have been fixed. The fexec and fhold directives now manipulate tokend, which is now always used to update p when the action terminates. Ragel 5.15 - Oct 31, 2006 ========================= -A language independent test harness was introduced. Test cases can be written using a custom mini-language in the embedded actions. This mini-language is then translated to C, D and Java when generating the language-specific test cases. -Several existing tests have been ported to the language-independent format and a number of new language-independent test cases have been added. -The state-based embedding operators which access states that are not the start state and are not final (the 'middle' states) have changed. They were: <@/ eof action into middle states <@! error action into middle states <@^ local error action into middle states <@~ to-state action into middle states <@* from-state action into middle states They are now: <>/ eof action into middle states <>! error action into middle states <>^ local error action into middle states <>~ to-state action into middle states <>* from-state action into middle states -The verbose form of embeddings using the <- operator have been removed. This syntax was difficult to remember. -A new verbose form of state-based embedding operators have been added. These are like the symbol versions, except they replace the symbols: / ! ^ ~ * with literal keywords: eof err lerr to from -The following words have been promoted to keywords: when eof err lerr to from -The write statment now gets its own lexical scope in the scanner to ensure that commands are passed through as is (not affected by keywords). -Bug fix: in the code generation of fret in scanner actions the adjustment to p that is needed in some cases (dependent on content of patterns) was not happening. -The fhold directive, which decrements p, cannot be permitted in the pattern action of a scanner item because it will not behave consistently. At the end of a pattern action p could be decremented, set to a new value or left alone. This depends on the contents of the scanner's patterns. The user cannot be expected to predict what will happen to p. -Conditions in D code require a cast to the widec type when computing widec. -Like Java, D code also needs if (true) branches for control flow in actions in order to fool the unreachable code detector. This is now abstracted in all code generators using the CTRL_FLOW() function. -The NULL_ITEM value in java code should be -1. This is needed for maintaining tokstart. Ragel 5.14 - Oct 1, 2006 ======================== -Fixed the check for use of fcall in actions embedded within longest match items. It was emitting an error if an item's longest-match action had an fcall, which is allowed. This bug was introduced while fixing a segfault in version 5.8. -A new minimization option was added: MinimizeMostOps (-l). This option minimizes at every operation except on chains of expressions and chains of terms (eg, union and concat). On these chains it minimizes only at the last operation. This makes test cases with many states compile faster, without killing the performance on grammars like strings2.rl. -The -l minimiziation option was made the default. -Fixes to Java code: Use of the fc value did not work, now fixed. Static data is now declared with the final keyword. Patch from Colin Fleming. Conditions now work when generating Java code. -The option -p was added to rlcodegen which causes printable characters to be printed in GraphViz output. Patch from Colin Fleming. -The "element" keyword no longer exists, removed from vim syntax file. Updated keyword highlighting. -The host language selection is now made in the frontend. -Native host language types are now used when specifying the alphtype. Previously all languages used the set defined by C, and these were mapped to the appropriate type in the backend. Ragel 5.13 - Sep 7, 2006 ======================== -Fixed a careless error which broke Java code generation. Ragel 5.12 - Sep 7, 2006 ======================== -The -o flag did not work in combination with -V. This was fixed. -The split code generation format uses only the required number of digits when writing out the number in the file name of each part. -The -T0, -F0 and -G0 codegens should write out the action list iteration variables only when there are regular, to state or from state actions. The code gens should not use anyActions(). -If two states have the same EOF actions, they are written out in the finish routine as one case. -The split and in-place goto formats would sometimes generate _out when it is not needed. This was fixed. -Improved the basic partitioning in the split code gen. The last partition would sometimes be empty. This was fixed. -Use of 'fcall *' was not causing top to be initialized. Fixed. -Implemented a Java backend, specified with -J. Only the table-based format is supported. -Implemented range compression in the frontend. This has no effect on the generated code, however it reduces the work of the backend and any programs that read the intermediate format. Ragel 5.11 - Aug 10, 2006 ========================= -Added a variable to the configure.in script which allows the building of the parsers to be turned off (BUILD_PARSERS). Parser building is off by default for released versions. -Removed configure tests for bison defines header file. Use --defines=file instead. -Configure script doesn't test for bison, flex and gperf when building of the parsers is turned off. -Removed check for YYLTYPE structure from configure script. Since shipped code will not build parsers by default, we don't need to be as accomodating of other versions of bison. -Added a missing include that showed up with g++ 2.95.3. -Failed configure test for Objective-C compiler is now silent. Ragel 5.10 - Jul 31, 2006 ========================= -Moved the check for error state higher in the table-based processing loop. -Replaced naive implementations of condition searching with proper ones. In the table-based formats the searching is also table-based. In the directly executed formats the searching is also directly executable. -The minimization process was made aware of conditions. -A problem with the condition implementation was fixed. Previously we were taking pointers to transitions and then using them after a call to outTransCopy, which was a bad idea because they may be changed by the call. -Added test mailbox3.rl which is based on mailbox2.rl but includes conditions for restricting header and message body lengths. -Eliminated the initial one-character backup of p just before resuming execution. -Added the -s option to the frontend for printing statistics. This currently includes just the number of states. -Sped up the generation of the in-place goto-driven (-G2) code style. -Implemented a split version of in-place goto-driven code style. This code generation style is suitable for producing fast implementations of very large machines. Partitioning is currently naive. In the future a high-quality partitioning program will be employed. The flag for accessing this feature is -Pn, where n is the number of partitions. -Converted mailbox1.rl, strings2.rl and cppscan1.rl tests to support the split code generation. -Fixes and updates were made to the runtests script: added -c for compiling only, changed the -me option to -e, and added support for testing the split code style. Ragel 5.9 - Jul 19, 2006 ======================== -Fixed a bug in the include system which caused malformed output from the frontend when the include was made from a multi-line machine spec and the included file ended in a single line spec (or vice versa). -Static data is now const. -Actions which referenced states but were not embedded caused the frontend to segfault, now fixed. -Manual now built with pdflatex. -The manual was reorganized and expanded. Chapter sequence is now: Introduction, Constructing Machines, Embedding Actions, Controlling Nondeterminism and Interfacing to the Host program. Ragel 5.8 - Jun 17, 2006 ======================== -The internal representation of the alphabet type has been encapsulated into a class and all operations on it have been defined as C++ operators. -The condition implementation now supports range transitions. This allows conditions to be embedded into arbitrary machines. Conditions are still exprimental. -More condition embedding operators were added 1. Isolate the start state and embed a condition into all transitions leaving it: >when cond OR >?cond 2. Embed a condition into all transitions: when cond OR $when cond OR $?cond 3. Embed a condition into pending out transitions: %when cond OR %?cond -Improvements were made to the determinization process to support pending out conditions. -The Vim sytax file was fixed so that :> doesn't cause the match of a label. -The test suite was converted to a single-file format which uses less disk space than the old directory-per-test format. Ragel 5.7 - May 14, 2006 ======================== -Conditions will not be embedded like actions because they involve a manipulation of the state machine they are specified in. They have therefore been taken out of the verbose action embedding form (using the <- compound symbol). A new syntax for specifying conditions has been created: m = '\n' when {i==4}; -Fixed a bug which prevented state machine commands like fcurs, fcall, fret, etc, from being accounted for in from-state actions and to-state actions. This prevented some necessary support code from being generated. -Implemented condition testing in remaining code generators. -Configure script now checks for gperf, which is required for building. -Added support for case-insensitive literal strings (in addition to regexes). A case-insensitive string is made by appending an 'i' to the literal, as in 'cmd'i or "cmd"i. -Fixed a bug which caused all or expressions inside of all regular expressions to be case-insensitive. For example /[fo]o bar/ would make the [fo] part case-insensitive even though no 'i' was given following the regular expression. Ragel 5.6 - Apr 1, 2006 ======================= -Added a left-guarded concatenation operator. This operator <: is equivalent to ( expr1 $1 . expr2 >0 ). It is useful if you want to prefix a sequence with a sequence of a subset of the characters it matches. For example, one can consume leading whitespace before tokenizing a sequence of whitespace separated words: ( ' '* <: ( ' '+ | [a-z]+ )** ) -Removed context embedding code, which has been dead since 5.0. Ragel 5.5 - Mar 28, 2006 ======================== -Implemented a case-insensitive option for regular expressions: /get/i. -If no input file is given to the ragel program it reads from standard input. -The label of the start state has been changed from START to IN to save on required screen space. -Bug fix: \0 was not working in literal strings, due to a change that reduced memory usage by concatenating components of literal strings. Token data length is now passed from the scanner to the paser so that we do not need to rely on null termination. Ragel 5.4 - Mar 12, 2006 ======================== -Eliminated the default transition from the frontend implementation. This default transition was a space-saving optimization that at best could reduce the number of allocated transitions by one half. Unfortunately it complicated the implementation and this stood in the way of introducing conditionals. The default transition may be reintroduced in the future. -Added entry-guarded concatenation. This operator :>, is syntactic sugar for expr1 $0 . expr >1. This operator terminates the matching of the first machine when a first character of the second machine is matched. For example in any* . ';' we never leave the any* machine. If we use any* :> ';' then the any* machine is terminiated upon matching the semi-colon. -Added finish-guarded concatenation. This operator :>>, is syntactic sugar for expr1 $0 . expr @1. This operator is like entry guarded concatenation except the first machine is terminated when the second machine enters a final state. This is useful for delaying the guard until a full pattern is matched. For example as in '/*' any* :>> '*/'. -Added strong subtraction. Where regular subtraction removes from the first machine any strings that are matched by the second machine, strong subtraction removes any strings from the first that contain any strings of the second as a substring. Strong subtraction is syntactic sugar for expr1 - ( any* expr2 any* ). -Eliminated the use of priorities from the examples. Replaced with subtraction, guarded concatenation and longest-match kleene star. -Did some initial work on supporting conditional transitions. Far from complete and very buggy. This code will only be active when conditionals are used. Ragel 5.3 - Jan 27, 2006 ======================== -Added missing semi-colons that cause the build to fail when using older versions of Bison. -Fix for D code: if the contents of an fexec is a single word, the generated code will get interpreted as a C-style cast. Adding two brackets prevents this. Can now turn eliminate the "access this.;" in cppscan5 that was used to get around this problem. -Improved some of the tag names in the intermediate format. -Added unsigned long to the list of supported alphabet types. -Added ids of actions and action lists to XML intermediate format. Makes it more human readable. -Updated to latest Aapl package. Ragel 5.2 - Jan 6, 2006 ======================== -Ragel emits an error if the target of fentry, fcall, fgoto or fnext is inside a longest match operator, or if an action embedding in a longest match machine uses fcall. The fcall command can still be used in pattern actions. -Made improvements to the clang, rlscan, awkemu and cppscan examples. -Some fixes to generated label names: they should all be prefixed with _. -A fix to the Vim syntax highlighting script was made -Many fixes and updates to the documentation. All important features and concepts are now documented. A second chapter describing Ragel's use was added. Ragel 5.1 - Dec 22, 2005 ======================== -Fixes to the matching of section delimiters in Vim syntax file. -If there is a longest match machine, the tokend var is now initialized by write init. This is not necessary for correct functionality, however prevents compiler warnings. -The rlscan example was ported to the longest match operator and changed to emit XML data. -Fix to the error handling in the frontend: if there are errors in the lookup of names at machine generation time then do not emit anything. -If not compiling the full machine in the frontend (by using -M), avoid errors and segfaults caused by names that are not part of the compiled machine. -Longest match bug fix: need to init tokstart when returing from fsm calls that are inside longest match actions. -In Graphviz drawing, the arrow into the start state is not a real transition, do not draw to-state actions on the label. -A bug fix to the handling of non-tag data within an XML tag was made. -Backend exit value fixed: since the parser now accepts nothing so as to avoid a redundant parse error when the frontend dies, we must force an error. The backend should now be properly reporting errors. -The longest match machine now has it's start state set final. An LM machine is in a final state when it has not matched anything, when it has matched and accepted a token and is ready for another, and when it has matched a token but is waiting for some lookahead before determining what to do about it (similar to kleene star). -Element statement removed from some tests. -Entry point names are propagated to the backend and used to label the entry point arrows in Graphviz output. Ragel 5.0 - Dec 17, 2005 ======================== (additional details in V5 release notes) -Ragel has been split into two executables: A frontend which compiles machines and emits them in an XML format, and a backend which generates code or a Graphviz dot file from the XML input. The purpose of this split is to allow Ragel to interface with other tools by means of the XML intermediate format and to reduce complexity by strictly separating the previously entangled phases. The intermediate format will provide a better platform inspecting compiled machines and for extending Ragel to support other host languages. -The host language interface has been reduced significantly. Ragel no longer expects the machine to be implemented as a structure or class and does not generate functions corresponding to initialization, execution and EOF. Instead, Ragel just generates the code of these components, allowing all of them to be placed in a single function if desired. The user specifies a machine in the usual manner, then indicates at which place in the program text the state machine code is to be generated. This is done using the write statement. It is possible to specify to Ragel how it should access the variables it needs (such as the current state) using the access statement. -The host language embedding delimiters have been changed. Single line machines start with '%%' and end at newline. Multiline machines start with '%%{' and end with '}%%'. The machine name is given with the machine statement at the very beginning of the specification. This purpose of this change is to make it easier separate Ragel code from the host language. This will ease the addition of supported host languages. -The structure and class parsing which was previously able to extract a machine's name has been removed since this feature is dependent on the host language and inhibits the move towards a more language-independent frontend. -The init, element and interface statements have been made obsolete by the new host language interface and have been removed. -The fexec action statement has been changed to take only the new position to move to. This statement is more useful for moving backwards and reparsing input than for specifying a whole new buffer entirely and has been shifted to this new use. Giving it only one argument also simplifies the parsing of host code embedded in a Ragel specification. This will ease the addition of supported host languages. -Introduced the fbreak statement, which allows one to stop processing data immediately. The machine ends up in the state that the current transition was to go to. The current character is not changed. -Introduced the noend option for writing the execute code. This inhibits checking if we have reached pe. The machine will run until it goes into the error state or fbreak is hit. This allows one to parse null-terminate strings without first computing the length. -The execute code now breaks out of the processing loop when it moves into the error state. Previously it would run until pe was hit. Breaking out makes the noend option useful when an error is encountered and allows user code to determine where in the input the error occured. It also eliminates needlessly iterating the input buffer. -Introduced the noerror, nofinal and noprefix options for writing the machine data. The first two inhibit the writing of the error state and the first-final state should they not be needed. The noprefix eliminates the prefixing of the data items with the machine name. -Support for the D language has been added. This is specified in the backend with the -D switch. -Since the new host language interface has been reduced considerably, Ragel no longer needs to distinguish between C-based languages. Support for C, C++ and Objective-C has been folded into one option in the backend: -C -The code generator has been made independent of the languages that it supports by pushing the language dependent apsects down into the lower levels of the code generator. -Many improvements to the longest match construction were made. It is no longer considered experimental. A longest match machine must appear at the top level of a machine instantiation. Since it does not generate a pure state machine (it may need to backtrack), it cannot be used as an operand to other operators. -References to the current character and current state are now completely banned in EOF actions. Ragel 4.2 - Sep 16, 2005 ======================== (additional details in V4 release notes) -Fixed a bug in the longest match operator. In some states it's possible that we either match a token or match nothing at all. In these states we need to consult the LmSwitch on error so it must be prepared to execute an error handler. We therefore need to init act to this error value (which is zero). We can compute if we need to do this and the code generator emits the initialization only if necessary. -Changed the definition of the token end of longest match actions. It now points to one past the last token. This makes computing the token length easier because you don't have to add one. The longest match variables token start, action identifier and token end are now properly initialized in generated code. They don't need to be initialized in the user's code. -Implemented to-state and from-state actions. These actions are executed on transitions into the state (after the in transition's actions) and on transitions out of the state (before the out transition's actions). See V4 release notes for more information. -Since there are no longer any action embedding operators that embed both on transitions and on EOF, any actions that exist in both places will be there because the user has explicitly done so. Presuming this case is rare, and with code duplication in the hands of the user, we therefore give the EOF actions their own action switch in the finish() function. This is further motivated by the fact that the best solution is to do the same for to-state and from-state actions in the main loop. -Longest match actions can now be specified using a named action. Since a word following a longest match item conflicts with the concatenation of a named machine, the => symbol must come immediately before a named action. -The longest match operator permits action and machine definitions in the middle of a longest match construction. These are parsed as if they came before the machine definition they are contained in. Permitting action and machine definitions in a longest match construction allows objects to be defined closer to their use. -The longest match operator can now handle longest match items with no action, where previously Ragel segfaulted. -Updated to Aapl post 2.12. -Fixed a bug in epsilon transition name lookups. After doing a name lookup the result was stored in the parse tree. This is wrong because if a machine is used more than once, each time it may resolve to different targets, however it will be stored in the same place. We now store name resolutions in a separated data structure so that each walk of a parse tree uses the name resolved during the corresponding walk in the name lookup pass. -The operators used to embed context and actions into states have been modified. The V4 release notes contain the full details. -Added zlen builtin machine to represent the zero length machine. Eventually the name "null" will be phased out in favour of zlen because it is unclear whether null matches the zero length string or if it does not match any string at all (as does the empty builtin). -Added verbose versions of action, context and priority embedding. See the V4 release notes for the full details. A small example: machine <- all exec { foo(); } <- final eof act1 -Bugfix for machines with epsilon ops, but no join operations. I had wrongfully assumed that because epsilon ops can only increase connectivity, that no states are ever merged and therefore a call to fillInStates() is not necessary. In reality, epsilon transitions within one machine can induce the merging of states. In the following, state 2 follows two paths on 'i': main := 'h' -> i 'i h' i: 'i'; -Changed the license of the guide from a custom "do not propagate modified versions of this document" license to the GPL. Ragel 4.1 - Jun 26, 2005 ======================== (additional details in V4 release notes) -A bug in include processing was fixed. Surrounding code in an include file was being passed through to the output when it should be ignored. Includes are only for including portions of another machine into he current. This went unnoticed because all tested includes were wrapped in #ifndef ... #endif directives and so did not affect the compilation of the file making the include. -Fixes were made to Vim syntax highlighting file. -Duplicate actions are now removed from action lists. -The character-level negation operator ^ was added. This operator produces a machine that matches single characters that are not matched by the machine it is applied to. This unary prefix operator has the same precedence level as !. -The use of + to specify the a positive literal number was discontinued. -The parser now assigns the subtraction operator a higher precedence than the negation of literal number. Ragel 4.0 - May 26, 2005 ======================== (additional details in V4 release notes) -Operators now strictly embed into a machine either on a specific class of characters or on EOF, but never both. This gives a cleaner association between the operators and the physical state machine entitites they operate on. This change is made up of several parts: 1. '%' operator embeds only into leaving characters. 2. All global and local error operators only embed on error character transitions, their action will not be triggerend on EOF in non-final states. 3. EOF action embedding operators have been added for all classes of states to make up for functionality removed from other operators. These are >/ $/ @/ %/. 4. Start transition operator '>' no longer implicitly embeds into leaving transtions when start state is final. -Ragel now emits warnings about the improper use of statements and values in action code that is embedded as an EOF action. Warnings are emitted for fpc, fc, fexec, fbuf and fblen. -Added a longest match construction operator |* machine opt-action; ... *|. This is for repetition where an ability to revert to a shorter, previously matched item is required. This is the same behaviour as flex and re2c. The longest match operator is not a pure FSM construction, it introduces transitions that implicitly hold the current character or reset execution to a previous location in the input. Use of this operator requires the caller of the machine to occasionally hold onto data after a call to the exectute routine. Use of machines generated with this operator as the input to other operators may have undefined results. See examples/cppscan for an example. This is very experimental code. -Action ids are only assigned to actions that are referenced in the final constructed machine, preventing gaps in the action id sequence. Previously an action id was assigned if the action was referenced during parsing. -Machine specifications now begin with %% and are followed with an optional name and either a single Ragel statement or a sequence of statements enclosed in {}. -Ragel no longer generates the FSM's structure or class. It is up to the user to declare the structure and to give it a variable named curs of type integer. If the machine uses the call stack the user must also declare a array of integers named stack and an integer variable named top. -In the case of Objective-C, Ragel no longer generates the interface or implementation directives, allowing the user to declare additional methods. -If a machine specification does not have a name then Ragel tries to find a name for it by first checking if the specification is inside a struct, class or interface. If it is not then it uses the name of the previous machine specification. If still no name is found then this is an error. -Fsm specifications now persist in memory and statements accumulate. -Ragel now has an include statement for including the statements of a machine spec in another file (perhaps because it is the corresponding header file). The include statement can also be used to draw in the statements of another fsm spec in the current file. -The fstack statement is now obsolete and has been removed. -A new statement, simply 'interface;', indicates that ragel should generate the machine's interface. If Ragel sees the main machine it generates the code sections of the machine. Previously, the header portion was generated if the (now removed) struct statement was found and code was generated if any machine definition was found. -Fixed a bug in the resolution of fsm name references in actions. The name resolution code did not recurse into inline code items with children (fgoto*, fcall*, fnext*, and fexec), causing a segfault at code generation time. -Cleaned up the code generators. FsmCodeGen was made into a virtual base class allowing for the language/output-style specific classes to inherit both a language specific and style-specific base class while retaining only one copy of FsmCodeGen. Language specific output can now be moved into the language specific code generators, requiring less duplication of code in the language/output-style specific leaf classes. -Fixed bugs in fcall* implementation of IpgGoto code generation. -If the element type has not been defined Ragel now uses a constant version of the alphtype, not the exact alphtype. In most cases the data pointer of the execute routine should be const. A non-const element type can still be defined with the element statement. -The fc special value now uses getkey for retrieving the current char rather than *_p, which is wrong if the element type is a structure. -User guide converted to TeX and updated for new 4.0 syntax and semantics. Ragel 3.7 - Oct 31, 2004 ======================== -Bug fix: unreferenced machine instantiations causing segfault due to name tree and parse tree walk becomming out of syncronization. -Rewrote representation of inline code blocks using a tree data structure. This allows special keywords such as fbuf to be used as the operatands of other fsm commands. -Documentation updates. -When deciding whether or not to generate machine instantiations, search the entire name tree beneath the instantiation for references, not just the root. -Removed stray ';' in keller2.rl -Added fexec for restarting the machine with new buffer data (state stays the same), fbuf for retrieving the the start of the buf, and fblen for retrieving the orig buffer length. -Implemented test/cppscan2 using fexec. This allows token emitting and restart to stay inside the execute routine, instead of leaving and re-entering on every token. -Changed examples/cppscan to use fexec and thereby go much faster. -Implemented flex and re2c versions of examples/cppscan. Ragel version goes faster than flex version but not as fast as re2c version. -Merged in Objective-C patch from Erich Ocean. -Turned off syncing with stdio in C++ tests to make them go faster. -Renamed C++ code generaion classes with the Cpp Prefix instead of CC to make them easier to read. -In the finish function emit fbuf as 0 cast to a pointer to the element type so it's type is not interpreted as an integer. -The number -128 underflows char alphabets on some architectures. Removed uses of it in tests. -Disabled the keller2 test because it causes problems on many architectures due to its large size and compilation requirements. Ragel 3.6 - Jul 10, 2004 ======================== -Many documentation updates. -When resolving names, return a set of values so that a reference in an action block that is embedded more than once won't report distinct entry points that are actually the same. -Implemented flat tables. Stores a linear array of indicies into the transition array and only a low and high key value. Faster than binary searching for keys but not usable for large alphabets. -Fixed bug in deleting of transitions leftover from converstion from bst to list implementation of transitions. Other code cleanup. -In table based output calculate the cost of using an index. Don't use if cheaper. -Changed fstate() value available in init and action code to to fentry() to reflect the fact that the values returned are intended to be used as targets in fgoto, fnext and fcall statements. The returned state is not a unique state representing the label. There can be any number of states representing a label. -Added keller2 test, C++ scanning tests and C++ scanning example. -In table based output split up transitions into targets and actions. This allows actions to be omitted. -Broke the components of the state array into separate arrays. Requires adding some fields where they could previously be omitted, however allows finer grained control over the sizes of items and an overal size reduction. Also means that state numbers are not an offset into the state array but instead a sequence of numbers, meaning the context array does not have any wasted bits. -Action lists and transition also have their types chosen to be the smallest possible for accomodating the contained values. -Changed curs state stored in fsm struct from _cs to curs. Keep fsm->curs == -1 while in machine. Added tests curs1 and curs2. -Implemented the notion of context. Context can be embedded in states using >:, $:, @: and %: operators. These embed a named context into start states, all states, non-start/non-final and final states. If the context is declared using a context statment context name; then the context can be quered for any state using fsm_name_ctx_name(state) in C code and fsm_name::ctx_name(state) in C++ code. This feature makes it possible to determine what "part" of the machine is currently active. -Fixed crash on machine generation of graphs with no final state. If there is no reference to a final state in a join operation, don't generate one. -Updated Vim sytax: added labels to inline code, added various C++ keywords. Don't highlight name separations as labels. Added switch labels, improved alphtype, element and getkey. -Fixed line info in error reporting of bad epsilon trans. -Fixed fstate() for tab code gen. -Removed references to malloc.h. Ragel 3.5 - May 29, 2004 ======================== -When parse errors occur, the partially generated output file is deleted and an non-zero exit status is returned. -Updated Vim syntax file. -Implemented the setting of the element type that is passed to the execute routine as well as method for specifying how ragel should retrive the key from the element type. This lets ragel process arbitrary structures inside of which is the key that is parsed. element struct Element; getkey fpc->character; -The current state is now implemented with an int across all machines. This simplifies working with current state variables. For example this allows a call stack to be implemented in user code. -Implemented a method for retrieving the current state, the target state, and any named states. fcurs -retrieve the current state ftargs -retrieve the target state fstate(name) -retrieve a named state. -Implemented a mechanism for jumping to and calling to a state stored in a variable. fgoto *; -goto the state returned by the C/C++ expression. fcall *; -call the state returned by the C/C++ expression. -Implemented a mechanism for specifying the next state without immediately transfering control there (any code following statement is executed). fnext label; -set the state pointed to by label as the next state. fnext *; -set the state returned by the C/C++ expression as the next. -Action references are determined from the final machine instead of during the parse tree walk. Some actions can be referenced in the parse tree but not show up in the final machine. Machine analysis is now done based on this new computation. -Named state lookup now employs a breadth-first search in the lookup and allows the user to fully qualify names, making it possible to specify jumps/calls into parts of the machine deep in the name hierarchy. Each part of name (separated by ::) employs a breadth first search from it's starting point. -Name references now must always refer to a single state. Since references to multiple states is not normally intended, it no longer happens automatically. This frees the programmer from thinking about whether or not a state reference is unique. It also avoids the added complexity of determining when to merge the targets of multiple references. The effect of references to multiple states can be explicitly created using the join operator and epsilon transitions. -M option was split into -S and -M. -S specifies the machine spec to generate for graphviz output and dumping. -M specifies the machine definition or instantiation. -Machine function parameters are now prefixed with and underscore to avoid the hiding of class members. Ragel 3.4 - May 8, 2004 ======================= -Added the longest match kleene star operator **, which is synonymous with ( ( ) $0 %1 ) *. -Epsilon operators distinguish between leaving transitions (going to an another expression in a comma separated list) and non-leaving transitions. Leaving actions and priorities are appropriately transferred. -Relative priority of following ops changed to: 1. Action/Priority 2. Epsilon 3. Label If label is done first then the isolation of the start state in > operators will cause the label to point to the old start state that doesn't have the new action/priority. -Merged >! and >~, @! and @~, %! and %~, and $! and $~ operators to have one set of global error action operators (>!, @!, %! and $!) that are invoked on error by unexpected characters as well as by unexepected EOF. -Added the fpc keyword for use in action code. This is a pointer to the current character. *fpc == fc. If an action is invoked on EOF then fpc == 0. -Added >^, @^, %^, and $^ local error operators. Global error operators (>!, @!, $!, and %!) cause actions to be invoked if the final machine fails. Local error actions cause actions to be invoked if if the current machine fails. -Changed error operators to mean embed global/local error actions in: >! and !^ -the start state. @! and @^ -states that are not the start state and are not final. %! and %^ -final states. $! and $^ -all states. -Added >@! which is synonymous >! then @! -Added >@^ which is synonymous >^ then @^ -Added @%! which is synonymous @! then %! -Added @%^ which is synonymous >^ then @^ -FsmGraph representation of transition lists was changed from a mapping of alphabet key -> transition objects using a BST to simply a list of transition objects. Since the transitions are no longer divided by single/range, the fast finding of transition objects by key is no longer required functionality and can be eliminated. This new implementation uses the same amount of memory however causes less allocations. It also make more sense for supporting error transitions with actions. Previously an error transition was represented by a null value in the BST. -Regular expression ranges are checked to ensure that lower <= upper. -Added printf-like example. -Added atoi2, erract2, and gotcallret to the test suite. -Improved build test to support make -jN and simplified the compiling and running of tests. Ragel 3.3 - Mar 7, 2004 ======================= -Portability bug fixes were made. Minimum and maximum integer values are now taken from the system. An alignment problem on 64bit systems was fixed. Ragel 3.2 - Feb 28, 2004 ======================== -Added a Vim syntax file. -Eliminated length var from generated execute code in favour of an end pointer. Using length requires two variables be read and written. Using an end pointer requires one variable read and written and one read. Results in more optimizable code. -Minimization is now on by default. -States are ordered in output by depth first search. -Bug in minimization fixed. States were not being distinguished based on error actions. -Added null and empty builtin machines. -Added EOF error action operators. These are >~, >@, $~, and %~. EOF error operators embed actions to take if the EOF is seen and interpreted as an error. The operators correspond to the following states: -the start state -any state with a transition to a final state -any state with a transiion out -a final state -Fixed bug in generation of unreference machine vars using -M. Unreferenced vars don't have a name tree built underneath when starting from instantiations. Need to instead build the name tree starting at the var. -Calls, returns, holds and references to fc in out action code are now handled for ipgoto output. -Only actions referenced by an instantiated machine expression are put into the action index and written out. -Added rlscan, an example that lexes Ragel input. Ragel 3.1 - Feb 18, 2004 ======================== -Duplicates in OR literals are removed and no longer cause an assertion failure. -Duplicate entry points used in goto and call statements are made into deterministic entry points. -Base FsmGraph code moved from aapl into ragel, as an increasing amount of specialization is required. Too much time was spent attempting to keep it as a general purpose template. -FsmGraph code de-templatized and heirarchy squashed to a single class. -Single transitions taken out of FsmGraph code. In the machine construction stage, transitions are now implemented only with ranges and default transtions. This reduces memory consumption, simplifies code and prevents covered transitions. However it requires the automated selection of single transitions to keep goto-driven code lean. -Machine reduction completely rewritten to be in-place. As duplicate transitions and actions are found and the machine is converted to a format suitable for writing as C code or as GraphViz input, the memory allocated for states and transitions is reused, instead of newly allocated. -New reduction code consolodates ranges, selects a default transition, and selects single transitions with the goal of joining ranges that are split by any number of single characters. -Line directive changed from "# " to the more common format "#line ". -Operator :! changed to @!. This should have happened in last release. -Added params example. Ragel 3.0 - Jan 22, 2004 ======================== -Ragel now parses the contents of struct statements and action code. -The keyword fc replaces the use of *p to reference the current character in action code. -Machine instantiations other than main are allowed. -Call, jump and return statements are now available in action code. This facility makes it possible to jump to an error handling machine, call a sub-machine for parsing a field or to follow paths through a machine as determined by arbitrary C code. -Added labels to the language. Labels can be used anywhere in a machine expression to define an entry point. Also references to machine definitions cause the implicit creation of a label. -Added epsilon transitions to the language. Epsilon operators may reference labels in the current name scope resolved when join operators are evaluated and at the root of the expression tree of machine assignment/instantiation. -Added the comma operator, which joins machines together without drawing any transitions between them. This operator is useful in combination with labels, the epsilon operator and user code transitions for defining machines using the named state and transition list paradigm. It is also useful for invoking transitions based on some analysis of the input or on the environment. -Added >!, :!, $!, %! operators for specifying actions to take should the machine fail. These operators embed actions to execute if the machine fails in -the start state -any state with a transition to a final state -any state with a transiion out -a final state The general rule is that if an action embedding operator embeds an action into a set of transitions T, then the error-counterpart with a ! embeds an action into the error transition taken when any transition T is a candidate, but does not match the input. -The finishing augmentation operator ':' has been changed to '@'. This frees the ':' symbol for machine labels and avoids hacks to the parser to allow the use of ':' for both labels and finishing augmentations. The best hack required that label names be distinct from machine definition names as in main := word : word; This restriction is not good because labels are local to the machine that they are used in whereas machine names are global entities. Label name choices should not be restricted by the set of names that are in use for machines. -Named priority syntax now requires parenthesis surrounding the name and value pair. This avoids grammar ambiguities now that the ',' operator has been introduced and makes it more clear that the name and value are an asscociated pair. -Backslashes are escaped in line directive paths. Ragel 2.2 - Oct 6, 2003 ======================= -Added {n}, {,n}, {n,} {n,m} repetition operators. {n} -- exactly n repetitions {,n} -- zero to n repetitions {n,} -- n or more repetitions {n,m} -- n to m repetitions -Bug in binary search table in Aapl fixed. Fixes crashing on machines that add to action tables that are implicitly shared among transitions. -Tests using obsolete minimization algorithms are no longer built and run by default. -Added atoi and concurrent from examples to the test suite. Ragel 2.1 - Sep 22, 2003 ======================== -Bug in priority comparison code fixed. Segfaulted on some input with many embedded priorities. -Added two new examples. Ragel 2.0 - Sep 7, 2003 ======================= -Optional (?), One or More (+) and Kleene Star (*) operators changed from prefix to postfix. Rationale is that postfix version is far more common in regular expression implementations and will be more readily understood. -All priority values attached to transitions are now accompanied by a name. Transitions no longer have default priority values of zero assigned to them. Only transitions that have different priority values assigned to the same name influence the NFA-DFA conversion. This scheme reduces side-effects of priorities. -Removed the %! statement for unsetting pending out priorities. With named priorities, it is not necessary to clear the priorities of a machine with $0 %! because non-colliding names can be used to avoid side-effects. -Removed the clear keyword, which was for removing actions from a machine. Not required functionality and it is non-intuitive to have a language feature that undoes previous definitions. -Removed the ^ modifier to repetition and concatenation operators. This undocumented feature prevented out transitions and out priorities from being transfered from final states to transitions leaving machines. Not required functionality and complicates the language unnecessarily. -Keyword 'func' changed to 'action' as a part of the phasing out of the term 'function' in favour of 'action'. Rationale is that the term 'function' implies that the code is called like a C function, which is not necessarily the case. The term 'action' is far more common in state machine compiler implementations. -Added the instantiation statement, which looks like a standard variable assignment except := is used instead of =. Instantiations go into the same graph dictionary as definitions. In the the future, instantiations will be used as the target for gotos and calls in action code. -The main graph should now be explicitly instantiated. If it is not, a warning is issued. -Or literal basic machines ([] outside of regular expressions) now support negation and ranges. -C and C++ interfaces lowercased. In the C interface an underscore now separates the fsm machine and the function name. Rationale is that lowercased library and generated routines are more common. C output: int fsm_init( struct clang *fsm ); int fsm_execute( struct clang *fsm, char *data, int dlen ); int fsm_finish( struct clang *fsm ); C++ output: int fsm::init( ); int fsm::execute( char *data, int dlen ); int fsm::finish( ); -Init, execute and finish all return -1 if the machine is in the error state and can never accept, 0 if the machine is in a non-accepting state that has a path to a final state and 1 if the machine is in an accepting state. -Accept routine eliminated. Determining whether or not the machine accepts is done by examining the return value of the finish routine. -In C output, fsm structure is no longer a typedef, so referencing requires the struct keyword. This is to stay in line with C language conventions. -In C++ output, constructor is no longer written by ragel. As a consequence, init routine is not called automatically. Allows constructor to be supplied by user as well as the return value of init to be examined without calling it twice. -Static start state and private structures are taken out of C++ classes. Ragel 1.5.4 - Jul 14, 2003 ========================== -Workaround for building with bison 1.875, which produces an optimization that doesn't build with newer version gcc. Ragel 1.5.3 - Jul 10, 2003 ========================== -Fixed building with versions of flex that recognize YY_NO_UNPUT. -Fixed version numbers in ragel.spec file. Ragel 1.5.2 - Jul 7, 2003 ========================= -Transition actions and out actions displayed in the graphviz output. -Transitions on negative numbers handled in graphviz output. -Warning generated when using bison 1.875 now squashed. Ragel 1.5.1 - Jun 21, 2003 ========================== -Bugs fixed: Don't delete the output objects when writing to standard out. Copy mem into parser buffer with memcpy, not strcpy. Fixes buffer mem errror. -Fixes for compiling with Sun WorkShop 6 compilers. Ragel 1.5.0 - Jun 10, 2003 ========================== -Line directives written to the output so that errors in the action code are properly reported in the ragel input file. -Simple graphviz dot file output format is supported. Shows states and transitions. Does not yet show actions. -Options -p and -f dropped in favour of -d output format. -Added option -M for specifying the machine to dump with -d or the graph to generate with -V. -Error recovery implemented. -Proper line and column number tracking implemented in the scanner. -All action/function code is now embedded in the main Execute routine. Avoids duplication of action code in the Finish routine and the need to call ExecFuncs which resulted in huge code bloat. Will also allow actions to modify cs when fsm goto, call and return is supported in action code. -Fsm spec can have no statements, nothing will be generated. -Bug fix: Don't accept ] as the opening of a .-. range a reg exp. -Regular expression or set ranges (ie /[0-9]/) are now handled by the parser and consequently must be well-formed. The following now generates a parser error: /[+-]/ and must be rewritten as /[+\-]/. Also fixes a bug whereby ] might be accepted as the opening of a .-. range causing /[0-9]-[0-9]/ to parse incorrectly. -\v, \f, and \r are now treated as whitespace in an fsm spec. Ragel 1.4.1 - Nov 19, 2002 ========================== -Compile fixes. The last release (integer alphabets) was so exciting that usual portability checks got bypassed. Ragel 1.4.0 - Nov 19, 2002 ========================== -Arbitrary integer alphabets are now fully supported! A new language construct: 'alphtype ' added for specifying the type of the alphabet. Default is 'char'. Possible alphabet types are: char, unsigned char, short, unsigned short, int, unsigned int -Literal machines specified in decimal format can now be negative when the alphabet is a signed type. -Literal machines (strings, decimal and hex) have their values checked for overflow/underflow against the size of the alphabet type. -Table driven and goto driven output redesigned to support ranges. Table driven uses a binary search for locating single characters and ranges. Goto driven uses a switch statement for single characters and nested if blocks for ranges. -Switch driven output removed due to a lack of consistent advantages. Most of the time the switch driven FSM is of no use because the goto FSM makes smaller and faster code. Under certain circumstances it can produce smaller code than a goto driven fsm and be almost as fast, but some sporadic case does not warrant maintaining it. -Many warnings changed to errors. -Added option -p for printing the final fsm before minimization. This lets priorities be seen. Priorties are all reset to 0 before minimization. The exiting option -f prints the final fsm after minimization. -Fixed a bug in the clang test and example that resulted in redundant actions being executed. Ragel 1.3.4 - Nov 6, 2002 ========================= -Fixes to Chapter 1 of the guide. -Brought back the examples and made them current. -MSVC is no longer supported for compiling windows binaries because its support for the C++ standard is frustratingly inadequate, it will cost money to upgrade if it ever gets better, and MinGW is a much better alternative. -The build system now supports the --host= option for building ragel for another system (used for cross compiling a windows binary with MinGW). -Various design changes and fixes towards the goal of arbitrary integer alphabets and the handling of larger state machines were made. -The new shared vector class is now used for action lists in transitions and states to reduce memory allocations. -An avl tree is now used for the reduction of transitions and functions of an fsm graph before making the final machine. The tree allows better scalability and performance by not requiring consecutively larger heap allocations. -Final stages in the separation of fsm graph code from action embedding and priority assignment is complete. Makes the base graph leaner and easier to reuse in other projects (like Keller). Ragel 1.3.3 - Oct 22, 2002 ========================== -More diagrams were added to section 1.7.1 of the user guide. -FSM Graph code was reworked to spearate the regex/nfa/minimizaion graph algorithms from the manipulation of state and transition properties. -An rpm spec file from Cris Bailiff was added. This allows an rpm for ragel to be built with the command 'rpm -ta ragel-x.x.x.tar.gz' -Fixes to the build system and corresponding doc updates in the README. -Removed autil and included the one needed source file directly in the top level ragel directory. -Fixed a bug that nullified the 20 times speedup in large compilations claimed by the last version. -Removed awk from the doc build (it was added with the last release -- though not mentioned in the changelog). -Install of man page was moved to the doc dir. The install also installs the user guide to $(PREFIX)/share/doc/ragel/ Ragel 1.3.2 - Oct 16, 2002 ========================== -Added option -v (or --version) to show version information. -The subtract operator no longer removes transition data from the machine being subtracted. This is left up to the user for the purpose of making it possible to transfer transitions using subtract and also for speeding up the subtract routine. Note that it is possible to explicitly clear transition data before a doing a subtract. -Rather severe typo bug fixed. Bug was related to transitions with higher priorities taking precedence. A wrong ptr was being returned. It appears to have worked most of the time becuase the old ptr was deleted and the new one allocated immediatly after so the old ptr often pointed to the same space. Just luck though. -Bug in the removing of dead end paths was fixed. If the start state has in transitions then those paths were not followed when finding states to keep. Would result in non-dead end states being removed from the graph. -In lists and in ranges are no longer maintained as a bst with the key as the alphabet character and the value as a list of transitions coming in on that char. There is one list for each of inList, inRange and inDefault. Now that the required functionality of the graph is well known it is safe to remove these lists to gain in speed and footprint. They shouldn't be needed. -IsolateStartState() runs on modification of start data only if the start state is not already isolated, which is now possible with the new in list representation. -Concat, Or and Star operators now use an approximation to removeUnreachableStates that does not require a traversal of the entire graph. This combined with an 'on-the-fly' management of final bits and final state status results is a dramatic speed increase when compiling machines that use those operators heavily. The strings2 test goes 20 times faster. -Before the final minimization, after all fsm operations are complete, priority data is reset which enables better minimization in cases where priorities would otherwise separate similar states. Ragel 1.3.1 - Oct 2, 2002 ========================= -Range transitions are now used to implement machines made with /[a-z]/ and the .. operator as well as most of the builtin machines. The ranges are not yet reflected in the output code, they are expanded as if they came from the regular single transitions. This is one step closer to arbitrary integer output. -The builtin machine 'any' was added. It is equiv to the builtin extend, matching any characters. -The builtin machine 'cntrl' now includes newline. -The builtin machine 'space' now includes newline. -The builtin machine 'ascii' is now the range 0-127, not all characters. -A man page was written. -A proper user guide was started. Chapter 1: Specifying Ragel Programs was written. It even has some diagrams :) Ragel 1.3.0 - Sep 4, 2002 ========================= -NULL keyword no longer used in table output. -Though not yet in use, underlying graph structure changed to support range transitions. As a result, most of the code that walks transition lists is now implemented with an iterator that hides the complexity of the transition lists and ranges. Range transitions will be used to implement /[a-z]/ style machines and machines made with the .. operator. Previously a single transition would be used for each char in the range, which is very costly. Ranges eliminate much of the space complexity and allow for the .. operator to be used with very large (integer) alphabets. -New minimization similar to Hopcroft's alg. It does not require n^2 space and runs close to O(n*log(n)) (an exact analysis of the alg is very hard). It is much better than the stable and approx minimization and obsoletes them both. An exact implementation of Hopcroft's alg is desirable but not possible because the ragel implementation does not assume a finite alphabet, which Hopcroft's requires. Ragel will support arbitrary integer alphabets which must be treated as an infinite set for implementation considerations. -New option -m using above described minimization to replace all previous minimization options. Old options sill work but are obsolete and not advertised with -h. -Bug fixed in goto style output. The error exit set the current state to 0, which is actually a valid state. If the machine was entered again it would go into the first state, very wrong. If the first state happened to be final then an immediate finish would accept when in fact it should fail. -Slightly better fsm minimization now capable due to clearing of the transition ordering numbers just prior to minimization. Ragel 1.2.2 - May 25, 2002 ========================== -Configuration option --prefix now works when installing. -cc file extension changed to cpp for better portability. -Unlink of output file upon error no longer happens, removes dependency on unlink system command. -All multiline strings removed: not standard c++. -Awk build dependency removed. -MSVC 6.0 added to the list of supported compilers (with some tweaking of bison and flex output). Ragel 1.2.1 - May 13, 2002 ========================== -Automatic dependencies were fixed, they were not working correctly. -Updated AUTHORS file to reflect contributors. -Code is more C++ standards compliant: compiles with g++ 3.0 -Fixed bugs that only showed up in g++ 3.0 -Latest (unreleased) Aapl. -Configuration script bails out if bison++ is installed. Ragel will not compile with bison++ because it is coded in c++ and bison++ automatically generates a c++ parser. Ragel uses a c-style bison parser. Ragel 1.2.0 - May 3, 2002 ========================= -Underlying graph structure now supports default transitions. The result is that a transition does not need to be made for each char of the alphabet when making 'extend' or '/./' machines. Ragel compiles machines that use the aforementioned primitives WAY faster. -The ugly hacks needed to pick default transitions now go away due to the graph supporting default transitions directly. -If -e is given, but minimization is not turned on, print a warning. -Makefiles use automatic dependencies. Ragel 1.1.0 - Apr 15, 2002 ========================== -Added goto fsm: much faster than any other fsm style. -Default operator (if two machines are side by side with no operator between them) is concatenation. First showed up in 1.0.4. -The fsm machine no longer auotmatically builds the flat table for transition indicies. Instead it keeps the key,ptr pair. In tabcodegen the flat table is produced. This way very large alphabets with sparse transitions will not consume large amounts of mem. This is also in prep for fsm graph getting a default transition. -Generated code contains a statement explicitly stating that ragel fsms are NOT covered by the GPL. Technically, Ragel copies part of itself to the output to make the generic fsm execution routine (for table driven fsms only) and so the output could be considered under the GPL. But this code is very trivial and could easlily be rewritten. The actual fsm data is subject to the copyright of the source. To promote the use of Ragel, a special exception is made for the part of the output copied from Ragel: it may be used without restriction. -Much more elegant code generation scheme is employed. Code generation class members need only put the 'codegen' keyword after their 'void' type in order to be automatically registerd to handle macros of the same name. An awk script recognises this keyword and generates an appropriate driver. -Ragel gets a test suite. -Postfunc and prefunc go away because they are not supported by non loop-driven fsms (goto, switch) and present duplicate functionality. Universal funcs can be implemented by using $ operator. -Automatic dependencies used in build system, no more make depend target. -Code generation section in docs. -Uses the latests aapl. Ragel 1.0.5 - Mar 3, 2002 ========================= -Bugfix in SetErrorState that caused an assertion failure when compiling simple machines that did not have full transition tables (and thus did not show up on any example machines). Assertion failure did not occur when using the switch statement code as ragel does not call SetErrorState in that case. -Fixed some missing includes, now compiles on redhat. -Moved the FsmMachTrans Compare class out of FsmMachTrans. Some compilers don't deal with nested classes in templates too well. -Removed old unused BASEREF in fsmgraph and ragel now compiles using egcs-2.91.66 and presumably SUNWspro. The baseref is no longer needed because states do not support being elements in multiple lists. I would rather be able to support more compilers than have this feature. -Started a README with compilation notes. Started an AUTHORS file. -Started the user documentation. Describes basic machines and operators. Ragel 1.0.4 - Mar 1, 2002 ========================= -Ported to the version of Aapl just after 2.2.0 release. See http://www.ragel.ca/aapl/ for details on aapl. -Fixed a bug in the clang example: the newline machine was not stared. -Added explanations to the clang and mailbox examples. This should help people that want to learn the lanuage as the manual is far from complete. Ragel 1.0.3 - Feb 2, 2002 ========================= -Added aapl to the ragel tree. No longer requires you to download and build aapl separately. Should avoid discouraging impatient users from compiling ragel. -Added the examples to the ragel tree. -Added configure script checks for bison and flex. -Fixed makefile so as not to die with newer versions of bison that write the header of the parser to a .hh file. -Started ChangeLog file. Ragel 1.0.2 - Jan 30, 2002 ========================== -Bug fix in calculating highIndex for table based code. Was using the length of out tranisition table rather than the value at the end. -If high/low index are at the limits, output a define in their place, not the high/low values themselves so as not to cause compiler warnings. -If the resulting machines don't have any indicies or functions, then omit the empty unrefereced static arrays so as not to cause compiler warnings about unused static vars. -Fixed variable sized indicies support. The header cannot have any reference to INDEX_TYPE as that info is not known at the time the header data is written. Forces us to use a void * for pointers to indicies. In the c++ versions we are forced to make much of the data non-member static data in the code portion for the same reason. Ragel 1.0.1 - Jan 28, 2002 ========================== -Exe name change from reglang to ragel. -Added ftabcodegen output code style which uses a table for states and transitions but uses a switch statement for the function execution. -Reformatted options in usage dump to look better. -Support escape sequences in [] sections of regular expressions. Ragel 1.0 - Jan 25, 2002 ======================== -Initial release. ragel-6.8/missing0000755000175000017500000002415211736361705011016 00000000000000#! /bin/sh # Common stub for a few missing GNU programs while installing. scriptversion=2012-01-06.13; # UTC # Copyright (C) 1996, 1997, 1999, 2000, 2002, 2003, 2004, 2005, 2006, # 2008, 2009, 2010, 2011, 2012 Free Software Foundation, Inc. # Originally by Fran,cois Pinard , 1996. # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2, or (at your option) # any later version. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # You should have received a copy of the GNU General Public License # along with this program. If not, see . # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. if test $# -eq 0; then echo 1>&2 "Try \`$0 --help' for more information" exit 1 fi run=: sed_output='s/.* --output[ =]\([^ ]*\).*/\1/p' sed_minuso='s/.* -o \([^ ]*\).*/\1/p' # In the cases where this matters, `missing' is being run in the # srcdir already. if test -f configure.ac; then configure_ac=configure.ac else configure_ac=configure.in fi msg="missing on your system" case $1 in --run) # Try to run requested program, and just exit if it succeeds. run= shift "$@" && exit 0 # Exit code 63 means version mismatch. This often happens # when the user try to use an ancient version of a tool on # a file that requires a minimum version. In this case we # we should proceed has if the program had been absent, or # if --run hadn't been passed. if test $? = 63; then run=: msg="probably too old" fi ;; -h|--h|--he|--hel|--help) echo "\ $0 [OPTION]... PROGRAM [ARGUMENT]... Handle \`PROGRAM [ARGUMENT]...' for when PROGRAM is missing, or return an error status if there is no known handling for PROGRAM. Options: -h, --help display this help and exit -v, --version output version information and exit --run try to run the given command, and emulate it if it fails Supported PROGRAM values: aclocal touch file \`aclocal.m4' autoconf touch file \`configure' autoheader touch file \`config.h.in' autom4te touch the output file, or create a stub one automake touch all \`Makefile.in' files bison create \`y.tab.[ch]', if possible, from existing .[ch] flex create \`lex.yy.c', if possible, from existing .c help2man touch the output file lex create \`lex.yy.c', if possible, from existing .c makeinfo touch the output file yacc create \`y.tab.[ch]', if possible, from existing .[ch] Version suffixes to PROGRAM as well as the prefixes \`gnu-', \`gnu', and \`g' are ignored when checking the name. Send bug reports to ." exit $? ;; -v|--v|--ve|--ver|--vers|--versi|--versio|--version) echo "missing $scriptversion (GNU Automake)" exit $? ;; -*) echo 1>&2 "$0: Unknown \`$1' option" echo 1>&2 "Try \`$0 --help' for more information" exit 1 ;; esac # normalize program name to check for. program=`echo "$1" | sed ' s/^gnu-//; t s/^gnu//; t s/^g//; t'` # Now exit if we have it, but it failed. Also exit now if we # don't have it and --version was passed (most likely to detect # the program). This is about non-GNU programs, so use $1 not # $program. case $1 in lex*|yacc*) # Not GNU programs, they don't have --version. ;; *) if test -z "$run" && ($1 --version) > /dev/null 2>&1; then # We have it, but it failed. exit 1 elif test "x$2" = "x--version" || test "x$2" = "x--help"; then # Could not run --version or --help. This is probably someone # running `$TOOL --version' or `$TOOL --help' to check whether # $TOOL exists and not knowing $TOOL uses missing. exit 1 fi ;; esac # If it does not exist, or fails to run (possibly an outdated version), # try to emulate it. case $program in aclocal*) echo 1>&2 "\ WARNING: \`$1' is $msg. You should only need it if you modified \`acinclude.m4' or \`${configure_ac}'. You might want to install the \`Automake' and \`Perl' packages. Grab them from any GNU archive site." touch aclocal.m4 ;; autoconf*) echo 1>&2 "\ WARNING: \`$1' is $msg. You should only need it if you modified \`${configure_ac}'. You might want to install the \`Autoconf' and \`GNU m4' packages. Grab them from any GNU archive site." touch configure ;; autoheader*) echo 1>&2 "\ WARNING: \`$1' is $msg. You should only need it if you modified \`acconfig.h' or \`${configure_ac}'. You might want to install the \`Autoconf' and \`GNU m4' packages. Grab them from any GNU archive site." files=`sed -n 's/^[ ]*A[CM]_CONFIG_HEADER(\([^)]*\)).*/\1/p' ${configure_ac}` test -z "$files" && files="config.h" touch_files= for f in $files; do case $f in *:*) touch_files="$touch_files "`echo "$f" | sed -e 's/^[^:]*://' -e 's/:.*//'`;; *) touch_files="$touch_files $f.in";; esac done touch $touch_files ;; automake*) echo 1>&2 "\ WARNING: \`$1' is $msg. You should only need it if you modified \`Makefile.am', \`acinclude.m4' or \`${configure_ac}'. You might want to install the \`Automake' and \`Perl' packages. Grab them from any GNU archive site." find . -type f -name Makefile.am -print | sed 's/\.am$/.in/' | while read f; do touch "$f"; done ;; autom4te*) echo 1>&2 "\ WARNING: \`$1' is needed, but is $msg. You might have modified some files without having the proper tools for further handling them. You can get \`$1' as part of \`Autoconf' from any GNU archive site." file=`echo "$*" | sed -n "$sed_output"` test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"` if test -f "$file"; then touch $file else test -z "$file" || exec >$file echo "#! /bin/sh" echo "# Created by GNU Automake missing as a replacement of" echo "# $ $@" echo "exit 0" chmod +x $file exit 1 fi ;; bison*|yacc*) echo 1>&2 "\ WARNING: \`$1' $msg. You should only need it if you modified a \`.y' file. You may need the \`Bison' package in order for those modifications to take effect. You can get \`Bison' from any GNU archive site." rm -f y.tab.c y.tab.h if test $# -ne 1; then eval LASTARG=\${$#} case $LASTARG in *.y) SRCFILE=`echo "$LASTARG" | sed 's/y$/c/'` if test -f "$SRCFILE"; then cp "$SRCFILE" y.tab.c fi SRCFILE=`echo "$LASTARG" | sed 's/y$/h/'` if test -f "$SRCFILE"; then cp "$SRCFILE" y.tab.h fi ;; esac fi if test ! -f y.tab.h; then echo >y.tab.h fi if test ! -f y.tab.c; then echo 'main() { return 0; }' >y.tab.c fi ;; lex*|flex*) echo 1>&2 "\ WARNING: \`$1' is $msg. You should only need it if you modified a \`.l' file. You may need the \`Flex' package in order for those modifications to take effect. You can get \`Flex' from any GNU archive site." rm -f lex.yy.c if test $# -ne 1; then eval LASTARG=\${$#} case $LASTARG in *.l) SRCFILE=`echo "$LASTARG" | sed 's/l$/c/'` if test -f "$SRCFILE"; then cp "$SRCFILE" lex.yy.c fi ;; esac fi if test ! -f lex.yy.c; then echo 'main() { return 0; }' >lex.yy.c fi ;; help2man*) echo 1>&2 "\ WARNING: \`$1' is $msg. You should only need it if you modified a dependency of a manual page. You may need the \`Help2man' package in order for those modifications to take effect. You can get \`Help2man' from any GNU archive site." file=`echo "$*" | sed -n "$sed_output"` test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"` if test -f "$file"; then touch $file else test -z "$file" || exec >$file echo ".ab help2man is required to generate this page" exit $? fi ;; makeinfo*) echo 1>&2 "\ WARNING: \`$1' is $msg. You should only need it if you modified a \`.texi' or \`.texinfo' file, or any other file indirectly affecting the aspect of the manual. The spurious call might also be the consequence of using a buggy \`make' (AIX, DU, IRIX). You might want to install the \`Texinfo' package or the \`GNU make' package. Grab either from any GNU archive site." # The file to touch is that specified with -o ... file=`echo "$*" | sed -n "$sed_output"` test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"` if test -z "$file"; then # ... or it is the one specified with @setfilename ... infile=`echo "$*" | sed 's/.* \([^ ]*\) *$/\1/'` file=`sed -n ' /^@setfilename/{ s/.* \([^ ]*\) *$/\1/ p q }' $infile` # ... or it is derived from the source name (dir/f.texi becomes f.info) test -z "$file" && file=`echo "$infile" | sed 's,.*/,,;s,.[^.]*$,,'`.info fi # If the file does not exist, the user really needs makeinfo; # let's fail without touching anything. test -f $file || exit 1 touch $file ;; *) echo 1>&2 "\ WARNING: \`$1' is needed, and is $msg. You might have modified some files without having the proper tools for further handling them. Check the \`README' file, it often tells you about the needed prerequisites for installing this package. You may also peek at any GNU archive site, in case some other package would contain this missing \`$1' program." exit 1 ;; esac exit 0 # Local variables: # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-time-zone: "UTC" # time-stamp-end: "; # UTC" # End: ragel-6.8/README0000664000175000017500000000153212043335171010264 00000000000000 Ragel State Machine Compiler -- README ====================================== 1. Build Requirements --------------------- * Make * g++ If you would like to modify Ragel and need to build Ragel's scanners and parsers from the specifications then set "build_parsers=yes" the DIST file and reconfigure. This variable is normally set to "no" in the distribution tarballs and "yes" in version control. You will need the following programs: * ragel (the most recent version) * kelbt (the most recent version) To build the user guide set "build_manual=yes" in the DIST file and reconfigure. You will need the following extra programs: * fig2dev * pdflatex 2. Compilation and Installation ------------------------------- Ragel uses autoconf and automake. $ ./configure --prefix=PREFIX $ make $ make install