3 * @ALLOW_GENFLAGS: -T0 -T1 -F0 -F1 -G0 -G1 -G2 -P
12 action pass { fsm->pass(fc); }
13 action buf { fsm->buf(fc); }
15 action emit_slit { fsm->token( TK_Slit ); }
16 action emit_dlit { fsm->token( TK_Dlit ); }
17 action emit_id { fsm->token( TK_Id ); }
18 action emit_integer_decimal { fsm->token( TK_IntegerDecimal ); }
19 action emit_integer_octal { fsm->token( TK_IntegerOctal ); }
20 action emit_integer_hex { fsm->token( TK_IntegerHex ); }
21 action emit_float { fsm->token( TK_Float ); }
22 action emit_symbol { fsm->token( fsm->tokBuf.data[0] ); }
23 action tokst { fsm->tokStart = fsm->col; }
25 # Single and double literals.
26 slit = ( 'L'? ( "'" ( [^'\\\n] | /\\./ )* "'" ) $buf ) >tokst %emit_slit;
27 dlit = ( 'L'? ( '"' ( [^"\\\n] | /\\./ )* '"' ) $buf ) >tokst %emit_dlit;
30 id = ( [a-zA-Z_] [a-zA-Z0-9_]* ) >tokst $buf %emit_id;
33 fract_const = digit* '.' digit+ | digit+ '.';
34 exponent = [eE] [+\-]? digit+;
35 float_suffix = [flFL];
37 ( fract_const exponent? float_suffix? |
38 digit+ exponent float_suffix? ) >tokst $buf %emit_float;
40 # Integer decimal. Leading part buffered by float.
41 integer_decimal = ( ( '0' | [1-9] [0-9]* ) [ulUL]{0,3} $buf ) %emit_integer_decimal;
43 # Integer octal. Leading part buffered by float.
44 integer_octal = ( '0' [0-9]+ [ulUL]{0,2} $buf ) %emit_integer_octal;
46 # Integer hex. Leading 0 buffered by float.
47 integer_hex = ( '0' ( 'x' [0-9a-fA-F]+ [ulUL]{0,2} ) $buf ) %emit_integer_hex;
49 # Only buffer the second item, first buffered by symbol. */
50 namesep = '::' @buf %{fsm->token( TK_NameSep );};
51 deqs = '==' @buf %{fsm->token( TK_EqualsEquals );};
52 neqs = '!=' @buf %{fsm->token( TK_NotEquals );};
53 and_and = '&&' @buf %{fsm->token( TK_AndAnd );};
54 or_or = '||' @buf %{fsm->token( TK_OrOr );};
55 mult_assign = '*=' @buf %{fsm->token( TK_MultAssign );};
56 percent_assign = '%=' @buf %{fsm->token( TK_PercentAssign );};
57 plus_assign = '+=' @buf %{fsm->token( TK_PlusAssign );};
58 minus_assign = '-=' @buf %{fsm->token( TK_MinusAssign );};
59 amp_assign = '&=' @buf %{fsm->token( TK_AmpAssign );};
60 caret_assign = '^=' @buf %{fsm->token( TK_CaretAssign );};
61 bar_assign = '|=' @buf %{fsm->token( TK_BarAssign );};
62 plus_plus = '++' @buf %{fsm->token( TK_PlusPlus );};
63 minus_minus = '--' @buf %{fsm->token( TK_MinusMinus );};
64 arrow = '->' @buf %{fsm->token( TK_Arrow );};
65 arrow_star = '->*' @buf %{fsm->token( TK_ArrowStar );};
66 dot_star = '.*' @buf %{fsm->token( TK_DotStar );};
68 # Buffer both items. *
69 div_assign = '/=' @{fsm->buf('/');fsm->buf(fc);} %{fsm->token( TK_DivAssign );};
71 # Double dot is sent as two dots.
72 dot_dot = '..' %{fsm->token('.'); fsm->buf('.'); fsm->token('.');};
74 # Three char compounds, first item already buffered. */
75 dot_dot_dot = '...' %{fsm->buf('.'); fsm->buf('.'); fsm->token( TK_DotDotDot );};
78 compound = namesep | deqs | neqs | and_and | or_or | mult_assign |
79 div_assign | percent_assign | plus_assign | minus_assign |
80 amp_assign | caret_assign | bar_assign | plus_plus | minus_minus |
81 arrow | arrow_star | dot_star | dot_dot | dot_dot_dot;
83 # Single char symbols.
85 ( punct - [./_"'] ) >tokst $buf %emit_symbol |
86 # Do not immediately buffer slash, may be start of comment.
87 '/' >tokst %{ fsm->buf('/'); fsm->token( '/' ); } |
88 # Dot covered by float.
91 # Comments and whitespace.
92 commc = '/*' @{fsm->pass('/'); fsm->pass('*');} ( any* $0 '*/' @1 ) $pass;
93 commcc = '//' @{fsm->pass('/'); fsm->pass('/');} ( any* $0 '\n' @1 ) $pass;
94 whitespace = ( any - ( 0 | 33..126 ) )+ $pass;
97 /* On EOF char, write out the non token buffer. */
98 fsm->nonTokBuf.append(0);
99 cout << fsm->nonTokBuf.data;
100 fsm->nonTokBuf.clear();
103 # Using 0 as eof. If seeingAs a result all null characters get ignored.
106 # All outside code tokens.
108 id | slit | dlit | float | integer_decimal |
109 integer_octal | integer_hex | compound | symbol );
110 nontok = ( commc | commcc | whitespace | EOF );
113 '\n' @{ fsm->line += 1; fsm->col = 1; } |
114 [^\n] @{ fsm->col += 1; } )*;
116 main := ( ( tokens | nontok )** ) & position;
121 void Scanner::init( )
124 /* A count of the number of characters in
125 * a token. Used for % sequences. */
133 int Scanner::execute( char *data, int len )
137 char *pe = data + len;
140 if ( cs == Scanner_error )
142 if ( cs >= Scanner_first_final )
147 int Scanner::finish( )
150 if ( cs == Scanner_error )
152 if ( cs >= Scanner_first_final )
157 void Scanner::token( int id )
160 if ( nonTokBuf.length > 0 ) {
162 cout << nonTokBuf.data;
168 cout << '<' << id << '>' << tokBuf.data;
183 void Buffer::upAllocate( int len )
186 data = (char*) malloc( len );
188 data = (char*) realloc( data, len );
192 void test( char *buf )
194 Scanner scanner(cout);
196 scanner.execute( buf, strlen(buf) );
198 /* The last token is ignored (because there is no next token). Send
199 * trailing null to force the last token into whitespace. */
201 if ( scanner.execute( &eof, 1 ) <= 0 ) {
202 cerr << "cppscan: scan failed" << endl;
215 "/* Construct an fsmmachine from a graph. */\n"
216 "RedFsmAp::RedFsmAp( FsmAp *graph, bool complete )\n"
220 " assert( sizeof(RedTransAp) <= sizeof(TransAp) );\n"
222 " reduceMachine();\n"
226 " /* Get the transition that we want to extend. */\n"
227 " RedTransAp *extendTrans = list[pos].value;\n"
229 " /* Look ahead in the transition list. */\n"
230 " for ( int next = pos + 1; next < list.length(); pos++, next++ ) {\n"
231 " if ( ! keyOps->eq( list[pos].highKey, nextKey ) )\n"
249 #ifdef _____OUTPUT_____
254 /* Construct an fsmmachine from a graph. */
255 <195>RedFsmAp<197>::<195>RedFsmAp<40>( <195>FsmAp <42>*<195>graph<44>, <195>bool <195>complete <41>)
257 <195>graph<40>(<195>graph<41>)<44>,
259 <195>assert<40>( <195>sizeof<40>(<195>RedTransAp<41>) <60><<61>= <195>sizeof<40>(<195>TransAp<41>) <41>)<59>;
261 <195>reduceMachine<40>(<41>)<59>;
265 /* Get the transition that we want to extend. */
266 <195>RedTransAp <42>*<195>extendTrans <61>= <195>list<91>[<195>pos<93>]<46>.<195>value<59>;
268 /* Look ahead in the transition list. */
269 <195>for <40>( <195>int <195>next <61>= <195>pos <43>+ <218>1<59>; <195>next <60>< <195>list<46>.<195>length<40>(<41>)<59>; <195>pos<212>++<44>, <195>next<212>++ <41>) <123>{
270 <195>if <40>( <33>! <195>keyOps<211>-><195>eq<40>( <195>list<91>[<195>pos<93>]<46>.<195>highKey<44>, <195>nextKey <41>) <41>)
273 <195>return <195>false<59>;