Access Control is now enabled for Gitlab Pages so you can now restrict Pages to authorized users only. If needed, make your website publicly available : Navigate to your project's Settings > General > Visibility and select Everyone in pages section.

Commit 6622d1b8 authored by Tony Licata's avatar Tony Licata

ProloGraal doesn't use clauses to store prolog queries anymore, prolog queries...

ProloGraal doesn't use clauses to store prolog queries anymore, prolog queries are now stocked into ProloGraalQuery instances. Modified parser to handle two behaviour, parsing queries or parsing clauses
parent 1e6a869c
......@@ -66,11 +66,11 @@ public class ProloGraalLanguage extends TruffleLanguage<ProloGraalContext> {
@Override
protected CallTarget parse(ParsingRequest request) {
Source source = request.getSource();
List<ProloGraalClause> requestedClauses = new ArrayList<>();
List<ProloGraalQuery> queries = new ArrayList<>();
if (request.getArgumentNames().isEmpty()) {
long time = System.currentTimeMillis();
requestedClauses = ProloGraalParserImpl.parseProloGraal(source);
queries = ProloGraalParserImpl.parseProloGraal(source);
long time2 = System.currentTimeMillis();
if (DEBUG_MODE) {
System.out.println("Parsing time : " + (time2 - time) + "ms");
......@@ -79,7 +79,7 @@ public class ProloGraalLanguage extends TruffleLanguage<ProloGraalContext> {
ProloGraalRuntime runtime = new ProloGraalRuntime(this.getContextReference().get());
RootNode eval = new ProloGraalEvalRootNode(this, runtime,requestedClauses);
RootNode eval = new ProloGraalEvalRootNode(this, runtime, queries);
return Truffle.getRuntime().createCallTarget(eval);
}
......
......@@ -57,7 +57,7 @@ public final class ProloGraalConsultBuiltin extends ProloGraalBuiltinClause {
}
Source source = Source.newBuilder(ProloGraalLanguage.ID, fileContent, null).build();
//we filter clauses to remove goal lists from returned clauses
List<ProloGraalClause> clauses = ProloGraalParserImpl.parseProloGraal(source).stream().filter(proloGraalClause -> proloGraalClause.getHead() != null).collect(Collectors.toList());
List<ProloGraalClause> clauses = ProloGraalParserImpl.parseClauses(source).stream().filter(proloGraalClause -> proloGraalClause.getHead() != null).collect(Collectors.toList());
context.getRuntime().addProloGraalClauses(clauses);
return new ProloGraalSuccess(getVariables());
......
......@@ -45,7 +45,7 @@ public final class ProloGraalConsultStringBuiltin extends ProloGraalBuiltinClaus
consultContentString = consultContentString.substring(1,consultContentString.length()-1);
Source source = Source.newBuilder(ProloGraalLanguage.ID, consultContentString, null).build();
//we filter clauses to remove goal lists from returned clauses
List<ProloGraalClause> clauses = ProloGraalParserImpl.parseProloGraal(source).stream().filter(proloGraalClause -> proloGraalClause.getHead()!=null).collect(Collectors.toList());
List<ProloGraalClause> clauses = ProloGraalParserImpl.parseClauses(source);
context.getRuntime().addProloGraalClauses(clauses);
return new ProloGraalSuccess(getVariables());
}else{
......
......@@ -26,15 +26,15 @@ public final class ProloGraalEvalRootNode extends RootNode {
@CompilationFinal
private boolean registered;
private final List<ProloGraalClause> requests;
private final List<ProloGraalQuery> queries;
private final ContextReference<ProloGraalContext> reference;
public ProloGraalEvalRootNode(ProloGraalLanguage language, ProloGraalRuntime runtime, List<ProloGraalClause> requests) {
public ProloGraalEvalRootNode(ProloGraalLanguage language, ProloGraalRuntime runtime, List<ProloGraalQuery> queries) {
super(null); // internal frame
this.runtime = runtime;
this.language = language;
this.reference = language.getContextReference();
this.requests = requests;
this.queries = queries;
}
@Override
......@@ -66,17 +66,19 @@ public final class ProloGraalEvalRootNode extends RootNode {
ArrayList<ProloGraalBoolean> answers = new ArrayList<>();
for(ProloGraalClause request : requests){
for(ProloGraalQuery request : queries){
Deque<Integer> currentBranches = new ArrayDeque<>();
ProloGraalClause goal = new ProloGraalClause();
goal.setHead(new ProloGraalAtom(request.getVariables(),"goals"));
/*
if(request.getGoals().size()==0){
goal.addGoal(request.getHead());
}else if(request.getGoals().size()>0 && request.getHead() == null){
request.getGoals().forEach(proloGraalTerm -> goal.addGoal(proloGraalTerm));
} else{
continue;
}
} */
request.getGoals().forEach(proloGraalTerm -> goal.addGoal(proloGraalTerm));
ProloGraalRuntime runtime;
runtime = new ProloGraalRuntime(language.getContextReference().get());
runtime.addProloGraalClause(goal);
......
......@@ -125,7 +125,7 @@ public class ProloGraalInterpreterNode extends RootNode {
if (!skipParsing) {
// parse the source to get a runtime
runtime = new ProloGraalRuntime(language.getContextReference().get());
runtime.addProloGraalClauses(ProloGraalParserImpl.parseProloGraal(source));
runtime.addProloGraalClauses(ProloGraalParserImpl.parseClauses(source));
lastRuntime = runtime;
} else {
runtime = lastRuntime;
......
......@@ -8,7 +8,7 @@ grammar ProloGraal;
// parser
prolograal :
clause* EOF // zero or more clauses and the EOF
(clause | query)* EOF // zero or more clauses or queries and the EOF
;
// an atom can be the lexical definition of an atom or an empty list
......@@ -66,10 +66,14 @@ composedClause :
head CLAUSE_MARKER goalList
;
// a query is a goalList.
query :
goalList
;
// a clause is either a fact, a goal list or a composed clause
clause :
fact |
goalList | //TODO clause can temporary be a goalList
composedClause
;
......
......@@ -155,6 +155,18 @@ public class ProloGraalBaseListener implements ProloGraalListener {
* <p>The default implementation does nothing.</p>
*/
@Override public void exitComposedClause(ProloGraalParser.ComposedClauseContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void enterQuery(ProloGraalParser.QueryContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void exitQuery(ProloGraalParser.QueryContext ctx) { }
/**
* {@inheritDoc}
*
......
......@@ -127,6 +127,16 @@ public interface ProloGraalListener extends ParseTreeListener {
* @param ctx the parse tree
*/
void exitComposedClause(ProloGraalParser.ComposedClauseContext ctx);
/**
* Enter a parse tree produced by {@link ProloGraalParser#query}.
* @param ctx the parse tree
*/
void enterQuery(ProloGraalParser.QueryContext ctx);
/**
* Exit a parse tree produced by {@link ProloGraalParser#query}.
* @param ctx the parse tree
*/
void exitQuery(ProloGraalParser.QueryContext ctx);
/**
* Enter a parse tree produced by {@link ProloGraalParser#clause}.
* @param ctx the parse tree
......
......@@ -26,10 +26,39 @@ public class ProloGraalListenerImpl extends ProloGraalBaseListener {
private Deque<ProloGraalTerm<?>> elements = new ArrayDeque<>();
// stack of final clauses
private Deque<ProloGraalClause> clauses = new ArrayDeque<>();
// stack of final queries
private Deque<ProloGraalQuery> queries = new ArrayDeque<>();
private boolean parsingClauses = false;
// provides temporary storage for the tail of a list since it needs special handling
private ProloGraalTerm<?> tail;
public void setParsingClauses(boolean parsingClauses){
this.parsingClauses = parsingClauses;
}
/**
* Returns the queries parsed from the file. Must be called after walking through the tree using the default
* {@link org.antlr.v4.runtime.tree.ParseTreeWalker}.
* @return The list of parsed clauses, in order of encounter in the source file
*/
public List<ProloGraalQuery> getQueries() {
List<ProloGraalQuery> r = new ArrayList<>();
// we use a descending iterator to reverse the order of the clauses
// since a stack is LIFO and we need to read FIFO to get the correct order
Iterator<ProloGraalQuery> it = queries.descendingIterator();
it.forEachRemaining(r::add);
if (ProloGraalLanguage.DEBUG_MODE) {
System.out.println(r);
}
return r;
}
/**
* Returns the clauses parsed from the file. Must be called after walking through the tree using the default
* {@link org.antlr.v4.runtime.tree.ParseTreeWalker}.
......@@ -52,7 +81,8 @@ public class ProloGraalListenerImpl extends ProloGraalBaseListener {
}
public void debug() {
System.out.println(clauses.stream().map(x -> x.toString() + "\n").collect(Collectors.joining()));
System.out.println("Clauses:\n"+clauses.stream().map(x -> x.toString() + "\n").collect(Collectors.joining()));
System.out.println("Queries:\n"+queries.stream().map(x -> x.toString() + "\n").collect(Collectors.joining()));
}
private void throwParseError(ParserRuleContext ctx, String message) {
......@@ -60,29 +90,67 @@ public class ProloGraalListenerImpl extends ProloGraalBaseListener {
message);
}
private Map<ProloGraalVariable, ProloGraalVariable> getVariables(){
if(parsingClauses)
return clauses.peek().getVariables();
return queries.peek().getVariables();
}
private void addGoal(ProloGraalTerm<?> goal){
if(parsingClauses){
clauses.peek().addGoal(goal);
}else{
queries.peek().addGoal(goal);
}
}
@Override
public void enterQuery(ProloGraalParser.QueryContext ctx) {
// when we enter a query, we need to create a new "context" for it.
// Queries amd clauses are the "top-level" of Prolog.
if(!parsingClauses) {
queries.push(new ProloGraalQuery());
}else{
clauses.push(new ProloGraalClause());
}
}
//TODO: some prolog texts, could both be parsed into a clause (fact) or query having only one goal.
// this fix using the parsingClausesBoolean works for the moment,
// but could have side effects like
// could throw an exception if it parses a real clause (head + goalList) while parsing queries.
@Override
public void enterClause(ProloGraalParser.ClauseContext ctx) {
// when we enter a clause, we need to create a new "context" for it.
// Clauses are the "top-level" of Prolog.
clauses.push(new ProloGraalClause());
// Clauses and queries are the "top-level" of Prolog.
if(parsingClauses) {
clauses.push(new ProloGraalClause());
}else{
queries.push(new ProloGraalQuery());
}
}
@Override
public void exitGoal(ProloGraalParser.GoalContext ctx) {
// add the goal to the current clause
clauses.peek().addGoal(elements.pop());
addGoal(elements.pop());
}
@Override
public void exitHead(ProloGraalParser.HeadContext ctx) {
// set the head of the current clause
clauses.peek().setHead(elements.pop());
if(parsingClauses){
clauses.peek().setHead(elements.pop());
}else{
addGoal(elements.pop());
}
}
@Override
public void enterAtom(ProloGraalParser.AtomContext ctx) {
// create an atom an push it to the element stack
ProloGraalAtom atom = new ProloGraalAtom(clauses.peek().getVariables(), ctx.getText());
ProloGraalAtom atom = new ProloGraalAtom(getVariables(), ctx.getText());
elements.push(atom);
}
......@@ -91,32 +159,32 @@ public class ProloGraalListenerImpl extends ProloGraalBaseListener {
// create a number according to its type (Integer or Double) and push it to the element stack
String n = ctx.getText();
try {
elements.push(new ProloGraalIntegerNumber(clauses.peek().getVariables(), Integer.parseInt(n)));
elements.push(new ProloGraalIntegerNumber(getVariables(), Integer.parseInt(n)));
} catch (NumberFormatException ex) {
elements.push(new ProloGraalDoubleNumber(clauses.peek().getVariables(), Double.parseDouble(n)));
elements.push(new ProloGraalDoubleNumber(getVariables(), Double.parseDouble(n)));
}
}
@Override
public void enterVariable(ProloGraalParser.VariableContext ctx) {
// create a new variable
ProloGraalVariable variable = new ProloGraalVariable(clauses.peek().getVariables(), ctx.getText());
ProloGraalVariable variable = new ProloGraalVariable(getVariables(), ctx.getText());
// check if the current clause's variables list already contains a reference to this new variable (using its name to compare)
if (clauses.peek().getVariables().containsKey(variable)) {
if (getVariables().containsKey(variable)) {
// if the variable already exists in the clause, we must not add a new one but use a reference instead
elements.push(clauses.peek().getVariables().get(variable));
elements.push(getVariables().get(variable));
} else {
// else we can just add the variable to the element stack
elements.push(variable);
// and we must directly add it to the current clause's variables list as well
clauses.peek().getVariables().put(variable, variable);
getVariables().put(variable, variable);
}
}
@Override
public void enterComposedTerm(ProloGraalParser.ComposedTermContext ctx) {
// when we enter a composed term, we push a new structure immediately to "mark" its beginning
elements.push(new ProloGraalStructure(clauses.peek().getVariables()));
elements.push(new ProloGraalStructure(getVariables()));
}
@Override
......@@ -175,7 +243,7 @@ public class ProloGraalListenerImpl extends ProloGraalBaseListener {
@Override
public void enterList(ProloGraalParser.ListContext ctx) {
// similar to structures, add a new list to the stack when we enter one
elements.push(new ProloGraalList(clauses.peek().getVariables()));
elements.push(new ProloGraalList(getVariables()));
}
@Override
......
package ch.heiafr.prolograal.parser;
import ch.heiafr.prolograal.runtime.ProloGraalClause;
import ch.heiafr.prolograal.runtime.ProloGraalQuery;
import com.oracle.truffle.api.source.Source;
import org.antlr.v4.runtime.BaseErrorListener;
......@@ -59,7 +60,7 @@ public class ProloGraalParserImpl {
* Parse the given source file using the listener method.
* @return The list of clauses in the source file, in the order in which they are encountered.
*/
public static List<ProloGraalClause> parseProloGraal(Source source) {
public static List<ProloGraalQuery> parseProloGraal(Source source) {
ProloGraalLexer lexer = new ProloGraalLexer(CharStreams.fromString(source.getCharacters().toString()));
ProloGraalParser parser = new ProloGraalParser(new CommonTokenStream(lexer));
......@@ -75,6 +76,38 @@ public class ProloGraalParserImpl {
// create our listener implementation
ProloGraalListenerImpl listener = new ProloGraalListenerImpl();
listener.setParsingClauses(false);
// and walk through it using the default walker
ParseTreeWalker.DEFAULT.walk(listener, tree);
if (ProloGraalLanguage.DEBUG_MODE) {
listener.debug();
}
return listener.getQueries();
}
/**
* Parse the given source file using the listener method.
* @return The list of clauses in the source file, in the order in which they are encountered.
*/
public static List<ProloGraalClause> parseClauses(Source source) {
ProloGraalLexer lexer = new ProloGraalLexer(CharStreams.fromString(source.getCharacters().toString()));
ProloGraalParser parser = new ProloGraalParser(new CommonTokenStream(lexer));
lexer.removeErrorListeners();
parser.removeErrorListeners();
BailoutErrorListener errListener = new BailoutErrorListener(source);
lexer.addErrorListener(errListener);
parser.addErrorListener(errListener);
ProloGraalParserImpl.source = source;
ParseTree tree = parser.prolograal();
// create our listener implementation
ProloGraalListenerImpl listener = new ProloGraalListenerImpl();
listener.setParsingClauses(true);
// and walk through it using the default walker
ParseTreeWalker.DEFAULT.walk(listener, tree);
......
package ch.heiafr.prolograal.runtime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
* Class representing a query.
* @author Tony Licata
*/
public class ProloGraalQuery {
// the goals of this query
private List<ProloGraalTerm<?>> goals;
// the variables contained in this query and its goals
// mapping Variable to Variable to be able to retrieve elements by their hash (a Set can only tell us if the hash
// is there or not, we cannot get the element)
private Map<ProloGraalVariable, ProloGraalVariable> variables;
public ProloGraalQuery() {
goals = new ArrayList<>();
variables = new HashMap<>();
}
// copy constructor
public ProloGraalQuery(ProloGraalQuery other) {
variables = new HashMap<>();
this.goals = other.goals.stream().sequential().map(x -> x.copy(variables)).collect(Collectors.toList());
}
public void addGoal(ProloGraalTerm<?> goal) {
goals.add(goal);
}
public List<ProloGraalTerm<?>> getGoals() {
return goals;
}
public Map<ProloGraalVariable, ProloGraalVariable> getVariables() {
return variables;
}
@Override
public String toString() {
return goals.stream().map(Object::toString).collect(Collectors.joining(",")) + ".";
}
public ProloGraalQuery copy() {
return new ProloGraalQuery(this);
}
}
\ No newline at end of file
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment