Grammatiche ambigue

Da testwiki.
Versione del 2 lug 2021 alle 09:13 di 79.36.113.90 (discussione)
(diff) ← Versione meno recente | Versione attuale (diff) | Versione più recente → (diff)
Vai alla navigazione Vai alla ricerca

Template:Risorsa

Una grammatica è detta ambigua se genera stringhe uguali tramite almeno due derivazioni differenti (quindi due alberi di derivazione diversi). Per meglio specificare, questa ambiguità è detta ambiguità sintattica. Solitamente una grammatica ambigua risulta più sintetica, ma presenta problemi spiegati successivamente.

Definizioni

Esempio di albero che deriva una proposizione ambigua

Il grado di ambiguità di una proposizione x su un linguaggio L(G) è il numero di alberi di derivazione distinti che producono x sulla grammatica G (eventualmente infiniti).

Il grado di ambiguità di una grammatica G è il massimo tra i gradi di ambiguità delle proposizioni che compongono il linguaggio L(G).

Il problema di decidere se una grammatica è ambigua o no, è un problema indecidibile: non esiste un algoritmo che termini in un numero finito di passi con una risposta è decidibile/non è decidibile. L'assenza di ambiguità può essere però mostrata attraverso ragionamenti induttivi, permettendo così di analizzare un numero finiti di casi. Viceversa la presenza di ambiguità può essere dimostrata mostrando un caso d'esempio (detto witness).

Tipi di ambiguità

Nelle seguenti sezioni presentiamo alcune tipologie di ambiguità spesso ricorrenti e ne mostriamo un'idea di risoluzione per eliminare l'ambiguità delle stesse.

Ambiguità da ricorsione bilaterale

Una grammatica nella forma AA...A è ambigua. Esempio:

AAbA|c
cbcbc può essere generato in due modi:
  • AAbAAbcAbAbccbAbccbcbc
  • AAbAAbAbAcbAbAcbcbAcbcbc

La grammatica dell'esempio sopra può essere riscritta in formato non ambiguo nei seguenti modi:

AcbA|c
AAbc|c

Ambiguità dall'unione di linguaggi

Siano due linguaggi L1=L(G1),L2=L(G2) che condividono alcune proposizioni, cioè L1L2, allora la grammatica per il linguaggio L1L2 è ambigua perché ammette due distinte derivazioni xL1L2.

Ovviamente l'insieme delle proposizioni non ambigue è (L1L2)(L2L1). Questa situazione è facilmente risolvibile imponendo a priori che L1L2=.

Esempio:

G1
AAa|a
G2
AbA|aA|ε

Ambiguità dalla concatenazione di linguaggi

Similmente all'unione, la concatenazione può causare ambiguità. Questo avviene quando il suffisso di qualche preposizione del primo linguaggio è prefisso di qualche preposizione del secondo.

Formalmente: xL1,yL2 t.c. x=uvy=vz con vε, uL1 e zL2. In questo caso la grammatica G=G1G2 è ambigua per le preposizioni uvzG.

L'enunciato sopra è facilmente dimostrabile, due sono le possibili derivazioni:

SS1S2 + uS2 + uvz
SS1S2 + uvS2 + uvz

Un classico esempio sono la concatenazione di due linguaggi di Dyck che condividono una coppia di simboli. Per risolvere il problema è possibile inserire un nuovo simbolo terminale che agisca da separatore nell'assioma, ad esempio:

SS1#S2

Ambiguità in frasi condizionali

Questa ambiguità nasce dalla programmazione di compilatori. Si prenda per esempio il classico problema di annidiare clausole if-then di un linguaggio (questo problema è chiamato Dangling else):

S  if EXP then S else S | if EXP then S | ISTR

Non rientra in questo problema le clausole EXP e ISTR, che possiamo considerare anche terminali. Sia ora data la seguente stringa generata dalla grammatica di cui sopra:

if EXP then if EXP then ISTR else ISTR

Questa grammatica a quale sequenza di generazione corrisponde? Vediamo come possono essere applicate la parentesi graffe in stile linguaggio C:

if EXP then {
    if EXP then {
        ISTR
    } else {
        ISTR
    }
}

ma potrebbe anche essere interpretato come:

if EXP then {
    if EXP then {
        ISTR
    }
} else {
    ISTR
}

Queste due sequenze dimostrano l'ambiguità del linguaggio/grammatica.

Soluzioni

Proponiamo qui due possibili soluzioni:

  • introdurre un terminale endif:
S  if EXP then S else S endif | if EXP then S endif | ISTR
  • forzare gli annidiati ad avere else:
S  SE | ST
SE  if EXP then SE else SE | ISTR
ST  if EXP then SE else ST | if EXP then S

Ambiguità in regexp

Molte espressioni regolari sono ambigue. Si prenda un esempio banale:

a+aa*

la sua grammatica (SAaB,AaA,|BaB|ε) è evidentemente ambigua.

La soluzione all'esempio sopra è eliminare la ridondanza di a*:

a+a
SAa
AaA|a

Ambiguità per perdita di ordine

Un'altra ambiguità molto comune avviene quando una stringa può essere generata utilizzando come punto di partenza due termini di una stessa regola. Spieghiamo meglio con un esempio:

SaSb|aSbb|ε

Il problema di questa regola è che tutte le stringhe nella forma anbm con m>2 sono ambigue. Si prenda per esempio aabbb, essa può essere generata sia a partire da aSb che a partire da aSbb.

Per risolvere queste ambiguità si divide la regola imponendo così un ordine alla derivazione:

SaXb|X
XaXbb|ε

Si noti come la regola aXb non è stata inserita nella ricorsione perché non necessaria.

Altri progetti

Template:Interprogetto