如何解析转义序列

本文关键字:转义序列 何解析 | 更新日期: 2023-09-27 18:15:52

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

我特别想到了两个。

这里有一个例子,foo '''<bar baz有两个:'''<

当我现在一个字符一个字符地扫描字符串

  1. 我是否应该检测反斜杠',然后检查下一个字符是否可执行或
  2. 我是否应该检查字符,然后回头看看它之前是否有反斜杠' ?

是否有主要 (dis)优势?

如何解析转义序列

你需要知道你在哪里。实现这一点的方法是使用状态机。如果你只做'r, 't, 'n, '"'',你可以用一个非常简单的。像这样:

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();
    }
}