javacc
Analisi Sintattica
Nicola Fanizzi
Corso di Linguaggi di Programmazione
Dipartimento di Informatica
Università degli Studi di Bari
15 maggio 2014
Sommario
3
1
2
Introduzione
Parsing top-down
ricorsivo
Costruire un Parser
LL(1)
Specifica e prodotti
File di specifica
Metodi del parser
Costanti ed Eccezioni
Token, scanner e flusso
di input
Catena dei token
N. Fanizzi
Linguaggi di prog.+Lab
4
5
Ricorsione e Iterazione
Iterazioni
Esempi
Scelta delle produzioni
Lookahead locale
Algoritmo di scelta
Lookahead Sintattico e
Semantico
Esempi
NL_Xlator
Bowd
CSV2HTML
Calcolatore
javacc – Analisi Sintattica
15 maggio 2014
2 / 85
Introduzione
Sommario
1
Introduzione
Parsing top-down ricorsivo
Costruire un Parser LL(1)
2
Specifica e prodotti
3
Ricorsione e Iterazione
4
Scelta delle produzioni
5
Esempi
N. Fanizzi
Linguaggi di prog.+Lab
javacc – Analisi Sintattica
15 maggio 2014
3 / 85
Introduzione
Parsing I
L’analizzatore sintattico (o parser) verifica se la sequenza di
token in input costituisca un programma corretto:
Definizione (Obiettivo del Parsing)
Determinare se la stringa di token in input può essere generata da
una determinata grammatica libera da contesto
N. Fanizzi
Linguaggi di prog.+Lab
javacc – Analisi Sintattica
15 maggio 2014
4 / 85
Introduzione
Parsing II
Il generatore di parser top-down:
produce codice (Java) che si avvale del token manager
metodo getNextToken()
determina se una sequenza di token possa essere generata da
una data grammatica libera da contesto
altrimenti segnala l’errore
grammatiche LL(k)
costruendo l’albero di derivazione a partire dal simbolo iniziale
fino alle foglie (token)
N. Fanizzi
Linguaggi di prog.+Lab
javacc – Analisi Sintattica
15 maggio 2014
5 / 85
Introduzione
Parsing top-down ricorsivo
Parsing top-down ricorsivo
Grammatica con produzioni:
normalmente se la stringa
di token successiva nella
sequenza di input può
essere derivata da S
S −→ print(E);
S −→ while(E) do S
S −→ { L }
E −→ id
E −→ num
L −→ S L
L −→ parseE termina
normalmente se la stringa
di token successiva può
essere derivata da E
Implementazione
per ogni non-terminale della
grammatica, una funzione
ricorsiva:
N. Fanizzi
Linguaggi di prog.+Lab
parseS() termina
parseL termina
normalmente se la stringa
di token successiva può
essere derivata da L
javacc – Analisi Sintattica
15 maggio 2014
6 / 85
Introduzione
Parsing top-down ricorsivo
Inizializzazione e controllo token
1
Token currentToken = ParseTokenManager.getNextToken();
2
boolean checkToken(int expectedTokenType) {
if (currentToken.kind == expectedTokenType) {
5
currentToken = ParseTokenManager.getNextToken();
6
} else {
7
error("Parse error"); }
8}
3
4
N. Fanizzi
Linguaggi di prog.+Lab
javacc – Analisi Sintattica
15 maggio 2014
7 / 85
Introduzione
Parsing top-down ricorsivo
Esempio: Parse.java / I
S −→ print(E); | while ( E ) do S | { L }
void ParseS() {
switch(currentToken.kind) {
3
case ParseConstants.PRINT:
4
checkToken(ParseConstants.PRINT);
5
checkToken(ParseConstants.LEFT_PARENTHESIS);
6
ParseE();
7
checkToken(ParseConstants.RIGHT_PARENTHESIS);
8
checkToken(ParseConstants.SEMICOLON);
9
break;
10
case ParseConstants.WHILE:
11
checkToken(ParseConstants.WHILE);
12
checkToken(ParseConstants.LEFT_PARENTHESIS);
13
ParseE();
14
checkToken(ParseConstants.RIGHT_PARENTHESIS);
15
checkToken(ParseConstants.DO);
16
ParseS();
17
break;
1
2
N. Fanizzi
Linguaggi di prog.+Lab
javacc – Analisi Sintattica
15 maggio 2014
8 / 85
Introduzione
Parsing top-down ricorsivo
Esempio: Parse.java / II
case ParseConstants.LEFT_BRACE:
checkToken(ParseConstants.LEFT_BRACE);
ParseL();
checkToken(ParseConstants.RIGHT_BRACE);
break;
default:
error("Errore nella derivazione di S"); }
18
19
20
21
22
23
24
}
25
26
}
S −→ print(E); | while ( E ) do S | { L }
N. Fanizzi
Linguaggi di prog.+Lab
javacc – Analisi Sintattica
15 maggio 2014
9 / 85
Introduzione
Parsing top-down ricorsivo
Esempio: Parse.java / III
E −→ id | num
void ParseE() {
switch(currentToken.kind) {
3
case ParseConstants.ID:
4
checkToken(ParseConstants.ID);
5
break;
6
case ParseConstants.NUM:
7
checkToken(ParseConstants.NUM);
8
break;
9
default:
10
error("Errore di parsing");
11
}
12 }
1
2
N. Fanizzi
Linguaggi di prog.+Lab
javacc – Analisi Sintattica
15 maggio 2014
10 / 85
Introduzione
Parsing top-down ricorsivo
Esempio: Parse.java / IV
L −→ S L | void ParseL() {
switch(currentToken.kind) {
3
case RIGHT_BRACE: // simbolo nel FOLLOW
4
/* nessuna azione: stringa vuota */
5
break;
6
default:
7
ParseS();
8
ParseL();
9
}
10 }
1
2
N. Fanizzi
Linguaggi di prog.+Lab
javacc – Analisi Sintattica
15 maggio 2014
11 / 85
Introduzione
Costruire un Parser LL(1)
Costruire un Parser LL(1)
1
Creare una grammatica EBNF libera per il linguaggio
2
Rimuovere ambiguità, ricorsione sinistra e casi fattorizzabili
(a sinistra)
3
Determinare gli insiemi FIRST e FOLLOW
4
Costruire la tabella di parsing
5
Usare la tabella per creare la suite di funzioni che
implementano il parser
6
Convertire la grammatica in funzioni di parsing
N. Fanizzi
Linguaggi di prog.+Lab
javacc – Analisi Sintattica
15 maggio 2014
12 / 85
Specifica e prodotti
Sommario
1
Introduzione
2
Specifica e prodotti
File di specifica
Metodi del parser
Costanti ed Eccezioni
Token, scanner e flusso di input
Catena dei token
3
Ricorsione e Iterazione
4
Scelta delle produzioni
5
Esempi
N. Fanizzi
Linguaggi di prog.+Lab
javacc – Analisi Sintattica
15 maggio 2014
13 / 85
Specifica e prodotti
File di specifica
File di specifica
options{
/* codice per settare varie opzioni */
}
PARSER_BEGIN(NomeParser)
public class NomeParser {
/* segmento per la classe del parse, anche vuoto */
}
PARSER_END(NomeParser)
TOKEN_MGR_DECLS :
{
/* eventuali dichiarazioni usate dal token manager */
}
/* Espr. regolari per i token & azioni */
/* Regole sintattiche & azioni */
N. Fanizzi
Linguaggi di prog.+Lab
javacc – Analisi Sintattica
15 maggio 2014
14 / 85
Specifica e prodotti
File di specifica
Regole per il parser I
Forma tipica di una regola grammaticale JavaCC:
void nonTerminalName() : { /* Dichiarazioni Java */ }
{ /* Definizione delle regole di produzione */
}
sezione /* Dichiarazioni Java */ :
anche vuota;
usata tipicamente per inizializzare variabili,
ad es., per la costruzione di un albero di parsing astratto
sezione regole EBNF (parti destre, separate da ”|”)
Non-terminali sono seguiti da ”()”
corrispondono infatti a metodi Java
Terminali (token) compresi tra parentesi angolari < e >
es. <WHILE>, <STRINGA>, <MINORE_O_UGUALE>
possono contenere anche azione sem.: blocco di codice Java
N. Fanizzi
Linguaggi di prog.+Lab
javacc – Analisi Sintattica
15 maggio 2014
15 / 85
Specifica e prodotti
File di specifica
Regole per il parser II
Espressioni regolari ammesse:
[e] o (e)? indicano che e è opzionale
(e1 | e2 | e3 | ... )
scelta tra e1, e2, e3, ...
(e)+ una o più occorrenze di e
(e)* zero o più occorrenze di e
N. Fanizzi
Linguaggi di prog.+Lab
javacc – Analisi Sintattica
15 maggio 2014
16 / 85
Specifica e prodotti
File di specifica
Regole per il parser III
Esempio
S −→ while(E) S
S −→ V = E;
Corrispondente rappresentazione JavaCC:
S = statement; E = expression; V = variable
void statement() : {}
{
<WHILE> <LPAREN> expression() <RPAREN> statement()
| variable() <GETS> expression() <SEMICOLON>
}
N. Fanizzi
Linguaggi di prog.+Lab
javacc – Analisi Sintattica
15 maggio 2014
17 / 85
Specifica e prodotti
File di specifica
Linea di comando
Con debugging del parser:
javacc -debug_parser NomeParser.jj
javac NomeParser*.java
java NomeParser
segnala le chiamate dei metodi e l’uscita
Con debugging del token manager:
javacc -debug_token_manager NomeParser.jj
javac NomeParser*.java
java NomeParser
produce molte informazioni diagnostiche ed è tipicamente
usato per osservare il trace, un singolo token per volta
N. Fanizzi
Linguaggi di prog.+Lab
javacc – Analisi Sintattica
15 maggio 2014
18 / 85
Specifica e prodotti
File di specifica
File prodotti da JavaCC
Elaborando il file di specifica Parser1.jj, si ottengono i file:
Parser1.java
ParseException.java
Token.java
Parser1Constants.java
Parser1TokenManager.java
TokenMgrError.java
SimpleCharStream.java
Parser1.java contiene, nella classe Parser1
il codice Java fornito nel blocco PARSER_BEGIN/PARSER_END
il codice prodotto da JavaCC per la grammatica
N. Fanizzi
Linguaggi di prog.+Lab
javacc – Analisi Sintattica
15 maggio 2014
19 / 85
Specifica e prodotti
File di specifica
Esempi semplici I
PARSER_BEGIN(Simple1)
public class Simple1 {
3
public static void
4
main(String args[]) throws ParseException {
5
Simple1 parser = new Simple1(System.in);
6
parser.input();
7
}
8
}
9 PARSER_END(Simple1)
1
2
10
void input() :
{}
13 { matchedBraces() ("\n"|"\r")* <EOF> }
11
12
14
void matchedBraces() :
{}
17 { "{" [ matchedBraces() ] "}" }
15
16
non ammette spazi
N. Fanizzi
Linguaggi di prog.+Lab
javacc – Analisi Sintattica
15 maggio 2014
20 / 85
Specifica e prodotti
File di specifica
Esempi semplici II
PARSER_BEGIN(Simple2)
public class Simple2 {
3
public static void
4
main(String args[])
5
throws ParseException {
6
Simple2 parser
7
= new Simple2(System.in);
8
parser.input();
9
}
10 }
11 PARSER_END(Simple2)
1
17
2
18
void input() :
{}
21 {
22
matchedBraces() <EOF>
23 }
19
20
24
13
void matchedBraces() :
{}
27 {
28
"{" [ matchedBraces() ] "}"
29 }
14
30
12
SKIP :
{
15
" " | "\t" | "\n" | "\r"
16 }
N. Fanizzi
Linguaggi di prog.+Lab
25
26
31
32
// fine Simple2
javacc – Analisi Sintattica
15 maggio 2014
21 / 85
Specifica e prodotti
File di specifica
Esempi semplici III
1
PARSER_BEGIN(IdList)
" "
| "\t"
23 | "\n"
24 | "\r"
25 }
21
2
3
4
22
/** ID lister. */
public class IdList {
5
/** Main entry point. */
public static void
main(String args[])
throws ParseException {
IdList parser
= new IdList(System.in);
parser.Input();
}
6
7
8
9
10
11
12
13
14
15
20
28
33
/** Top level production. */
void Input() :
36 {}
37 {
38
( <Id> )+ <EOF>
39 }
35
PARSER_END(IdList)
18
19
TOKEN :
{
29
< Id: ["a"-"z","A"-"Z"]
30
( ["a"-"z","A"-"Z","0"-"9"] )*
31
>
32 }
27
34
}
16
17
26
SKIP :
{
N. Fanizzi
Linguaggi di prog.+Lab
javacc – Analisi Sintattica
15 maggio 2014
22 / 85
Specifica e prodotti
File di specifica
Esempi semplici IV
1
PARSER_BEGIN(FormaPrefissa)
public class FormaPrefissa {
3
/* segue */
4
}
5 PARSER_END(FormaPrefissa)
19
2
20
6
24
SKIP :
8{
9
" " | "\n"
10 }
7
void formula():
{}
22 {
espr() <EOF>
23 }
21
25
void espr():
{}
28 {
11
29
(<PIU> | <MENO>
12 TOKEN :
30 |
<PER> | <DIVISO>)
13 {
31
espr() espr()
14
< PIU: "+"> | < MENO: "-">
32 | <INTERO>
15 | < PER: "*"> | < DIVISO: "/"> 33 }
16 | < INTERO: (["0"-"9"])+ >
34
17 }
35
18
36 // fine FormaPrefissa
N. Fanizzi
Linguaggi di prog.+Lab
26
27
javacc – Analisi Sintattica
15 maggio 2014
23 / 85
Specifica e prodotti
File di specifica
Esempi semplici V
1
2
public static void main(String args[])
FormaPrefissa parser;
{
3
if (args.length < 1) {
System.out.print("Uso: java FormaPrefissa <nomefile>");
return;
}
try {
parser = new FormaPrefissa(new java.io.FileInputStream(args[0]));
} catch (java.io.FileNotFoundException e) {
System.out.println("File " + args[0] + " non trovato.");
return;
}
try {
parser.formula();
System.out.println("Corretta");
} catch (ParseException e) {
System.out.println(e.getMessage());
System.out.println("Errata");
}
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
}
N. Fanizzi
Linguaggi di prog.+Lab
javacc – Analisi Sintattica
15 maggio 2014
24 / 85
Specifica e prodotti
Metodo getToken()
Metodi del parser
I
Parser1.java contiene anche il metodo getToken() che fornisce
token senza fare avanzare l’input
getToken(i) restituisce l’i-esimo token:
getToken(1) token corrente
getToken(2) token successivo, . . .
L’argomento passato dev’essere un intero non negativo
getToken(0) token precedente
N. Fanizzi
Linguaggi di prog.+Lab
javacc – Analisi Sintattica
15 maggio 2014
25 / 85
Specifica e prodotti
Metodo getToken()
Metodi del parser
II
Il token restituito da getToken() dipende dal contesto della
chiamata:
1
2
3
4
5
6
7
void printfStatement(): {Token t;} {
"printf"
...
")"
{ t=getToken(1);}
"+"
}
getToken(1) restituisce ")"
N. Fanizzi
Linguaggi di prog.+Lab
javacc – Analisi Sintattica
15 maggio 2014
26 / 85
Specifica e prodotti
Costanti ed Eccezioni
Costanti ed Eccezioni
La classe Parser1 implementa l’interfaccia
Parser1Constants;
tutte le costanti sono disponibili al parser
Quando il parser incontra un errore, genera una
ParseException definita nell’omonimo file .java
N. Fanizzi
Linguaggi di prog.+Lab
javacc – Analisi Sintattica
15 maggio 2014
27 / 85
Specifica e prodotti
Token, scanner e flusso di input
Token
Token.java contiene i campi dei token
kind, image, next,
beginLine, beginColumn, endLine, endColumn
campi addizionali che supportano ulteriori funzionalità
L’array tokenImage fornisce una stringa stampabile per ogni
token
includono i doppi apici per facilitare la stampa di errori
tranne che per <EOF>, <UNSIGNED>, <ID>
in una grammatica,
il nome d’un token tra < > denota un oggetto Token;
senza, denota il valore del campo kind
(o l’indice per tokenImage)
N. Fanizzi
Linguaggi di prog.+Lab
javacc – Analisi Sintattica
15 maggio 2014
28 / 85
Specifica e prodotti
Token, scanner e flusso di input
Token manager e stream di input
Il token manager è definito nella classe Parser1TokenManager
contiene il metodo getNextToken()
chiamato dal parser per richiedere un token (oggetto)
in caso di errore, getNextToken() lancia un’eccezione
TokenErrorException, definita in TokenMgrError.java.
Si genera anche la classe SimpleCharStream
per il flusso usato dal token manager per l’input di caratteri
N. Fanizzi
Linguaggi di prog.+Lab
javacc – Analisi Sintattica
15 maggio 2014
29 / 85
Specifica e prodotti
Catena dei token
Catena dei token
Gli oggetti restituiti al parser dal token manager sono concatenati
attraverso il campo next che contiene un riferimento al prossimo
token:
image
"a"
"b"
next
"c"
null
Questo permette di scorrere la catena in avanti
Se il parser salva dei riferimenti ai token potrà sempre avervi
accesso più tardi
N. Fanizzi
Linguaggi di prog.+Lab
javacc – Analisi Sintattica
15 maggio 2014
30 / 85
Ricorsione e Iterazione
Sommario
1
Introduzione
2
Specifica e prodotti
3
Ricorsione e Iterazione
Iterazioni
Esempi
4
Scelta delle produzioni
5
Esempi
N. Fanizzi
Linguaggi di prog.+Lab
javacc – Analisi Sintattica
15 maggio 2014
31 / 85
Ricorsione e Iterazione
Iterazioni
Iterazioni con * e +
Per ripetere un pattern senza usare la ricorsione,
si possono usare operatori ad hoc,
ad es.:
expr −→ term ("+"term)*
invece di
expr −→ term termList
termlist −→ "+"term termList
termList −→ Con gli operatori * e + il codice diventa più efficiente delle
versioni ricorsive equivalenti
Inoltre, si può usare anche l’operatore ?
N. Fanizzi
Linguaggi di prog.+Lab
javacc – Analisi Sintattica
15 maggio 2014
32 / 85
Ricorsione e Iterazione
Esempi
Iterazioni – esempi I
Esempio
void expr() : { }
{
3
term()
4
termList()
5}
1
2
6
void termList(): {}
{
9
"+"
10
term()
11
termList()
12
|
13
{}
14 }
7
8
diventa:
N. Fanizzi
Linguaggi di prog.+Lab
javacc – Analisi Sintattica
15 maggio 2014
33 / 85
Ricorsione e Iterazione
Esempi
Iterazioni – esempi II
void expr() : {}
{
3
term()
4
(
5
"+"
6
term()
7
)*
8}
1
2
N. Fanizzi
Linguaggi di prog.+Lab
javacc – Analisi Sintattica
15 maggio 2014
34 / 85
Ricorsione e Iterazione
Esempi
Iterazioni – esempi III
Esempio
con addizione e sottrazione
void expr() : {}
{
3
term()
4
termList()
5}
1
2
6
void termList (): {}
{
9
"+"
// addizione
10
term ()
11
termList ()
12
|
13
"-"
// sottrazione
14
term ()
15
termList ()
16
|
17
{}
18 }
7
8
N. Fanizzi
Linguaggi di prog.+Lab
javacc – Analisi Sintattica
15 maggio 2014
35 / 85
Ricorsione e Iterazione
Esempi
Iterazioni – esempi IV
Se si cercasse di semplificare
void expr() : {}
{
3
term()
4
termList()
5}
1
2
6
void termList (): {}
{
9
"+"
10
term ()
11
// gen codice per l’addizione
12
termList ()
13
|
14
"-"
15
term ()
16
// gen codice per la sottrazione
17
termList ()
18
|
19
{}
20 }
7
8
N. Fanizzi
Linguaggi di prog.+Lab
javacc – Analisi Sintattica
15 maggio 2014
36 / 85
Ricorsione e Iterazione
Esempi
Iterazioni – esempi V
void expr() : {}
{
3
term()
4
(
5
("+"|"-")
6
// gen codice ???
7
term()
8
)*
9}
1
2
generare codice per somma o differenza? Meglio:
void expr() : {Token t;}
{
3
term()
4
(
5
(t="+"|t="-")
6
// gen codice sceglie in base a t
7
term ()
8
)*
9}
1
2
e.g. sfruttando kind del token e costanti
N. Fanizzi
Linguaggi di prog.+Lab
javacc – Analisi Sintattica
15 maggio 2014
37 / 85
Scelta delle produzioni
Sommario
1
Introduzione
2
Specifica e prodotti
3
Ricorsione e Iterazione
4
Scelta delle produzioni
Lookahead locale
Algoritmo di scelta
Lookahead Sintattico e Semantico
5
Esempi
N. Fanizzi
Linguaggi di prog.+Lab
javacc – Analisi Sintattica
15 maggio 2014
38 / 85
Scelta delle produzioni
Punti di scelta I
Dato il nonterminale da espandere secondo la propria disciplina
in generale il parser deve scegliere tra più parti destre delle
produzioni del nonterminale,
nei cosiddetti punti di scelta
ad ogni punto corrisponde un insieme di scelta contenente i
(prefissi di) token generabili a partire da quel punto
se gli insiemi sono disgiunti, la scelta è deterministica
cfr. grammatiche LL(k)
N. Fanizzi
Linguaggi di prog.+Lab
javacc – Analisi Sintattica
15 maggio 2014
39 / 85
Scelta delle produzioni
Punti di scelta II
Si supponga di specificare la grammatica: S −→ bcd | def
PARSER_BEGIN(G2)
class G2
3{
4}
5 PARSER_END(G2)
6 void S(): {}
7{
8
// qui un punto di scelta
9
"b" "c" "d"
// ins. di selezione {"b"}
10
|
11
"d" "e" "f"
// ins. di selezione {"d"}
12 }
1
2
Ad un punto di scelta il parser sceglie sulla base del prossimo
token e dell’insieme di selezione per ogni produzione
N. Fanizzi
Linguaggi di prog.+Lab
javacc – Analisi Sintattica
15 maggio 2014
40 / 85
Scelta delle produzioni
Punti di scelta III
Se la grammatica è LL(1), ad ogni punto di scelta, questa è
determinata univocamente dal prossimo token. Altrimenti:
void S(): {}
{
3
"b" "c" "d"
4|
5
"b" "e" "f"
6}
1
2
// ins. di selezione {"b"}
// ins. di selezione {"b"}
stesso insieme di selezione: un token non basta.
Conoscendo in anticipo (look ahead) il token successivo, si
potrebbe determinare l’alternativa corretta.
N. Fanizzi
Linguaggi di prog.+Lab
javacc – Analisi Sintattica
15 maggio 2014
41 / 85
Scelta delle produzioni
Punti di scelta IV
Per default si considera solo il token corrente ad ogni punto
di scelta
In caso di alternative multiple, si sceglie la prima elencata
Esempio per la grammatica precedente:
se l’input fosse "b""c""d", il parser sceglierebbe la prima
strada e completerebbe il lavoro
anche se fosse "b""e""f", il parser seguirebbe la prima
strada, ma poi con "e" sarebbe lanciata un’eccezione
Sebbene la specifica sia problematica,
JavaCC compila comunque un parser
ma genera anche messaggi di avvertimento del tipo:
Warning: choice conflict...
N. Fanizzi
Linguaggi di prog.+Lab
javacc – Analisi Sintattica
15 maggio 2014
42 / 85
Scelta delle produzioni
Lookahead locale
Lookahead locale I
Per ovviare ai casi precedenti, si usa la direttiva LOOKAHEAD
void S(): {}
{
3
LOOKAHEAD(2) // nel punto di selezione
4
"b" "c" "d"
5|
6
"b" "e" "f"
7}
1
2
N. Fanizzi
Linguaggi di prog.+Lab
javacc – Analisi Sintattica
15 maggio 2014
43 / 85
Scelta delle produzioni
Lookahead locale
Lookahead locale II
Altra variazione
void S(): {}
{
3
"bcd" // ins. di selezione {"bcd"}: token unico
4
|
5
"bef" // ins. di selezione {"bef"}: token unico
6}
1
2
nessun problema: grammatica LL(1)
N. Fanizzi
Linguaggi di prog.+Lab
javacc – Analisi Sintattica
15 maggio 2014
44 / 85
Scelta delle produzioni
Lookahead locale
Lookahead locale III
La direttiva LOOKAHEAD va solo nei punti di scelta:
1
quando si usa |
2
quando si usano *, +, ?
void S(): {}
{
3
// qui NO
4
B()
5
// qua NO
6
(
7
// qui OK
8
C()
9
|
10
D()
11
)
12 }
1
2
N. Fanizzi
Linguaggi di prog.+Lab
javacc – Analisi Sintattica
15 maggio 2014
45 / 85
Scelta delle produzioni
Lookahead locale
Lookahead locale IV
void S(): {}
2{
3
(
4
// p.d.s. primo |
5
B()
6
|
7
// p.d.s. secondo |
8
C()
9
|
10
D()
11
)
1
12
13
)?
N. Fanizzi
// p.d.s. per +
F()
19
20
)+
21
22
(
23
// p.d.s. per *
G()
24
25
)*
26
27
}
29
// p.d.s. per ?
E()
15
(
18
28
(
14
16
17
30
31
32
Linguaggi di prog.+Lab
javacc – Analisi Sintattica
15 maggio 2014
46 / 85
Scelta delle produzioni
Lookahead locale
Lookahead locale – esempi I
Per il frammento
( "b" "c" )* "d"
il parser generato conterrà:
while (tokenCorrente == "b")
{
3
consuma "b"
4
consuma "c"
5
}
6 consuma "d"
1
2
N. Fanizzi
Linguaggi di prog.+Lab
javacc – Analisi Sintattica
15 maggio 2014
47 / 85
Scelta delle produzioni
Lookahead locale
Lookahead locale – esempi II
inserendo una direttiva LOOKAHEAD(2) nel punto di scelta,
la struttura cambia:
while (tokenCorrente == "b" && tokenSucc == "c")
{
3
consuma "b"
4
consuma "c"
5}
6 consuma "d"
1
2
ma è superflua;
N. Fanizzi
Linguaggi di prog.+Lab
javacc – Analisi Sintattica
15 maggio 2014
48 / 85
Scelta delle produzioni
Lookahead locale
Lookahead locale – esempi III
serve invece nel caso seguente
(LOOKAHEAD (2) "b" "c" )* "b" "d"
interpretato con
while (tokenCorrente == "b" && tokenSucc == "c")
{
3
consuma "b"
4
consuma "c"
5
}
6 consuma "b"
7 consuma "d"
1
2
N. Fanizzi
Linguaggi di prog.+Lab
javacc – Analisi Sintattica
15 maggio 2014
49 / 85
Scelta delle produzioni
Lookahead locale
Lookahead locale – esempi IV
Lo stesso vale anche per l’operatore +
la specifica
(LOOKAHEAD (2) "b" "c" )+ "b"
genera un ciclo:
do {
consuma "b"
3
consuma "c"
4 } while (tokenCorrente == "b" && tokenSucc == "c")
5 consuma "b"
1
2
N. Fanizzi
Linguaggi di prog.+Lab
javacc – Analisi Sintattica
15 maggio 2014
50 / 85
Scelta delle produzioni
Lookahead locale
Lookahead locale – esempi V
Infine nel caso di ?:
("b")?
il codice sarebbe del tipo:
if (tokenCorrente == "b")
{
3
consuma "b"
4
}
1
2
N. Fanizzi
Linguaggi di prog.+Lab
javacc – Analisi Sintattica
15 maggio 2014
51 / 85
Scelta delle produzioni
Algoritmo di scelta
Algoritmo di scelta – esempi I
In una grammatica LL(1)
al più una parte destra è annullabile (può derivare )
Consideriamo una grammatica LL(1)
P −→ Q
P −→ R
P −→ T
Supponiamo sia annullabile T.
Quindi l’insieme di selezione per T è FIRST(T) + FOLLOW (P).
Per le altre, gli ins. corrispondono ai FIRST delle parti destre.
N. Fanizzi
Linguaggi di prog.+Lab
javacc – Analisi Sintattica
15 maggio 2014
52 / 85
Scelta delle produzioni
Algoritmo di scelta
Algoritmo di scelta – esempi II
In un parser ricorsivo discendente (pseudo-codice) si avrebbe:
void P()
{
3
switch(tokenCorrente) {
4
case tokenCorrente in FIRST(Q):
5
Q(); break;
6
case tokenCorrente in FIRST(R):
7
R(); break;
8
case tokenCorrente in FIRST(T)+FOLLOW(P):
9
T(); break;
10
default:
11
solleva eccezione;
12
}
13 }
1
2
Nota: Ultimo test inutile, si può semplificare il default:
N. Fanizzi
Linguaggi di prog.+Lab
javacc – Analisi Sintattica
15 maggio 2014
53 / 85
Scelta delle produzioni
Algoritmo di scelta
Algoritmo di scelta – esempi III
void P()
{
3
switch(tokenCorrente) {
4
case tokenCorrente in FIRST(Q):
5
Q(); break;
6
case tokenCorrente in FIRST(R):
7
R(); break;
8
default:
9
T(); break;
10
}
11 }
1
2
I test precedono le chiamate di Q() e R(), ma non di T().
Il default deve sempre corrispondere alla derivazione di :
quindi non servirà calcolare i FOLLOW , bastano i FIRST
N. Fanizzi
Linguaggi di prog.+Lab
javacc – Analisi Sintattica
15 maggio 2014
54 / 85
Scelta delle produzioni
Algoritmo di scelta
Algoritmo di scelta in JavaCC I
JavaCC adotta la seconda strategia:
il codice generato non esegue test sui token nei FOLLOW
i test sulle alternative annullabili vanno previsti per ultimi
altrimenti il funzionamento del parser sarebbe compromesso
Esempio
PARSER_BEGIN(Gram)
import java.io.*;
3 class Gram
4{
5
public static void main (String[] args)
6
throws IOException, ParseException {
7
Gram parser = new Gram(FileInputStream(args[0]));
8
parser.S();
9
}
10 }
11 PARSER_END(Gram)
12 // da saltare
1
2
N. Fanizzi
Linguaggi di prog.+Lab
javacc – Analisi Sintattica
15 maggio 2014
55 / 85
Scelta delle produzioni
Algoritmo di scelta
Algoritmo di scelta in JavaCC II
SKIP:
{
15
" " | "\n" | "\r" | "\t"
16 }
17 // grammatica
18 void S() : {}
19 {
20
{ System.out.println("fine");}
21
|
22
"z" S()
// ins. sel. {"z"}
23 }
13
14
// ins. sel. {EOF}
Prima alternativa: produzione vuota (solo un’azione sem.)
si doveva mettere alla fine
JavaCC dà un warning:
can expand to the empty token sequence
il parser viene generato ma la parte relativa a "z" viene
eliminata perché irraggiungibile
N. Fanizzi
Linguaggi di prog.+Lab
javacc – Analisi Sintattica
15 maggio 2014
56 / 85
Scelta delle produzioni
Algoritmo di scelta
Algoritmo di scelta in JavaCC III
L’assenza di warning da parte di JavaCC non garantisce che la
specifica sia corretta
Esempio
JavaCC compila senza warning
void S() : {}
{
3
Q() "z"
4}
5 // -------------------6 void Q() : {}
7{
8
"z"
// ins. selezione {"z"}
9
|
10
{}
// ins. selezione {"z"}
11 }
1
2
tuttavia il parser ottenuto risconosce "zz" ma non "z"
(pur essendo entrambe accettabili)
N. Fanizzi
Linguaggi di prog.+Lab
javacc – Analisi Sintattica
15 maggio 2014
57 / 85
Scelta delle produzioni
Algoritmo di scelta
Algoritmo di scelta in JavaCC IV
Per l’input "z", il parser usa la prima alternativa di Q(),
ma poi non ci sono altre occorrenze di "z" nell’input per il
consumo della "z" nella prod. di S()
si doveva perseguire la seconda alternativa in Q() che
richiede e non consuma la "z" sull’input,
lasciandola disponibile per la regola di S()
La grammatica non è LL(1)
Gli ins. di selezione delle alternative in Q() coincidono
JavaCC non calcola tale insieme per la seconda,
quindi non si accorge della violazione della proprietà delle
grammatiche LL(1)
N. Fanizzi
Linguaggi di prog.+Lab
javacc – Analisi Sintattica
15 maggio 2014
58 / 85
Scelta delle produzioni
Lookahead Sintattico e Semantico
Lookahead Sintattico e Semantico
Oltre alla direttiva LOOKAHEAD(n) che specifica il numero n di
token da esaminare in anticipo per decidere in un punto di scelta:
lookahead sintattico specifica sintattica dell’espansione attesa
per la scelta della prima alternativa
se si verifica, si prende la prima strada
altrimenti si procede alla prossima scelta
lookahead semantico specifica una condizione booleana
(tra graffe)
true il parser segue la prima alternativa
false considera la prossima
N. Fanizzi
Linguaggi di prog.+Lab
javacc – Analisi Sintattica
15 maggio 2014
59 / 85
Scelta delle produzioni
Lookahead Sintattico e Semantico
Lookahead Sintattico I
Esempio
lookahead sintattico
void S() : {}
{
3
LOOKAHEAD(C() "a")
4
A()
5
|
6
B()
7}
1
13
2
14
8
void A() : {}
{
11
C() "a" "a"
12 }
9
10
N. Fanizzi
Linguaggi di prog.+Lab
void B() : {}
15 {
16
C() "b" "b"
17 }
18
void C() : {}
20 {
21
"c" "c"
22 }
19
23
24
javacc – Analisi Sintattica
15 maggio 2014
60 / 85
Scelta delle produzioni
Lookahead Sintattico e Semantico
Lookahead Sintattico II
Data l’espansione specificata C()"a"
il parser cerca sul flusso di input una sottostringa
che corrisponde a C() seguita da un token "a"
In caso di successo, si segue la prima alternativa A()
altrimenti si considera la successiva
Esempio se si avesse in input "c""c""a""a",
si sceglierebbe la prima prod.
Usando invece la direttiva LOOKAHEAD(3) non vi sarebbero
problemi perché la stringa per C() ha lunghezza 2.
N. Fanizzi
Linguaggi di prog.+Lab
javacc – Analisi Sintattica
15 maggio 2014
61 / 85
Scelta delle produzioni
Lookahead Sintattico e Semantico
Lookahead Sintattico III
Se, invece, la regola di C() fosse:
void C (): {}
{
3
("c")+
4}
1
2
nessuna direttiva di lookahead numerico funzionerebbe,
al contrario di quello sintattico
N. Fanizzi
Linguaggi di prog.+Lab
javacc – Analisi Sintattica
15 maggio 2014
62 / 85
Scelta delle produzioni
Lookahead Sintattico e Semantico
Lookahead Semantico I
Esempio
lookahead semantico
void S() : {}
2{
3 LOOKAHEAD({ getToken(1).kind == ID &&
4
getToken(2).kind == ASGN })
5 A()
6 |
7 D()
8}
1
9
void A() : {}
{
12
<ID> <ASGN> E()
13 }
10
11
14
void D() : {}
{
17
<ID> <ID>
18 }
15
16
N. Fanizzi
Linguaggi di prog.+Lab
javacc – Analisi Sintattica
15 maggio 2014
63 / 85
Scelta delle produzioni
Lookahead Sintattico e Semantico
Lookahead Semantico II
Nota il metodo getToken() non consuma token in input
getToken(1) restituisce il token corrente;
getToken(2) restituisce il token che lo segue
N. Fanizzi
Linguaggi di prog.+Lab
javacc – Analisi Sintattica
15 maggio 2014
64 / 85
Esempi
Sommario
1
Introduzione
2
Specifica e prodotti
3
Ricorsione e Iterazione
4
Scelta delle produzioni
5
Esempi
NL_Xlator
Bowd
CSV2HTML
Calcolatore
N. Fanizzi
Linguaggi di prog.+Lab
javacc – Analisi Sintattica
15 maggio 2014
65 / 85
Esempi
NL_Xlator
Esempi: NL_Xlator I
1
PARSER_BEGIN(NL_Xlator2)
2
3
4
/** New line translator. */
public class NL_Xlator2 {
5
/** Main entry point. */
public static void main(String args[]) throws ParseException {
NL_Xlator parser = new NL_Xlator(System.in);
parser.ExpressionList();
}
6
7
8
9
10
11
12
}
13
14
PARSER_END(NL_Xlator)
15
SKIP :
{
18
" " | "\t" | "\n" | "\r"
19 }
16
17
20
21
TOKEN :
N. Fanizzi
Linguaggi di prog.+Lab
javacc – Analisi Sintattica
15 maggio 2014
66 / 85
Esempi
NL_Xlator
Esempi: NL_Xlator II
22
{
< ID: ["a"-"z","A"-"Z","_"] ( ["a"-"z","A"-"Z","_","0"-"9"] )* >
| < NUM: ( ["0"-"9"] )+ >
25 }
23
24
26
/** Top level production. */
void ExpressionList() : { String s; }
29 {
30
{
31
System.out.println("Please type in an expression
32 followed by a \";\" or ^D to quit:"); System.out.println("");
33
}
34
( s=Expression() ";"
35
{
36
System.out.println(s); System.out.println("");
37
System.out.println("Please type in another expression
38 followed by a \";\" or ^D to quit:"); System.out.println("");
39
}
40
)*
41
<EOF>
42 }
27
28
43
N. Fanizzi
Linguaggi di prog.+Lab
javacc – Analisi Sintattica
15 maggio 2014
67 / 85
Esempi
NL_Xlator
Esempi: NL_Xlator III
/** An Expression. */
String Expression() :
46 {
47
java.util.Vector termimage = new java.util.Vector();
48
String s;
49 }
50 {
51
s=Term()
52
{ termimage.addElement(s); }
53
( "+" s=Term()
54
{ termimage.addElement(s); }
55
)*
56
{
57
if (termimage.size() == 1) {
58
return (String)termimage.elementAt(0);
59
} else {
60
s = "the sum of " + (String)termimage.elementAt(0);
61
for (int i = 1; i < termimage.size()-1; i++) {
62
s += ", " + (String)termimage.elementAt(i);
63
}
64
if (termimage.size() > 2) { s += ","; }
65
s += " and " + (String)termimage.elementAt(termimage.size()-1);
44
45
N. Fanizzi
Linguaggi di prog.+Lab
javacc – Analisi Sintattica
15 maggio 2014
68 / 85
Esempi
NL_Xlator
Esempi: NL_Xlator IV
return s;
66
}
67
}
68
69
}
70
/** A Term. */
String Term() :
73 {
74
java.util.Vector factorimage = new java.util.Vector();
75
String s;
76 }
77 {
78
s=Factor()
79
{ factorimage.addElement(s); }
80
( "*" s=Factor()
81
{ factorimage.addElement(s); }
82
)*
83
{
84
if (factorimage.size() == 1) {
85
return (String)factorimage.elementAt(0);
86
} else {
87
s = "the product of " + (String)factorimage.elementAt(0);
71
72
N. Fanizzi
Linguaggi di prog.+Lab
javacc – Analisi Sintattica
15 maggio 2014
69 / 85
Esempi
NL_Xlator
Esempi: NL_Xlator V
for (int i = 1; i < factorimage.size()-1; i++) {
s += ", " + (String)factorimage.elementAt(i);
}
if (factorimage.size() > 2) { s += ","; }
s += " and " + (String)factorimage.elementAt(factorimage.size()-1);
return s;
88
89
90
91
92
93
}
94
}
95
96
}
97
/** A Factor. */
String Factor() : { Token t; String s; }
100 {
101
t=<ID> { return t.image; }
102 | t=<NUM> { return t.image; }
103 | "(" s=Expression() ")"
{ return s; }
104 }
98
99
N. Fanizzi
Linguaggi di prog.+Lab
javacc – Analisi Sintattica
15 maggio 2014
70 / 85
Esempi
Bowd
Esempi: Bowd I
1
2
PARSER_BEGIN(Bowd)
import java.io.* ;
3
class Bowd {
public static void main(String args [])
6
throws IOException {
7
System.out.print:("Lettura da standard input");
8
BufferedReader in = new BufferedReader(
9
new InputStreamReader(System.in));
10
String linea = in.readLine();
11
System.out.print(sostituzione(linea));
12
}
4
5
13
14
15
16
17
N. Fanizzi
static String sostituzione(String inStringa) {
Reader sr = new StringReader(inStringa);
Bowd parser = new Bowd(sr);
StringBuffer buffer = new StringBuffer();
Linguaggi di prog.+Lab
javacc – Analisi Sintattica
15 maggio 2014
71 / 85
Esempi
Bowd
Esempi: Bowd II
try { parser.inizio(buffer); }
catch(TokenMgrError e)
20
{throw new IllegalStateException();}
21
catch(ParseException e)
22
{throw new IllegalStateException();}
23
return buffer.toString();
24
} // sostituzione
25 } // classe
26 PARSER_END(Bowd)
18
19
27
TOKEN :
{
30
< PAROLA_DI_4_LETTERE : (<LETTERA>){4}>
31 | < PAROLA_DI_PIU_DI_4_LETTERE :
32
(<LETTERA>){5} (<LETTERA>)* >
33 | < #LETTERA : ["a"-"z","A"-"Z"] >
34 | < ALTRO : ~[] >
28
29
N. Fanizzi
Linguaggi di prog.+Lab
javacc – Analisi Sintattica
15 maggio 2014
72 / 85
Esempi
Bowd
Esempi: Bowd III
35
}
36
void inizio(StringBuffer buffer) :
{ Token t; }
39 {
40
( <PAROLA_DI_4_LETTERE>
41
{ buffer.append("****"); }
42
| ( t=<PAROLA_DI_PIU_DI_4_LETTERE> | t=<ALTRO>)
43
{ buffer.append(t.image); }
44
)*
45
<EOF>
46 }
37
38
N. Fanizzi
Linguaggi di prog.+Lab
javacc – Analisi Sintattica
15 maggio 2014
73 / 85
Esempi
CSV2HTML
Esempi: CSV2HTML I
CSV: Formato standard (export da fogli elettronici)
Esempio
STUDENT, ID NAME, DATE OF BIRTH
129384, Davy Jones, 03/04/81
3 328649, Clare Manstead, 30/11/81
4 237090, Richard Stoppit, 22/06/82
5 523343, Brian Hardwick, 15/11/81
6 908423, Sally Brush, 06/06/81
7 328453, Elisa Strudel, 12/09/82
8 883632, Peter Smith, 03/05/83
9 542033, Ryan Alcot, 04/12/80
1
2
Grammatica
file: riga() ( <FINELINEA> riga())* [<FINELINEA>)] <EOF>
linea: (record)+
3 record: <RECORD> [<VIRGOLA>]
1
2
N. Fanizzi
Linguaggi di prog.+Lab
javacc – Analisi Sintattica
15 maggio 2014
74 / 85
Esempi
CSV2HTML
Esempi: CSV2HTML II
1
2
PARSER_BEGIN(CSV2HTML)
import java.io.*;
3
public class CSV2HTML {
public static void main(String args[]) {
6
if(args.length!=2) { errore(); }
7
FileInputStream myIn = null;
8
PrintStream myOut = null;
9
try {
10
myIn = new FileInputStream(args[0]);
11
myOut = new PrintStream(args[1]);
12
} catch(Exception e) {
13
System.err.println("errore apertura file.");
14
System.exit(0);
15
}
4
5
16
17
18
19
String p = "<html>\n <head>\n" +
"<title>Tabella generata da CSV2HTML </title>\n" +
" </head>\n <body>\n";
N. Fanizzi
Linguaggi di prog.+Lab
javacc – Analisi Sintattica
15 maggio 2014
75 / 85
Esempi
CSV2HTML
Esempi: CSV2HTML III
try {
CSV2HTML parser = new CSV2HTML(myIn);
22
p+= parser.file();
23
} catch(ParseException e) {
24
System.err.println("errore parsing");
25
System.exit(0);
26
}
27
p += " </body>\n</html>";
28
System.out.print("Tabella convertita:\n"+p);
29
myOut.print(p); myOut.close();
30
} // main
31
private static void errore() {
32
System.err.println("USO: CSV2HTML inFile outFile");
33
System.exit(0);
34
} // errore
35 } // classe
20
21
36
37
PARSER_END(CSV2HTML)
38
N. Fanizzi
Linguaggi di prog.+Lab
javacc – Analisi Sintattica
15 maggio 2014
76 / 85
Esempi
CSV2HTML
Esempi: CSV2HTML IV
SKIP :
{
41
" " | "\t"
42 }
39
40
43
TOKEN :
{
46
<VIRGOLA: ",">
47 | <RECORD: (~[",","\r","\n"])+ >
48 | <FINELINEA: "\r\n" | "\r" | "\n" >
49 }
44
45
50
String file() : { String tab=" <table border=’1’>\n", r; }
{
53
r=riga() <FINELINEA> { tab+=r; }
54
( r=riga() <FINELINEA> { tab+=r; } )*
55
( <FINELINEA> )? <EOF>
56
{ return tab+=" </table>\n"; }
57 }
51
52
N. Fanizzi
Linguaggi di prog.+Lab
javacc – Analisi Sintattica
15 maggio 2014
77 / 85
Esempi
CSV2HTML
Esempi: CSV2HTML V
58
String riga() : { String d, r="\t<tr>\n"; }
{
61
( d=record() { r+=d; } )+
62
{ return r+="\t</tr>\n"; }
63 }
59
60
64
String record() : { Token t; }
{
67
t=<RECORD> ( <VIRGOLA> )?
68
{ return "\t\t<td> " + t.image + " </td>\n";}
69 }
65
66
N. Fanizzi
Linguaggi di prog.+Lab
javacc – Analisi Sintattica
15 maggio 2014
78 / 85
Esempi
Calcolatore
Esempi: Calcolatore I
PARSER_BEGIN(Calcolatore)
public class Calcolatore {
3
public static void main (String args []) {
4
Calcolatore parser = new Calcolatore(System.in);
5
double v = 0;
6
System.out.println("Immettere espressione");
7
System.out.print("[op.ammessi:");
8
System.out.print("+,-,*,/,abs,exp,log,sin,cos,tan]");
9
System.out.print("\n> ");
10
try {
11
v = parser.start();
12
} catch (Exception e) {
13
System.err.println("impossibile calcolare il valore.");
14
System.exit(1);
15
} // catch
16
System.out.print("Valore:"+v);
17
} // main
18 } // class
1
2
N. Fanizzi
Linguaggi di prog.+Lab
javacc – Analisi Sintattica
15 maggio 2014
79 / 85
Esempi
Calcolatore
Esempi: Calcolatore II
19
PARSER_END(Calcolatore)
20
SKIP:
{ " " | "\r" | "\t"
23 }
21
22
24
TOKEN:
{
27
< EOL: "\n" >
28 | < #CIFRA: ["0" - "9"] >
29 | < NUMFP:
30
(<CIFRA>)+ "." (<CIFRA>)* (<ESP>)?
31
| "." (<CIFRA>)+ (<ESP>)?
32
| (<CIFRA>)+ <ESP>
33
| (<CIFRA>)+ (<ESP>)?
34
>
35 | < #ESP: ["e","E"] (["+","-"])? (<CIFRA>)+ >
36 }
25
26
37
N. Fanizzi
Linguaggi di prog.+Lab
javacc – Analisi Sintattica
15 maggio 2014
80 / 85
Esempi
Calcolatore
Esempi: Calcolatore III
double start(): { double r; }
{
40
r=espressione() <EOL>
41
{ return r; }
42 }
38
39
43
double espressione(): { double t,r; }
{ // E ::= T RE
46
t=termine() r=restoE(t)
47
{ return r; }
48 }
44
45
49
50
double restoE(double accu): { double t,r; }
{ // RE ::= "+" T RE | "." T RE | epsilon
53
"+" t=termine() r=restoE(accu+t)
54
{ return r; }
55
|
56
"-" t=termine() r=restoE(accu-t)
51
52
N. Fanizzi
Linguaggi di prog.+Lab
javacc – Analisi Sintattica
15 maggio 2014
81 / 85
Esempi
Calcolatore
Esempi: Calcolatore IV
{ return r; }
| // vuota
{ return accu; }
57
58
59
60
}
61
double termine() : { double f,r; }
{ // T ::= F RT
64
f=fattore() r=restoT(f)
65
{ return r; }
66 }
62
63
67
double restoT(double accu): { double f,r; }
{ // RE ::= "*" F RT | "/" F RT | epsilon
70
"*" f=fattore() r=restoT(accu*f)
71
{ return r;}
72
|
73
"/" f=fattore() r=restoT(accu/f)
74
{ return r; }
75
|
// vuota
68
69
N. Fanizzi
Linguaggi di prog.+Lab
javacc – Analisi Sintattica
15 maggio 2014
82 / 85
Esempi
Calcolatore
Esempi: Calcolatore V
{ return accu; }
76
77
}
78
double fattore(): {double f; Token t; }
{ // F ::= nfp | "-" F | "fn" F | "(" E ")"
81
t=<NUMFP>
82
{ return Double.parseDouble(t.image); }
83 |
"-" f=fattore()
84
{ return -f; }
85 |
"abs" f=fattore()
86
{ return Math.abs(f); }
87 |
"exp" f=fattore()
88
{ return Math.exp(f); }
89 |
"log" f=fattore()
90
{ return Math.log(f); }
91 |
"sin" f=fattore()
92
{ return Math.sin(f); }
93 |
"cos" f=fattore()
94
{ return Math.cos(f); }
79
80
N. Fanizzi
Linguaggi di prog.+Lab
javacc – Analisi Sintattica
15 maggio 2014
83 / 85
Esempi
Calcolatore
Esempi: Calcolatore VI
"tan" f=fattore()
{ return Math.tan(f); }
97 | "(" f=espressione() ")"
98
{ return f; }
99 }
95
|
96
N. Fanizzi
Linguaggi di prog.+Lab
javacc – Analisi Sintattica
15 maggio 2014
84 / 85
Riferimenti
Riferimenti
D. Galles: Modern Compiler Design. Scott/Jones Publishing
A.J. Dos Reis: Compiler Construction Using Java, JavaCC, and
Yacc, Wiley-IEEE Computer Society Press
T. S. Norvell. JavaCC Tutorial
N. Fanizzi: Manualetto JavaCC
N. Fanizzi
Linguaggi di prog.+Lab
javacc – Analisi Sintattica
15 maggio 2014
85 / 85