Tôi thường xác định quy tắc cho end_of_line. Điều này dựa trên mẹo trong http://kschiess.github.io/parslet/tricks.html để khớp với end_of_file.
class MyParser < Parslet::Parser
rule(:cr) { str("\n") }
rule(:eol?) { any.absent? | cr }
rule(:line_body) { (eol?.absent? >> any).repeat(1) }
rule(:line) { cr | line_body >> eol? }
rule(:lines?) { line.repeat (0)}
root(:lines?)
end
puts MyParser.new.parse(""" this is a line
so is this
that was too
This ends""").inspect
Rõ ràng nếu bạn muốn làm nhiều hơn với các phân tích cú pháp hơn bạn có thể đạt được với String :: split ("\ n"), bạn sẽ thay thế line_body
với một cái gì đó hữu ích :)
tôi đã nhanh chóng trả lời câu hỏi này và nhét nó lên. Tôi chỉ mặc dù tôi sẽ giải thích sai lầm tôi đã thực hiện, và cho bạn thấy làm thế nào để tránh những sai lầm của loại đó.
Đây là câu trả lời đầu tiên của tôi.
rule(:eol) { str('\n') | any.absent? }
rule(:line) { (eol.absent? >> any).repeat >> eol }
rule(:lines) { line.as(:line).repeat }
Tôi không theo quy tắc thông thường của tôi:
- Luôn chắc đếm lặp lại rõ ràng
- Bất kỳ quy tắc mà có thể phù hợp với không dây chiều dài, nên có tên kết thúc bằng một '?'
Vì vậy, cho phép áp dụng những ...
rule(:eol?) { str('\n') | any.absent? }
# as the second option consumes nothing
rule(:line?) { (eol.absent? >> any).repeat(0) >> eol? }
# repeat(0) can consume nothing
rule(:lines?) { line.as(:line?).repeat(0) }
# We have a problem! We have a rule that can consume nothing inside a `repeat`!
đây thấy lý do tại sao chúng tôi có được một vòng lặp vô hạn. Khi đầu vào được tiêu thụ, bạn chỉ kết thúc với số end of file
, khớp với eol?
và do đó line?
(vì nội dung đường có thể trống). Ở bên trong lines
'repeat
, nó giữ phù hợp mà không cần tốn bất cứ thứ gì và vòng lặp mãi mãi.
Chúng tôi cần thay đổi quy tắc đường để luôn luôn tiêu thụ thứ gì đó.
rule(:cr) { str('\n') }
rule(:eol?) { cr | any.absent? }
rule(:line_body) { (eol.absent? >> any).repeat(1) }
rule(:line) { cr | line_body >> eol? }
rule(:lines?) { line.as(:line).repeat(0) }
Bây giờ line
có để phù hợp với một cái gì đó, hoặc là một cr
(đối với dòng trống), hoặc ít nhất một ký tự tiếp theo là tùy chọn eol?
. Tất cả các repeat
đều có các vật thể tiêu thụ một thứ gì đó. Chúng tôi bây giờ là vàng.
Điều này trông giống như một giải pháp tốt đẹp. Cách giải quyết của tôi là làm việc với '\ n', và thêm một dòng mới vào chuỗi đến để ngăn chặn lỗi kết hợp ở cuối. Điều này có vẻ sạch hơn, mặc dù. Cảm ơn! – Danyel