2

コンパイラのスキャナを書いていますが、入力 " {\0} " に問題があります。私のスキャナーがすべきことは、空白をスキップし、「{」を認識し、無効な文字を認識し、「}」を認識し、空白をスキップし、eof を検出することです。代わりに、 \0 をスキップします。

私のスキャナーは、「役に立たない」文字 (「 」以下の値) をスキップするように設定されています。このため、無効な文字定数として処理される代わりに、\0 文字はスキップされます (このエラー ケースはまだ実装していませんが、いずれにせよ、このケースでは私のコードはreadCharConst(Token t)関数に取り込まれません...) . 私が知りたいのは、'\0' を単一の文字としてではなく、'\' の後に '0' が続くものとして処理するために何をすべきかということです。

ここに私の機能のいくつかがあります:

public Token next() {
    while (ch <= ' ') {
        nextCh(); // skip blanks, tabs, eols
    }
    Token t = new Token(Kind.none, line, col);
    switch (ch) {
    // cases for identifiers, numbers, meta-chars, ...
    case '\'':
     readCharConst(t);
         break; 
    default:
     error(t, Message.INVALID_CHAR, ch);
     nextCh();
     t.kind = Kind.none;
     }
     return t;
}

と:

public void nextCh() {
    try {
        ch = (char) in.read();
        if (ch == LF) { // detects new_line
            col = 0;
            line++;
        } else if (ch != EOF) { // do not increment col for EOF
            col++;
        }
    } catch (IOException e) {
        ch = EOF;
        e.printStackTrace();
    }
}

と:

private void readCharConst(Token t) {
    nextCh();
    if (ch == '\'') {
        error(t, Message.EMPTY_CHARCONST);
    } else {
        t.val = (int) ch;
        t.kind = Kind.charConst;
        nextCh();
        if (ch != '\'') {
            error(t, Message.MISSING_QUOTE);
        }
        nextCh();
    }
}

注意:すべてのエスケープシーケンスを検出し、残りをデフォルトの状態で処理するために、while (ch <= ' ')を aに置き換えることで問題を解決しました。while(ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r'|| ch == '\b' || ch == '\f' || ch == '\"' || ch == '\'' || ch == '\\')それにもかかわらず、私のコース スライドでは、\r、\n、\t は char 定数として扱われるべきであると述べています (私の意見では、シーケンスを '\' の後にチャー)。

4

1 に答える 1

0

実際、私はそれを手に入れたと思います。「\」を読むのではなく、正しい文字をスキップするだけです。これらの文字は、値が ' ' (10 進数の ASCII 値: 32) より小さいエスケープ シーケンスです。したがって、スキップする文字は'\b'(val:8)、'\t'(val:9)、'\n'(val:10)、'\f'(val:12)、'\r'(val:13) ですが、他のすべての文字は my のデフォルトのケースで処理されます。スイッチ。そのため、while を次のように変更しました。

while (ch == ' ' || ch == '\b' || ch == '\t' || ch == '\n' || ch == '\f' || ch == '\r')
// skip blanks and all esc. seq. with value < ' ' (others, like '\'' might need to be treated)          
nextCh();

実際、「\」はここでは何の関係もありません (私が入力した内容と一致しません)。これがおそらく私が反対票を投じた理由です。そのケースは、上記のエスケープ シーケンスを認識しようとしている場合にのみ、それらが入力 (たとえば、 input " '\\n' ") に明示的に表示されている必要があります。

于 2012-10-16T09:50:16.490 に答える