Consider this very simple grammer:
namespace org.example.brackets.agl
grammar Brackets {
sentence = '[' 'x' ']';
skip WHITESPACE = "\s+";
}
And this Java program that uses it to get completions on some example strings:
import net.akehurst.language.agl.Agl;
import net.akehurst.language.agl.simple.ContextWithScope;
import net.akehurst.language.api.processor.CompletionItem;
import net.akehurst.language.api.processor.LanguageProcessor;
import net.akehurst.language.asm.api.Asm;
import java.io.InputStream;
import java.util.List;
import java.util.Scanner;
import static java.nio.charset.StandardCharsets.UTF_8;
public class BracketsSuggestions {
private static final String GRAMMAR_STRING = readResource(BracketsSuggestions.class.getResourceAsStream("Brackets.agl"));
private static final LanguageProcessor<Asm, ContextWithScope<Object, Object>> LANGUAGE_PROCESSOR = Agl.INSTANCE.processorFromStringSimpleJava(
GRAMMAR_STRING, null, null, null, null, null,
Agl.INSTANCE.configurationSimple(), null).getProcessor();
public static void main(String[] args) {
System.out.print("Initial suggestions: ");
printSuggestions("", 0);
System.out.print("Suggestions after '[': ");
printSuggestions("[", 1);
System.out.print("Suggestions after '[ ': ");
printSuggestions("[ ", 2);
System.out.print("Suggestions after '[x': ");
printSuggestions("[x", 2);
System.out.print("Suggestions within '[ ': ");
printSuggestions("[ ", 1);
System.out.print("Suggestions within '[]': ");
printSuggestions("[]", 1);
System.out.print("Suggestions within '[ ]': ");
printSuggestions("[ ]", 3);
System.out.print("Suggestions after '[x]': ");
printSuggestions("[x]", 3);
System.out.print("Suggestions after '[x] ': ");
printSuggestions("[x] ", 4);
}
private static String readResource(InputStream resourceStream) {
return new Scanner(resourceStream, UTF_8).useDelimiter("\\A").next();
}
private static void printSuggestions(String str, int position) {
System.out.println(String.join(", ", getSuggestions(str, position)));
}
private static List<String> getSuggestions(String str, int position) {
try {
return LANGUAGE_PROCESSOR.expectedItemsAt(str, position, LANGUAGE_PROCESSOR.optionsDefault()).getItems().stream().map(CompletionItem::getText)
.toList();
} catch (ClassCastException e) {
e.printStackTrace();
return List.of();
}
}
}
Hopefully this is an appropriate way to initialise the LanguageProcessor; I don't know if I should be providing more parameters or using some other configuration.
This is the kind of output I would expect ("[x]" would be acceptable in place of "[", as would "x]" in place of "x"; indeed, that may even be preferable):
Initial suggestions: [
Suggestions after '[': x
Suggestions after '[ ': x
Suggestions after '[x': ]
Suggestions within '[ ': x
Suggestions within '[]': x
Suggestions within '[ ]': x
Suggestions after '[x]':
Suggestions after '[x] ':
But here is the actual output:
Initial suggestions: [ x ], [
Suggestions after '[': [ x ], [
Suggestions after '[ ': x
Suggestions after '[x':
Suggestions within '[ ': [ x ], [
Suggestions within '[]': [ x ], [
Suggestions within '[ ]': x
Suggestions after '[x]':
Suggestions after '[x] ':
Note the clearly incorrect suggestion of "[" after an existing "[" and the missing suggestions of "]" and "x". The suggestion of "[ x ]" after a "[" also appears incorrect, although it could be interpreted as suggesting the existing string be replaced by "[ x ]".
The problem may be related to whitespace; whitespace appears to be expected between each literal, although the grammar doesn't require it (parsing works as expected). But removing the line from the grammar that makes whitespace skippable results in almost identical suggestions (still incorrect and lacking).
ClassCastException
Finally, note that I have to catch ClassCastException in the program above, because with another grammar like below it throws this exception (for every attempt to get completions except the last one):
java.lang.ClassCastException: class net.akehurst.language.grammar.asm.SimpleListDefault cannot be cast to class net.akehurst.language.grammar.api.TangibleItem (net.akehurst.language.grammar.asm.SimpleListDefault and net.akehurst.language.grammar.api.TangibleItem are in unnamed module of loader 'app')
at net.akehurst.language.agl.completionProvider.SpineDefault.expectedNextLeafNonTerminalOrTerminal_delegate$lambda$1(CompletionProviderAbstract.kt:69)
at kotlin.SynchronizedLazyImpl.getValue(LazyJVM.kt:83)
at net.akehurst.language.agl.completionProvider.SpineDefault.getExpectedNextLeafNonTerminalOrTerminal(CompletionProviderAbstract.kt:64)
at net.akehurst.language.agl.simple.CompletionProviderSimple.provide(CompletionProviderSimple.kt:66)
at net.akehurst.language.agl.processor.LanguageProcessorAbstract.expectedItemsAt(LanguageProcessorAbstract.kt:296)
at BracketsSuggestions.getSuggestions(BracketsSuggestions.java:50)
at BracketsSuggestions.printSuggestions(BracketsSuggestions.java:45)
at BracketsSuggestions.main(BracketsSuggestions.java:21)
Grammar causing the exception:
namespace org.example.bracketscomplex.agl
grammar BracketsComplex {
sentence = word | bracketed;
bracketed = '[' word* ']';
word = NAME;
leaf NAME = NAME_CHAR+;
leaf NAME_CHAR = "[-.0-9]";
skip WHITESPACE = "\s+";
}
Consider this very simple grammer:
And this Java program that uses it to get completions on some example strings:
Hopefully this is an appropriate way to initialise the
LanguageProcessor; I don't know if I should be providing more parameters or using some other configuration.This is the kind of output I would expect ("[x]" would be acceptable in place of "[", as would "x]" in place of "x"; indeed, that may even be preferable):
But here is the actual output:
Note the clearly incorrect suggestion of "[" after an existing "[" and the missing suggestions of "]" and "x". The suggestion of "[ x ]" after a "[" also appears incorrect, although it could be interpreted as suggesting the existing string be replaced by "[ x ]".
The problem may be related to whitespace; whitespace appears to be expected between each literal, although the grammar doesn't require it (parsing works as expected). But removing the line from the grammar that makes whitespace skippable results in almost identical suggestions (still incorrect and lacking).
ClassCastException
Finally, note that I have to catch
ClassCastExceptionin the program above, because with another grammar like below it throws this exception (for every attempt to get completions except the last one):Grammar causing the exception: