Se sono solo parlando di espressioni regolari da un punto di vista teorico, ci sono queste tre costrutti:
ab # concatenation
a|b # alternation
a* # repetition or Kleene closure
Che cosa si potrebbe poi basta fare:
- creare una regola
S -> (fullRegex)
- per ogni termine ripetuto
(x)*
in fullRegex
creare una regola X -> x X
e X -> ε
, quindi sostituire (x)*
con X
.
- per ogni alternanza
(a|b|c)
creare regole Y -> a
, Y -> b
e Y -> c
, quindi sostituire (a|b|c)
con Y
sufficiente ripetere questo modo ricorsivo (si noti che tutto x,
a
, b
e c
può ancora essere complesse espressioni regolari). Si noti che ovviamente è necessario utilizzare identificatori univoci per ogni passaggio.
Questo dovrebbe essere sufficiente. Questo certamente non darà la grammatica più elegante o efficiente, ma è a questo che serve la normalizzazione (e dovrebbe essere fatto in un passaggio separato e ci sono well-defined steps per farlo).
Un esempio: 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
fonte
2012-10-30 13:38:36
Spero che tu stia scherzando quando ci chiedete per un intero contorno per l'algoritmo. Come avrai notato, sarebbe stato molto lavoro. Se hai una domanda specifica su un problema specifico, non esitare a chiedere, ma non chiederci di progettare il codice in modo pratico per te. – Jasper
Non dovrebbe il tuo cfg essere 'S -> a S; S -> b S; S -> epsilon'? Penso che l'unica stringa che il tuo cfg fornito corrisponderà è "" perché nessuna altra stringa che accetta è finita. – Wug
Questo dipende molto anche dagli elementi di sintassi delle espressioni regolari che si desidera consentire? Solo regex in senso teorico? O regex nel senso esteso in cui è utilizzato nella maggior parte dei motori? –