私はコンパイラを作成しています。プロパティに値を設定します
public sealed class Token
{
public TokenType Type { get; private set; }
public string Lexeme { get; private set; }
public int CurrentLine { get; private set; }
public Token(TokenType type, string lexeme, int currentLine)
{
Type = type;
Lexeme = lexeme;
CurrentLine = currentLine;
}
}
TokenType
は、私は別のトークンタイプを持っている列挙型である:私はToken
定義を次のようしています。
public enum TokenType
{
// keyword
PrintKeyword,
VarKeyword,
//...
// literal
IntegerLiteral,
//...
// identifier
Identifier,
//...
}
トークナイザは、パーサーにトークンのストリームを渡し、パーサが抽象構文ツリーを生成し始めます。私の実装では、各ノードタイプに対して1つのクラスがあります。
class Operand
{
Token token { get; set; }
//Token.Type
//IntegerLiteral || Identifier
}
class Term
{
Token termOperator { get; set; }
//Token.Type
//Multiplication || Division
Operand termOperand1 { get; set; }
Operand termOperand2 { get; set; }
}
//...
ご覧のとおり、クラスの1つはOperand
で、パーサーが指定したトークンを格納します。 <OperandObjHere>.token
はIntegerLiteral
またはIdentifier
しか受け入れないように、どうすれば保護できますか?セットメソッドでそれを唯一の方法でチェックしていて、ルールと一致しない場合に例外をスローしますか?それはベストプラクティスですか?私はまた、各ノードタイプのための別のクラスを作成する方法が行くかどうか知りたいですか?
アーチに何か問題があると感じます。多分あなたのコードをより多面的にする必要があります。容認できない値をフィルタリングしようとすると奇妙に見えるからです。 –
パーサーは、タームになると思われるトークンの1つを見つけた後にのみパーサーを作成するため、不正なタームを作成することはありません。 – harold
この質問は非常に幅広く、特にこれが何か解決すべき価値があることを示す良い[mcve]がなければ([このコメント](https://stackoverflow.com/questions/45775416/restrict-values-set-to-the -property#comment78509140_45775416))。また、解決する必要がある場合は、 'Token'プロパティが基本型(例えば、"ノード ")の仮想メンバであり、各サブクラスが独自の制限を適用することができる、多態的なアプローチが優れていることに同意します。設定者または明示的なフィルタリングメカニズム(例えば、有効な値の保護されたコレクション)を介して実装されます。 –