Vediamo il funzionamento di un analizzatore lessicale (chiamato anche Scanner)
Facciamo un'espressione di esempio:
INPUT : cout << 3+2+3;
FORMATTING PERFORMED BY SCANNER : {cout}|space|{<<}|space|{3}{+}{2}{+}{3}{;}
non l'output effettivo però.
LO SCANNER CERCA SEMPLICEMENTE RIPETUTAMENTE UN LEXEME NEL TESTO DEL PROGRAMMA SORGENTE FINO A QUANDO L'INPUT NON È ESAURITO
Lexeme è una sottostringa di input che forma una stringa di terminali valida presente nella grammatica. Ogni lessema segue uno schema che viene spiegato alla fine (la parte che il lettore può finalmente saltare)
(La regola importante è cercare il prefisso più lungo possibile che formi una stringa di terminali valida fino a quando non si incontra il successivo spazio bianco ... spiegato di seguito)
LEXEMES:
- cout
- <<
(sebbene "<" sia anche una stringa di terminale valida, ma la regola sopra menzionata deve selezionare il modello per lexeme "<<" al fine di generare il token restituito dallo scanner)
- 3
- +
- 2
- ;
TOKENS: i token vengono restituiti uno alla volta (da Scanner quando richiesto da Parser) ogni volta che Scanner trova un lessema (valido). Scanner crea, se non già presente, una voce di tabella dei simboli (avente attributi: principalmente token-category e pochi altri) , quando trova un lessema, per generarne il token
'#' denota una voce della tabella dei simboli. Ho indicato il numero del lessema nell'elenco sopra per facilità di comprensione, ma tecnicamente dovrebbe essere l'indice di record effettivo nella tabella dei simboli.
I seguenti token vengono restituiti dallo scanner al parser nell'ordine specificato per l'esempio precedente.
<identificatore, # 1>
<Operatore, # 2>
<Letterale, # 3>
<Operatore, # 4>
<Letterale, # 5>
<Operatore, # 4>
<Letterale, # 3>
<Punctuator, # 6>
Come puoi vedere la differenza, un token è una coppia a differenza del lessema che è una sottostringa di input.
E il primo elemento della coppia è la classe / categoria del token
Le classi di token sono elencate di seguito:
PAROLE CHIAVE
IDENTIFICATORI
LETTERALI
PUNTUATORI
OPERATORI
E ancora una cosa, Scanner rileva gli spazi bianchi, li ignora e non forma alcun segno per uno spazio bianco. Non tutti i delimitatori sono spazi bianchi, uno spazio bianco è una forma di delimitatore utilizzata dagli scanner per il suo scopo. Tabulazioni, Newline, Spazi, Caratteri di escape in input sono tutti chiamati collettivamente delimitatori di spazi bianchi. Pochi altri delimitatori sono ";" ',' ':' ecc, che sono ampiamente riconosciuti come lessemi che formano token.
Il numero totale di token restituiti qui è 8, tuttavia per i lessemi vengono inserite solo 6 voci nella tabella dei simboli. Anche i lessemi sono 8 in totale (vedere la definizione di lessema)
--- Puoi saltare questa parte
A ***pattern*** is a rule ( say, a regular expression ) that is used to check if a string-of-terminals is valid or not
.
If a substring of input composed only of grammar terminals is
following the rule specified by any of the listed patterns , it is
validated as a lexeme and selected pattern will identify the category
of lexeme, else a lexical error is reported due to either (i) not
following any of the rules or (ii) input consists of a bad
terminal-character not present in grammar itself.
for example :
1. No Pattern Exists : In C++ , "99Id_Var" is grammar-supported string-of-terminals but is not recognised by any of patterns hence lexical error is reported .
2. Bad Input Character : $,@,unicode characters may not be supported as a valid character in few programming languages.`