Declaración de Terminales y No Terminales
La lista de símbolos que se declaran en la especificación sirve para nombrar y definir el tipo de cada uno de los símbolos terminales y no terminales que aparecen en la gramática. Debe cuidarse que el nombre de cada uno de los símbolos sea diferente de las palabras reservadas de CUP. Cada símbolo se representa en tiempo de ejecución como un objeto de tipo Symbol. En el caso de los terminales, son retornados por el scanner y colocados en el stack del parser. El lexer debería proveer el valor del terminal en la instancia de variable value. En el caso de los no terminales, reemplazan una serie de objetos Symbol en el stack si se reconoce el lado derecho de alguna producción. Las declaraciones de terminales y no terminales se utilizan para que el parser tenga conocimiento de qué tipo de objetos debería ser usado para cada símbolo. La declaración tiene la forma:
terminal classname name1, name2, ...; non terminal classname name1, name2, ...;
y
terminal name1, name2, ...; non terminal name1, name2, ...;
donde classname puede estar compuesta por varias partes separadas por ".". La classname especificada representa el tipo de valor del símbolo. Si no se declara ninguna classname, el símbolo no toma ningún valor, y cualquier referencia a dicho símbolo tendrá valor null. Los no terminales pueden definirse tanto con la palabra "nonterminal" (sin espacio en blanco) como con las palabras "non terminal" (con espacio).