From eafd7a3974e8605fd02794269db6114a3446e016 Mon Sep 17 00:00:00 2001 From: Lorry Tar Creator Date: Mon, 13 Oct 2014 19:14:30 +0000 Subject: ragel-6.9 --- examples/Makefile.am | 91 +++ examples/Makefile.in | 728 +++++++++++++++++++++ examples/README | 40 ++ examples/atoi.cpp | 120 ++++ examples/atoi.rl | 59 ++ examples/awkemu.c | 217 +++++++ examples/awkemu.rl | 116 ++++ examples/clang.c | 456 ++++++++++++++ examples/clang.rl | 150 +++++ examples/concurrent.cpp | 986 +++++++++++++++++++++++++++++ examples/concurrent.rl | 126 ++++ examples/cppscan.cpp | 908 +++++++++++++++++++++++++++ examples/cppscan.rl | 208 ++++++ examples/format.c | 544 ++++++++++++++++ examples/format.rl | 191 ++++++ examples/gotocallret.cpp | 282 +++++++++ examples/gotocallret.rl | 96 +++ examples/mailbox.cpp | 1563 ++++++++++++++++++++++++++++++++++++++++++++++ examples/mailbox.rl | 207 ++++++ examples/params.c | 374 +++++++++++ examples/params.rl | 102 +++ examples/pullscan.c | 294 +++++++++ examples/pullscan.rl | 170 +++++ examples/rlscan.cpp | 1055 +++++++++++++++++++++++++++++++ examples/rlscan.rl | 300 +++++++++ examples/statechart.cpp | 187 ++++++ examples/statechart.rl | 116 ++++ 27 files changed, 9686 insertions(+) create mode 100644 examples/Makefile.am create mode 100644 examples/Makefile.in create mode 100644 examples/README create mode 100644 examples/atoi.cpp create mode 100644 examples/atoi.rl create mode 100644 examples/awkemu.c create mode 100644 examples/awkemu.rl create mode 100644 examples/clang.c create mode 100644 examples/clang.rl create mode 100644 examples/concurrent.cpp create mode 100644 examples/concurrent.rl create mode 100644 examples/cppscan.cpp create mode 100644 examples/cppscan.rl create mode 100644 examples/format.c create mode 100644 examples/format.rl create mode 100644 examples/gotocallret.cpp create mode 100644 examples/gotocallret.rl create mode 100644 examples/mailbox.cpp create mode 100644 examples/mailbox.rl create mode 100644 examples/params.c create mode 100644 examples/params.rl create mode 100644 examples/pullscan.c create mode 100644 examples/pullscan.rl create mode 100644 examples/rlscan.cpp create mode 100644 examples/rlscan.rl create mode 100644 examples/statechart.cpp create mode 100644 examples/statechart.rl (limited to 'examples') diff --git a/examples/Makefile.am b/examples/Makefile.am new file mode 100644 index 0000000..b4c6a94 --- /dev/null +++ b/examples/Makefile.am @@ -0,0 +1,91 @@ +# +# 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 + +RAGEL = ../ragel/ragel +FLEX = flex +RE2C = re2c + +noinst_PROGRAMS = \ + atoi awkemu clang concurrent cppscan format gotocallret mailbox params \ + pullscan rlscan statechart + +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 + +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 $< > $@ diff --git a/examples/Makefile.in b/examples/Makefile.in new file mode 100644 index 0000000..957d7e7 --- /dev/null +++ b/examples/Makefile.in @@ -0,0 +1,728 @@ +# Makefile.in generated by automake 1.14.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2013 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@ +am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +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 = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ + $(top_srcdir)/depcomp README +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) +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +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) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) +AM_V_CXX = $(am__v_CXX_@AM_V@) +am__v_CXX_ = $(am__v_CXX_@AM_DEFAULT_V@) +am__v_CXX_0 = @echo " CXX " $@; +am__v_CXX_1 = +CXXLD = $(CXX) +CXXLINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) \ + -o $@ +AM_V_CXXLD = $(am__v_CXXLD_@AM_V@) +am__v_CXXLD_ = $(am__v_CXXLD_@AM_DEFAULT_V@) +am__v_CXXLD_0 = @echo " CXXLD " $@; +am__v_CXXLD_1 = +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) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +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) + $(AM_V_CXXLD)$(CXXLINK) $(atoi_OBJECTS) $(atoi_LDADD) $(LIBS) + +awkemu$(EXEEXT): $(awkemu_OBJECTS) $(awkemu_DEPENDENCIES) $(EXTRA_awkemu_DEPENDENCIES) + @rm -f awkemu$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(awkemu_OBJECTS) $(awkemu_LDADD) $(LIBS) + +clang$(EXEEXT): $(clang_OBJECTS) $(clang_DEPENDENCIES) $(EXTRA_clang_DEPENDENCIES) + @rm -f clang$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(clang_OBJECTS) $(clang_LDADD) $(LIBS) + +concurrent$(EXEEXT): $(concurrent_OBJECTS) $(concurrent_DEPENDENCIES) $(EXTRA_concurrent_DEPENDENCIES) + @rm -f concurrent$(EXEEXT) + $(AM_V_CXXLD)$(CXXLINK) $(concurrent_OBJECTS) $(concurrent_LDADD) $(LIBS) + +cppscan$(EXEEXT): $(cppscan_OBJECTS) $(cppscan_DEPENDENCIES) $(EXTRA_cppscan_DEPENDENCIES) + @rm -f cppscan$(EXEEXT) + $(AM_V_CXXLD)$(CXXLINK) $(cppscan_OBJECTS) $(cppscan_LDADD) $(LIBS) + +format$(EXEEXT): $(format_OBJECTS) $(format_DEPENDENCIES) $(EXTRA_format_DEPENDENCIES) + @rm -f format$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(format_OBJECTS) $(format_LDADD) $(LIBS) + +gotocallret$(EXEEXT): $(gotocallret_OBJECTS) $(gotocallret_DEPENDENCIES) $(EXTRA_gotocallret_DEPENDENCIES) + @rm -f gotocallret$(EXEEXT) + $(AM_V_CXXLD)$(CXXLINK) $(gotocallret_OBJECTS) $(gotocallret_LDADD) $(LIBS) + +mailbox$(EXEEXT): $(mailbox_OBJECTS) $(mailbox_DEPENDENCIES) $(EXTRA_mailbox_DEPENDENCIES) + @rm -f mailbox$(EXEEXT) + $(AM_V_CXXLD)$(CXXLINK) $(mailbox_OBJECTS) $(mailbox_LDADD) $(LIBS) + +params$(EXEEXT): $(params_OBJECTS) $(params_DEPENDENCIES) $(EXTRA_params_DEPENDENCIES) + @rm -f params$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(params_OBJECTS) $(params_LDADD) $(LIBS) + +pullscan$(EXEEXT): $(pullscan_OBJECTS) $(pullscan_DEPENDENCIES) $(EXTRA_pullscan_DEPENDENCIES) + @rm -f pullscan$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(pullscan_OBJECTS) $(pullscan_LDADD) $(LIBS) + +rlscan$(EXEEXT): $(rlscan_OBJECTS) $(rlscan_DEPENDENCIES) $(EXTRA_rlscan_DEPENDENCIES) + @rm -f rlscan$(EXEEXT) + $(AM_V_CXXLD)$(CXXLINK) $(rlscan_OBJECTS) $(rlscan_LDADD) $(LIBS) + +statechart$(EXEEXT): $(statechart_OBJECTS) $(statechart_DEPENDENCIES) $(EXTRA_statechart_DEPENDENCIES) + @rm -f statechart$(EXEEXT) + $(AM_V_CXXLD)$(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@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.cpp.o: +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ $< + +.cpp.obj: +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + 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-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + 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" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +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 TAGS all all-am check check-am clean clean-generic \ + clean-noinstPROGRAMS cscopelist-am ctags ctags-am 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 tags-am 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: diff --git a/examples/README b/examples/README new file mode 100644 index 0000000..12773cb --- /dev/null +++ b/examples/README @@ -0,0 +1,40 @@ + + 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. diff --git a/examples/atoi.cpp b/examples/atoi.cpp new file mode 100644 index 0000000..45677f3 --- /dev/null +++ b/examples/atoi.cpp @@ -0,0 +1,120 @@ + +#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; +} diff --git a/examples/atoi.rl b/examples/atoi.rl new file mode 100644 index 0000000..7164b68 --- /dev/null +++ b/examples/atoi.rl @@ -0,0 +1,59 @@ +/* + * Convert a string to an integer. + */ + +#include +#include +#include + +%%{ + machine atoi; + write data; +}%% + +long long atoi( char *str ) +{ + char *p = str, *pe = str + strlen( str ); + int cs; + long long val = 0; + bool neg = false; + + %%{ + action see_neg { + neg = true; + } + + action add_digit { + val = val * 10 + (fc - '0'); + } + + main := + ( '-'@see_neg | '+' )? ( digit @add_digit )+ + '\n'; + + # Initialize and execute. + write init; + write exec; + }%% + + 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; +} diff --git a/examples/awkemu.c b/examples/awkemu.c new file mode 100644 index 0000000..2fdcb01 --- /dev/null +++ b/examples/awkemu.c @@ -0,0 +1,217 @@ + +#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; +} diff --git a/examples/awkemu.rl b/examples/awkemu.rl new file mode 100644 index 0000000..6615943 --- /dev/null +++ b/examples/awkemu.rl @@ -0,0 +1,116 @@ +/* + * 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; +} diff --git a/examples/clang.c b/examples/clang.c new file mode 100644 index 0000000..c8fb683 --- /dev/null +++ b/examples/clang.c @@ -0,0 +1,456 @@ + +#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; +} + diff --git a/examples/clang.rl b/examples/clang.rl new file mode 100644 index 0000000..60491e5 --- /dev/null +++ b/examples/clang.rl @@ -0,0 +1,150 @@ +/* + * 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; +} + diff --git a/examples/concurrent.cpp b/examples/concurrent.cpp new file mode 100644 index 0000000..c2278cb --- /dev/null +++ b/examples/concurrent.cpp @@ -0,0 +1,986 @@ + +#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; +} diff --git a/examples/concurrent.rl b/examples/concurrent.rl new file mode 100644 index 0000000..224f960 --- /dev/null +++ b/examples/concurrent.rl @@ -0,0 +1,126 @@ +/* + * 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; +} diff --git a/examples/cppscan.cpp b/examples/cppscan.cpp new file mode 100644 index 0000000..6894311 --- /dev/null +++ b/examples/cppscan.cpp @@ -0,0 +1,908 @@ + +#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; +} diff --git a/examples/cppscan.rl b/examples/cppscan.rl new file mode 100644 index 0000000..1ead5aa --- /dev/null +++ b/examples/cppscan.rl @@ -0,0 +1,208 @@ +/* + * 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; + +%%{ + machine Scanner; + write data nofinal; + + # Floating literals. + fract_const = digit* '.' digit+ | digit+ '.'; + exponent = [eE] [+\-]? digit+; + float_suffix = [flFL]; + + c_comment := + any* :>> '*/' + @{ fgoto main; }; + + 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 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. + '/*' { fgoto c_comment; }; + '//' [^\n]* '\n'; + ( any - 33..126 )+; + + *|; +}%% + +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); + + %% write init; + + /* 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; + } + + %% write exec; + + /* 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; +} diff --git a/examples/format.c b/examples/format.c new file mode 100644 index 0000000..768b063 --- /dev/null +++ b/examples/format.c @@ -0,0 +1,544 @@ + +#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; +} + diff --git a/examples/format.rl b/examples/format.rl new file mode 100644 index 0000000..f8a37be --- /dev/null +++ b/examples/format.rl @@ -0,0 +1,191 @@ +/* + * 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; +} + diff --git a/examples/gotocallret.cpp b/examples/gotocallret.cpp new file mode 100644 index 0000000..18a9531 --- /dev/null +++ b/examples/gotocallret.cpp @@ -0,0 +1,282 @@ + +#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; +} diff --git a/examples/gotocallret.rl b/examples/gotocallret.rl new file mode 100644 index 0000000..32c01a2 --- /dev/null +++ b/examples/gotocallret.rl @@ -0,0 +1,96 @@ +/* + * 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; +} diff --git a/examples/mailbox.cpp b/examples/mailbox.cpp new file mode 100644 index 0000000..7e9c46e --- /dev/null +++ b/examples/mailbox.cpp @@ -0,0 +1,1563 @@ + +#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; +} diff --git a/examples/mailbox.rl b/examples/mailbox.rl new file mode 100644 index 0000000..94590fd --- /dev/null +++ b/examples/mailbox.rl @@ -0,0 +1,207 @@ +/* + * 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; +} diff --git a/examples/params.c b/examples/params.c new file mode 100644 index 0000000..485e1c3 --- /dev/null +++ b/examples/params.c @@ -0,0 +1,374 @@ + +#line 1 "params.rl" +/* + * Parse command line arguments. + */ + +#include +#include + +#define BUFLEN 1024 + +struct params +{ + char buffer[BUFLEN+1]; + int buflen; + int cs; +}; + + +#line 61 "params.rl" + + + +#line 25 "params.c" +static const int params_start = 23; +static const int params_first_final = 23; +static const int params_error = 0; + +static const int params_en_main = 23; + + +#line 64 "params.rl" + +void params_init( struct params *fsm ) +{ + fsm->buflen = 0; + +#line 39 "params.c" + { + fsm->cs = params_start; + } + +#line 69 "params.rl" +} + +void params_execute( struct params *fsm, const char *data, int len ) +{ + const char *p = data; + const char *pe = data + len; + + +#line 53 "params.c" + { + if ( p == pe ) + goto _test_eof; + switch ( fsm->cs ) + { +tr11: +#line 38 "params.rl" + { printf("help\n"); } + goto st23; +tr17: +#line 39 "params.rl" + { printf("version\n"); } + goto st23; +tr21: +#line 30 "params.rl" + { + if ( fsm->buflen < BUFLEN ) + fsm->buffer[fsm->buflen++] = 0; + } +#line 42 "params.rl" + { printf("machine: \"%s\"\n", fsm->buffer); } + goto st23; +tr25: +#line 30 "params.rl" + { + if ( fsm->buflen < BUFLEN ) + fsm->buffer[fsm->buflen++] = 0; + } +#line 41 "params.rl" + { printf("spec: \"%s\"\n", fsm->buffer); } + goto st23; +tr29: +#line 30 "params.rl" + { + if ( fsm->buflen < BUFLEN ) + fsm->buffer[fsm->buflen++] = 0; + } +#line 40 "params.rl" + { printf("output: \"%s\"\n", fsm->buffer); } + goto st23; +st23: + if ( ++p == pe ) + goto _test_eof23; +case 23: +#line 98 "params.c" + if ( (*p) == 45 ) + goto st1; + goto st0; +st0: + fsm->cs = 0; + goto _out; +st1: + if ( ++p == pe ) + goto _test_eof1; +case 1: + switch( (*p) ) { + case 45: goto st2; + case 63: goto st6; + case 72: goto st6; + case 77: goto st14; + case 83: goto st17; + case 104: goto st6; + case 111: goto st20; + case 118: goto st13; + } + goto st0; +st2: + if ( ++p == pe ) + goto _test_eof2; +case 2: + switch( (*p) ) { + case 104: goto st3; + case 118: goto st7; + } + goto st0; +st3: + if ( ++p == pe ) + goto _test_eof3; +case 3: + if ( (*p) == 101 ) + goto st4; + goto st0; +st4: + if ( ++p == pe ) + goto _test_eof4; +case 4: + if ( (*p) == 108 ) + goto st5; + goto st0; +st5: + if ( ++p == pe ) + goto _test_eof5; +case 5: + if ( (*p) == 112 ) + goto st6; + goto st0; +st6: + if ( ++p == pe ) + goto _test_eof6; +case 6: + if ( (*p) == 0 ) + goto tr11; + goto st0; +st7: + if ( ++p == pe ) + goto _test_eof7; +case 7: + if ( (*p) == 101 ) + goto st8; + goto st0; +st8: + if ( ++p == pe ) + goto _test_eof8; +case 8: + if ( (*p) == 114 ) + goto st9; + goto st0; +st9: + if ( ++p == pe ) + goto _test_eof9; +case 9: + if ( (*p) == 115 ) + goto st10; + goto st0; +st10: + if ( ++p == pe ) + goto _test_eof10; +case 10: + if ( (*p) == 105 ) + goto st11; + goto st0; +st11: + if ( ++p == pe ) + goto _test_eof11; +case 11: + if ( (*p) == 111 ) + goto st12; + goto st0; +st12: + if ( ++p == pe ) + goto _test_eof12; +case 12: + if ( (*p) == 110 ) + goto st13; + goto st0; +st13: + if ( ++p == pe ) + goto _test_eof13; +case 13: + if ( (*p) == 0 ) + goto tr17; + goto st0; +st14: + if ( ++p == pe ) + goto _test_eof14; +case 14: + if ( (*p) == 0 ) + goto st16; + goto tr18; +tr18: +#line 36 "params.rl" + { fsm->buflen = 0; } +#line 24 "params.rl" + { + if ( fsm->buflen < BUFLEN ) + fsm->buffer[fsm->buflen++] = (*p); + } + goto st15; +tr20: +#line 24 "params.rl" + { + if ( fsm->buflen < BUFLEN ) + fsm->buffer[fsm->buflen++] = (*p); + } + goto st15; +st15: + if ( ++p == pe ) + goto _test_eof15; +case 15: +#line 233 "params.c" + if ( (*p) == 0 ) + goto tr21; + goto tr20; +st16: + if ( ++p == pe ) + goto _test_eof16; +case 16: + if ( (*p) == 0 ) + goto st0; + goto tr18; +st17: + if ( ++p == pe ) + goto _test_eof17; +case 17: + if ( (*p) == 0 ) + goto st19; + goto tr22; +tr22: +#line 36 "params.rl" + { fsm->buflen = 0; } +#line 24 "params.rl" + { + if ( fsm->buflen < BUFLEN ) + fsm->buffer[fsm->buflen++] = (*p); + } + goto st18; +tr24: +#line 24 "params.rl" + { + if ( fsm->buflen < BUFLEN ) + fsm->buffer[fsm->buflen++] = (*p); + } + goto st18; +st18: + if ( ++p == pe ) + goto _test_eof18; +case 18: +#line 271 "params.c" + if ( (*p) == 0 ) + goto tr25; + goto tr24; +st19: + if ( ++p == pe ) + goto _test_eof19; +case 19: + if ( (*p) == 0 ) + goto st0; + goto tr22; +st20: + if ( ++p == pe ) + goto _test_eof20; +case 20: + if ( (*p) == 0 ) + goto st22; + goto tr26; +tr26: +#line 36 "params.rl" + { fsm->buflen = 0; } +#line 24 "params.rl" + { + if ( fsm->buflen < BUFLEN ) + fsm->buffer[fsm->buflen++] = (*p); + } + goto st21; +tr28: +#line 24 "params.rl" + { + if ( fsm->buflen < BUFLEN ) + fsm->buffer[fsm->buflen++] = (*p); + } + goto st21; +st21: + if ( ++p == pe ) + goto _test_eof21; +case 21: +#line 309 "params.c" + if ( (*p) == 0 ) + goto tr29; + goto tr28; +st22: + if ( ++p == pe ) + goto _test_eof22; +case 22: + if ( (*p) == 0 ) + goto st0; + goto tr26; + } + _test_eof23: fsm->cs = 23; 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_eof11: fsm->cs = 11; goto _test_eof; + _test_eof12: fsm->cs = 12; goto _test_eof; + _test_eof13: fsm->cs = 13; goto _test_eof; + _test_eof14: fsm->cs = 14; goto _test_eof; + _test_eof15: fsm->cs = 15; goto _test_eof; + _test_eof16: fsm->cs = 16; goto _test_eof; + _test_eof17: fsm->cs = 17; goto _test_eof; + _test_eof18: fsm->cs = 18; goto _test_eof; + _test_eof19: fsm->cs = 19; goto _test_eof; + _test_eof20: fsm->cs = 20; goto _test_eof; + _test_eof21: fsm->cs = 21; goto _test_eof; + _test_eof22: fsm->cs = 22; goto _test_eof; + + _test_eof: {} + _out: {} + } + +#line 77 "params.rl" +} + +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; +} diff --git a/examples/params.rl b/examples/params.rl new file mode 100644 index 0000000..a8ffeae --- /dev/null +++ b/examples/params.rl @@ -0,0 +1,102 @@ +/* + * 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; +} diff --git a/examples/pullscan.c b/examples/pullscan.c new file mode 100644 index 0000000..a72ca2f --- /dev/null +++ b/examples/pullscan.c @@ -0,0 +1,294 @@ + +#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; +} + + diff --git a/examples/pullscan.rl b/examples/pullscan.rl new file mode 100644 index 0000000..d9e8a57 --- /dev/null +++ b/examples/pullscan.rl @@ -0,0 +1,170 @@ +#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; +} + + diff --git a/examples/rlscan.cpp b/examples/rlscan.cpp new file mode 100644 index 0000000..1c428f8 --- /dev/null +++ b/examples/rlscan.cpp @@ -0,0 +1,1055 @@ + +#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; +} diff --git a/examples/rlscan.rl b/examples/rlscan.rl new file mode 100644 index 0000000..d4d4bf9 --- /dev/null +++ b/examples/rlscan.rl @@ -0,0 +1,300 @@ +/* + * 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 ); +} + + +%%{ + 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; + +#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; +} diff --git a/examples/statechart.cpp b/examples/statechart.cpp new file mode 100644 index 0000000..afe3b9c --- /dev/null +++ b/examples/statechart.cpp @@ -0,0 +1,187 @@ + +#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; +} diff --git a/examples/statechart.rl b/examples/statechart.rl new file mode 100644 index 0000000..a04471b --- /dev/null +++ b/examples/statechart.rl @@ -0,0 +1,116 @@ +/* + * 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; +} -- cgit v1.2.1