私は作成している言語の解析段階に取り組んでおり、以下の問題があります。オペレータ優先パーザにインデントチェックを挿入するにはどうすればよいですか?
let test2 = // I'd like this to be an error.
"""
2
+ 2
"""
let result = run (spaces >>. expr) test2
val result : ParserResult<CudaExpr,unit> =
Success: Add (LitInt32 2,LitInt32 2)
私はすでに用語は、オペレータが間違ったインデントレベルにあるとき私にエラーを与えることはなく、
誤っ
2 +
2
インデントされたときに、次の例を作ることができました。私は前に解析チェックのようなものが必要です。
let operators expr i =
let f expr (s: CharStream<_>) = if i <= s.Column then expr s else pzero s
opp.TermParser <- f expr
f opp.ExpressionParser
上記の機能は、オペレータの相が構成されている方法です、あなたが見ることができるように、用語のパーサは、インデントのチェックを行う機能に包まれますが、最後の行に障害があります。
ここでは、完全なパーサーの簡略化した例を示します。
#r "../../packages/FParsec.1.0.2/lib/net40-client/FParsecCS.dll"
#r "../../packages/FParsec.1.0.2/lib/net40-client/FParsec.dll"
open FParsec
type Expr =
| V of string
| Add of Expr * Expr
let identifier = many1Satisfy2L isAsciiLetter (fun x -> isAsciiLetter x || isDigit x || x = ''') "identifier" .>> spaces |>> V
let indentations expressions (s: CharStream<_>) =
let i = s.Column
let expr_indent expr (s: CharStream<_>) =
let expr (s: CharStream<_>) = if i <= s.Column then expr s else pzero s
many1 expr s
expr_indent (expressions i) s
let expr =
let opp = new OperatorPrecedenceParser<_,_,_>()
opp.AddOperator(InfixOperator("+", spaces, 6, Associativity.Left, fun x y -> Add(x,y)))
let operators expr i =
let f (s: CharStream<_>) = if i <= s.Column then expr s else pzero s
opp.TermParser <- f
f opp.ExpressionParser
let rec expr s = indentations (operators identifier) s
expr
let test2 = // I'd like this to be an error.
"""
a
+
b
"""
let result = run (spaces >>. expr) test2
ここまでの完全なパーサはhereです。
[ユーザー状態](http://www.quanttec.com/fparsec/users-guide/parsing-with-user-state.html)を利用して、インデントレベルを式の用語を入力し、演算子や別の用語を解析するときに一貫していることを確認します。 – rmunn
私はそれを考えましたが、私はこの方法がより簡単であることを発見しました。 –