5

Google Go のセミコロン挿入を flex ファイルに追加することに興味があります。

Go ドキュメントから:

セミコロン

C と同様に、Go の正式な文法ではセミコロンを使用してステートメントを終了します。C とは異なり、これらのセミコロンはソースに表示されません。代わりに、レクサーはスキャン時にセミコロンを自動的に挿入する単純なルールを使用するため、入力テキストにはセミコロンがほとんど含まれません。

ルールはこれです。改行の前の最後のトークンが識別子 (int や float64 などの単語を含む) である場合、数値や文字列定数などの基本的なリテラル、またはトークンの 1 つ

break continue fallthrough return ++ -- ) }

lexer は常にトークンの後にセミコロンを挿入します。これは、「ステートメントを終了できるトークンの後に改行が来る場合は、セミコロンを挿入する」と要約できます。

右中括弧の直前のセミコロンも省略できます。

go func() { for { dst <- <-src } }()

セミコロンは必要ありません。慣用的な Go プログラムでは、初期化子、条件、および継続要素を区切るために、 for ループ句などの場所にのみセミコロンがあります。また、コードをそのように記述する場合、1 行で複数のステートメントを区切るためにも必要です。

1 つの警告。制御構造 (if、for、switch、または select) の左中括弧を次の行に配置しないでください。これを行うと、中括弧の前にセミコロンが挿入され、望ましくない効果が生じる可能性があります。このように書きます

if i < f() {
    g()
}

このようではない

if i < f()  // wrong! 
{           // wrong!
    g()     // wrong!
}           // wrong!

これを行うにはどうすればよいですか (ストリームにトークンを挿入するにはどうすればよいですか? 一致した最後のトークンを見て、それが良いアイデアかどうかを確認するにはどうすればよいですか?

私もバイソンを使用していますが、Goはセミコロンの挿入にレクサーを使用しているようです。

4

3 に答える 3

8

必要に応じてセミコロンを挿入する関数を介してレクサー結果トークンを渡すことができます。挿入の必要性が検出されると、次のトークンを入力ストリームに戻すことができます。基本的には、次のターンで再びレクシングします。

以下は、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");}
     ;
%%

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;
  }
}

入力用

abc def
ghi
jkl;

それは印刷します

WORD: abc
WORD: def
SEMICOLON
WORD: ghi
SEMICOLON
WORD: jkl
SEMICOLON

非定数トークンを unput するには、少し余分な作業が必要です。アイデアを示すために、例を単純にしようとしました。

于 2012-06-04T21:47:28.050 に答える
1

\nおよびのレクサー規則を変更}して、レクサーによって返された最後のトークンを調べます。これには、レクサーがすべてのルールに対して返された最後のトークンを記録する必要があります。

次に、改行ルールは次のようになります。

\n   { if (newline_is_semi(last_token)) {
          return SEMICOLON;
       }
     }

newline_is_semiリストしたトークンのリストに last_token があるかどうかを確認します。

右中括弧の前のオプションのセミコロンを処理するには: '}' に一致する場合、last_token が SEMICOLON であるかどうかを確認し、そうでない場合は '}' を削除して SEMICOLON を返します。

'}'  { if (last_token != SEMICOLON) {
          unput('}');
          return SEMICOLON;
       }
     }
于 2012-06-05T15:10:17.370 に答える