【问题标题】:How to parse an escape sequence? [closed]如何解析转义序列? [关闭]
【发布时间】:2016-10-31 17:17:46
【问题描述】:

我正在为自己的标记编写解析器,我需要处理一些转义序列,但我不确定应该选择哪种策略。

特别是我有两个想法。

这是一个示例 foo \\\<bar baz,其中有两个:\\\<

当我现在按字符扫描字符串时

  1. 我应该检测反斜杠\,然后检查下一个字符是否是可扩展字符还是
  2. 我是否应该检查该字符,然后回头看看它前面是否有反斜杠\

两者都有主要(缺点)优势吗?

【问题讨论】:

  • 写一个状态机。一个非常简单的。当您在未转义状态下看到反斜杠时,切换到转义状态。当您看到处于转义状态的反斜杠时,它就是一个反斜杠(或者如果它是一个t,它就是一个制表符——等等等等)。在解释了转义字符后,状态返回到未转义字符。这本质上是选项 #2,但考虑它的方式略有不同。
  • 您的问题应该说明您正在编写自己的标记。否则“我正在编写解析器”非常非常模棱两可。
  • 我认为您可以使用另一种方法。如果您创建一个堆栈,然后将转义字符放入其中的输入中,然后检查每次推送到堆栈。如果您发现堆栈中的元素相同您定义的项目,弹出它直到堆栈为空。
  • 选项 2 我认为可能容易出错,因为它不检查非转义字符之前的反斜杠。或者它假设单独的反斜杠应该按字面意思解释,这会导致 `\` 的一致性问题。
  • 操作,here's a quickie one。抱歉解析器摇摆不定。不抱歉。

标签: c# string parsing escaping


【解决方案1】:

你需要知道你在哪里。做到这一点的方法是状态机。如果你只做\r\t\n\"\\,你可以用一个非常简单的方法来解决。像这样(fiddle here):

public static class StringExtensions
{
    private enum UnescapeState
    {
        Unescaped,
        Escaped
    }

    public static String Unescape(this String s)
    {
        var sb = new System.Text.StringBuilder();
        UnescapeState state = UnescapeState.Unescaped;

        foreach (var ch in s)
        {
            switch (state)
            {
                case UnescapeState.Escaped:
                    switch (ch)
                    {
                        case 't':
                            sb.Append('\t');
                            break;
                        case 'n':
                            sb.Append('\n');
                            break;
                        case 'r':
                            sb.Append('\r');
                            break;

                        case '\\':
                        case '\"':
                            sb.Append(ch);
                            break;

                        default:
                            throw new Exception("Unrecognized escape sequence '\\" + ch + "'");

                        //  Finally, what about stuff like '\x0a'? That's a much more 
                        //  complicated state machine. When you see 'x' in Escaped state,
                        //  you transition to UnescapeState.HexDigit0, then either 
                        //  UnescapeState.HexDigit1 or throw an exception, etc. 
                        //  Wicked fun to write. 
                    }
                    state = UnescapeState.Unescaped;
                    break;

                case UnescapeState.Unescaped:
                    if (ch == '\\')
                    {
                        state = UnescapeState.Escaped;
                    }
                    else
                    {
                        sb.Append(ch);
                    }
                    break;
            }
        }

        if (state == UnescapeState.Escaped)
        {
            throw new Exception("Unterminated escape sequence");
        }

        return sb.ToString();
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-04-14
    • 2014-11-22
    • 2014-09-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-01
    • 1970-01-01
    相关资源
    最近更新 更多