Nếu bạn chỉ nói về biểu thức thông thường từ một quan điểm lý thuyết, có ba cấu trúc:
ab # concatenation
a|b # alternation
a* # repetition or Kleene closure
gì sau đó bạn có thể chỉ cần làm:
- tạo ra một quy tắc
S -> (fullRegex)
- cho mỗi cụm từ lặp lại
(x)*
trong fullRegex
tạo quy tắc X -> x X
và X -> ε
, sau đó thay thế (x)*
bằng X
.
- cho mỗi thay đổi luân phiên
(a|b|c)
tạo các quy tắc Y -> a
, Y -> b
và Y -> c
, sau đó thay thế (a|b|c)
với Y
Chỉ cần lặp lại này một cách đệ quy (lưu ý rằng tất cả x,
a
, b
và c
vẫn có thể được biểu thức thông thường phức tạp). Lưu ý rằng tất nhiên bạn phải sử dụng số nhận dạng duy nhất cho mỗi bước.
Điều này là đủ. Điều này chắc chắn sẽ không cung cấp cho ngữ pháp thanh lịch hoặc hiệu quả nhất, nhưng đó là những gì bình thường hóa (và nó nên được thực hiện trong một bước riêng biệt và có well-defined steps để làm điều này).
Một ví dụ: a(b|cd*(e|f)*)*
S -> a(b|cd*(e|f)*)*
S -> a X1; X1 -> (b|cd*(e|f)*) X1; X1 -> ε
S -> a X1; X1 -> Y1 X1; X1 -> ε; Y1 -> b; Y1 -> cd*(e|f)*
S -> a X1; X1 -> Y1 X1; X1 -> ε; Y1 -> b; Y1 -> c X2 (e|f)*; X2 -> d X2; X2 -> ε
... and a few more of those steps, until you end up with:
S -> a X1
X1 -> Y1 X1
X1 -> ε
Y1 -> b
Y1 -> c X2 X3
X2 -> d X2
X2 -> ε
X3 -> Y2 X3
X3 -> ε
Y2 -> e
Y2 -> f
Nguồn
2012-10-30 13:38:36
tôi hy vọng bạn đang đùa khi bạn yêu cầu chúng tôi cho toàn bộ một phác thảo cho các thuật toán. Như bạn có thể nhận thấy rằng sẽ có rất nhiều công việc. Nếu bạn có câu hỏi cụ thể về một vấn đề cụ thể, vui lòng hỏi, nhưng đừng yêu cầu chúng tôi thiết kế mã của bạn cho bạn. – Jasper
Không nên cfg của bạn là 'S -> a S; S -> b S; S -> epsilon'? Tôi nghĩ chuỗi duy nhất mà cfg cung cấp của bạn sẽ khớp là "" vì không có chuỗi nào khác mà nó chấp nhận là hữu hạn. – Wug
Điều này cũng thực sự phụ thuộc vào yếu tố cú pháp regex nào bạn muốn cho phép? Chỉ có regex theo nghĩa lý thuyết? Hoặc regex theo nghĩa mở rộng, trong đó nó được sử dụng trong hầu hết các động cơ? –