/* -*-Java-*- */

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

aspect AbsGrammarGeneration {
    void ASTNode.genAbsGrammar(PrintStream pStream) {
		for (int i=0; i<getNumChild(); i++) {
			getChild(i).genAbsGrammar(pStream);
		}
    }

    public void Start.genAbsGrammar(PrintStream pStream) {
		pStream.println("// Predefined types");
		pStream.println("Start ::= ComplexElement;");
		pStream.println("abstract Thing ::=;");
		pStream.println("abstract Element;");
 		pStream.println("ComplexElement : Element ::=  OwlIdentifier Attribute* Element*;");
// 		pStream.println("ComplexElement ::=  id1:OwlIdentifier id2:OwlIdentifier;");
		pStream.println("abstract SimpleElement : Element;");
		pStream.println("StringElement : SimpleElement ::= OwlIdentifier;");
		pStream.println("IntElement : SimpleElement ::= <INTEGER_LITERAL>;");
		pStream.println("FloatElement : SimpleElement ::= <FLOAT_LITERAL>;");
		pStream.println("Attribute ::= Value;");
		pStream.println("RdfDatatype : Attribute ::= ;");
		pStream.println("RdfId : Attribute ::= ;");
		pStream.println("Xmlns : Attribute ::= ;");
		pStream.println("XmlnsProtege : Attribute ::= ;");
		pStream.println("XmlnsRdf : Attribute ::= ;");
		pStream.println("XmlnsXsd : Attribute ::= ;");
		pStream.println("XmlnsRdfs : Attribute ::= ;");
		pStream.println("XmlnsOwl : Attribute ::= ;");
		pStream.println("XmlnsDaml : Attribute ::= ;");
		pStream.println("XmlnsP1 : Attribute ::= ;");
		pStream.println("XmlnsDc : Attribute ::= ;");
		pStream.println("XmlBase : Attribute ::= ;");
		pStream.println("RdfResource : Attribute ::= ;");
		pStream.println("RdfAbout : Attribute ::= ;");
		pStream.println("RdfParseType : Attribute ::= ;");
		pStream.println("Version : Attribute ::= ;");
		pStream.println("Value ::= <STRING_LITERAL>;");
		pStream.println("OwlIdentifier ::= <IDENTIFIER>;");
		pStream.println("AttrValue ::= <STRING_LITERAL>;");
		pStream.println();
		pStream.println("// Generated types");
		super.genAbsGrammar(pStream);
    }

    void OwlClassDecl.genAbsGrammar(PrintStream pStream) {
		pStream.print(getId());
		pStream.print(" : "+getSuperClass().getId());	
		pStream.print(" ::=");
		Restrictions restrs = getOwnRestrictions();
		for (int i=0; i<restrs.getNumOwlRestriction(); i++) {
			pStream.print(" ");
			restrs.getOwlRestriction(i).genAbsGrammar(pStream);
		}
		pStream.println(";");
    }

    void OwlRestriction.genAbsGrammar(PrintStream pStream) {
// 		pStream.print(getRestrictionPropertyId());
		pStream.print(getRestrictionClassId().substring(0,1).toLowerCase()+
					  getRestrictionClassId().substring(1));
		pStream.print(":");
		pStream.print(getRestrictionClassId());
		if (allValuesFrom()) {
			pStream.print("*");
		}
    }

    String OwlRestriction.getRestrictionPropertyId() {
		for (int i=0; i<getNumElement(); i++) {
			ComplexElement e = (ComplexElement) getElement(i);
			if (e instanceof OwlOnProperty) {
				return e.getId(); 
			}
		}
		return "_Unknown_";
    } 

    String OwlRestriction.getRestrictionClassId() {
		for (int i=0; i<getNumElement(); i++) {
			ComplexElement e = (ComplexElement) getElement(i);
			if (e instanceof OwlAllValuesFrom || 
				e instanceof OwlSomeValuesFrom) {
				return e.getId(); // Ugly as hell!!
			}
		}
		return "_Unknown_";
    } 

    syn lazy boolean OwlRestriction.allValuesFrom() {
		for (int i=0; i<getNumElement(); i++) {
			if (getElement(i) instanceof OwlAllValuesFrom) {
				return true;
			}
		}
		return false;
    }

}



aspect JavaCCGen {

	public void ASTNode.genJavaCC(PrintStream pStream) {
		for (int i=0; i<getNumChild(); i++) {
			getChild(i).genAbsGrammar(pStream);
		}		
	}

	public void Start.genJavaCC(PrintStream pStream) {
		genJavaCCHeader(pStream);
		pStream.println();
		genTokenDefs(pStream);
		pStream.println();
		genJavaCCLiterals(pStream);
		pStream.println();
		genJavaCCIdentifiers(pStream);
		pStream.println();
		genJavaCCSeparators(pStream);
		pStream.println();
		genJavaCCOperators(pStream);
		pStream.println();

		// OK, so now it's time to start generating some real grammar
		// productions.
		genJavaCCGrammar(pStream);
	}

	void ASTNode.genTokenDefs(PrintStream pStream) {
		for (int i=0; i<getNumChild(); i++) {
			getChild(i).genTokenDefs(pStream);
		}		
	}

	void Start.genTokenDefs(PrintStream pStream) {
		pStream.println("<DEFAULT, BOUNDS> TOKEN : /* RESERVED WORDS */");
		pStream.println("{");
		pStream.println("  <XML \t : \"xml\" >");
		super.genTokenDefs(pStream);
		pStream.println("}");
		pStream.println();
	}

	void OwlClassDecl.genTokenDefs(PrintStream pStream) {
		pStream.println(" |<"+getId().toUpperCase()+" \t : \""+getId()+"\">");
	}

	void ASTNode.genJavaCCGrammar(PrintStream pStream) {
		for (int i=0; i<getNumChild(); i++) {
			getChild(i).genJavaCCGrammar(pStream);
		}		
	}

	void Start.genJavaCCGrammar(PrintStream pStream) {
		pStream.println("Start Start() #Start : {}");
		pStream.println("{");
		pStream.println("    (Device())*");
		pStream.println("    { return jjtThis; }");
		pStream.println("}");
		pStream.println();
		super.genJavaCCGrammar(pStream);
	}
	
	void OwlClassDecl.genJavaCCGrammar(PrintStream pStream) {
		pStream.println("void "+getId()+"() : {}");
		pStream.println("{");
		if (getId().equals("Device")) {
			pStream.print("  \"<\"");
// 			pStream.print("\"<\" ( <DEVICE> \">\"");
// 			Restrictions restr = getRestrictions();
// 			for (int i=0; i< getNumRestriction(); i++) {
// 				OwlRestriction res = restr.getOwlRestriction(i);
// 				pStream.print("("+res.getRestrictionClassId()+")"+
// 							  (res.allValuesFrom()?"*":"")+" ");
// 			}
// 			pStream.println(" #Device("+getNumRestriction()+"))");
// 			// List all subclasses
// 			Iterator subIter = getSubClasses().iterator();
// 			while (subIter.hasNext()) {
// 				OwlClassDecl subClass = (OwlClassDecl) subIter.next();
// 				pStream.println("| "+subClass.getId()+"()");
// 			}
		}
		pStream.print("  ( <"+getId().toUpperCase()+"> \">\"");
		Restrictions restr = getRestrictions();
		for (int i=0; i< getNumRestriction(); i++) {
			OwlRestriction res = restr.getOwlRestriction(i);
			pStream.print("("+res.getRestrictionClassId()+"())"+
						  (res.allValuesFrom()?"*":"")+" ");
		}
		pStream.println(" #"+getId()+"("+getNumRestriction()+"))");
		// List all subclasses
		Iterator subIter = getSubClasses().iterator();
		while (subIter.hasNext()) {
			OwlClassDecl subClass = (OwlClassDecl) subIter.next();
			pStream.println("      | "+subClass.getId()+"()");
		}
		pStream.println("}");
	}
}

aspect ParserGen {
	public void Start.genParser(PrintStream pStream) {
		pStream.println("import java.io.FileNotFoundException;");
		pStream.println("import java.io.FileReader;");
		pStream.println("import java.io.InputStreamReader;");
		pStream.println("import java.io.Reader;");
		pStream.println("");
		pStream.println("import AST.SiarasParser;");
		pStream.println("import AST.ParseException;");
		pStream.println("import AST.Start;");
		pStream.println("");
		pStream.println("public class Parser {");
		pStream.println();
		pStream.println("	protected static Start parse(String args[]) {");
		pStream.println("		Reader r = getReader(args);");
		pStream.println("		Start ast = null;");
		pStream.println("		try {");
		pStream.println("			SiarasParser parser = new SiarasParser(r);");
		pStream.println();
		pStream.println("			ast = parser.Start();");
		pStream.println("		} catch (ParseException e) {");
		pStream.println("			System.out.println(e.getMessage());");
		pStream.println("		}");
		pStream.println("		return ast;");
		pStream.println("	}");
		pStream.println();
		pStream.println("	private static Reader getReader(String[] args) {");
		pStream.println("		Reader r = null;");
		pStream.println("		if (args.length != 1) {");
		pStream.println("			r = new InputStreamReader(System.in);");
		pStream.println("		} else {");
		pStream.println("			try {");
		pStream.println("				r = new FileReader(args[0]);");
		pStream.println("			} catch (FileNotFoundException e1) {");
		pStream.println("				System.err.println(\"Dumper: file \" + args[0] + \" not found\");");
		pStream.println("			}");
		pStream.println("		}");
		pStream.println("		return r;");
		pStream.println("	}");
		pStream.println("}");
	}
}