C#文件流读取字符串(Coco / R Taste)

时间:2011-12-26 18:38:13

标签: c# filestream cocor

我在C#中使用Coco R样本Taste。

我正在尝试扩展代码以在给出操作时编写字符串,例如

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中的扩展操作: Filestream以这种方式使用

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}}。 我想知道我是否可以帮助找到一个从文件流中读取字符串的操作。

我之前没有做过任何文件流管理。

1 个答案:

答案 0 :(得分:2)

<强> EDIT3 在再次研究这些内容之后,我发现这种方法存在更大的问题。首先解释一下:Coco / R从atg文件生成扫描器和解析器,Taste.cs中的主程序使用这些来编译Taste.TAS。

然后将编译好的Taste.TAS输入到CodeGen.cs的Interpret方法中,该方法按照虚拟机接收的操作码进行操作,因此它的ReadInt()方法应该从Taste.IN读取,其中包含示例已编译的Taste.TAS程序的数据。

因此,要在CodeGen.cs中添加对hello world的支持,仅更改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-method中,您需要使用对字符串列表的引用:

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]类,但由于它默认只适用于字符串,因此需要一些棘手的读取和搜索操作来获取跨越多行的字符串(如果支持),所以你不要为程序的其余部分提供文件流。