a = char 'a'
a 剖析器會消化 a 字元,並傳回字元 a,若為其它字元則會剖析失敗。
序列剖析器
序列剖析器可組合數個剖析器,這些剖析器以do區塊組合,並依序應用這些剖析器分析,若序列中某個剖析器失敗,則整個剖析器便失敗,如下例:
openClose = do{ char '('
; char ')'
}
openClose 會先剖析 ( 字元,若剖析成功,則再剖析 ) 字元。預測剖析器
預測剖析器依掃描之首字元來選擇子剖析器,子剖析器以 <|> 運算子組合,此掃描首字元會被消化掉。
任何一個子剖析器成功,則傳回該子剖析器之值。
aORb = char 'a'
<|> char 'b'
a
b
aORb 可剖析 a 字元或 b 字元。
try 剖析器
預測剖析器可利用 <|> 運算子來建構。
testOr = string "(a)"
<|> string "(b)"
testOr 剖析器因只依掃描之首字元來選擇剖析器,而上例首字元均為 (,故無法明確選擇用那個剖析器,會出現下列錯誤。
Main> run testOr "(b)"
parse error at (line 1, column 2):
unexpected 'b'
expecting 'a'
必須用左因子分解法修改剖析器才可,如下:
testOr1 = do{ char '('
; char 'a' <|> char 'b'
; char ')'
}
若不想用左因子分解法,則可使用 try 剖析器,try 剖析器若剖析失敗,則會把消化的輸入復原。
testOr2 = try (string "(a)")
<|> string "(b)"
testOr3 = do{ try (string "(a"); char ')'; return "(a)" }
<|> string "(b)"
空條件剖析指若沒有任何剖析器可選擇,則會在沒有消化任何輸入下,成功傳回值。
parens :: Parser ()
parens = do{
char '('
;
parens ;
char ')' ;
parens
}
<|> return ()
上述剖析器可剖析以下字串
()
(())
分隔字串處理(sepBy, endBy, sepEndBy)
parsec 提供2個剖析組合子,sepBy 及 endBy,用來處理實體由分隔字串區分之串列,最常見的格式應該是csv(comma seperated values)逗號分隔值組。
這些組合子均接受兩個參數,第一個是剖析實體之組合子,另一個是剖析分隔字串之組合子,最後在無法繼續剖析時,傳回實體值之串列。
簡單的語義如下例:
x endBy _
x_x_x_x_x_ -> [x,x,x,x,x]
x sepBy _
x_x_x_x_x -> [x,x,x,x,x]
x sepEndBy _
x_x_x_x_x_ -> [x,x,x,x,x]
x_x_x_x_x -> [x,x,x,x,x]
xa_ -> [x] a 並非 x 可剖析,故傳回一個 a。
num endBy . 接受下列字串並傳回:
1. -> [1]
1.1. -> [1,1]
1.1.2. -> [1,1,2]
letter sepEndBy ,
"" -> []
a -> [a]
a, -> [a]
a,b -> [a,b]
a,b, -> [a,b]
ab -> [a]
parens ;
char ')' ;
parens
}
<|> return ()
上述剖析器可剖析以下字串
()
(())
分隔字串處理(sepBy, endBy, sepEndBy)
parsec 提供2個剖析組合子,sepBy 及 endBy,用來處理實體由分隔字串區分之串列,最常見的格式應該是csv(comma seperated values)逗號分隔值組。
這些組合子均接受兩個參數,第一個是剖析實體之組合子,另一個是剖析分隔字串之組合子,最後在無法繼續剖析時,傳回實體值之串列。
簡單的語義如下例:
x endBy _
x_x_x_x_x_ -> [x,x,x,x,x]
x sepBy _
x_x_x_x_x -> [x,x,x,x,x]
x sepEndBy _
x_x_x_x_x_ -> [x,x,x,x,x]
x_x_x_x_x -> [x,x,x,x,x]
xa_ -> [x] a 並非 x 可剖析,故傳回一個 a。
num endBy . 接受下列字串並傳回:
1. -> [1]
1.1. -> [1,1]
1.1.2. -> [1,1,2]
letter sepEndBy ,
"" -> []
a -> [a]
a, -> [a]
a,b -> [a,b]
a,b, -> [a,b]
ab -> [a]
沒有留言:
張貼留言