• Non ci sono risultati.

Analizzatore lessicale Analizzatore lessicale

N/A
N/A
Protected

Academic year: 2022

Condividi "Analizzatore lessicale Analizzatore lessicale"

Copied!
25
0
0

Testo completo

(1)

Analizzatore lessicale Analizzatore lessicale

Legge la stringa in input e la trasforma in un flusso di token da sottoporre all’analizzatore sintattico.

Le frasi di un linguaggio sono stringhe di token (simboli atomici).

Richieste

Richieste per per l’analizzatorel’analizzatore lessicalelessicale::

1. Rimuovere spazi, tabulazioni, a capo, . . .

2. Raccogliere i digit in interi, in modo che nella

parsificazione i numeri siano trattati come elementi atomici: 3 + 25 – 2

<num, 3> <+, > < num, 25> <-, > < num, 2>

(2)

3. Riconoscere parole chiave e identificatori:

count = count + inc id = id + id

Per l’analisi sintattica non è importante conoscere i lessemi associati ad ogni identificatore, ma lo è per la traduzione.

Quando in input viene identificato un lessema, esso viene

memorizzato nella symbol table e il puntatore alla entry nella symbol table diventa un attributo del token id.

Le parole chiave di solito soddisfano le regole per la costruzione degli identificatori, quindi serve un meccanismo per decidere quando un lessema forma una parola chiave o un identificatore.

È più facile se le parole chiave sono riservate: un lessema è un id solo se non è una keyword.

(3)

input

lettura di un carattere

Analizzatore

lessicale Parsificatore

ritorno indietro

di un carattere token e attributi

L’analizzatore lessicale e il parsificatore formano una coppia produttore – consumatore: l’analizzatore produce i token e il parsificatore li consuma.

Come dimensionare il buffer?

Di solito il buffer contiene un token: l’interazione può essere implementata con una chiamata da parte del parsificatore della procedura di analisi lessicale, che ritorna i token su richiesta.

(4)

Anche per l’input di solito viene usato un buffer in cui viene letto un blocco di caratteri alla volta.

Analizzatore Analizzatore

lessicale lessicale

ritorno indietro di un carattere

lettura di un

carattere Restituzione di un

token al chiamante

tokenval tokenval

Variabile globale che contiene il valore dell’attributo

L’analizzatore restituisce la codifica del token, di solito un numero maggiore della codifica dei caratteri (256 . . .)

(5)

function lexan begin

while true do c := readcar

if c = ‘ ’ or ‘tab’ then do nothing

else if c = newline then lineno := lineno + 1

else if isdigit (c) then “costruisci il numero formato da c e dai digit successivi in tokenval”

return il token num

else if isalfa (c) then “identifica c e lettere e digit successivi come lessema”

“aggiorna la symbol table”

. . .

return il token id

else tokenval := NONE return c

end

(6)

function lexan begin

while true do c := readchar

if c = ‘ ‘ or ‘tab’ then do nothing

else if c = newline then lineno := lineno + 1 else if isdigit (c)

then tokenval := c c := readchar

while isdigit (c) do

tokenval := tokenval * 10 + c c := readchar

c := prechar return num . . .

(7)

Operazioni sulla symbol

Operazioni sulla symbol tabletable::

insert(s, t): ritorna l’indice della nuova entry per la stringa s, token t.

lookup(s): ritorna l’indice della entry per la stringa s, oppure 0 se la stringa non viene trovata.

Si può inizializzare la symbol table con le parole riservate:

Insert (“Div”, div)

(8)

esempio di implementazione:

esempio di implementazione:

ptr token attributi

0 1 2 3 4

div idid

D i v eos c o u n t eos i n c eos

(9)

function lexan

var lexbuf: array [1 . . 100] of char c: char

begin

while true do c := readchar

if c = ‘ ‘ or ‘tab’ then do nothing

else if c = newline then lineno := lineno + 1

else if isdigit (cc) then . . . . . .

return num

else if c “è una lettera”

then “metti cc e lettere e digit successivi in lexbuf”

“aggiorna la symbol table”

tokenval := il puntatore al lessema return il token id

else tokenval := NONE

return c (l’intero che codifica il carattere c) end

else if c = eof then return DONE

(10)

else if isalpha (c) then b := 0

while isalnum (c) do

lexbuf [b] := c c := readchar b := b + 1

if b >= BSIZE

then error (“errore di compilazione”) lexbuf [b] := eos

c := prechar

p := lookup (lexbuf)

if p = 0 then p := insert (lexbuf, id) tokenval := p

return symtable [p].token

(11)

Esempio

Esempio di di traduzionetraduzione

Tradurre in forma postfissa una sequenza di espressioni separate da ;

Le espressioni consistono di numeri, identificatori e degli operatori +, -, *, /, Div e Mod.

id rappresenta una sequenza non vuota di lettere e digit che iniziano con una lettera.

L’attributo lessema del token id dà la stringa di caratteri che formano il token.

L’attributo val del token num fornisce l’intero rappresentato da num.

(12)

list → E ; list list → ε

E → E + T E → E - T E → T

T → T * F T → T / F T → T div F T → T mod F T → F

F → ( E ) F → id

F → num

print (‘Mod’)

print (id.lessema) print (num.val) print (‘Div’) print (‘/’) print (‘+’)

print (‘*’) print (‘-’)

(13)

list → E ; list list → ε

E → T R’

R’ → + T R’ | - T R’

R’ → ε T → F R”

R” → * F R” | / F R”

R” → div F R”

R” → mod F R”

R” → ε F → ( E ) F → id

F → num list → E ; list

list → ε E → E + T E → E - T E → T

T → T * F T → T / F T → T div F T → T mod F T → F

F → ( E ) F → id

F → num

(14)

init init

symbol symbol

lexan lexan

parser parser

emitter emitter

error error

main

begin init parse

{termina con successo}

end

(15)

init: inizializza la symbol table con le keywordinit error

error: procedure error (m) print (lineno, m)

exit {termina senza successo}

lexan

lexan: analizzatore lessicale precedente

(16)

procedure parse begin

cc := lexan list

if cc = DONE then “successo”

end

list → E ; list { (, id, num}

list → ε {DONE}

procedure list

begin if cc = ‘(’ or cc = id or cc = num then cc := lexan

E

if cc = ‘;’ then cc := lexan

else error (“errore di sintassi”) list

else if cc = DONE then do nothing else error (“errore di sintassi”) end

(17)

procedure list

begin if cc = ‘(’ or cc = id or cc = num then cc := lexan

E

if cc = ‘;’ then cc := lexan

else error (“errore di sintassi”) list

else if cc =DONE then do nothing else error (“errore di sintassi”) end

procedure parse begin

cc := lexan list

if cc = DONE then “successo”

end

procedure parse begin

cc := lexan

while cc ≠ DONE do E

if cc = ‘;’ then cc := lexan

else error (“errore di sintassi”) {“successo”}

end

(18)

Gui(E → T R’) = {(, id, num} Gui(R’ → - T R’) = {-}

Gui(R’ → + T R’) = {+} Gui(R’ → ε ) = {;, )}

procedure E

begin if cc = ‘(’ or cc = id or cc = num then cc := lexan

T R’

else errore ( ) end

procedure R’

begin if cc = ‘+’ or ‘-’ then cc := lexan T

R’

else if cc = ‘;’ or cc = ) then do nothing else errore ( )

end

(19)

procedure E begin T

while (cc = ‘+’ or cc = ‘-’) do cc := lexan

T end

procedure T begin F

while (cc = ‘*’ or cc = ‘/’ or cc = div or cc = mod) do cc := lexan

F end

Gui(T → T R”) = {(, id, num} Gui(R” div F R”) = {div}

Gui(R” → * F R”) = {*} Gui(R” mod F R”) = {mod}

Gui(R” → / F R”) = {/} Gui(R” → ε) = {+, -, ;, )}

(20)

procedure F begin

if cc = ‘(’ then cc := lexan E

if cc = ‘)’ then cc := lexan

else error (“errore di sintassi”) else if cc = num then cc := lexan

else if cc = id then cc := lexan else error (“errore di sintassi”) end

Gui(F → (E) ) = { ( }

Gui(F → num ) = {num}

Gui(F → id ) = {id}

(21)

{print (‘Mod’)}

{print (id.lessema)}

{print (num.val)}

{print (‘Div’)}

{print (‘/’)}

{print (‘+’)}

{print (‘*’)}

{print (‘-’)}

list → E ; list list → ε

E → T R’

R’ → + T R’

R’ → - T R’

R’ → ε T → F R”

R” → * F R”

R” → / F R”

R” → div F R”

R” → mod F R”

R” → ε F → ( E ) F → id

F → num list → E ; list

list → ε E → T R’

R’ → + T R’

R’ → - T R’

R’ → ε T → F R”

R” → * F R”

R” → / F R”

R” → div F R”

R” → mod F R”

R” → ε F → ( E ) F → id

F → num

(22)

procedure E begin T

while (cc = ‘+’ or cc = ‘-’) do

cc := lexan T

end

emit (t, NONE) t := cc

var t

(23)

procedure T begin F

while (cc = ‘*’ or cc = ‘/’ or cc = div or cc = mod) do

cc := lexan F

end

emit (t, NONE) t := cc

var t

(24)

procedure F begin

if cc = ‘(’ then cc := lexan E

if cc = ‘)’ then cc := lexan

else error (“errore di sintassi”) else if cc = num then

cc := lexan else if cc = id then

cc := lexan else error (“errore di sintassi”) end

emit (num, tokenval) emit (id, tokenval)

(25)

procedure emit (t, tval) begin

if t = ‘+’ or t = ‘-’ or t = ‘*’ or t = ‘/’

then print (t)

else if t = div then print (Div) else if t = mod then print (Mod) else if t = num then print (tval)

else if t = id then print (symtable[tval].ptr) end

Riferimenti

Documenti correlati

Un'ulteriore analogia tra le due opere è costituita dalla presenza per ciascuno dei due testi di una versione latina anonima redatta a breve distanza dalla

(Science for Democracy, 2019, online), recente- mente dichiarata ammissibile dalla Commissione Europea, merita una discussione approfondita. Dal 22 luglio ha preso avvio la

It can be stated as a general axiom of international labour mobility that: “the deeper the economic integration – including obvi- ously free movement of the labour force – among a

So, the challenge for the future editions of the Challenge – and the process we wanted to start with this first edition of the Challenge – is to identify the right benchmarking

definisco il nome della funzione di parsing generata il tipo dei Token in input calc :: [Token] -&gt; T. definisco il nome della funzione da chiamare in caso

Ciò è interessante soprattutto nel caso delle funzioni: i parametri formali di una funzione sono visibili nel corpo della funzione, e quindi anche all’interno dei blocchi che

Ma se tutti i termini del nostro documento sono comuni con quelli del thesaurus (li abbiamo aggiunti al thesaurus prima di cominciare) come faremo per mettere in evidenza quelli

Non a caso, nell’impianto del QCER (CdE, 2002) la competenza grammaticale e quella lessicale sono considerate parti della competenza linguistica. Se ci basiamo sul