C# Файловый поток чтения строк (Coco/R Taste)

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

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

напиши привет мир

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

Расширенный вкус.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 ответ

Решение

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

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

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

Хаки как всегда (идет в 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 - просто для дальнейшего использования. Чтобы прочитать строковый литерал из файла, вы можете использовать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], но поскольку он по умолчанию работает только со строками, он требует некоторых сложных операций чтения и поиска для получения строк, занимающих несколько строк (если поддерживается), поэтому вы не добавляете поток файлов для остальной части программы,

Другие вопросы по тегам