2

を使用して大文字と小文字を区別しない中置演算子を実現するためOperatorPrecedenceParserに、入力を前処理し、文字列リテラルで区切られたテキストとして解析しています。次に、テキスト部分を検索して、大文字にする必要がある中置演算子を探します ( に知られている演算子に準拠するためOPP)。その後、実際の解析が行われます。

私の質問は、両方のフェーズを 1 つのパーサーに結合できるかということです。私は試した

// preprocess: Parser<string,_>
// scalarExpr: Parser<ScalarExpr,_>
let filter = (preprocess .>> eof) >>. (scalarExpr .>> eof)

しかし、入力の最後で失敗し、一見scalarExpr. 入力は独立して解析できるので、 の問題preprocessだと思いますが、うまくいかないようです。これは可能ですか?scalarExpreof

参照用の他のパーサーは次のとおりです。

let stringLiteral = 
  let subString = manySatisfy ((<>) '"')
  let escapedQuote = stringReturn "\"\"" "\""
  (between (pstring "\"") (pstring "\"") (stringsSepBy subString escapedQuote)) 

let canonicalizeKeywords =
  let keywords = 
    [
      "OR"
      "AND"
      "CONTAINS"
      "STARTSWITH"
      "ENDSWITH"
    ]
  let caseInsensitiveKeywords = HashSet(keywords, StringComparer.InvariantCultureIgnoreCase)
  fun text ->
    let re = Regex(@"([\w][\w']*\w)")
    re.Replace(text, MatchEvaluator(fun m ->
      if caseInsensitiveKeywords.Contains(m.Value) then m.Value.ToUpperInvariant()
      else m.Value))

let preprocess = 
  stringsSepBy 
    ((manySatisfy ((<>) '"')) |>> canonicalizeKeywords) 
    (stringLiteral |>> (fun s -> "\"" + s + "\"")) 
4

1 に答える 1