分号插入ala谷歌与flex一起去

Aar*_*ken 3 parsing lex go lexer flex-lexer

我有兴趣在我的flex文件中添加分号插入ala Google Go.

来自Go文档:

分号

与C一样,Go的正式语法使用分号来终止语句; 与C不同,这些分号不会出现在源代码中.相反,词法分析器使用一个简单的规则在扫描时自动插入分号,因此输入文本大多没有分号.

规则是这样的.如果换行符之前的最后一个标记是一个标识符(包括int和float64之类的单词),则是一个基本文字,例如数字或字符串常量,或者其中一个标记

break continue fallthrough return ++ -- ) }
Run Code Online (Sandbox Code Playgroud)

词法分析器总是在令牌后插入分号.这可以概括为"如果新行出现在可以结束语句的标记之后,则插入分号".

在结束括号之前也可以省略分号,所以语句如

go func() { for { dst <- <-src } }()
Run Code Online (Sandbox Code Playgroud)

不需要分号.Idiomatic Go程序仅在诸如for循环子句之类的地方使用分号,以分隔初始化程序,条件和继续元素.如果您以这种方式编写代码,它们也是分隔行上多个语句所必需的.

一个警告.你永远不应该把控制结构的开括号(if,for,switch或select)放在下一行.如果这样做,将在大括号之前插入分号,这可能会导致不良影响.写这样的

if i < f() {
    g()
}
Run Code Online (Sandbox Code Playgroud)

不喜欢这个

if i < f()  // wrong! 
{           // wrong!
    g()     // wrong!
}           // wrong!
Run Code Online (Sandbox Code Playgroud)

我将如何进行此操作(如何在流中插入令牌,如何查看匹配的最后一个令牌以查看它是否是一个好主意等等)?

我也在使用野牛,但Go似乎只是用他们的词法分析器插入分号.

Gun*_*her 5

您可以通过在必要时插入分号的函数传递lexer结果标记.在检测到需要插入时,可以将下一个令牌放回输入流,基本上在下一轮中再次使用它.

下面是一个在换行符之前插入SEMICOLON的示例,当它跟随WORD时.野牛文件"insert.y"是这样的:

%{
#include <stdio.h>

void yyerror(const char *str) {
  printf("ERROR: %s\n", str);
}

int main() {
  yyparse();
  return 0;
}
%} 
%union {
  char *string;
}
%token <string> WORD
%token SEMICOLON NEWLINE
%%
input: 
     | input WORD          {printf("WORD: %s\n", $2); free($2);}
     | input SEMICOLON     {printf("SEMICOLON\n");}
     ;
%%
Run Code Online (Sandbox Code Playgroud)

而lexer是由flex生成的:

%{
#include <string.h>
#include "insert.tab.h"
int f(int token);
%}
%option noyywrap
%%
[ \t]          ;
[^ \t\n;]+     {yylval.string = strdup(yytext); return f(WORD);}
;              {return f(SEMICOLON);}
\n             {int token = f(NEWLINE); if (token != NEWLINE) return token;}
%%
int insert = 0;

int f(int token) {
  if (insert && token == NEWLINE) {
    unput('\n');
    insert = 0;
    return SEMICOLON;
  } else {
    insert = token == WORD;
    return token;
  }
}
Run Code Online (Sandbox Code Playgroud)

用于输入

abc def
ghi
jkl;
Run Code Online (Sandbox Code Playgroud)

它打印

WORD: abc
WORD: def
SEMICOLON
WORD: ghi
SEMICOLON
WORD: jkl
SEMICOLON
Run Code Online (Sandbox Code Playgroud)

输出非常量令牌需要一些额外的工作 - 我试图保持这个例子简单,只是为了给出这个想法.