GwieF.com : project.GrieF.com : Classes : CSGparser
logo

CSGparser.java


package com.gwief.jTrace;

/*
    CSGparser.java by Damian Newport
    Parses the given URL filling the given scene3D with the described model
*/

import java.io.*;
import java.net.*;
import java.util.*;

public class CSGparser {
    Scene3D scene;
    double width;
    double height;
    
    public String error = "Unknown Error!";
    
    StreamTokenizer st;
    Vector Names = new Vector();
    Vector Lights = new Vector();
    URL page;

    public CSGparser(Scene3D Scene, double Width, double Height){
        scene = Scene;
        width = Width;
        height = Height;
    }
    
    public final boolean parse(String filename){
        /* Camera */
        // Camera cam = new Camera(new Vector3D(0,0,-10), new Vector3D(0,0,10), new Vector3D(-1,0,0), width, height, 40);
        Camera cam = new Camera(new Vector3D(0,0,-10), 0,0,0, width, height, 40);
        scene.setcamera(cam);
        
        if(filename.compareTo("none") == 0){
            
            /* Demo Render */
            
            Shape3D planea = new Shape3D("planea", 5);
            planea.transform.addRotateX(-90);
            planea.material.setcolor(1,0,0);
            scene.addshape(planea);

            Light lighta = new Light(new Vector3D(0,0,-10), new Color3D(1,1,1), 20);
            scene.addlight(lighta);


            scene.setCSGstart(planea);
            
            return true;
        }
        
        if (! getfile(filename)){
            return false;
        }
        if (! parser()){
            return false;
        }
        

        
        return true;
    }
    

    
    boolean getfile(String address){
        try {
            page = new URL(address);
            getData(page);
        } catch (MalformedURLException e){
            error = "Bad URL: " + address;
            return false;
        }
        return true;
    }
        
    boolean getData(URL url){
        URLConnection conn = null;
        InputStreamReader in;
        BufferedReader data;
        try {
            conn = this.page.openConnection();
            conn.connect();
            
            in = new InputStreamReader(conn.getInputStream());
            data = new BufferedReader(in);

            /* setup tokeniser */
            st = new StreamTokenizer(data);
            st.slashSlashComments(true);
            st.slashStarComments(true);
            st.lowerCaseMode(true);
            st.quoteChar(034);
            
        } catch(IOException e) {
            error = "Error! " + e.toString();
            return false;
        }
        return true;
    }
    
    int nexttoken (){
        try {
            return st.nextToken();
        }catch (IOException e){
            error = "Error! " + e.toString();
            return st.TT_EOF;
        }
    }
    
    boolean parser (){
        
        final String SHAPE = "shape";
        final String CSGNODE = "node";
        final String CSGSTART = "startnode";
        final String LIGHT = "light";
        final String SCENE = "scene";
        
        boolean done = false;
        int c;
        while (! done) {
            c = nexttoken();
            switch (c) {
                case StreamTokenizer.TT_EOF:
                    return true;
                case StreamTokenizer.TT_WORD:
                    if (st.sval.compareTo(SHAPE) == 0){
                        if (! shape()){
                            return false;
                        }
                    }else if (st.sval.compareTo(CSGNODE) == 0){
                        if (! csgnode()){
                            return false;
                        }
                        
                    }else if (st.sval.compareTo(CSGSTART) == 0){
                        if (! csgstart()){
                            return false;
                        }
                    }else if (st.sval.compareTo(LIGHT) == 0){
                        if (! light()){
                            return false;
                        }
                    }else if (st.sval.compareTo(SCENE) == 0){
                        if (! doscene()){
                            return false;
                        }
                    }
                    break;
                default:
                    error = "Unexpected " + st.toString();
                    return false;
            }
        }
        return false;
    }

    boolean shape (){
        int c;
        boolean built = false;
        
        final String BOX = "box";
        final String SPHERE = "sphere";
        final String CYLINDER = "cylinder";
        final String CONE = "cone";
        final String HYPERBOLOID = "hyperboloid";
        
        int expect = 'N';
        int Shape = 0;      // default shape = sphere
        String Shapename = "";
        Shape3D thisShape = new Shape3D("temp");
        
        while (true){
            c = nexttoken();
            switch (c) {
                case StreamTokenizer.TT_EOF:
                    error = "Unexpected End Of File";
                    return false;
                case StreamTokenizer.TT_WORD:
                    if (expect == 'S'){
                        if (st.sval.compareTo(SPHERE) == 0){
                            Shape = 0;
                        }else if (st.sval.compareTo(BOX) == 0){
                            Shape = 1;
                        }else if (st.sval.compareTo(CYLINDER) == 0){
                            Shape = 2;
                        }else if (st.sval.compareTo(CONE) == 0){
                            Shape = 3;
                        }else if (st.sval.compareTo(HYPERBOLOID) == 0){
                            Shape = 4;
                        }else {
                            error = "Unknown shape '" + st.sval + "' on line " + st.lineno();
                            return false;
                        }
                        expect = ')';
                        break;
                    }else if (expect == 'N'){
                        Shapename = st.sval;
                        expect = '(';
                    }else{
                        error = "Unexpected " + st.toString();
                        return false;
                    }
                    break;
                default:
                    if (c == expect){
                        switch (expect){
                            case '(':
                                expect = 'S';
                                break;
                            case ')':
                                expect = '{';
                                if (! CheckNames(Shapename)){
                                    thisShape = addshape(Shapename,Shape);
                                    built = true;
                                }else{
                                    error = "Error! Name '" + Shapename + "' already taken, at line " + st.lineno();
                                    return false;
                                }
                                break;
                            case '{':
                                if (built == true){
                                    if (! shapeop(thisShape)){
                                        return false;
                                    }
                                    return true;
                                }else{
                                    error = "Unexpected " + st.toString();
                                    return false;
                                }
                            default:
                                error = "Unexpected " + st.toString();
                                return false;
                        }
                    }
                    break;
            }
        }
    }
    
    /* returns true if the name is found */
    private final boolean CheckNames(String a){
        Iterator it = Names.iterator();
        Node temp;
        while(it.hasNext()){
            temp = (Node)it.next();
            if (a.compareTo(temp.name) == 0){
                return true;
            }
        }
        return false;
    }
    
    /* returns the CSGnode associated with the name */
    private final CSGnode getName(String a){
        Iterator it = Names.iterator();
        Node temp;
        while(it.hasNext()){
            temp = (Node)it.next();
            if (a.compareTo(temp.name) == 0){
                return temp.getCSGnode();
            }
        }
        return null;
    }
    
    private final Shape3D addshape(String name, int type){
        Shape3D temp = new Shape3D(name, type);
        scene.addshape(temp);
        Node nod = new Node(temp, name);
        Names.add(nod);
        return temp;
    }
    
    private final CSGnode addnode(String name, CSGnode nodea, int op, CSGnode nodeb){
        CSGnode temp = new CSGnode(nodea, op, nodeb);
        Names.add(new Node(temp, name));
        return temp;
    }
    
    private final boolean shapeop(Shape3D shape){
        
        final String TRANSLATE = "translate";
        final String ROTATEX = "rotatex";
        final String ROTATEY = "rotatey";
        final String ROTATEZ = "rotatez";
        final String ROTATE = "rotate";
        final String SCALE = "scale";
        
        final String COLOR = "color";
        final String N = "shine";
        final String KS = "specular";
        final String KD = "diffuse";
        final String TRANSPARENCY = "transparency";
        final String REFLECTION = "reflection";
        final String DENSITY = "density";

        boolean tra = false;    // have we translated
        boolean rot = false;    // have we rotated
        boolean sca = false;    // have we scaled
        
        final char COMMAND = 'C';
        final char NUMBER = 'N';
        
        char expect = COMMAND;
        String op = "";
        boolean triad = false;
        
        int count = 0;
        double num1=0;
        double num2=0;
        double num3=0;
        
        int c;
        while (true) {
            c = nexttoken();
            switch (c) {
                case StreamTokenizer.TT_EOF:
                    error = "Unexpected End Of File";
                    return false;
                case StreamTokenizer.TT_WORD:
                    if(COMMAND == expect){
                        if (st.sval.compareTo(TRANSLATE) == 0){
                            op = TRANSLATE;
                            triad = true;
                        }else if (st.sval.compareTo(ROTATEX) == 0){
                            op = ROTATEX;
                            triad = false;
                        }else if (st.sval.compareTo(ROTATEY) == 0){
                            op = ROTATEY;
                            triad = false;
                        }else if (st.sval.compareTo(ROTATEZ) == 0){
                            op = ROTATEZ;
                            triad = false;
                        }else if (st.sval.compareTo(ROTATE) == 0){
                            op = ROTATE;
                            triad = true;
                        }else if (st.sval.compareTo(SCALE) == 0){
                            op = SCALE;
                            triad = true;
                        }else if (st.sval.compareTo(COLOR) == 0){
                            op = COLOR;
                            triad = true;
                        }else if (st.sval.compareTo(N) == 0){
                            op = N;
                            triad = false;
                        }else if (st.sval.compareTo(KS) == 0){
                            op = KS;
                            triad = false;
                        }else if (st.sval.compareTo(KD) == 0){
                            op = KD;
                            triad = false;
                        }else if (st.sval.compareTo(TRANSPARENCY) == 0){
                            op = TRANSPARENCY;
                            triad = false;
                        }else if (st.sval.compareTo(REFLECTION) == 0){
                            op = REFLECTION;
                            triad = false;
                        }else if (st.sval.compareTo(DENSITY) == 0){
                            op = DENSITY;
                            triad = false;
                        }else{
                            error = "Unexpected " + st.toString();
                            return false;
                        }
                        expect = '(';
                        break;
                    }else{
                        error = "Unexpected " + st.toString();
                        return false;
                    }
                case StreamTokenizer.TT_NUMBER:
                    if (expect == NUMBER){
                        if (triad == false){
                            num1 = st.nval;
                            expect = ')';
                        }else{
                            if(count == 0){
                                num1 = st.nval;
                                count++;
                                expect = ',';
                            }else if(count == 1){
                                num2 = st.nval;
                                count++;
                                expect = ',';
                            }else if(count == 2){
                                num3 = st.nval;
                                count++;
                                expect = ')';
                            }else{
                                error = "Unexpected " + st.toString();
                                return false;
                            }
                        }
                        break;
                    }else{
                        error = "Unexpected " + st.toString();
                        return false;
                    }
                default:
                    if (c == expect){
                        switch (expect){
                            case '(':
                                expect = NUMBER;
                                break;
                            case ')':
                                expect = ';';
                                break;
                            case ',':
                                expect = NUMBER;
                                break;
                            case ';':
                                if (op.compareTo(TRANSLATE) == 0){
                                    if(Math.abs(num1) > rayTrace.MAX){
                                        error = "x translation outside valid range on line " + st.lineno();
                                        return false;
                                    }
                                    if(Math.abs(num2) > rayTrace.MAX){
                                        error = "y translation outside valid range on line " + st.lineno();
                                        return false;
                                    }
                                    if(Math.abs(num3) > rayTrace.MAX){
                                        error = "z translation outside valid range on line " + st.lineno();
                                        return false;
                                    }
                                    shape.transform.addTranslate(num1,num2,num3);
                                    count = 0;
                                    expect = COMMAND;
                                    break;
                                }else if (op.compareTo(ROTATEX) == 0){
                                    shape.transform.addRotateX(num1);
                                    count = 0;
                                    expect = COMMAND;
                                    break;
                                }else if (op.compareTo(ROTATEY) == 0){
                                    shape.transform.addRotateY(num1);
                                    count = 0;
                                    expect = COMMAND;
                                    break;
                                }else if (op.compareTo(ROTATEZ) == 0){
                                    shape.transform.addRotateZ(num1);
                                    count = 0;
                                    expect = COMMAND;
                                    break;
                                }else if (op.compareTo(ROTATE) == 0){
                                    shape.transform.addRotate(num1,num2,num3);
                                    count = 0;
                                    expect = COMMAND;
                                    break;
                                }else if (op.compareTo(SCALE) == 0){
                                    if ((num1 < rayTrace.TINY) || (num2 < rayTrace.TINY) || (num3 < rayTrace.TINY)){
                                        error = "Unable to scale by ~ 0, on line " + st.lineno();
                                        return false;
                                    }
                                    shape.transform.addScale(num1,num2,num3);
                                    count = 0;
                                    expect = COMMAND;
                                    break;
                                }else if (op.compareTo(COLOR) == 0){
                                    if((num1 > 1) || (num1 < 0)){
                                        error = "red outside valid range on line " + st.lineno();
                                        return false;
                                    }
                                    if((num2 > 1) || (num2 < 0)){
                                        error = "green valid range on line " + st.lineno();
                                        return false;
                                    }
                                    if((num3 > 1) || (num3 < 0)){
                                        error = "blue valid range on line " + st.lineno();
                                        return false;
                                    }
                                    shape.material.setcolor(num1,num2,num3);
                                    count = 0;
                                    expect = COMMAND;
                                    break;
                                }else if (op.compareTo(N) == 0){
                                    shape.material.setn(num1);
                                    count = 0;
                                    expect = COMMAND;
                                    break;
                                }else if (op.compareTo(KS) == 0){
                                    if((num1 > 1) || (num1 < 0)){
                                        error = "Ks outside valid range on line " + st.lineno();
                                        return false;
                                    }
                                    shape.material.setKs(num1);
                                    count = 0;
                                    expect = COMMAND;
                                    break;
                                }else if (op.compareTo(KD) == 0){
                                    if((num1 > 1) || (num1 < 0)){
                                        error = "Kd outside valid range on line " + st.lineno();
                                        return false;
                                    }
                                    shape.material.setKd(num1);
                                    count = 0;
                                    expect = COMMAND;
                                    break;
                                }else if (op.compareTo(REFLECTION) == 0){
                                    if((num1 > 1) || (num1 < 0)){
                                        error = "reflection outside valid range on line " + st.lineno();
                                        return false;
                                    }
                                    shape.material.setreflect(num1);
                                    count = 0;
                                    expect = COMMAND;
                                    break;
                                }else if (op.compareTo(TRANSPARENCY) == 0){
                                    if((num1> 1) || (num1 < 0)){
                                        error = "transparency outside valid range on line " + st.lineno();
                                        return false;
                                    }
                                    shape.material.settransparency(num1);
                                    count = 0;
                                    expect = COMMAND;
                                    break;
                                }else if (op.compareTo(DENSITY) == 0){
                                    if((num1 > 1) || (num1 < 0)){
                                        error = "density outside valid range on line " + st.lineno();
                                        return false;
                                    }
                                    shape.material.setdensity(num1);
                                    count = 0;
                                    expect = COMMAND;
                                    break;
                                }else{
                                    error = "Unexpected " + st.toString();
                                    return false;
                                }
                            default:
                                error = "Unexpected " + st.toString();
                                return false;
                        }
                        break;
                    }else if (c == '}'){
                        if (expect == COMMAND){
                            return true;
                        }else{
                            error = "Unexpected " + st.toString();
                            return false;
                        }
                    }else{
                        error = "Unexpected " + st.toString();
                        return false;
                    }
            }       
        }
    }
    
    private final boolean csgnode(){

        final String ADD = "add";
        final String SUBTRACT = "subtract";
        final String INTERSECT = "intersect";
        final String BAH = "difference";
        
        final char NODE = 'N';
        final char NAME = 'Q';
        final char OP = 'O';
        
        char expect = NAME;
        
        String name = "";
        int op = -1;
        
        boolean built = false;
        boolean donenode1 = false;
        CSGnode node1;
        CSGnode node2 = node1 = new CSGnode();
        CSGnode thisnode = new CSGnode();
        
        int c;
        while (true) {
            c = nexttoken();
            switch (c) {
                case StreamTokenizer.TT_EOF:
                    error = "Unexpected End Of File";
                    return false;
                case StreamTokenizer.TT_WORD:
                    if (expect == NODE){
                        if (CheckNames(st.sval)){
                            if (! donenode1){
                                node1 = getName(st.sval);
                                donenode1 = true;
                                expect = ',';
                                break;
                            }else{
                                node2 = getName(st.sval);
                                expect = ')';
                                break;
                            }
                        }else{
                            error = "Unrecognised CSGnode or Shape '" + st.sval + "' on line " + st.lineno();
                            return false;
                        }
                    }else if (expect == NAME){
                            if (! CheckNames(st.sval)){
                                name = st.sval;
                                expect = '(';
                                break;
                            }else{
                                error = "Error one line " + st.lineno() + " Name '" + st.sval + "' already taken";
                                return false;
                            }
                    }else if (expect == OP){
                        if (st.sval.compareTo(ADD) == 0){
                            op = 0;
                            expect = ',';
                            break;
                        }else if (st.sval.compareTo(INTERSECT) == 0){
                            op = 1;
                            expect = ',';
                            break;
                        }else if (st.sval.compareTo(BAH) == 0){
                            op = 2;
                            expect = ',';
                            break;
                        }else if (st.sval.compareTo(SUBTRACT) == 0){
                            op = 3;
                            expect = ',';
                            break;
                        }else{
                            error = "Unexpected " + st.toString();
                            return false;
                        }
                    }else{
                        error = "Unexpected " + st.toString();
                        return false;
                    }
                default:
                    if (c == expect){
                        switch (expect){
                            case '(':
                                expect = NODE;
                                break;
                            case ')':
                                thisnode = addnode(name, node1, op, node2);
                                built = true;
                                expect = '{';
                                break;
                            case '{':
                                if (built == true){
                                    if (! nodeop(thisnode)){
                                        return false;
                                    }
                                    return true;
                                }else{
                                    error = "Unexpected " + st.toString();
                                    return false;
                                }
                            case ',':
                                if (op == -1){
                                    expect = OP;
                                    break;
                                }else{
                                    expect = NODE;
                                    break;
                                }
                            default:
                                error = "Unexpected " + st.toString();
                                return false;
                    }
                }else{
                    error = "Unexpected " + st.toString();
                    return false;
                }
            }
        }
    }
    
    private final boolean nodeop(CSGnode node){
        
        final String TRANSLATE = "translate";
        final String ROTATEX = "rotatex";
        final String ROTATEY = "rotatey";
        final String ROTATEZ = "rotatez";
        final String ROTATE = "rotate";
        final String SCALE = "scale";
        
        boolean tra = false;    // have we translated
        boolean rot = false;    // have we rotated
        boolean sca = false;    // have we scaled
        
        final char COMMAND = 'C';
        final char NUMBER = 'N';
        
        char expect = COMMAND;
        String op = "";
        boolean triad = false;
        
        int count = 0;
        double num1=0;
        double num2=0;
        double num3=0;
        
        int c;
        while (true) {
            c = nexttoken();
            switch (c) {
                case StreamTokenizer.TT_EOF:
                    error = "Unexpected End Of File";
                    return false;
                case StreamTokenizer.TT_WORD:
                    if(COMMAND == expect){
                        if (st.sval.compareTo(TRANSLATE) == 0){
                            op = TRANSLATE;
                            triad = true;
                        }else if (st.sval.compareTo(ROTATEX) == 0){
                            op = ROTATEX;
                            triad = false;
                        }else if (st.sval.compareTo(ROTATEY) == 0){
                            op = ROTATEY;
                            triad = false;
                        }else if (st.sval.compareTo(ROTATEZ) == 0){
                            op = ROTATEZ;
                            triad = false;
                        }else if (st.sval.compareTo(ROTATE) == 0){
                            op = ROTATE;
                            triad = true;
                        }else if (st.sval.compareTo(SCALE) == 0){
                            op = SCALE;
                            triad = true;
                        }else{
                            error = "Unexpected " + st.toString();
                            return false;
                        }
                        expect = '(';
                        break;
                    }else{
                        error = "Unexpected " + st.toString();
                        return false;
                    }
                case StreamTokenizer.TT_NUMBER:
                    if (expect == NUMBER){
                        if (triad == false){
                            num1 = st.nval;
                            expect = ')';
                        }else{
                            if(count == 0){
                                num1 = st.nval;
                                count++;
                                expect = ',';
                            }else if(count == 1){
                                num2 = st.nval;
                                count++;
                                expect = ',';
                            }else if(count == 2){
                                num3 = st.nval;
                                count++;
                                expect = ')';
                            }else{
                                error = "Unexpected " + st.toString();
                                return false;
                            }
                        }
                        break;
                    }else{
                        error = "Unexpected " + st.toString();
                        return false;
                    }
                default:
                    if (c == expect){
                        switch (expect){
                            case '(':
                                expect = NUMBER;
                                break;
                            case ')':
                                expect = ';';
                                break;
                            case ',':
                                expect = NUMBER;
                                break;
                            case ';':
                                if (op.compareTo(TRANSLATE) == 0){
                                    if(Math.abs(num1) > rayTrace.MAX){
                                        error = "x translation outside valid range on line " + st.lineno();
                                        return false;
                                    }
                                    if(Math.abs(num2) > rayTrace.MAX){
                                        error = "y translation outside valid range on line " + st.lineno();
                                        return false;
                                    }
                                    if(Math.abs(num3) > rayTrace.MAX){
                                        error = "z translation outside valid range on line " + st.lineno();
                                        return false;
                                    }
                                    node.transform.addTranslate(num1,num2,num3);
                                    count = 0;
                                    expect = COMMAND;
                                    break;
                                }else if (op.compareTo(ROTATEX) == 0){
                                    node.transform.addRotateX(num1);
                                    count = 0;
                                    expect = COMMAND;
                                    break;
                                }else if (op.compareTo(ROTATEY) == 0){
                                    node.transform.addRotateY(num1);
                                    count = 0;
                                    expect = COMMAND;
                                    break;
                                }else if (op.compareTo(ROTATEZ) == 0){
                                    node.transform.addRotateZ(num1);
                                    count = 0;
                                    expect = COMMAND;
                                    break;
                                }else if (op.compareTo(ROTATE) == 0){
                                    node.transform.addRotate(num1,num2,num3);
                                    count = 0;
                                    expect = COMMAND;
                                    break;
                                }else if (op.compareTo(SCALE) == 0){
                                    if ((num1 < rayTrace.TINY) || (num2 < rayTrace.TINY) || (num3 < rayTrace.TINY)){
                                        error = "Unable to scale by ~ 0, on line " + st.lineno();
                                        return false;
                                    }
                                    node.transform.addScale(num1,num2,num3);
                                    count = 0;
                                    expect = COMMAND;
                                    break;
                                }else{
                                    error = "Unexpected " + st.toString();
                                    return false;
                                }
                            default:
                                error = "Unexpected " + st.toString();
                                return false;
                        }
                        break;
                    }else if (c == '}'){
                        if (expect == COMMAND){
                            return true;
                        }else{
                            error = "Unexpected " + st.toString();
                            return false;
                        }
                    }else{
                        error = "Unexpected " + st.toString();
                        return false;
                    }
            }       
        }
    }
    
    private final boolean csgstart(){
        int c = nexttoken();
        if (CheckNames(st.sval)){
            String temp = st.sval;
            c = nexttoken();
            if (c == ';'){
                scene.setCSGstart(getName(temp));
                return true;
            }else{
                error = "Error! Unexpected " + st.toString() + " Expecting ';'";
                return false;
            }
        }
        error = "Unrecognised CSGnode or Shape '" + st.sval + "' on line " + st.lineno();
        return false;
    }
    
    private final boolean light(){
        Light light = new Light();
        String Name = "";
        
        final String COLOR = "color";
        final String POSITION = "position";
        final String INTENSITY = "intensity";

        final char COMMAND = 'C';
        final char NUMBER = 'N';
        final char NAME = 'L';
        
        char expect = NAME;
        String op = "";
        boolean triad = false;
        boolean built = false;
        
        int count = 0;
        double num1=0;
        double num2=0;
        double num3=0;
        
        int c;
        while (true) {
            c = nexttoken();
            switch (c) {
                case StreamTokenizer.TT_EOF:
                    error = "Unexpected End Of File";
                    return false;
                case StreamTokenizer.TT_WORD:
                    if(NAME == expect){
                        Name = st.sval;
                        expect = '{';
                        break;
                    }else if(COMMAND == expect){
                        if (st.sval.compareTo(COLOR) == 0){
                            op = COLOR;
                            triad = true;
                            expect = '(';
                        }else if (st.sval.compareTo(POSITION) == 0){
                            op = POSITION;
                            triad = true;
                            expect = '(';
                        }else if (st.sval.compareTo(INTENSITY) == 0){
                            op = INTENSITY;
                            triad = false;
                            expect = '(';
                        }else{
                            error = "Unexpected " + st.toString();
                            return false;
                        }
                        break;
                    }else{
                        error = "Unexpected " + st.toString();
                        return false;
                    }
                case StreamTokenizer.TT_NUMBER:
                    if (expect == NUMBER){
                        if (triad == false){
                            num1 = st.nval;
                            expect = ')';
                        }else{
                            if(count == 0){
                                num1 = st.nval;
                                count++;
                                expect = ',';
                            }else if(count == 1){
                                num2 = st.nval;
                                count++;
                                expect = ',';
                            }else if(count == 2){
                                num3 = st.nval;
                                count++;
                                expect = ')';
                            }else{
                                error = "Unexpected " + st.toString();
                                return false;
                            }
                        }
                        break;
                    }else{
                        error = "Unexpected " + st.toString();
                        return false;
                    }
                default:
                    if (c == expect){
                        switch (expect){
                            case '{':
                                light = addlight(Name);
                                built = true;
                                expect = COMMAND;
                                break;
                            case '(':
                                expect = NUMBER;
                                break;
                            case ')':
                                expect = ';';
                                break;
                            case ',':
                                expect = NUMBER;
                                break;
                            case ';':
                                if (op.compareTo(COLOR) == 0){
                                    if((num1 > 1) || (num1 < 0)){
                                        error = "red outside valid range on line " + st.lineno();
                                        return false;
                                    }
                                    if((num2 > 1) || (num2 < 0)){
                                        error = "green outside valid range on line " + st.lineno();
                                        return false;
                                    }
                                    if((num3 > 1) || (num3 < 0)){
                                        error = "blue outside valid range on line " + st.lineno();
                                        return false;
                                    }
                                    light.setcolor(num1,num2,num2);
                                    count = 0;
                                    expect = COMMAND;
                                    break;
                                }else if (op.compareTo(POSITION) == 0){
                                    if(Math.abs(num1) > rayTrace.MAX){
                                        error = "x position outside valid range on line " + st.lineno();
                                        return false;
                                    }
                                    if(Math.abs(num2) > rayTrace.MAX){
                                        error = "y position outside valid range on line " + st.lineno();
                                        return false;
                                    }
                                    if(Math.abs(num3) > rayTrace.MAX){
                                        error = "z position outside valid range on line " + st.lineno();
                                        return false;
                                    }
                                    light.setposition(num1,num2,num3);
                                    count = 0;
                                    expect = COMMAND;
                                    break;
                                }else if (op.compareTo(INTENSITY) == 0){
                                    if (num1 < 0){
                                        error = "Intensity cannot be negative on line " + st.lineno();
                                        return false;
                                    }
                                    light.setintensity(num1);
                                    count = 0;
                                    expect = COMMAND;
                                    break;
                                }else{
                                    error = "Unexpected " + st.toString();
                                    return false;
                                }
                            default:
                                error = "Unexpected " + st.toString();
                                return false;
                        }
                        break;
                    }else if (c == '}'){
                        if (expect == COMMAND){
                            return true;
                        }else{
                            error = "Unexpected " + st.toString();
                            return false;
                        }
                    }else{
                        error = "Unexpected " + st.toString();
                        return false;
                    }
            }       
        }
    }
    
    /* returns true if the name is found */
    private final boolean CheckLights(String a){
        Iterator it = Lights.iterator();
        Node temp;
        while(it.hasNext()){
            temp = (Node)it.next();
            if (a.compareTo(temp.name) == 0){
                return true;
            }
        }
        return false;
    }
    
    /* returns the Light associated with the name */
    private final Light getLight(String a){
        Iterator it = Lights.iterator();
        Node temp;
        while(it.hasNext()){
            temp = (Node)it.next();
            if (a.compareTo(temp.name) == 0){
                return temp.getLight();
            }
        }
        return null;
    }
    
    private final Light addlight(String name){
        Light temp = new Light();
        scene.addlight(temp);
        Node nod = new Node(temp, name);
        Lights.add(nod);
        return temp;
    }
    
    private final boolean doscene(){
        return true;
    }
}