2012-08-09 15 views
5

Estoy tratando de pensar en una buena forma de analizar cadenas utilizando JavaCC sin confundirlo por error con otro token. Estas cadenas deberían poder tener espacios, letras y números.Análisis de cadenas con JavaCC

Mi identificador y número de contadores son los siguientes:

<IDENTIFIER: (["a"-"z", "A"-"Z"])+> 
<NUMBER: (["0"-"9"])+> 

Mi token de cadena actual es:

<STRING: "\"" (<IDENTIFIER> | <NUMBERS> | " ")+ "\""> 

Idealmente, quiero sólo para salvar la materia que hay dentro de las comillas. Tengo un archivo separado en el que hago el ahorro real de variables y valores. ¿Debo eliminar las citas allí?

en principio había un método en el archivo del analizador de la siguiente manera:

variable=<INDENTIFIER> <ASSIGN> <QUOTE> message=<IDENTIFIER> <QUOTE> 
{File.saveVariable(variable.image, message.image);} 

Pero, como puede imaginar, esto no permitía espacios o números para el caso. Para identificadores como nombres de variables, solo quiero permitir letras.

Así que, me gustaría obtener algunos consejos sobre cómo podría capturar literales de cadenas. En particular, me gustaría hacer cadenas como:

" hello", "hello ", " hello " and "\nhello", "hello\n", "\nhello\n" 

válido en mi sintaxis.

+0

Debería aceptar la respuesta de DerMike, parece ser bastante perfecta. –

Respuesta

10

Al pasar el primer ", su analizador quisiera ingresar en STRING STATE y dejarlo en el siguiente (Bonus: sin comillas) ".

igual:

TOKEN: 
{ 
    <QUOTE:"\""> : STRING_STATE 
} 

<STRING_STATE> MORE: 
{ 
    "\\" : ESC_STATE 
} 

<STRING_STATE> TOKEN: 
{ 
    <ENDQUOTE:<QUOTE>> : DEFAULT 
| <CHAR:~["\"","\\"]> 
} 

<ESC_STATE> TOKEN: 
{ 
    <CNTRL_ESC:["\"","\\","/","b","f","n","r","t"]> : STRING_STATE 
} 

Usted puede utilizar esto como:

/** 
* Match a quoted string. 
*/ 
String string() : 
{ 
    StringBuilder builder = new StringBuilder(); 
} 
{ 
    <QUOTE> (getChar(builder))* <ENDQUOTE> 
    { 
    return builder.toString(); 
    } 
} 

/** 
* Match char inside quoted string. 
*/ 
void getChar(StringBuilder builder): 
{ 
    Token t; 
} 
{ 
    (t = <CHAR> | t = <CNTRL_ESC>) 
    { 
    if (t.image.length() < 2) 
    { 
     // CHAR 
     builder.append(t.image.charAt(0)); 
    } 
    else if (t.image.length() < 6) 
    { 
     // ESC 
     char c = t.image.charAt(1); 
     switch (c) 
     { 
     case 'b': builder.append((char) 8); break; 
     case 'f': builder.append((char) 12); break; 
     case 'n': builder.append((char) 10); break; 
     case 'r': builder.append((char) 13); break; 
     case 't': builder.append((char) 9); break; 
     default: builder.append(c); 
     } 
    } 
    } 
} 

HTH.