7

次のように、 Ironyで PHP スタイルの変数を定義しようとしています。

variable.Rule = "$" + identifier;

$と の間にスペースを入れることが許可されていることを除いて、うまく機能しますidentifier。それを防ぎたい。どのように?

新しいカスタマイズされた端末を作成する必要がありますか? IdentifierTerminalもしそうなら、私はまだ魔法を利用することができますか?


調べてみると、実際には「 NameIncludesPrefix IdentifierTerminal」のフラグがあることがわかりますが、それは 1 か所でしか使用されていません。接頭辞がこのCompoundTokenDetailsオブジェクトに保存されているように見えます...使用方法がわかりません。編集:気にしないでください、これは行き止まりでした。これらのフラグは、変数の動作に修飾子を追加するためのものです。


これはちょっと効く...

class VariableTerminal : Terminal
{
    public VariableTerminal(string name) : base(name)
    {
    }

    public override IList<string> GetFirsts()
    {
        return new[] { "$" };
    }

    public override Token TryMatch(ParsingContext context, ISourceStream source)
    {
        if (source.PreviewChar != '$') return null;
        do
        {
            source.PreviewPosition++;
        } while (!source.EOF() && char.IsLetter(source.PreviewChar));

        var token = source.CreateToken(OutputTerminal);
        return token;
    }
}

私はそれが何でOuputTerminalあるかはよくわかりません..現在のプレビュー位置に基づいたある種の動的プロパティだと思いますか? Irony での解析方法は少し奇妙だと思います...

とにかく、これの問題は、次のコードのように構文エラーがある場合に、VariableTerminal以前に で行っていた方法ではなく、this を使用した場合です。"$" + IdentifierTerminal"

p cat

と言っていた識別子端末

予想される構文エラー: { real string $ true false ...

しかし、変数は代わりにこのエラーを返します:

無効な文字: 'c'

前のエラーの方が便利だったと思います。なぜ別のエラーが吐き出されているのかよくわかりません...代わりにそれを言うにはどうすればよいですか?

4

5 に答える 5

6

私にとっては、あなたが望むものが現在サポートされていないことは明らかです(ソースで確認してください)。間にスペースを入れない '#number' として識別されるパスカル文字(一番下)に関する議論も参照してください。

非ターミナルを使用することは、私が信じている方法ではありません。文法は本質的に機能し、トークン間に空白を含めることができます。したがって、本当に必要なのは、プロジェクト wikiのアドバイスに従うことです。ページの下部にあるカスタム ターミナルのセクションを参照し、必要に応じてターミナル クラスを拡張してください。

または、最も簡単なオプションは、プレフィックスを必須にするフラグを導入することです。クラスの拡張IdentifierTerminalとメソッドのオーバーライドTryMatch

CompoundTerminalBaseクラスでこのメソッドを見ると、TryMatchメソッドが基本的に行うことは次のとおりです。

  1. ReadPrefix (ただし、プレフィックスが見つかったかどうかは無視しない)
  2. ReadBody (本文が読み取られなかった場合は失敗します)
  3. 読み取りサフィックス

プレフィックスが見つかった場合、メソッドはフラグをReadPrefix設定します。details.Prefixしたがって、呼び出した後ReadPrefix、新しく導入された必須プレフィックスのフラグを確認したい場合があります。設定されている場合は、details.Prefixフラグも設定されているかどうかを確認できます。そうでない場合は、エラーが発生します。

幸運を :)

于 2011-03-17T13:10:23.547 に答える
3

どのバージョンの Irony を使用しているかはわかりませんが、現在のバージョンでは、AllFirstChars を使用して動作させることができました。

        var localVariable = new IdentifierTerminal(NodeType.LocalVariable);
        localVariable.AllFirstChars = "$";

お役に立てれば

于 2011-11-28T15:51:11.827 に答える
1

これが役立つかどうかわからない:

http://irony.codeplex.com/discussions/70460

したがって、2行で共有します。

  var identifier = new IdentifierTerminal("Identifier", IdFlags.NameIncludesPrefix);
  identifier.AddPrefix(Strings.AllLatinLetters, IdFlags.None);   //[a-zA-Z]([a-zA-Z0-9])

まったく同じように使用することはないと思いますが、似たようなものかもしれません。

于 2011-02-21T02:29:41.517 に答える
0
var identifier = new IdentifierTerminal("identifier", IdFlags.NameIncludesPrefix);
identifier.AddPrefix("$", IdFlags.None);

トリックを行う必要があります。

于 2011-03-17T13:12:04.240 に答える
0

これはパーサーではなくスキャナーで処理する必要があるという Jan の意見に同意します。

extraFirstChars に '$' を含めると、目的が達成されますか?

public IdentifierTerminal(string name, string extraChars, string extraFirstChars)
于 2011-03-18T19:18:53.483 に答える