从Flex发出INDENT / OUTDENT令牌

问题描述 投票:1回答:1

我在这里找到了一个在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中是不可能的。

任何想法,我如何才能改变它以使其起作用?有我需要的工作示例吗?

c bison flex-lexer yacc lex
1个回答
0
投票

关于如何改变它以使其正常工作的任何想法?有没有我需要的工作示例吗?

您可以基于RE/flex随附的Python lexer示例创建代码,请参见ptokens.l。该词法分析器完全支持Python的语法规则,例如缩进块,隐式和显式的行联接,而这是process_indent()无法实现的。当多个块关闭时,将生成多个“ OUTDENT”(RE / flex“ dedent”)。

该示例要求RE / flex是Flex的更高级版本。但是RE / flex非常类似于Flex,并且接受Flex规范,因此继续进行RE / flex应该很容易。

最新问题
© www.soinside.com 2019 - 2024. All rights reserved.