-
Notifications
You must be signed in to change notification settings - Fork 86
/
flexexample10.l
113 lines (93 loc) · 3.11 KB
/
flexexample10.l
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
/* Example taken from the Flex documentation on multiple input buffers
Fixed the example from the documentation that assigns yyin, which is bad
practice because it changes the file stream we are currently reading
and that we should use again after the file(s) are included. Assigning
yyin should only be done when changing input without the intent to return
back to the old input.
- with global yytext, yyleng, yylineno, and yylex() using --bison:
reflex --flex --main --bison --noyywrap flexexample10.l
c++ -o flexexample10 lex.yy.cpp
./flexexample10 < flexexample10.test
- or with yyFlexLexer class:
reflex --flex --main --noyywrap flexexample10.l
c++ -o flexexample10 lex.yy.cpp
./flexexample10 < flexexample10.test
Actually, this example code from the Flex documentation can be simplified by
using Flex and reflex yypush_buffer_state() and yypop_buffer_state(), though
you may want to add some logic to that code to put a limit on the number of
files opened to prevent infinite loops on cyclic file includes:
include BEGIN(incl);
[a-z]+ ECHO;
[^a-z\n]*\n? ECHO;
<incl>[ \t]*
<incl>[^ \t\r\n]+ {
FILE *fd = fopen( yytext, "r" );
if ( ! fd )
{
fprintf( stderr, "Cannot open file %s\n", yytext );
exit( 1 );
}
yypush_buffer_state( yy_create_buffer( fd, YY_BUF_SIZE ) );
BEGIN(INITIAL);
}
<<EOF>> {
fclose(yyin);
yypop_buffer_state();
if ( ! YY_CURRENT_BUFFER )
{
yyterminate();
}
}
*/
/* the "incl" state is used for picking up the name
* of an include file
*/
%x incl
%{
#define MAX_INCLUDE_DEPTH 10
YY_BUFFER_STATE include_stack[MAX_INCLUDE_DEPTH];
int include_stack_ptr = 0;
%}
%%
include BEGIN(incl);
[a-z]+ ECHO;
[^a-z\n]*\n? ECHO;
<incl>[ \t]* /* eat the whitespace */
<incl>[^ \t\r\n]+ { /* got the include file name */
if ( include_stack_ptr >= MAX_INCLUDE_DEPTH )
{
fprintf( stderr, "Includes nested too deeply\n" );
exit( 1 );
}
include_stack[include_stack_ptr++] =
YY_CURRENT_BUFFER;
/* we should not assign yyin, because this changes the file stream we
are currently reading that we want to continue after the include!
yyin = fopen( yytext, "r" );
removed and replaced by:
FILE *fd = fopen( yytext, "r" );
*/
FILE *fd = fopen( yytext, "r" );
if ( ! fd )
{
fprintf( stderr, "Cannot open file %s\n", yytext );
exit( 1 );
}
yy_switch_to_buffer(
yy_create_buffer( fd, YY_BUF_SIZE ) );
BEGIN(INITIAL);
}
<<EOF>> {
if ( --include_stack_ptr < 0 )
{
yyterminate();
}
else
{
fclose(yyin);
yy_delete_buffer( YY_CURRENT_BUFFER );
yy_switch_to_buffer(
include_stack[include_stack_ptr] );
}
}
%%