Ragel 5.21 - May 9, 2007
========================
+ -Fixed an inconsistency in the value of p following an error. In the C
+ directly executable code (rlgen-cd -G2) p is left at the character where
+ the error occurred, which is correct. In all other code generators it was
+ left at the following character. This was fixed. Now in all code generators
+ p is left at the character where the error occurred.
-Bug fix: when fhold was used in scanner pattern actions which get executed
on the last character of the pattern (pattern matches which do not require
any lookahead), fhold was modifying p instead of tokend. This was fixed and
the patact.rl test was modified to cover the case.
-Fixed typos in the guide, improved the state action embedding operator
- section.
+ section and added subsections on the variable, import, and export
+ statements.
-Implemented a better solution than the pri hack for resolving the '-'
ambiguity: force a shortest match of term.
-Fixed bugs in the binary searching for condition keys in both the Ruby and
void version()
{
cout << "Ragel State Machine Compiler version " VERSION << " " PUBDATE << endl <<
- "Copyright (c) 2001-2006 by Adrian Thurston" << endl;
+ "Copyright (c) 2001-2007 by Adrian Thurston" << endl;
}
/* Total error count. */
" goto _out;\n";
}
- out << "_resume:\n";
-
if ( redFsm->errState != 0 ) {
outLabelUsed = true;
out <<
" goto _out;\n";
}
+ out << "_resume:\n";
+
if ( redFsm->anyFromStateActions() ) {
out <<
" switch ( " << FSA() << "[" << CS() << "] ) {\n";
"\n";
}
+ if ( redFsm->errState != 0 ) {
+ outLabelUsed = true;
+ out <<
+ " if ( " << CS() << " == " << redFsm->errState->id << " )\n"
+ " goto _out;\n";
+ }
+
if ( hasEnd ) {
out <<
" if ( ++" << P() << " != " << PE() << " )\n"
" goto _out;\n";
}
+ if ( redFsm->errState != 0 ) {
+ outLabelUsed = true;
+ out <<
+ " if ( " << CS() << " == " << redFsm->errState->id << " )\n"
+ " goto _out;\n";
+ }
+
out << "_resume:\n";
if ( redFsm->anyFromStateActions() ) {
"\n";
}
+ if ( redFsm->errState != 0 ) {
+ outLabelUsed = true;
+ out <<
+ " if ( " << CS() << " == " << redFsm->errState->id << " )\n"
+ " goto _out;\n";
+ }
+
if ( hasEnd ) {
out <<
" if ( ++" << P() << " != " << PE() << " )\n"
" if ( " << P() << " == " << PE() << " )\n"
" goto _out;\n";
}
-
- out << "_resume:\n";
if ( redFsm->errState != 0 ) {
outLabelUsed = true;
" goto _out;\n";
}
+ out << "_resume:\n";
+
if ( redFsm->anyFromStateActions() ) {
out <<
" _acts = " << ARR_OFF( A(), FSA() + "[" + CS() + "]" ) << ";\n"
"\n";
}
+ if ( redFsm->errState != 0 ) {
+ outLabelUsed = true;
+ out <<
+ " if ( " << CS() << " == " << redFsm->errState->id << " )\n"
+ " goto _out;\n";
+ }
+
if ( hasEnd ) {
out <<
" if ( ++" << P() << " != " << PE() << " )\n"
" goto _out;\n";
}
- out << "_resume:\n";
-
if ( redFsm->errState != 0 ) {
outLabelUsed = true;
out <<
" goto _out;\n";
}
+ out << "_resume:\n";
+
if ( redFsm->anyFromStateActions() ) {
out <<
" switch ( " << FSA() << "[" << CS() << "] ) {\n";
"\n";
}
+ if ( redFsm->errState != 0 ) {
+ outLabelUsed = true;
+ out <<
+ " if ( " << CS() << " == " << redFsm->errState->id << " )\n"
+ " goto _out;\n";
+ }
+
if ( hasEnd ) {
out <<
" if ( ++" << P() << " != " << PE() << " )\n"
" goto _out;\n";
}
+ if ( redFsm->errState != 0 ) {
+ outLabelUsed = true;
+ out <<
+ " if ( " << CS() << " == " << redFsm->errState->id << " )\n"
+ " goto _out;\n";
+ }
+
out << "_resume:\n";
if ( redFsm->anyFromStateActions() ) {
"\n";
}
+ if ( redFsm->errState != 0 ) {
+ outLabelUsed = true;
+ out <<
+ " if ( " << CS() << " == " << redFsm->errState->id << " )\n"
+ " goto _out;\n";
+ }
+
if ( hasEnd ) {
out <<
" if ( ++" << P() << " != " << PE() << " )\n"
" goto _out;\n";
}
- out << "_resume:\n";
-
if ( redFsm->errState != 0 ) {
outLabelUsed = true;
out <<
" goto _out;\n";
}
+ out << "_resume:\n";
+
if ( redFsm->anyFromStateActions() ) {
out <<
" _acts = " << ARR_OFF( A(), FSA() + "[" + CS() + "]" ) << ";\n"
"\n";
}
+ if ( redFsm->errState != 0 ) {
+ outLabelUsed = true;
+ out <<
+ " if ( " << CS() << " == " << redFsm->errState->id << " )\n"
+ " goto _out;\n";
+ }
+
if ( hasEnd ) {
out <<
" if ( ++" << P() << " != " << PE() << " )\n"
if ( hasEnd )
out << " if ( " << P() << " != " << PE() << " ) {\n";
+ if ( redFsm->errState != 0 )
+ out << " if ( " << CS() << " != " << redFsm->errState->id << " ) {\n";
+
out << " _resume: while ( true ) {\n";
out << " _again: do {\n";
- if ( redFsm->errState != 0 ) {
- out <<
- " if ( " << CS() << " == " << redFsm->errState->id << " )\n"
- " break _resume;\n";
- }
-
if ( redFsm->anyFromStateActions() ) {
out <<
" _acts = " << FSA() << "[" << CS() << "]" << ";\n"
"\n";
}
+ if ( redFsm->errState != 0 ) {
+ out <<
+ " if ( " << CS() << " == " << redFsm->errState->id << " )\n"
+ " break _resume;\n";
+ }
+
if ( hasEnd ) {
out <<
" if ( ++" << P() << " == " << PE() << " )\n"
/* Close the resume loop. */
out << " }\n";
+ /* The if guarding on the error state. */
+ if ( redFsm->errState != 0 )
+ out << " }";
+
/* The if guarding on empty string. */
if ( hasEnd )
out << " }\n";
if ( hasEnd )
out << INDENT_S() << "_out.call if " << P() << " == " << PE() ;
+ if ( redFsm->errState != 0 )
+ out << INDENT_S() << "_out.call if " << CS() << " == " << redFsm->errState->id ;
+
out << INDENT_S() << "_resume = nil"
<< INDENT_S() << "callcc { |_cc| _resume = _cc }" ;
- if ( redFsm->errState != 0)
- out << INDENT_S() << "_out.call if " << CS() << " == " << redFsm->errState->id ;
-
if ( redFsm->anyRegActions() || redFsm->anyActionGotos() ||
redFsm->anyActionCalls() || redFsm->anyActionRets() )
out << INDENT_U() << "callcc do |_again|" ;
<< INDENT_S();
}
+ if ( redFsm->errState != 0 )
+ out << INDENT_S() << "_out.call if " << CS() << " == " << redFsm->errState->id ;
+
out << INDENT_S() << P() << " += 1" ;
if ( hasEnd )
--- /dev/null
+/*
+ * @LANG: c
+ */
+
+#include <stdio.h>
+#include <string.h>
+
+%%{
+ machine foo;
+
+ action on_char { printf("char: %c\n", *p); }
+ action on_err { printf("err: %c\n", *p); }
+ action to_state { printf("to state: %c\n", *p); }
+
+ main := 'heXXX' $on_char $err(on_err) $to(to_state);
+}%%
+
+%% write data;
+
+int main()
+{
+ int cs;
+ char *p = "hello", *pe = p + strlen(p);
+ %%{
+ write init;
+ write exec;
+ }%%
+
+ printf( "rest: %s\n", p );
+
+ return 0;
+}
+
+#ifdef _____OUTPUT_____
+char: h
+to state: h
+char: e
+to state: e
+err: l
+rest: llo
+#endif
--- /dev/null
+/*
+ * @LANG: java
+ */
+
+class erract8
+{
+ %%{
+ machine erract8;
+
+ action on_char { System.out.println("char: " + data[p]); }
+ action on_err { System.out.println("err: " + data[p]); }
+ action to_state { System.out.println("to state: " + data[p]); }
+
+ main := 'heXXX' $on_char $err(on_err) $to(to_state);
+ }%%
+
+ %% write data;
+
+ static void test( char data[] )
+ {
+ int cs, p = 0, pe = data.length;
+ int top;
+
+ %% write init;
+ %% write exec;
+
+ System.out.println("rest: " + data[p] + data[p+1] + data[p+2]);
+ }
+
+ public static void main( String args[] )
+ {
+ test( "hello".toCharArray() );
+ }
+}
+
+/* _____OUTPUT_____
+char: h
+to state: h
+char: e
+to state: e
+err: l
+rest: llo
+*/
--- /dev/null
+#
+# @LANG: ruby
+#
+# Test the host language scanning for ruby.
+#
+
+%%{
+ machine erract9;
+
+ action on_char { print("char: ", data[p..p], "\n"); }
+ action on_err { print("err: ", data[p..p], "\n"); }
+ action to_state { print("to state: " , data[p..p], "\n"); }
+
+ main := 'heXXX' $on_char $err(on_err) $to(to_state);
+}%%
+
+%% write data;
+
+def run_machine( data )
+ p = 0;
+ pe = data.length
+ cs = 0
+
+ %% write init;
+ %% write exec;
+
+ print("rest: " , data[p..p+2], "\n")
+end
+
+inp = [
+ "hello\n",
+]
+
+inp.each { |str| run_machine(str) }
+
+=begin _____OUTPUT_____
+char: h
+to state: h
+char: e
+to state: e
+err: l
+rest: llo
+=end _____OUTPUT_____