2

ウィキペディアの補間定義 私はフレックス/バイソンを学んでいて、それを使って独自のシェルを書いています。私は変数補間を行うための良い方法を見つけようとしています。これに対する私の最初のアプローチは、ホームディレクトリの〜や$ myVarのようなものをフレックススキャンしてから、ルックアップ関数を使用して返されるものにyyval.stringを設定することでした。私の問題は、テキストが1つのトークンで表示される場合、これは役に立たないということです。

kbsh:/home/kbrandt% echo ~
/home/kbrandt
kbsh:/home/kbrandt% echo ~/foo
/home/kbrandt /foo
kbsh:/home/kbrandt%

私が変数に対して持っているlex定義:

\$[a-zA-Z/0-9_]+    {
    yylval.string=return_value(&variables, (yytext + sizeof(char)));;
    return(WORD);
}

次に、私の文法には、次のようなものがあります。

chdir_command:
    CD WORD { change_dir($2); }
    ;

この種のことを処理する良い方法を知っている人はいますか?私はこれについてすべて間違っていますか?

4

2 に答える 2

4

「従来の」シェルが変数置換などを処理する方法は、lex/yaccでは処理が困難です。それらが行うことは、マクロ展開のようなものであり、変数を展開した後、さらに変数を展開せずに入力を再トークン化します。したがって、たとえば、「foo」が「bar」として定義され、「bar」が「$y」として定義されている「xx${$ foo}」のような入力は、「xx$y」に展開されます。 1つの単語(および$ yは展開されません)。

これはフレックスで処理できますが、多くのサポートコードが必要です。flexのyy_buffer_stateのものを使用して、出力をバッファーにリダイレクトし、そこから再スキャンし、開始状態を慎重に使用して、変数を展開できる場合とできない場合を制御する必要があります。

ALPHA(1つ以上のアルファベット文字)、NUMERIC(1つ以上の数字)、WHITESPACE(1つ以上のスペースまたはタブ)などのトークンを返す非常に単純なレクサーを使用して、パーサーにそれらを適切にアセンブルさせる方がおそらく簡単です。最終的に次のようなルールになります。

simple_command: wordlist NEWLINE ;

wordlist: word | wordlist WHITESPACE word ;

word: word_frag
    | word word_frag { $$ = concat_string($1, $2); }
;

word_frag: single_quote_string
         | double_quote_string
         | variable
         | ALPHA
         | NUMERIC
        ...more options...
;

variable: '$' name { $$ = lookup($2); }
        | '$' '{' word '}' { $$ = lookup($3); }
        | '$' '{' word ':' ....

ご覧のとおり、これは非常に速く複雑になります。

于 2009-09-21T17:43:55.997 に答える
1

一般的に問題ないように見えます


何が行われているのかわかりません。単なるバッファであるため、変数名にreturn_valueなることを願っています。strdup(3)yytext

lexとparseの間の分業について質問している場合は、マクロ処理とパラメーター置換をスキャナーにプッシュし、文法にWORDs、リスト、コマンド、パイプライン、リダイレクトなどを処理させるのが完全に合理的であると確信しています。結局のところ、コードを使ってすべてを行うことは、スタイルが古く、おそらく演習の要点を打ち負かすことはできますが、十分に合理的です。

cd記号を作成したりchdir、それを文法の作成に使用したりすることは、設計上の最善の決定ではないと思います。コマンドが組み込みであるからといって、それが原則として表示される必要があるとは限りません。先に進んで、他のコマンドと同じようcdに解析します。chdir組み込みのセマンティクスを、プロダクションではなくアクションとしてチェックします。

結局のところ、シェルプロシージャとして再定義された場合はどうなるでしょうか。

于 2009-09-19T19:06:47.457 に答える