【问题标题】:Parser and Lexer for Python-like language类 Python 语言的解析器和词法分析器
【发布时间】:2017-03-03 23:37:49
【问题描述】:

我一直在使用对空格敏感的词法分析器和解析器来实现类似 Python 的语法。主要目标是了解解析器和词法分析器

到目前为止,我的想法是在词法分析器阶段使空格无关紧要。例如,下面的输入将导致下面的输出。

if x:
  x
else:
  y

变成:

if x :{ x}; else :{ y};

我遇到的问题是,我不确定这对于规范解决方案是否是好的输出。人们会期望输出如下所示;一个表达式。

if x:{x} else:{y};

我也有一个解析器,但它不处理显示的输出,因为它不希望在结果和替代之间有分号。

我目前解决这个问题的想法如下:

1) 预处理令牌流并将if e: {e}; else: {e}; 形式的每个表达式转换为if e: {e} else: {e},但这似乎是一个严重的hack。

2) 在解析器阶段,我可以定义if 表达式在后件体之后有一个分号。但这对我来说似乎很难看,因为如果我也想解析单行 if's,我的解析器中的那些 if 表达式也需要另一种情况。规则看起来类似于我的解析器中显示的规则。

IF ::= if Expr : Expr else : Expr;
   |   if Expr : Expr; else : Expr;

我的问题是,lex 和解析空格敏感语言的规范方法是什么?我的方法是完全错误的,还是没有办法绕过我目前的输出?

lex.x

%{
#include <stdlib.h>
#include <stdio.h>
#include <assert.h>

#define MAX_DEPTH 10

int nesting = 0 ;
unsigned int indent_stack[MAX_DEPTH] ;
unsigned int first[MAX_DEPTH] = { 1 };
unsigned int level = 0 ;



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("EOF") ; return 0 ; }

%%

unsigned int white_count(char* line) {
  unsigned int count = 0 ;
  while (*line == ' ')
    count++, line++ ;
  return count ;
}

void process_indent(char* line) {

  unsigned int indent = white_count(line) ;


  if (nesting)
    /* Ignore indents while nested. */
    return ;

  if (indent == indent_stack[level]) {
    if (!first[level])
      printf(" ;") ;
    first[level] = 0 ;
    return ;
  }

  if (indent > indent_stack[level]) {
    printf("{") ;
    level = level + 1;
    indent_stack[level] = indent ;
    first[level] = 0;
    return ;
  }

  while (indent < indent_stack[level]) {
    level = level -1;
    if(level > 0)
      printf(" };") ;
    else
      printf("};");
  }

  assert(level >= 0) ;
}

int main(int argc, char* argv[]) {
  indent_stack[0] = 0 ;
  yylex() ;
  printf("\n") ;
}
```

【问题讨论】:

    标签: c parsing lex


    【解决方案1】:

    我不知道规范,但我所做的是以某种方式计算空格(计算空格数,或空格数/制表符大小,或制表符数或您选择使用的任何内容),然后将其作为另一位数据添加到每个标记中,并在每个换行符处重置该计数。

    然后,当我解析内容时,我可以告诉我的 if 语句期望 else 语句的缩进 == if.indent 等。

    我也曾经将缩进作为自己的标记,它也可以工作。真的取决于你的语言还有什么其他语法。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-01-30
      • 2013-01-31
      • 1970-01-01
      • 1970-01-01
      • 2011-04-07
      • 2020-01-17
      • 1970-01-01
      • 2012-03-14
      相关资源
      最近更新 更多