我在这里找到了一个在Flex中处理Python风格的INDENT / OUTDENT的好例子:http://matt.might.net/articles/standalone-lexers-with-lex/
代码为:
%{
#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
#define MAX_DEPTH 72
int nesting = 0 ;
unsigned int indent_stack[MAX_DEPTH] ;
unsigned int level = 0 ;
unsigned int first = 1 ;
void process_indent(char* line) ;
%}
PUNCT [-+*/=<>:]*
ID [A-Za-z_][A-Za-z0-9_]*
INT [0-9]+
%option noyywrap
%%
^[ ]*\n {/* Ignore blank lines. */}
^[ ]*[^ \n]+ {int last = yyleng - 1;
process_indent(yytext) ;
while ((last >= 0) &&
(yytext[last] != ' ')) {
unput(yytext[last]);
last-- ;}}
"(" {printf(" "); ECHO; nesting++ ; }
")" {printf(" "); ECHO; nesting-- ; }
{ID}|{INT}|{PUNCT} {printf(" ") ; ECHO;}
[ \r] {}
\n {}
<<EOF>> { process_indent("") ; return 0 ; }
%%
unsigned int white_count(char* line) {
unsigned int count = 0 ;
while (*line == ' ')
count++, line++ ;
return count ;
}
void process_indent(char* line) {
if (nesting)
/* Ignore indents while nested. */
return ;
unsigned int indent = white_count(line) ;
if (indent == indent_stack[level]) {
if (!first) printf(" ;") ; // EMIT END_STATEMENT
first = 0 ;
return ;
}
if (indent > indent_stack[level]) {
printf(" {") ; // EMIT BLOCK_START
assert(level+1 < MAX_DEPTH) ;
indent_stack[++level] = indent ;
return ;
}
while (indent < indent_stack[level]) {
--level ;
printf(" }") ; // EMIT BLOCK_END
}
assert(level >= 0) ;
}
int main(int argc, char* argv[]) {
indent_stack[0] = 0 ;
yylex() ;
printf("\n") ;
}
基本上,它会像这样转换代码:
def f(x):
y = x * x
e = (m * c
* c)
if x > 0:
return e
else:
return y
到此:
def f ( x ) : { y = x * x ; e = ( m * c * c ) ;
if x > 0 : { return e } else : { return y } }
哪个是正是我需要的。有一个区别:我希望词法分析器return适当的标记,而不是打印出花括号。
问题出在OUTDENT上。这在while
功能的process_indent
块中发生(意味着:可能有多个one块要“关闭”)。这意味着我将必须同时返回多个令牌-这在Lex / Flex中是不可能的。
任何想法,我如何才能改变它以使其起作用?有我需要的工作示例吗?