Tôi đang cố gắng phân tích một ngôn ngữ rất đơn giản chỉ bao gồm các số thập phân hoặc số nhị phân. Ví dụ: dưới đây là một số thông tin nhập hợp lệ:Tại sao dường như toán tử Parsec Choice phụ thuộc vào thứ tự của các trình phân tích cú pháp?
#b1
#d1
#b0101
#d1234
Tôi gặp sự cố khi sử dụng toán tử lựa chọn của Parsec: <|>
. Theo hướng dẫn: Write yourself a Scheme in 48 hours:
[Toán tử lựa chọn] thử trình phân tích cú pháp đầu tiên, nếu không, hãy thử trình phân tích thứ hai. Nếu một trong hai thành công, thì nó trả về giá trị được trả về bởi trình phân tích cú pháp đó.
Nhưng theo kinh nghiệm của tôi, tôi thấy thứ tự của các trình phân tích cú pháp đã cung cấp vấn đề. Đây là chương trình của tôi:
import System.Environment
import Text.ParserCombinators.Parsec
main :: IO()
main = do
(x:_) <- getArgs
putStrLn ("Hello, " ++ readExp x)
bin :: Parser String
bin = do string "#b"
x <- many(oneOf "01")
return x
dec :: Parser String
dec = do string "#d"
x <- many(oneOf "")
return x
-- Why does order matter here?
parseExp = (bin <|> dec)
readExp :: String -> String
readExp input = case parse parseExp "test" input of
Left error -> "Error: " ++ show error
Right val -> "Found val" ++ show val
đây là làm thế nào tôi đang chạy chương trình:
phụ thuộc Cài đặt
$ cabal sandbox init
$ cabal install parsec
Biên soạn
$ cabal exec ghc Main
Run
$ ./Main "#d1"
Hello, Error: "test" (line 1, column 1):
unexpected "d"
expecting "#b"
$ ./Main "#b1"
Hello, Found val"1"
.210
Nếu tôi thay đổi thứ tự của các phân tích cú pháp như sau:
parseExp = (dec <|> bin)
sau đó chỉ số nhị phân được phát hiện và chương trình thất bại trong việc xác định các số thập phân.
Với các thử nghiệm mà tôi đã thực hiện, tôi thấy vấn đề này chỉ xảy ra khi một trong các trình phân tích cú pháp đã bắt đầu phân tích cú pháp đầu vào, ví dụ: nếu tìm thấy ký tự băm #
, trình phân tích cú pháp bin được kích hoạt sẽ kết thúc khi không thành công như ký tự tiếp theo được mong đợi là b
và không phải là d
. Nó có vẻ như có một số loại backtracking mà nên xảy ra, mà tôi không nhận thức được.
Đánh giá cao sự trợ giúp!
Nhưng trong trường hợp của tôi, trình phân tích cú pháp đầu tiên không thành công. Nó được kích hoạt kể từ khi ký tự đầu tiên khớp nhau, nhưng không thành công sau đó vì nó không tìm thấy ký tự được mong đợi tiếp theo. Tôi hy vọng rằng trình phân tích cú pháp tiếp theo nên được kích hoạt nhưng điều đó không xảy ra như bạn có thể thấy từ đầu ra mà tôi đã dán. – mandark
@mandark Điều này là do cách thức hoạt động của parsec. Tôi sẽ chỉnh sửa. – chi
Đáng ngạc nhiên hơn, tôi đã thấy các trình phân tích cú pháp 'attoparsec' có thể thành công hay thất bại tùy thuộc vào thứ tự của các đối số cho' <|> '. Tôi sẽ phải đặt câu hỏi của riêng mình về điều đó. – dfeuer