package com.slmn.model;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Deque;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;
import org.antlr.v4.runtime.ParserRuleContext;
import org.antlr.v4.runtime.misc.NotNull;
import org.antlr.v4.runtime.tree.ParseTreeProperty;
import org.antlr.v4.runtime.tree.TerminalNode;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.slmn.antlr.MsonBaseListener;
import com.slmn.antlr.MsonParser;
import com.slmn.antlr.MsonParser.ValueContext;
import com.slmn.antlr.MsonParser.*;
public class DefPhase extends MsonBaseListener {
static private final Logger logger = LoggerFactory
.getLogger(DefPhase.class);
public ParseTreeProperty<Scope> scopes = new ParseTreeProperty<Scope>();
Deque<PairContext> stack = new ArrayDeque<>();
List<String> objects = new ArrayList<>();
List<String> packages = new ArrayList<>();
Set<String> keywords = new TreeSet<>();
Set<String> ids = new TreeSet<>();
SymbolTable symtab;
Scope currentScope; // define symbols in this scope
private boolean isKeywords = false;
public DefPhase(SymbolTable symtab) {
this.symtab = symtab;
currentScope = symtab.globals;
}
@Override
public void exitMson(@NotNull MsonContext ctx) {
logger.info("{}", objects);
logger.info("{}", packages);
logger.info("{}", keywords);
logger.info("{}", ids);
}
@Override
public void enterDomainClass(@NotNull DomainClassContext ctx) {
DomainHeaderContext dhctx = ctx.domainHeader();
String objectName = dhctx.getChild(dhctx.getChildCount() - 1).getText();
objects.add(objectName);
// def class but leave superclass blank until ref phase
ClassSymbol cs = new ClassSymbol(objectName, currentScope, null);
cs.def = ctx; // point from symbol table into parse tree
saveScope(ctx, cs); // point from parse tree into symbol table
currentScope.define(cs); // def class in current scope
currentScope = cs; // set current scope to class scope
}
@Override
public void exitDomainClass(@NotNull DomainClassContext ctx) {
currentScope = currentScope.getEnclosingScope(); // pop scope
}
@Override
public void enterDomainArray(@NotNull DomainArrayContext ctx) {
DomainHeaderContext dhctx = (DomainHeaderContext) ctx.getChild(0);
String pn = dhctx.getChild(dhctx.getChildCount() - 1).getText();
if (pn.equals("KEYWORDS")) {
isKeywords = true;
}
}
@Override
public void exitDomainArray(@NotNull DomainArrayContext ctx) {
isKeywords = false;
}
@Override
public void enterPackage(@NotNull PackageContext ctx) {
ParserRuleContext prc = ctx.getParent();
if (!(prc instanceof DomainArrayContext)) {
return;
}
DomainArrayContext dac = (DomainArrayContext) prc;
DomainHeaderContext dhctx = (DomainHeaderContext) dac.getChild(0);
IdContext ic = (IdContext) dhctx.getChild(dhctx.getChildCount() - 1);
String pn = ic.getText();
packages.add(pn);
// def class but leave superclass blank until ref phase
ClassSymbol cs = new ClassSymbol(pn, currentScope, null);
cs.def = ic; // point from symbol table into parse tree
saveScope(ic, cs); // point from parse tree into symbol table
currentScope.define(cs); // def class in current scope
currentScope = cs; // set current scope to class scope
}
@Override
public void exitPackage(@NotNull PackageContext ctx) {
currentScope = currentScope.getEnclosingScope(); // pop scope
}
@Override
public void enterKeyword(@NotNull MsonParser.KeywordContext ctx) {
if (!isKeywords) {
String kw = ctx.getChild(0).getText();
keywords.add(kw);
}
}
@Override
public void enterDomainValue(@NotNull DomainValueContext ctx) {
DomainHeaderContext dhctx = (DomainHeaderContext) ctx.getChild(0);
if (!(ctx.getChild(2) instanceof ValueContext)) {
return;
}
ValueContext vc = (ValueContext) ctx.getChild(2);
IdContext ic;
IdArrayContext iac;
if (vc.getChild(0) instanceof IdContext) {
ic = (IdContext) vc.getChild(0);
} else if (vc.getChild(0) instanceof IdArrayContext) {
iac = (IdArrayContext) vc.getChild(0);
} else {
return;
}
ids.add(vc.getChild(0).getText());
}
void saveScope(ParserRuleContext ctx, Scope s) {
scopes.put(ctx, s);
}
}