Olá,
Não resisti, e já escrevi o parser tbm no método main, melhore isso ok?
Fiz várias modificações na gramática tbm.
Gramática:
grammar Robo;
// regras sintáticas (iniciam com letra minúscula
programa : INICIO ';' (comandos ';')* FIM ';';
comandos : MOVE_MOTOR '(' NUMERO ')'
| MOVE_ROBO '(' NUMERO ',' NUMERO ',' NUMERO ',' NUMERO ')'
| ESPERA_ENTRADA '(' NUMERO ')'
| ABRE_GARRA
| FECHA_GARRA;
// regras léxicas (iniciam com letras maiúsculas)
INICIO : 'Inicio';
FIM : 'Fim';
MOVE_MOTOR : 'Move_motor';
MOVE_ROBO : 'Move_robo';
ESPERA_ENTRADA : 'Espera_entrada';
ABRE_GARRA : 'Abre_garra';
FECHA_GARRA : 'Fecha_garra';
NUMERO : ('-')? ('0'..'9')+;
Parser:
package testeslexers;
import org.antlr.runtime.ANTLRStringStream;
import org.antlr.runtime.CommonTokenStream;
import org.antlr.runtime.Token;
import static testeslexers.RoboLexer.*;
/**
*
* @author David Buzatto
*/
public class Main {
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
String codigo = "Inicio;"
+ "Abre_garra;"
+ "Move_motor(20);"
+ "Move_robo(20,-1,2,0);"
+ "Move_motor(50);"
+ "Move_robo(-5,-10,7,55);"
+ "Move_motor(-30);"
+ "Move_robo(80,40,-30,-10);"
+ "Espera_entrada(7);"
+ "Fecha_garra;"
+ "Fim;";
RoboLexer lexer = new RoboLexer(
new ANTLRStringStream( codigo ) );
Token t = lexer.nextToken();
while ( t.getType() != EOF ) {
switch ( t.getType() ) {
case INICIO:
// consome o ";"
lexer.nextToken();
break;
case MOVE_MOTOR:
// consome o "("
lexer.nextToken();
// consome o parâmetro
t = lexer.nextToken();
int p = Integer.parseInt( t.getText() );
System.out.printf( "Move motor: %d\n", p );
// consome o ")"
lexer.nextToken();
// consome o ";"
lexer.nextToken();
break;
case MOVE_ROBO:
// consome o "("
lexer.nextToken();
// consome o parâmetro
t = lexer.nextToken();
int p1 = Integer.parseInt( t.getText() );
lexer.nextToken(); // consome a vírgula
t = lexer.nextToken();
int p2 = Integer.parseInt( t.getText() );
lexer.nextToken();
t = lexer.nextToken();
int p3 = Integer.parseInt( t.getText() );
lexer.nextToken();
t = lexer.nextToken();
int p4 = Integer.parseInt( t.getText() );
System.out.printf( "Move robo: %d, %d, %d, %d\n", p1, p2, p3, p4 );
// consome o ")"
lexer.nextToken();
// consome o ";"
lexer.nextToken();
break;
case ESPERA_ENTRADA:
// consome o "("
lexer.nextToken();
// consome o parâmetro
t = lexer.nextToken();
int pe = Integer.parseInt( t.getText() );
System.out.printf( "Espera entrada: %d\n", pe );
// consome o ")"
lexer.nextToken();
// consome o ";"
lexer.nextToken();
break;
case ABRE_GARRA:
System.out.println( "Abre garra" );
// consome o ";"
lexer.nextToken();
break;
case FECHA_GARRA:
System.out.println( "Fecha garra" );
// consome o ";"
lexer.nextToken();
break;
case FIM:
// consome o EOF
lexer.nextToken();
break;
}
t = lexer.nextToken();
}
}
}
Note que os espaços em branco ainda não são tratados e que eu retirei o sinal de + dos números por dois motivos: primeiro, a convenção para números positivos é não usar sinal; segundo, se você tentar dar um parseInt em um "+2" vai ocorrer uma NumberFormatException.
Veja que em cada lugar que coloquei um System.out.printf ou println é o lugar onde o comando já foi analizado e os parâmetros já estão carregados, bastando você mandar o robô executar o comando.
Outra coisa. Usei o ANTLR Works para editar a gramática e para gerar o código Java do lexer e do parser.
Como "tarefa" você pode então modificar a gramática para aceitar espaços em branco e ainda melhorar ela ainda mais.
Uma observação importante: as regras léxicas são tratadas como terminais na gramática e devem SEMPRE iniciar com letra maiúscula. As regras sintáticas representam os não terminais e suas respectivas regras de produção. Note que nessas produções você pode usar alguns meta-símbolos de expressões regulares (como o * por exemplo), o que não é permitido em uma gramática livre de contexto normal.
Segue em anexo os arquivos gerados, a gramática e os diagramas sintáticos.
P.S. Faltou falar: os erros sintáticos não estão sendo tratados tbm :(