Discussion:
[ragel-users] [PATCH 2/3] ocaml codegen: support -G1
ygrek
2012-06-18 20:48:31 UTC
Permalink
---
ragel/Makefile.am | 4 +-
ragel/gendata.cc | 6 -
ragel/mlfgoto.cc | 311 +++++++++++++++++++++++++++++++++++++++++++++++++++
ragel/mlfgoto.h | 51 +++++++++
ragel/reducedgen.cc | 6 +-
5 files changed, 369 insertions(+), 9 deletions(-)
create mode 100644 ragel/mlfgoto.cc
create mode 100644 ragel/mlfgoto.h

diff --git a/ragel/Makefile.am b/ragel/Makefile.am
index ae3e1ad..e35c924 100644
--- a/ragel/Makefile.am
+++ b/ragel/Makefile.am
@@ -13,7 +13,7 @@ ragel_SOURCES = \
dotcodegen.h parsetree.h rlscan.h version.h cdflat.h common.h \
csftable.h fsmgraph.h pcheck.h rubycodegen.h xmlcodegen.h cdftable.h \
csgoto.h gendata.h ragel.h rubyfflat.h goipgoto.h \
- mlcodegen.h mltable.h mlftable.h mlflat.h mlfflat.h mlgoto.h \
+ mlcodegen.h mltable.h mlftable.h mlflat.h mlfflat.h mlgoto.h mlfgoto.h \
main.cc parsetree.cc parsedata.cc fsmstate.cc fsmbase.cc \
fsmattach.cc fsmmin.cc fsmgraph.cc fsmap.cc fsmcond.cc rlscan.cc rlparse.cc \
inputdata.cc common.cc redfsm.cc gendata.cc cdcodegen.cc \
@@ -22,7 +22,7 @@ ragel_SOURCES = \
rubyftable.cc rubyflat.cc rubyfflat.cc rbxgoto.cc cscodegen.cc \
cstable.cc csftable.cc csflat.cc csfflat.cc csgoto.cc csfgoto.cc \
csipgoto.cc cssplit.cc dotcodegen.cc dotcodegen-orig.cc xmlcodegen.cc reducedgen.cc goipgoto.cc \
- mlcodegen.cc mltable.cc mlftable.cc mlflat.cc mlfflat.cc mlgoto.cc \
+ mlcodegen.cc mltable.cc mlftable.cc mlflat.cc mlfflat.cc mlgoto.cc mlfgoto.cc \
crackcodegen.h crackcodegen.cc crackflat.h crackflat.cc

BUILT_SOURCES = \
diff --git a/ragel/gendata.cc b/ragel/gendata.cc
index 55a9bb0..1a0050e 100644
--- a/ragel/gendata.cc
+++ b/ragel/gendata.cc
@@ -51,12 +51,6 @@

#include "goipgoto.h"

-#include "mltable.h"
-#include "mlftable.h"
-#include "mlflat.h"
-#include "mlfflat.h"
-#include "mlgoto.h"
-
#include "rubytable.h"
#include "rubyftable.h"
#include "rubyflat.h"
diff --git a/ragel/mlfgoto.cc b/ragel/mlfgoto.cc
new file mode 100644
index 0000000..b66d66e
--- /dev/null
+++ b/ragel/mlfgoto.cc
@@ -0,0 +1,311 @@
+/*
+ * Copyright 2001-2006 Adrian Thurston <thurston at complang.org>
+ * 2004 Erich Ocean <eric.ocean at ampede.com>
+ * 2005 Alan West <alan at alanz.com>
+ */
+
+/* This file is part of Ragel.
+ *
+ * Ragel is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Ragel is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Ragel; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "ragel.h"
+#include "mlfgoto.h"
+#include "redfsm.h"
+#include "gendata.h"
+#include "bstmap.h"
+
+std::ostream &OCamlFGotoCodeGen::EXEC_ACTIONS()
+{
+ /* Loop the actions. */
+ for ( GenActionTableMap::Iter redAct = redFsm->actionMap; redAct.lte(); redAct++ ) {
+ if ( redAct->numTransRefs > 0 ) {
+ /* We are at the start of a glob, write the case. */
+ out << "and f" << redAct->actListId << " () =\n";
+ out << "\tbegin try\n";
+
+ /* Write each action in the list of action items. */
+ for ( GenActionTable::Iter item = redAct->key; item.lte(); item++ )
+ ACTION( out, item->value, 0, false );
+
+ out << "\twith Goto_again -> () end;\n";
+ out << "\tdo_again ()\n";
+ }
+ }
+ return out;
+}
+
+/* Write out the function switch. This switch is keyed on the values
+ * of the func index. */
+std::ostream &OCamlFGotoCodeGen::TO_STATE_ACTION_SWITCH()
+{
+ /* Loop the actions. */
+ for ( GenActionTableMap::Iter redAct = redFsm->actionMap; redAct.lte(); redAct++ ) {
+ if ( redAct->numToStateRefs > 0 ) {
+ /* Write the entry label. */
+ out << "\t|" << redAct->actListId+1 << " ->\n";
+
+ /* Write each action in the list of action items. */
+ for ( GenActionTable::Iter item = redAct->key; item.lte(); item++ )
+ ACTION( out, item->value, 0, false );
+
+// out << "\tbreak;\n";
+ }
+ }
+
+ genLineDirective( out );
+ return out;
+}
+
+/* Write out the function switch. This switch is keyed on the values
+ * of the func index. */
+std::ostream &OCamlFGotoCodeGen::FROM_STATE_ACTION_SWITCH()
+{
+ /* Loop the actions. */
+ for ( GenActionTableMap::Iter redAct = redFsm->actionMap; redAct.lte(); redAct++ ) {
+ if ( redAct->numFromStateRefs > 0 ) {
+ /* Write the entry label. */
+ out << "\t| " << redAct->actListId+1 << " ->\n";
+
+ /* Write each action in the list of action items. */
+ for ( GenActionTable::Iter item = redAct->key; item.lte(); item++ )
+ ACTION( out, item->value, 0, false );
+
+// out << "\tbreak;\n";
+ }
+ }
+
+ genLineDirective( out );
+ return out;
+}
+
+std::ostream &OCamlFGotoCodeGen::EOF_ACTION_SWITCH()
+{
+ /* Loop the actions. */
+ for ( GenActionTableMap::Iter redAct = redFsm->actionMap; redAct.lte(); redAct++ ) {
+ if ( redAct->numEofRefs > 0 ) {
+ /* Write the entry label. */
+ out << "\t| " << redAct->actListId+1 << " ->\n";
+
+ /* Write each action in the list of action items. */
+ for ( GenActionTable::Iter item = redAct->key; item.lte(); item++ )
+ ACTION( out, item->value, 0, true );
+
+// out << "\tbreak;\n";
+ }
+ }
+
+ genLineDirective( out );
+ return out;
+}
+
+
+std::ostream &OCamlFGotoCodeGen::FINISH_CASES()
+{
+ for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
+ /* States that are final and have an out action need a case. */
+ if ( st->eofAction != 0 ) {
+ /* Write the case label. */
+ out << "\t\t| " << st->id << " -> ";
+
+ /* Jump to the func. */
+ out << "f" << st->eofAction->actListId << " ()\n";
+ }
+ }
+
+ return out;
+}
+
+unsigned int OCamlFGotoCodeGen::TO_STATE_ACTION( RedStateAp *state )
+{
+ int act = 0;
+ if ( state->toStateAction != 0 )
+ act = state->toStateAction->actListId+1;
+ return act;
+}
+
+unsigned int OCamlFGotoCodeGen::FROM_STATE_ACTION( RedStateAp *state )
+{
+ int act = 0;
+ if ( state->fromStateAction != 0 )
+ act = state->fromStateAction->actListId+1;
+ return act;
+}
+
+unsigned int OCamlFGotoCodeGen::EOF_ACTION( RedStateAp *state )
+{
+ int act = 0;
+ if ( state->eofAction != 0 )
+ act = state->eofAction->actListId+1;
+ return act;
+}
+
+void OCamlFGotoCodeGen::writeData()
+{
+ if ( redFsm->anyToStateActions() ) {
+ OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActionLoc), TSA() );
+ TO_STATE_ACTIONS();
+ CLOSE_ARRAY() <<
+ "\n";
+ }
+
+ if ( redFsm->anyFromStateActions() ) {
+ OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActionLoc), FSA() );
+ FROM_STATE_ACTIONS();
+ CLOSE_ARRAY() <<
+ "\n";
+ }
+
+ if ( redFsm->anyEofActions() ) {
+ OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActionLoc), EA() );
+ EOF_ACTIONS();
+ CLOSE_ARRAY() <<
+ "\n";
+ }
+
+ STATE_IDS();
+
+ out << "exception Goto_again" << TOP_SEP();
+}
+
+void OCamlFGotoCodeGen::writeExec()
+{
+ testEofUsed = false;
+ outLabelUsed = false;
+
+ out << " begin\n";
+
+ if ( redFsm->anyRegCurStateRef() )
+ out << " let _ps = ref 0 in\n";
+
+ if ( redFsm->anyConditions() )
+ out << " let _widec : " << WIDE_ALPH_TYPE() << " = ref 0 in\n";
+
+ out << "\n";
+ out << "\tlet rec do_start () =\n";
+ if ( !noEnd ) {
+ testEofUsed = true;
+ out <<
+ " if " << P() << " = " << PE() << " then\n"
+ " do_test_eof ()\n"
+ "\telse\n";
+ }
+
+ if ( redFsm->errState != 0 ) {
+ outLabelUsed = true;
+ out <<
+ " if " << vCS() << " = " << redFsm->errState->id << " then\n"
+ " do_out ()\n"
+ "\telse\n";
+ }
+ out << "\tdo_resume ()\n";
+
+ out << "and do_resume () =\n";
+
+ if ( redFsm->anyFromStateActions() ) {
+ out <<
+ " begin match " << AT(FSA(),vCS()) << " with\n";
+ FROM_STATE_ACTION_SWITCH();
+ SWITCH_DEFAULT() <<
+ " end;\n"
+ "\n";
+ }
+
+ out <<
+ " begin match " << vCS() << " with\n";
+ STATE_GOTOS();
+ SWITCH_DEFAULT() <<
+ " end\n"
+ "\n";
+ TRANSITIONS() <<
+ "\n";
+
+ if ( redFsm->anyRegActions() )
+ EXEC_ACTIONS() << "\n";
+
+ out << "\tand do_again () =\n";
+
+ if ( redFsm->anyToStateActions() ) {
+ out <<
+ " begin match " << AT(TSA(), vCS()) << " with\n";
+ TO_STATE_ACTION_SWITCH();
+ SWITCH_DEFAULT() <<
+ " end;\n"
+ "\n";
+ }
+
+ if ( redFsm->errState != 0 ) {
+ outLabelUsed = true;
+ out <<
+ " match " << vCS() << " with\n" <<
+ " | " << redFsm->errState->id << " -> do_out ()\n"
+ " | _ ->\n";
+ }
+
+ out << "\t" << P() << " <- " << P() << " + 1;\n";
+
+ if ( !noEnd ) {
+ out <<
+ " if " << P() << " <> " << PE() << " then\n"
+ " do_resume ()\n"
+ "\telse do_test_eof ()\n";
+ }
+ else {
+ out <<
+ " do_resume ()\n";
+ }
+
+// if ( testEofUsed )
+ out << "and do_test_eof () =\n";
+
+ if ( redFsm->anyEofTrans() || redFsm->anyEofActions() ) {
+ out <<
+ " if " << P() << " = " << vEOF() << " then\n"
+ " begin\n";
+
+ if ( redFsm->anyEofTrans() ) {
+ out <<
+ " match " << vCS() << " with\n";
+
+ for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
+ if ( st->eofTrans != 0 )
+ out << " | " << st->id << " -> tr" << st->eofTrans->id << " ()\n";
+ }
+
+ SWITCH_DEFAULT() << ";\n"; // fall through
+ }
+
+ if ( redFsm->anyEofActions() ) {
+ out <<
+ " try match " << AT(EA(), vCS()) << " with\n";
+ EOF_ACTION_SWITCH();
+ SWITCH_DEFAULT() <<
+ " \n"
+ " with Goto_again -> do_again () \n";
+ }
+
+ out <<
+ " end\n"
+ "\n";
+ }
+ else
+ out << "\t()\n";
+
+ if ( outLabelUsed )
+ out << "\tand do_out () = ()\n";
+
+ out << "\tin do_start ()\n";
+ out << " end;\n";
+}
diff --git a/ragel/mlfgoto.h b/ragel/mlfgoto.h
new file mode 100644
index 0000000..f361985
--- /dev/null
+++ b/ragel/mlfgoto.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2001-2006 Adrian Thurston <thurston at complang.org>
+ * 2004 Erich Ocean <eric.ocean at ampede.com>
+ * 2005 Alan West <alan at alanz.com>
+ */
+
+/* This file is part of Ragel.
+ *
+ * Ragel is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Ragel is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Ragel; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _MLFGOTO_H
+#define _MLFGOTO_H
+
+#include <iostream>
+#include "mlgoto.h"
+
+/*
+ * class OCamlFGotoCodeGen
+ */
+class OCamlFGotoCodeGen : virtual public OCamlGotoCodeGen
+{
+public:
+ OCamlFGotoCodeGen( const CodeGenArgs &args ) : OCamlCodeGen(args), OCamlGotoCodeGen(args) {}
+
+ std::ostream &EXEC_ACTIONS();
+ std::ostream &TO_STATE_ACTION_SWITCH();
+ std::ostream &FROM_STATE_ACTION_SWITCH();
+ std::ostream &FINISH_CASES();
+ std::ostream &EOF_ACTION_SWITCH();
+ unsigned int TO_STATE_ACTION( RedStateAp *state );
+ unsigned int FROM_STATE_ACTION( RedStateAp *state );
+ unsigned int EOF_ACTION( RedStateAp *state );
+
+ virtual void writeData();
+ virtual void writeExec();
+};
+
+#endif
diff --git a/ragel/reducedgen.cc b/ragel/reducedgen.cc
index 132a128..c857049 100644
--- a/ragel/reducedgen.cc
+++ b/ragel/reducedgen.cc
@@ -63,6 +63,7 @@
#include "mlflat.h"
#include "mlfflat.h"
#include "mlgoto.h"
+#include "mlfgoto.h"

#include "rubytable.h"
#include "rubyftable.h"
@@ -374,8 +375,11 @@ CodeGenData *ocamlMakeCodeGen( const CodeGenArgs &args )
case GenGoto:
codeGen = new OCamlGotoCodeGen(args);
break;
+ case GenFGoto:
+ codeGen = new OCamlFGotoCodeGen(args);
+ break;
default:
- cerr << "I only support the -T0 -T1 -F0 -F1 and -G0 output styles for OCaml.\n";
+ cerr << "I only support the -T0 -T1 -F0 -F1 -G0 and -G1 output styles for OCaml.\n";
exit(1);
}
--
1.7.10
ygrek
2012-06-18 20:48:32 UTC
Permalink
---
doc/ragel-guide.tex | 48 ++++++++++++++++++++++++++++--------------------
ragel/main.cc | 8 ++++----
2 files changed, 32 insertions(+), 24 deletions(-)

diff --git a/doc/ragel-guide.tex b/doc/ragel-guide.tex
index 0bc0f8e..720d4b2 100644
--- a/doc/ragel-guide.tex
+++ b/doc/ragel-guide.tex
@@ -101,7 +101,7 @@ maximally continuous. One is free to specify an entire parser using a single
regular expression. The single-expression model affords concise and elegant
descriptions of languages and the generation of very simple, fast and robust
code. Ragel compiles executable finite state machines from a high level regular language
-notation. Ragel targets C, C++, Objective-C, D, Go, Java and Ruby.
+notation. Ragel targets C, C++, Objective-C, D, Go, Java, Ruby and OCaml.

In addition to building state machines from regular expressions, Ragel allows
the programmer to directly specify state machines with state charts. These two
@@ -166,7 +166,7 @@ deterministic finite state automaton. Since every regular language has a state
machine representation and vice versa, the terms regular language and state
machine (or just machine) will be used interchangeably in this document.

-Ragel outputs machines to C, C++, Objective-C, D, Go, Java or Ruby code. The output is
+Ragel outputs machines to C, C++, Objective-C, D, Go, Java, Ruby or OCaml code. The output is
designed to be generic and is not bound to any particular input or processing
method. A Ragel machine expects to have data passed to it in buffer blocks.
When there is no more input, the machine can be queried for acceptance. In
@@ -2343,7 +2343,7 @@ stream. These can live in any scope. Control of the input processing loop is
also possible: the user may break out of the processing loop and return to it
at any time.

-In the case of the C, D, and Go host languages, Ragel is able to generate very
+In the case of the C, D, Go, OCaml host languages, Ragel is able to generate very
fast-running code that implements state machines as directly executable code.
Since very large files strain the host language compiler, table-based code
generation is also supported. In the future we hope to provide a partitioned,
@@ -2403,7 +2403,7 @@ int main( int argc, char **argv )

There are a number of variables that Ragel expects the user to declare. At a
very minimum the \verb|cs|, \verb|p| and \verb|pe| variables must be declared.
-In Go, Java and Ruby code the \verb|data| variable must also be declared. If
+In Go, Java, Ruby and OCaml code the \verb|data| variable must also be declared. If
EOF actions are used then the \verb|eof| variable is required. If
stack-based state machine control flow statements are used then the
\verb|stack| and \verb|top| variables are required. If a scanner is declared
@@ -2419,21 +2419,21 @@ execution loop, but not from within.

\item \verb|p| - Data pointer. In C/D code this variable is expected to be a
pointer to the character data to process. It should be initialized to the
-beginning of the data block on every run of the machine. In Go, Java and Ruby it is
-used as an offset to \verb|data| and must be an integer. In this case it should
+beginning of the data block on every run of the machine. In Go, Java, Ruby and OCaml
+it is used as an offset to \verb|data| and must be an integer. In this case it should
be initialized to zero on every run of the machine.

\item \verb|pe| - Data end pointer. This should be initialized to \verb|p| plus
-the data length on every run of the machine. In Go, Java and Ruby code this should
+the data length on every run of the machine. In Go, Java, Ruby and OCaml code this should
be initialized to the data length.

\item \verb|eof| - End of file pointer. This should be set to \verb|pe| when
the buffer block being processed is the last one, otherwise it should be set to
-null. In Go, Java and Ruby code \verb|-1| must be used instead of null. If the EOF
+null. In Go, Java, Ruby and OCaml code \verb|-1| must be used instead of null. If the EOF
event can be known only after the final buffer block has been processed, then
it is possible to set \verb|p = pe = eof| and run the execute block.

-\item \verb|data| - This variable is only required in Go, Java and Ruby code. It
+\item \verb|data| - This variable is only required in Go, Java, Ruby and OCaml code. It
must be an array containting the data to process.

\item \verb|stack| - This must be an array of integers. It is used to store
@@ -2447,8 +2447,8 @@ to \verb|stack|, giving the next available spot on the top of the stack.
\item \verb|act| - This must be an integer value. It is a variable sometimes
used by scanner code to keep track of the most recent successful pattern match.

-\item \verb|ts| - This must be a pointer to character data. In Go, Java and
-Ruby code this must be an integer. See Section \ref{generating-scanners} for
+\item \verb|ts| - This must be a pointer to character data. In Go, Java, Ruby and
+OCaml code this must be an integer. See Section \ref{generating-scanners} for
more information.

\item \verb|te| - Also a pointer to character data.
@@ -2465,7 +2465,8 @@ alphtype unsigned int;
The alphtype statement specifies the alphabet data type that the machine
operates on. During the compilation of the machine, integer literals are
expected to be in the range of possible values of the alphtype. The default
-is \verb|char| for all languages except Go where the default is \verb|byte|.
+is \verb|char| for all languages except Go where the default is \verb|byte| and
+OCaml where the default is \verb|int|.

\begin{multicols}{2}
C/C++/Objective-C:
@@ -2516,6 +2517,12 @@ D:
\end{verbatim}
\verbspace

+OCaml:
+\begin{verbatim}
+ int
+\end{verbatim}
+\verbspace
+
\end{multicols}

\section{Getkey Statement}
@@ -2560,7 +2567,7 @@ The variable statement specifies how to access a specific
variable. All of the variables that are declared by the user and
used by Ragel can be changed. This includes \verb|p|, \verb|pe|, \verb|eof|, \verb|cs|,
\verb|top|, \verb|stack|, \verb|ts|, \verb|te| and \verb|act|.
-In Go, Ruby and Java code generation the \verb|data| variable can also be changed.
+In Go, Ruby, Java and OCaml code generation the \verb|data| variable can also be changed.

\section{Pre-Push Statement}
\label{prepush}
@@ -2766,7 +2773,7 @@ export machine_to_export = 0x44;

When the write exports statement is used these machines are
written out in the generated code. Defines are used for C and constant integers
-are used for D, Java and Ruby. See Section \ref{import} for a description of the
+are used for D, Java, Ruby and OCaml. See Section \ref{import} for a description of the
import statement.

\section{Maintaining Pointers to Input Data}
@@ -2860,6 +2867,7 @@ language. The host-language options are:
\item \verb|-J | for Java code.
\item \verb|-R | for Ruby code.
\item \verb|-A | for C\# code.
+\item \verb|-O | for OCaml code.
\end{itemize}

\section{Choosing a Generated Code Style}
@@ -2923,17 +2931,17 @@ Code Output Style Options

\begin{tabular}{|c|c|c|}
\hline
-\verb|-T0|&binary search table-driven&C/D/Java/Ruby/C\#\\
+\verb|-T0|&binary search table-driven&C/D/Java/Ruby/C\#/OCaml\\
\hline
-\verb|-T1|&binary search, expanded actions&C/D/Ruby/C\#\\
+\verb|-T1|&binary search, expanded actions&C/D/Ruby/C\#/OCaml\\
\hline
-\verb|-F0|&flat table-driven&C/D/Ruby/C\#\\
+\verb|-F0|&flat table-driven&C/D/Ruby/C\#/OCaml\\
\hline
-\verb|-F1|&flat table, expanded actions&C/D/Ruby/C\#\\
+\verb|-F1|&flat table, expanded actions&C/D/Ruby/C\#/OCaml\\
\hline
-\verb|-G0|&goto-driven&C/D/C\#\\
+\verb|-G0|&goto-driven&C/D/C\#/OCaml\\
\hline
-\verb|-G1|&goto, expanded actions&C/D/C\#\\
+\verb|-G1|&goto, expanded actions&C/D/C\#/OCaml\\
\hline
\verb|-G2|&goto, in-place actions&C/D/Go\\
\hline
diff --git a/ragel/main.cc b/ragel/main.cc
index 6f09897..a601a61 100644
--- a/ragel/main.cc
+++ b/ragel/main.cc
@@ -127,15 +127,15 @@ void usage()
" -A The host language is C#\n"
" -O The host language is OCaml\n"
" -K The host language is Crack\n"
-"line directives: (C/D/Ruby/C#)\n"
+"line directives: (C/D/Ruby/C#/OCaml)\n"
" -L Inhibit writing of #line directives\n"
-"code style: (C/D/Java/Ruby/C#)\n"
+"code style: (C/D/Java/Ruby/C#/OCaml)\n"
" -T0 Table driven FSM (default)\n"
-"code style: (C/D/Ruby/C#)\n"
+"code style: (C/D/Ruby/C#/OCaml)\n"
" -T1 Faster table driven FSM\n"
" -F0 Flat table driven FSM\n"
" -F1 Faster flat table-driven FSM\n"
-"code style: (C/D/C#)\n"
+"code style: (C/D/C#/OCaml)\n"
" -G0 Goto-driven FSM\n"
" -G1 Faster goto-driven FSM\n"
"code style: (C/D)\n"
--
1.7.10
Loading...