2015-09-28 56 views
3

我還沒有找到一個例子 - 如何處理字符轉義。我發現了一個代碼示例:Sprache分析器和字符轉義

static void Main(string[] args) 
{ 
    string text = "'test \\\' text'"; 
    var result = Grammar.QuotedText.End().Parse(text); 
} 

public static class Grammar 
{ 
    private static readonly Parser<char> QuoteEscape = Parse.Char('\\'); 
    private static Parser<T> Escaped<T>(Parser<T> following) 
    { 
     return from escape in QuoteEscape 
       from f in following 
       select f; 
    } 

    private static readonly Parser<char> QuotedTextDelimiter = Parse.Char('\''); 

     private static readonly Parser<char> QuotedContent = 
      Parse.AnyChar.Except(QuotedTextDelimiter).Or(Escaped(QuotedTextDelimiter)); 

    public static Parser<string> QuotedText = (
     from lquot in QuotedTextDelimiter 
     from content in QuotedContent.Many().Text() 
     from rquot in QuotedTextDelimiter 
     select content 
     ).Token(); 
} 

它成功地解析文本,如果文本中不包含逃跑,但它不與字符轉義解析文本。

回答

2

我有一個類似的問題,使用"作爲分隔符和\作爲轉義字符解析字符串。我爲此寫了一個簡單的解析器(可能不是最優雅的解決方案),它似乎很好地工作。

你應該能夠適應它,因爲唯一的區別似乎是分隔符。

var escapedDelimiter = Parse.String("\\\"").Text().Named("Escaped delimiter"); 
var singleEscape = Parse.String("\\").Text().Named("Single escape character"); 
var doubleEscape = Parse.String("\\\\").Text().Named("Escaped escape character"); 
var delimiter = Parse.Char('"').Named("Delimiter"); 
var simpleLiteral = Parse.AnyChar.Except(singleEscape).Except(delimiter).Many().Text().Named("Literal without escape/delimiter character"); 

var stringLiteral = (from start in delimiter 
      from v in escapedDelimiter.Or(doubleEscape).Or(singleEscape).Or(simpleLiteral).Many() 
      from end in delimiter 
      select string.Concat(start) + string.Concat(v) + string.Concat(end)); 

關鍵部分是from v in ...。它首先搜索轉義分隔符,然後搜索雙轉義字符,然後搜索單個轉義字符,然後嘗試將其解析爲不帶任何轉義或分隔符的「simpleLiteral」。改變這裏的順序會導致解析錯誤(例如,如果你試圖在轉義分隔符之前解析單個轉義,你將永遠不會發現後者,對於雙重轉義和單一轉義也是如此)。 此步驟重複多次,直到發生未轉義的分隔符(from v in ...不處理未轉義的分隔符,但from end in delimiter當然會)。