質問

Bisonマニュアルから:

  

シンプルなインタラクティブコマンドパーサー   各入力が1行の場合、   yyparseを許可するのに十分である   エラー時に1を返し、呼び出し元を持ちます   次の場合、入力行の残りを無視します   それが起こります(そしてyyparseを呼び出します   もう一度)。

これはほとんど私が望むものですが、仕事に取り掛かるのに苦労しています。基本的に、flexでエラーを検出してエラーを検出し、エラーが検出された場合は、Bisonに行全体を破棄させます。私が今持っているものは、私のコマンドがまだ実行されているので、正しく動作していません:

kbsh: ls '/home
Error: Unterminated Single Quote
admin  kbrandt  tempuser
syntax error
kbsh: 

Bisonファイル内:

commands:
     /*Empty*/ { prompt(); } |
     command { prompt(); }
    ;

command:
    error {return 1; } |
    chdir_command |
    pwd_command |
    exit_command |
    WORD arg_list {
        execute_command($1, $2);
        //printf("%s, %s\n", $1, $2); 
    } |
    WORD { execute_command($1, NULL); }
    ;

そして私のフレックス:

'   {BEGIN inQuote; }

<inQuote>\n {printf("Error: Unterminated Single Quote\n"); BEGIN(0); return(ERROR);}
役に立ちましたか?

解決

レクサーでこれらのタイプの解析エラーを処理するための簡単な解決策を見つけるとは思わない。

レクサー(flex / lex)をできるだけ愚かに保ちます。基本的なトークン(識別子、キーワードなど)のストリームを提供し、パーサー(yacc / bison)にエラー検出を行わせます。 。実際、それはあなたのアプローチを少し再構築して、あなたが望むものにぴったり合ったセットアップです...

レクサー(parser.l)で、シンプルに(eol / newline処理なし)、次のような(完全ではない)を維持します:

}%

/* I don't recall if the backslashify is required below */
SINGLE_QUOTE_STRING \'.*\'
DOUBLE_QUOTE_STRING \".*\"

%%
{SINGLE_QUOTE_STRING} {
    yylval.charstr = copy_to_tmp_buffer(yytext);  // implies a %union
    return STRING;
}
{DOUBLE_QUOTE_STRING} {
    yylval.charstr = copy_to_tmp_buffer(yytext);  // implies a %union
    return STRING;
}
\n   return NEWLINE;

次に、parser.yファイルで実際の処理をすべて行います(完全ではありません):

command:
    error NEWLINE
        { yyclearin; yyerrorok; print_the_next_command_prompt(); }
    | chdir_command STRING NEWLINE
        { do_the_chdir(<*>lt;charstr>2); print_the_next_command_prompt(); }
    | ... and so on ...

ここで注意すべき点が2つあります:

  1. NEWLINEのようなもののyacc側へのシフト。これにより、ユーザーがコマンドの実行を完了したかどうかを判断できるため、すべてをクリアしてやり直すことができます(&quot; int yywrap(){return 1;} &quot;どこかに)。フレックスで早期に検出しようとした場合、いつエラーが発生することを知っていますか?
  2. chdirは1つのコマンドではなく(サブルールであり、表示しなかった場合を除く)、chdir_command STRING(chdirの引数)になりました。これにより、パーサーが何が間違っていたかを把握できるようになり、そのディレクトリが存在しない場合などにyyerrorを実行できます。

この方法で、次のようになります(chdirがどのように見えるかを推測します):

  
    

cd 'some_directory
    構文エラー
    cd 'some_directory'
    あなたはsome_directory男にいます!

  

そして、すべてトークナイザーではなく、yaccグラマーによって処理されます。

フレックスを可能な限りシンプルに保つことで、最も柔軟性が得られることがわかりました。 :)

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top