84384a9ce7f02a0cb919ae11bc09a3e0fd680836
[external/ragel.git] / examples / gotocallret / gotocallret.rl
1 /*
2  * Demonstrate the use of goto, call and return. This machine expects either a
3  * lower case char or a digit as a command then a space followed by the command
4  * arg. If the command is a char, then the arg must be an a string of chars.
5  * If the command is a digit, then the arg must be a string of digits. This
6  * choice is determined by action code, rather than though transition
7  * desitinations.
8  */
9
10 #include <iostream>
11 #include <stdlib.h>
12 #include <stdio.h>
13
14 using namespace std;
15
16 struct GotoCallRet 
17 {
18         char comm;
19         int cs, top, stack[32];
20
21         int init( );
22         int execute( const char *data, int len );
23         int finish( );
24 };
25
26 %%{
27         machine GotoCallRet;
28
29         # Error machine, consumes to end of 
30         # line, then starts the main line over.
31         garble_line := (
32                 (any-'\n')*'\n'
33         ) >{cout << "error: garbling line" << endl;} @{fgoto main;};
34
35         # Look for a string of alphas or of digits, 
36         # on anything else, hold the character and return.
37         alp_comm := alpha+ $!{fhold;fret;};
38         dig_comm := digit+ $!{fhold;fret;};
39
40         # Choose which to machine to call into based on the command.
41         action comm_arg {
42                 if ( comm >= 'a' )
43                         fcall alp_comm;
44                 else 
45                         fcall dig_comm;
46         }
47
48         # Specifies command string. Note that the arg is left out.
49         command = (
50                 [a-z0-9] @{comm = fc;} ' ' @comm_arg '\n'
51         ) @{cout << "correct command" << endl;};
52
53         # Any number of commands. If there is an 
54         # error anywhere, garble the line.
55         main := command* $!{fhold;fgoto garble_line;};
56 }%%
57
58 %% write data;
59
60 int GotoCallRet::init( )
61 {
62         %% write init;
63         return 1;
64 }
65
66 int GotoCallRet::execute( const char *data, int len )
67 {
68         const char *p = data;
69         const char *pe = data + len;
70
71         %% write exec;
72         if ( cs == GotoCallRet_error )
73                 return -1;
74         if ( cs >= GotoCallRet_first_final )
75                 return 1;
76         return 0;
77 }
78
79 int GotoCallRet::finish( )
80 {
81         %% write eof;
82         if ( cs == GotoCallRet_error )
83                 return -1;
84         if ( cs >= GotoCallRet_first_final )
85                 return 1;
86         return 0;
87 }
88
89 #define BUFSIZE 1024
90
91 int main()
92 {
93         char buf[BUFSIZE];
94
95         GotoCallRet gcr;
96         gcr.init();
97         while ( fgets( buf, sizeof(buf), stdin ) != 0 ) {
98                 gcr.execute( buf, strlen(buf) );
99         }
100         if ( gcr.finish() <= 0 )
101                 cerr << "gotocallret: error: parsing input" << endl;
102         return 0;
103 }