I'm trying to write a predictive editor for a grammar written in Rascal. The heart of this would be a function taking as input a list of symbols and returning as output a list of symbol types, such that an instance of any of those types would be a syntactically legal continuation of the input symbols under the grammar. So if the input list was [4,+] the output might be [integer]. Is there a clever way to do this in Rascal? I can think of imperative programming ways of doing it, but I suspect they don't take proper advantage of Rascal's power.
That's a pretty big question. Here's some lead to an answer but the full answer would be implementing it for you completely :-)
#
operator, so that you have a concise representation of the grammar which can be queried easily. The representation is defined over the modules Type
, ParseTree
which extends Type
and Grammar
.syntax E = @short E "+";
ParseTree
that you used to reify the original grammar, except in that one the rules are longer, as in prod(E, [E,+,E],...)
@short
tag), and extract their productions "prod
", which look like this prod(E,[E,+],...)
. For example using the /
operator: [candidate : /candidate:prod(_,_,/"short") := trees]
, and you could use a cursor position to find candidates which are close by instead of all short
trees in there.if (/match:prod(_,[*prefix, predicted, *postfix],_) := grammar) ...
, prefix is your query as extracted from the @short
rules. predicted
is your answer and postfix
is whatever would come after.predicted
symbol back as a type for the user to read: "<type(predicted, ())>"
(will pretty print it nicely even if it's some complex regexp type and does the quoting right etc.)