astra.ast.core.ASTRAClassElement Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of astra-compiler Show documentation
Show all versions of astra-compiler Show documentation
Core compiler artifact for the ASTRA Language
The newest version!
package astra.ast.core;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import astra.ast.element.ConstantElement;
import astra.ast.element.FunctionElement;
import astra.ast.element.GRuleElement;
import astra.ast.element.InferenceElement;
import astra.ast.element.InitialElement;
import astra.ast.element.ModuleElement;
import astra.ast.element.PackageElement;
import astra.ast.element.RuleElement;
import astra.ast.element.TypesElement;
import astra.ast.visitor.Utilities;
public class ASTRAClassElement implements IElement {
static Logger logger = Logger.getLogger(Logger.GLOBAL_LOGGER_NAME);
PackageElement packageElement;
List imports = new LinkedList<>();
ClassDeclarationElement declaration;
List ontologies = new LinkedList<>();
List initials = new LinkedList<>();
List functions = new LinkedList<>();
List inferences = new LinkedList<>();
List grules = new LinkedList<>();
List rules = new LinkedList<>();
List modules = new LinkedList<>();
List constants = new LinkedList<>();
private Token first, last;
private boolean local;
public ASTRAClassElement(String source, String contents) throws ParseException {
this(source, new ByteArrayInputStream(contents.getBytes()));
}
/**
* Main contstructor for ASTRAClassElement. This constructor parses the given
* input stream and generates the ASTRA model for the class. Exceptions are
* created for any parse errors.
*
* NOTE: Upon completion, this will be a coarse grained AST for ASTRA, but
* it will not necessarily be semantically valid. You should use the
* associated visitors to ensure semantic correctness.
*
* @param source the name of the source file
* @param in the input stream
* @throws ParseException - generated for any parsing error
*/
public ASTRAClassElement(String source, InputStream in) throws ParseException {
this(source, in, true);
}
public ASTRAClassElement(String source, InputStream in, boolean local) throws ParseException {
this.local = local;
ADTTokenizer tokenizer = new ADTTokenizer(in);
ASTRAParser parser = new ASTRAParser(tokenizer);
Token tok = tokenizer.nextToken();
first = tok;
if (tok.type == Token.PACKAGE) {
List list = parser.readTo(Token.SEMI_COLON);
packageElement = parser.createPackage(list.subList(0, list.size()-1));
tok = tokenizer.nextToken();
} else {
packageElement = new PackageElement("", null, null, "");
}
while (!(tok.type == Token.AGENT || tok.type == Token.ABSTRACT)) {
switch (tok.type) {
case Token.PACKAGE:
throw new ParseException("Package declaration must be the first line of the file", tok, tok);
case Token.IMPORT:
List list = parser.readTo(Token.SEMI_COLON);
imports.add(parser.createImport(list.subList(0, list.size()-1)));
tok = tokenizer.nextToken();
break;
default:
throw new ParseException("Unexpected statement: " + tok.token, tok, tok);
}
}
// Re-add the token because there are multiple possible first keywords for this class
List list = parser.readTo(Token.LEFT_BRACE);
list.add(0, tok);
declaration = parser.createClassDeclaration(list);
declaration.setParent(this);
// Here we check that the Agent Name and Package correspond to the source name
Utilities.validatePackageAndClassName(this, source);
boolean finished = false;
while (!finished) {
try {
tok = tokenizer.nextToken();
// System.out.println("tok: " + tok.token);
switch (tok.type) {
case Token.MODULE:
list = parser.readTo(Token.SEMI_COLON);
modules.add((ModuleElement) parser.createModule(list.subList(0, list.size()-1)).setParent(this));
break;
case Token.TYPES:
list = parser.readTo(Token.RIGHT_BRACE);
ontologies.add(parser.createTypes(list.subList(0, list.size()-1)));
break;
case Token.INITIAL:
list = parser.readTo(Token.SEMI_COLON);
initials.addAll(parser.createInitial(list.subList(0, list.size()-1)));
break;
case Token.CONSTANT:
list = parser.readTo(Token.SEMI_COLON);
constants.addAll(parser.createConstant(list.subList(0, list.size()-1)));
break;
case Token.INFERENCE:
list = parser.readTo(Token.SEMI_COLON);
inferences.add((InferenceElement) parser.createInference(list.subList(0, list.size()-1)).setParent(this));
break;
case Token.GRULE:
case Token.GOAL_TYPE:
list = parser.readTo(Token.RIGHT_BRACE);
grules.add((GRuleElement) parser.createGRule(list).setParent(this));
break;
case Token.ATOMIC:
case Token.SYNCHRONIZED:
list = parser.readTo(Token.RIGHT_BRACE);
rules.add((RuleElement) parser.createSynchronizedRule(list).setParent(this));
break;
case Token.RULE:
list = parser.readTo(Token.RIGHT_BRACE);
rules.add((RuleElement) parser.createRule(list).setParent(this));
break;
case Token.FUNCTION:
list = parser.readTo(Token.RIGHT_BRACE);
functions.add((FunctionElement) parser.createFunction(list).setParent(this));
break;
case Token.RIGHT_BRACE:
last = tok;
case Token.EOF:
finished = true;
break;
default:
throw new ParseException("Unknown token: " + tok.token, tok);
}
} catch (ParseException e) {
store(e);
} catch (Throwable th) {
store(new ParseException("Unexpected Error: " + th.getMessage(), th, 1, 1, 0));
th.printStackTrace();
logger.log(Level.SEVERE, "Unexpected Error", th);
} finally {
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
Token token = null;
List endList = new LinkedList();
while((token = tokenizer.nextToken()) != Token.EOF_TOKEN) {
endList.add(token);
}
if (!endList.isEmpty()) errorList.add( new ParseException("Code is outside the agent declaration", endList.get(0), endList.get(endList.size()-1)));
for(InitialElement elem : initials) {
elem.setParent(this);
}
}
List errorList = new LinkedList();
public void store(ParseException e) {
errorList.add(e);
}
public List getErrorList() {
return errorList;
}
public IElement[] getElements() {
List elements = new ArrayList();
elements.addAll(modules);
elements.addAll(initials);
elements.addAll(rules);
elements.addAll(functions);
return elements.toArray(new IElement[elements.size()]);
}
/**
* Returns all the rules specified in the agent class
* @return an array of rule elements
*/
public RuleElement[] getRules() {
return rules.toArray(new RuleElement[] {});
}
public ModuleElement[] getModules() {
return modules.toArray(new ModuleElement[] {});
}
public InitialElement[] getInitials() {
return initials.toArray(new InitialElement[] {});
}
@Override
public String getSource() {
return null;
}
@Override
public Object accept(IElementVisitor visitor, Object data) throws ParseException {
return visitor.visit(this, data);
}
public PackageElement packageElement() {
return packageElement;
}
public ImportElement[] imports() {
return imports.toArray(new ImportElement[] {});
}
public ClassDeclarationElement getClassDeclaration() {
return declaration;
}
public InferenceElement[] getInferences() {
return inferences.toArray(new InferenceElement[] {});
}
public FunctionElement[] getFunctions() {
return functions.toArray(new FunctionElement[] {});
}
public String getFilename() {
if (packageElement == null) return declaration.name() + ".java";
return packageElement.packageName().replace(".", "/") + "/" + declaration.name() + ".java";
}
@Override
public IElement getParent() {
return null;
}
@Override
public IElement setParent(IElement parent) {
return this;
}
@Override
public int getBeginLine() {
return first.beginLine;
}
public String getQualifiedName() {
return (packageElement.packageName().equals("") ? "":(packageElement.packageName() + ".")) + declaration.name();
}
@Override
public int getBeginColumn() {
return first.beginColumn;
}
@Override
public int charStart() {
return first.charStart;
}
@Override
public int charEnd() {
return last.charEnd;
}
public String toString() {
return this.getQualifiedName();
}
public List getOntologies() {
return this.ontologies;
}
public boolean local() {
return local;
}
public List getGRules() {
return grules;
}
public List getConstants() {
return constants;
}
}