C # Файловый поток чтения строк (Coco / R Taste) - PullRequest
1 голос
/ 26 декабря 2011

Я работаю с образцом вкуса Coco R в C #.

Я пытаюсь расширить код для записи строк, когда дается такая операция, как

write hello world

Я определил способ, в котором я могу хранить и писать строки.Я выкладываю соответствующий код для моей проблемы:

Расширенный Taste.ATG

| "write" 
    { Expr<out type>    (. if (type != integer) SemErr("integer type expected");
                            gen.Emit(Op.WRITE); .)
    | '"' 
    ident       (. name = Convert.ToString(t.val);
                            gen.Emit(Op.READS);
                            gen.Emit(Op.WRITES).)
    '"'
    }';'

Расширенные операции в CodeGen.cs: Файловый поток используется таким образом

public void Interpret (string data) { 
    int val;
    try {
        FileStream s = new FileStream(data, FileMode.Open);
        Console.WriteLine();
        pc = progStart; stack[0] = 0; top = 1; bp = 0;

и добавленные переключатели регистра, использующие файловый поток

case Op.READ:  val = ReadInt(s); Push(val); break;
case Op.READS: stackString[index] = ReadString(s) ; Push(index); index++; break;
case Op.WRITE: Console.WriteLine(Pop()); break;
case Op.WRITES: Console.WriteLine(stackString[Pop()]); break;

Проблема в том, что я нигде в Интернете не могу найти способ прочитать строку, ясно, что ReadString(s) не работаеттак же ReadInt(s) делает.Мне было интересно, могу ли я получить помощь, чтобы найти операцию, которая читает строку из потока файлов.

Я раньше не управлял файловым потоком.

1 Ответ

2 голосов
/ 27 декабря 2011

РЕДАКТИРОВАТЬ3 После повторного изучения этой проблемы я обнаружил большую проблему с этим подходом.Прежде всего, некоторые пояснения: Coco / R генерирует сканер и парсер из файла atg, основная программа в Taste.cs использует их для компиляции Taste.TAS.

Скомпилированный Taste.TAS затем передается в метод Interpret CodeGen.cs, который обрабатывает коды операций, которые он получает как виртуальная машина, поэтому этот метод ReadInt() должен считывать из Taste.IN,примеры данных для скомпилированной программы Taste.TAS.

Итак, чтобы добавить поддержку hello world в CodeGen.cs, недостаточно изменить метод Interpret, вам нужно будет исправить метод Emit.также, чтобы позволить компилятору добавить строку во время компиляции.

Hacky как всегда (идет в CodeGen.cs):

List<string> strStack = new List<string>();
public void Emit(Op op, string str)
{
    int idx = strStack.Count;
    strStack.Add(str);
    Emit(op, idx); // adds the opcode, 
}

В Taste.ATG у вас будетчтобы изменить инструкцию записи на Gen.Emit(Op.WRITES, t.val);

А в методе Interpret вам нужно будет использовать ссылку на список строк:

case Op.WRITES: Console.WriteLine(strStack[Next2()]); break;

EDIT4 - Justдля дальнейшего использования Чтобы прочитать строковый литерал из файла, вы можете использовать класс StreamReader, например, так:

    /// <summary>
    ///     Reads a string literal from a file, essentially implementing the regex pattern /\"{.*}\"/.
    ///     Ignores escape characters (for instance, "\"" will fail)
    /// </summary>
    /// <param name="fs">The file stream to read from.</param>
    /// <returns>The string literal without it's quotes upon success, null otherwise.</returns>
    static string ReadString(FileStream fs)
    {
        if (!fs.CanRead)
            return null; // cant read from stream, throw an exception here

        var reader = new StreamReader(fs);
        var sb = new StringBuilder();

        bool inString = false;

        while (true)
        {
            if (reader.Peek() < 0)
                return null; // reached EOF before string ended, throw exception here

            char ch = (char)reader.Read();

            if (inString)
                if (ch == '"')
                    break;
                else
                    sb.Append(ch);
            else
                if (ch == '"')
                    inString = true;
                else if (!char.IsWhiteSpace(ch))
                    return null; // string does not start with quote, throw exception here
        }

        return sb.ToString();
    }

Альтернативой может быть использование [Regex] [3] класс, но так как он по умолчанию работает только сстрок, требуются некоторые хитрые операции чтения и поиска для получения строк, занимающих несколько строк (если поддерживается), поэтому вы не добавляете поток файлов для остальной части программы.

...