Creato da pastuweb.com
Share My Page
My Social Accounts
Account FaceBook Account LinkedIn Account Twitter Account Google Plus Account Git Hub
Scanner JFlex: per riconoscimento lexemi
///////////////////////////////////
 
/// Scanner: protocollo PWXML ////
 
///////////////////////////////////
 
import java_cup.runtime.*;
 
%%
 
%class scanner
%unicode
%cup
%line
%column
 
 
%{
    private Symbol symbol(int type){
        return new Symbol(type, yyline, yycolumn);
    }
    private Symbol symbol(int type, Object value){
        return new Symbol(type, yyline, yycolumn, value);
    }
%}
 
num = [0-9]+
numero = {num}((","|"."){num})?
stringa = [a-zA-Z]+ ([_a-zA-Z0-9 \':;,\.\?ìèòàù!\(\)-]+)*
 
ora = (([0-1]?[0-9]) | ([2][0-3]))([0-5]?[0-9])([0-5]?[0-9])
mese = 0[1-9] | 1[0-2]
giorno = 0[1-9] | [1-2][0-9] | 3[0-1]
anno = [0-9]{4}
timestamp = {anno}{mese}{giorno}{ora}
  
apici = (" ")*"\""(" ")*
 
 
//tags
tag_pwxml_open = "<PWXML " | "<pwxml " 
tag_pwxml_close = "</PWXML>" | "</pwxml>" 
 
tag_comando_open = "<COMANDO " | "<comando " 
tag_comando_close = "</COMANDO>" | "</comando" 
 
tag_proprieta_open = "<PROPRIETA " | "<proprieta " 
tag_proprieta_close = "</PROPRIETA>" | "</proprieta>"  
 
tag_lista_open = "<LISTA " | "<lista " 
tag_lista_close = "</LISTA>" | "</lista>" 
 
tag_item_open = "<ITEM " | "<item " 
tag_item_close = "</ITEM>" | "</item>" 
 
// attributi
attr_value = "VALUE" | "value"
attr_timestamp = "TIMESTAMP" | "timestamp"
attr_name = "NAME" | "name"
attr_tipo = "TIPO" | "tipo"
attr_id= "ID" | "id"
 
%%
 
{tag_pwxml_open} {return new Symbol(sym.PWXML_OPEN);}
{tag_pwxml_close} {return new Symbol(sym.PWXML_CLOSE);}
{tag_comando_open} {return new Symbol(sym.COMANDO_OPEN);}
{tag_comando_close} {return new Symbol(sym.COMANDO_CLOSE);}
{tag_proprieta_open} {return new Symbol(sym.PROPRIETA_OPEN);}
{tag_proprieta_close} {return new Symbol(sym.PROPRIETA_CLOSE);}
{tag_lista_open} {return new Symbol(sym.LISTA_OPEN);}
{tag_lista_close} {return new Symbol(sym.LISTA_CLOSE);}
{tag_item_open} {return new Symbol(sym.ITEM_OPEN);}
{tag_item_close} {return new Symbol(sym.ITEM_CLOSE);}
 
{attr_value} {return new Symbol(sym.ATTR_VALUE);}
{attr_timestamp} {return new Symbol(sym.ATTR_TIMESTAMP);}
{attr_name} {return new Symbol(sym.ATTR_NAME);}
{attr_tipo} {return new Symbol(sym.ATTR_TIPO);}
{attr_id} {return new Symbol(sym.ATTR_ID);}
 
{apici} {return new Symbol(sym.APICI); }
">"  {return new Symbol(sym.PAR_ANG_C); }
"="  {return new Symbol(sym.UG);}
"/"  {return new Symbol(sym.DIV);}
 
 
//attenzione all'ordine, dal più specifico al più generico
{timestamp} {return new Symbol(sym.TIMESTAMP, new String(yytext())); }
{numero} {return new Symbol(sym.NUMERO, new String(yytext())); } //no Double per via della possibile virgola
{stringa} {return new Symbol(sym.STRINGA, new String(yytext()));}
 
 
[ \n\r\t]       {;}
.               {System.out.println("SCANNER ERROR: "+yytext());}
 

 

Parser CUP: creazione grammatica e popolamento di una symbol table da usare nel Main.java
///////////////////////////////////
 
/// Parser: protocollo PWXML ////
 
///////////////////////////////////
 
import java_cup.runtime.*;
import java.io.*;
import java.util.*;
 
init with {:
System.out.println("PARSERRIZZO...");
symbol_table = new Hashtable<String,String>();
:};
 
parser code {:
 
//variabili globali a livello di classe parser
public static boolean flagError = false;
public static String errMex = "";
public static Hashtable<String,String> symbol_table;
 
//Overriding delle funzioni per la gestione degli errori di CUP
public void report_error(String message, Object info) {
StringBuffer m = new StringBuffer(message);
if (info instanceof Symbol) {
if (((Symbol)info).left != 1 && ((Symbol)info).right != 1) {
if (((Symbol)info).left != -1 && ((Symbol)info).right != -1) {
int line = (((Symbol)info).left)+1;
int column = (((Symbol)info).right)+1;
m.append(" (linea "+line+", colonna "+column+")");
}
}
System.err.println(m);
}
}
public void syntax_error(Symbol cur_token){}
 
// ritorna il valore semantico che cè all'interno dello stack ad una certa posizione,
// usato all'interno delle action delle regole CUP
// utile
// - quando devo recuperare il valore di un simbolo Terminale o Non Terminale annegato nello stack
// - per crearci dietro una semantica
public Object stack(int position) { //NON USATA
return (((Symbol)stack.elementAt(tos+position)).value);
}
 
:};
 
 
action code {:
 
int flagDebug = 0;
private void stampa(String s, String tipo){ 
if (flagDebug == 1){
System.out.println(tipo+": "+ s);
}else{
if(tipo.equals("ERR")){
parser.errMex = "ERR: "+s; //interessa solo se ci sono Errori, nient'altro
parser.flagError = true;
System.out.println(parser.errMex);
}else{
System.out.println(tipo+": "+ s);
}
}
}
:};
 
 
//Terminal tokens: riconosciuti dallo scanner, il contenuto lo ricavo grazie alla classe Sym
terminal PWXML_OPEN, PWXML_CLOSE;
terminal COMANDO_OPEN, COMANDO_CLOSE;
terminal PROPRIETA_OPEN, PROPRIETA_CLOSE;
terminal LISTA_OPEN, LISTA_CLOSE;
terminal ITEM_OPEN, ITEM_CLOSE;
 
terminal ATTR_VALUE, ATTR_TIMESTAMP, ATTR_ID, ATTR_NAME, ATTR_TIPO;
 
terminal APICI, PAR_ANG_C, UG, DIV;
terminal String TIMESTAMP, NUMERO, STRINGA;
 
//NON Terminal tokens: servono per creare la sintassi, vengono mescolati tra loro e con i simboli Terminali
non terminal progr;
non terminal pwxml, comandi;
non terminal String attributi_pwxml, attributi_pwxml_list, attributo_pwxml;
non terminal String attributi_comando, attributi_comando_list, attributo_comando;
non terminal body_comando, body_comando_list;
 
non terminal proprieta, lista, item, item_list;
non terminal String attributi_lista, attributo_lista;
non terminal String attributi_proprieta, attributi_proprieta_list;
non terminal String attributi_item, attributi_item_list;
 
non terminal String content, alfanum;
 
//precedence per la regola valore
precedence left STRINGA;
 
//////////////////////////////////////
// Inizio Grammatica
//////////////////////////////////////
 
start with progr
;
 
progr ::= pwxml 
{: 
if( parser.flagError == false ){
System.out.println("");
stampa("errMex = \"empty\"  & flagError = "+parser.flagError,"INFO");
stampa("FINE PARSER!", "INFO"); 
}else{
System.out.println("");
stampa("errMex = \""+parser.errMex+"\"  & flagError = "+parser.flagError,"INFO");
stampa("FINE PARSER - trovato errore!", "INFO"); 
}
:}  
| error {: stampa("Controllare l'XML dal principio", "ERR"); :}
;
 
pwxml ::= PWXML_OPEN  attributi_pwxml comandi PWXML_CLOSE 
| PWXML_OPEN error comandi PWXML_CLOSE {: stampa("Errore negli attributi del tag PWXML", "ERR"); :} 
| PWXML_OPEN attributi_pwxml error PWXML_CLOSE {: stampa("Check del body del tag PWXML", "ERR"); :} 
 
 
comandi ::= COMANDO_OPEN attributi_comando body_comando_list COMANDO_CLOSE 
| COMANDO_OPEN error body_comando_list COMANDO_CLOSE {: stampa("Errore negli attributi del tag COMANDO", "ERR"); :}  
| COMANDO_OPEN attributi_comando error COMANDO_CLOSE {: stampa("Check del body del tag COMANDO", "ERR"); :} 
;
 
//body_comando: può contenere sia Property sia PerceptBundle
body_comando_list ::= body_comando | body_comando_list body_comando
;
body_comando ::= proprieta | lista
;
 
proprieta ::= PROPRIETA_OPEN attributi_proprieta:attr content:body PROPRIETA_CLOSE  
{: parser.symbol_table.put(attr, body); stampa(body,"BODY PROPRIETA"); :} 
//diverso nel caso di assenza di "content"
|  PROPRIETA_OPEN attributi_proprieta_list  DIV PAR_ANG_C 
;
 
lista ::= LISTA_OPEN attributi_lista item_list LISTA_CLOSE 
| LISTA_OPEN error item_list LISTA_CLOSE {: stampa("Errore negli attributi del tag LISTA", "ERR"); :}  
| LISTA_OPEN attributi_lista error LISTA_CLOSE {: stampa("Check del body del tag LISTA", "ERR"); :} 
;
 
item_list ::= item | item_list item
;
item ::= ITEM_OPEN attributi_item:attr content:body ITEM_CLOSE  
{: parser.symbol_table.put(attr, body); stampa(body,"BODY ITEM"); :} 
//diverso nel caso di assenza di "content"
|  ITEM_OPEN attributi_item_list  DIV PAR_ANG_C 
;
 
 
// ---------------------------------------------------------------------  sintassi ATTRIBUTI
//sintassi attributi di PWXML
attributi_pwxml ::= attributi_pwxml_list:attr PAR_ANG_C 
{: 
stampa(attr,"ATTR. PWXML");
:}
;
attributi_pwxml_list ::= attributo_pwxml:attr {: RESULT = new String(attr); :} 
;
attributo_pwxml ::= ATTR_ID UG APICI NUMERO:id APICI  
{: 
parser.symbol_table.put("ID", id);
RESULT = new String(" ID="+id);
:} 
|  ATTR_ID UG APICI error APICI  
{: 
stampa("ID - formato errato", "ERR");
RESULT = new String("");
:}
| ATTR_NAME UG APICI STRINGA:name APICI  
{: 
parser.symbol_table.put("NAME", name);
RESULT = new String(" NAME="+name);
:} 
|  ATTR_NAME UG APICI error APICI  
{: 
stampa("NAME - formato errato", "ERR");
RESULT = new String("");
:}
 
;
 
//sintassi attributi di COMANDO
attributi_comando ::= attributi_comando_list:attr PAR_ANG_C 
{: 
stampa(attr,"ATTR. COMANDO");
:}
;
attributi_comando_list ::= attributo_comando:attr {:RESULT = new String(attr); :} 
 
;
attributo_comando ::= ATTR_NAME UG APICI STRINGA:name APICI   
{: 
parser.symbol_table.put("COMANDO-NAME", name);
RESULT = new String(" NAME="+name);
:} 
 
;
 
//sintassi attributi di PROPRIETA
attributi_proprieta ::= attributi_proprieta_list:attr PAR_ANG_C  //chiamata dalla regola che gestisce il BODY
{: 
RESULT = new String(attr);
:}
;
attributi_proprieta_list ::= ATTR_NAME UG APICI STRINGA:name APICI ATTR_VALUE UG APICI alfanum:value APICI
{:
parser.symbol_table.put(name, value);
stampa(" NAME="+name+" VALUE="+value,"ATTR. PROPRIETA");
RESULT = new String(name+":"+value);
:}
| ATTR_NAME UG APICI STRINGA:name APICI 
{:
parser.symbol_table.put(name, "yes");
stampa(" NAME="+name+" VALUE=no-value","ATTR. PROPRIETA");
RESULT = new String(name+":yes");
:}
;
 
//sintassi attributi di PERCPET BUNDLE
attributi_lista ::= attributo_lista:temp PAR_ANG_C 
{: 
stampa(temp,"ATTR. LISTA");
:}
;
 
attributo_lista ::= ATTR_TIMESTAMP UG APICI TIMESTAMP:tempo APICI   
{: 
parser.symbol_table.put("TIMESTAMP", tempo);
RESULT = new String(" TIMESTAMP="+tempo);
:} 
| ATTR_NAME UG APICI STRINGA:name APICI ATTR_TIMESTAMP UG APICI TIMESTAMP:tempo APICI   
{: 
parser.symbol_table.put("TIMESTAMP-"+name, tempo);
RESULT = new String(name+":"+tempo);
:} 
;
 
 
//sintassi attributi di ITEM
attributi_item ::= attributi_item_list:attr PAR_ANG_C //chiamata dalla regola che gestisce il BODY
{: 
RESULT = new String(attr);
:}
;
attributi_item_list ::=  ATTR_TIPO UG APICI STRINGA:itemtipo  APICI  ATTR_VALUE UG APICI alfanum:value APICI  
{: 
parser.symbol_table.put(itemtipo, value);
stampa(" ITEMTIPO="+itemtipo+" VALUE="+value,"ATTR. ITEM");
RESULT = new String(itemtipo+":"+value);
:}
| ATTR_NAME UG APICI alfanum:name  APICI  ATTR_VALUE UG APICI alfanum:value APICI  
{: 
parser.symbol_table.put(name, value);
stampa(" NAME="+name+" VALUE="+value,"ATTR. ITEM");
RESULT = new String(name+":"+value);
:}
| ATTR_TIPO UG APICI alfanum:itemtipo APICI  
{: 
stampa(" ITEMTIPO="+itemtipo, "ATTR. ITEM");
RESULT = new String(itemtipo);
:}
| ATTR_NAME UG APICI alfanum:itemtipo APICI  
{: 
stampa("NAME="+itemtipo, "ATTR. ITEM");
RESULT = new String(itemtipo);
:}
;
 
 
//sono presenti alcuni lexemi che possono essere composti sia da numeri sia da caratteri,
// il problema è che HO 2 PATTERN che li IDENTIFICANO, quindi regola "alfanum"
alfanum ::= STRINGA:str {: RESULT = new String(str); :}
| NUMERO:num {: RESULT = new String(num); :} 
| TIMESTAMP:tempo {: RESULT = new String(tempo); :} 
;
 
//contenuto di un qualsiasi tag PWXML completo
 content ::= STRINGA:str {: RESULT = new String(str); :} 
 ;

 

Main: per esecuzione scanner+parser
import java.io.*;
import java.util.Hashtable;
import java.util.Set;
 
public class Main {
 
static public void main(String argv[]) {
 
try {
/* Istanzio lo scanner aprendo il file di ingresso argv[0] */
scanner l = new scanner(new FileReader(argv[0]));
/* Istanzio il parser */
parser p = new parser(l);
/* Avvio il parser */
Object result = p.parse();
} catch (Exception e) {
e.printStackTrace();
}
 
Set<String> keys = parser.symbol_table.keySet();
for(String key: keys){
System.out.println("Chiave: "+key+" \n\t\t valore: "+parser.symbol_table.get(key)+"\n");
}
 
}
}
 
XML custom: tag e attributi personalizzati
<PWXML id="100">
<COMANDO name="invioLibri">
<PROPRIETA name="utente" value="francesco pasturenzi"/>
<PROPRIETA name="categoria" value="Informatica"/>
<LISTA timestamp="20140203121212">
<ITEM name="Pro Puppet">
per scrivere ricette PaaS
</ITEM>
<ITEM name="Big Data for Dummies" value="150"/>
</LISTA>
</COMANDO>
</PWXML>
 
Output console
 
Microsoft Windows [Version 6.1.7601]
Copyright (c) 2009 Microsoft Corporation.  All rights reserved.
 
C:\Users\f.pasturenzi>jflex
 
C:\Users\f.pasturenzi>cd c:\tooljava\test\PWXML-protocollo
 
c:\tooljava\test\PWXML-protocollo>dir
 Volume in drive C is OSDisk
 Volume Serial Number is 4091-BD8E
 
 Directory of c:\tooljava\test\PWXML-protocollo
 
28/02/2014  17:58    <DIR>          .
28/02/2014  17:58    <DIR>          ..
11/02/2014  12:27               628 Main.java
28/02/2014  17:57             8.958 parser.cup
28/02/2014  17:35             2.706 scanner.flex
28/02/2014  17:58            25.525 scanner.java
28/02/2014  17:53               355 xmlInvioLibri.txt
               5 File(s)         38.172 bytes
               2 Dir(s)  409.591.697.408 bytes free
 
c:\tooljava\test\PWXML-protocollo>java java_cup/Main parser.cup
Opening files...
Parsing specification from standard input...
Checking specification...
Building parse tables...
  Computing non-terminal nullability...
  Computing first sets...
  Building state machine...
  Filling in tables...
  Checking for non-reduced productions...
Writing parser...
Closing files...
------- CUP v0.10k Parser Generation Summary -------
  0 errors and 0 warnings
  24 terminals, 24 non-terminals, and 46 productions declared,
  producing 132 unique parse states.
  0 terminals declared but not used.
  0 non-terminals declared but not used.
  0 productions never reduced.
  0 conflicts detected (0 expected).
  Code written to "parser.java", and "sym.java".
---------------------------------------------------- (v0.10k)
 
c:\tooljava\test\PWXML-protocollo>javac *.java
 
c:\tooljava\test\PWXML-protocollo>DIR
 Volume in drive C is OSDisk
 Volume Serial Number is 4091-BD8E
 
 Directory of c:\tooljava\test\PWXML-protocollo
 
28/02/2014  17:59    <DIR>          .
28/02/2014  17:59    <DIR>          ..
28/02/2014  17:59             8.851 CUP$parser$actions.class
28/02/2014  17:58             1.372 Main.class
11/02/2014  12:27               628 Main.java
28/02/2014  17:59             5.142 parser.class
28/02/2014  17:57             8.958 parser.cup
28/02/2014  17:58            47.723 parser.java
28/02/2014  17:59            10.286 scanner.class
28/02/2014  17:35             2.706 scanner.flex
28/02/2014  17:58            25.525 scanner.java
28/02/2014  17:59               989 sym.class
28/02/2014  17:58             1.320 sym.java
28/02/2014  17:53               355 xmlInvioLibri.txt
              12 File(s)        113.855 bytes
               2 Dir(s)  409.591.603.200 bytes free
 
c:\tooljava\test\PWXML-protocollo>Main xmlInvioLibri.txt
'Main' is not recognized as an internal or external command,
operable program or batch file.
 
c:\tooljava\test\PWXML-protocollo>java Main xmlInvioLibri.txt
PARSERRIZZO...
ATTR. PWXML:  ID=100
ATTR. COMANDO:  NAME=invioLibri
ATTR. PROPRIETA:  NAME=utente VALUE=francesco pasturenzi
ATTR. PROPRIETA:  NAME=categoria VALUE=Informatica
ATTR. LISTA:  TIMESTAMP=20140203121212
ATTR. ITEM: NAME=Pro Puppet
BODY ITEM: per scrivere ricette PaaS
ATTR. ITEM:  NAME=Big Data for Dummies VALUE=150
 
INFO: errMex = "empty"  & flagError = false
INFO: FINE PARSER!
 
Chiave: ID
                 valore: 100
 
Chiave: utente
                 valore: francesco pasturenzi
 
Chiave: TIMESTAMP
                 valore: 20140203121212
 
Chiave: Pro Puppet
                 valore: per scrivere ricette PaaS
 
Chiave: Big Data for Dummies
                 valore: 150
 
Chiave: COMANDO-NAME
                 valore: invioLibri
 
Chiave: categoria
                 valore: Informatica
 
 
c:\tooljava\test\PWXML-protocollo>
 
You can find this project on my GitHub Repository at this repository URL: https://github.com/pastuweb/jflex-cup-xml-parser-scanner