I am trying to rewrite java code using only concrete syntax (no AST). Next code works:
CompilationUnit rewritePackage(CompilationUnit input) =
visit(input) {
case (PackageDeclaration) `package <{Identifier "."}+ N>;` =>
(PackageDeclaration) `package <{Identifier "."}+ N>.<Identifier s>;`
when s:= [Identifier] "othertest"
};
Now I want to create {Identifier "."}+
in order to insert it into result of rewrite:
CompilationUnit rewritePackage(CompilationUnit input) =
visit(input) {
case (PackageDeclaration) `package <{Identifier "."}+ N>;` =>
(PackageDeclaration) `package <{Identifier "."}+ NUpdated>;`
when NUpdated := [{Identifier "."}+] "a1.b2"
};
and it does not work. I also tried with lists, no success.
Is it possible somehow to create {Identifier "."}+
? Or to convert list[Identifier]
to it? How can I achieve mapper( , toUpperCase)
on {Identifier "."}+
?
Is there a way to insert some str variable directly to concrete syntax?
In docs I found how {Identifier "."}+ can be transformed to list. But is there any other direct operations on {Identifier "."}+.
Would be nice to have pattern match in a form:
[ *Identifier firstIds, (Identifier)
someName
, *Identifier otherIds ]
First some short answers to make things clearer:
[NonTerminal] "string"
notation is unfinished. Currently it only supports named non-terminals, such as [Identifiers] xxx
. This is a known TODO and its already tracked as an issue.To create an {Identifier "."}+
list, use concrete syntax patterns like so:
syntax Identifiers = {Identifier "."}+ elems;
private {Identifier "."}+ insert(Identifier first, {Identifier "."}+ tail)
= (Identifiers) `<Identifier first>.<{Identifier "."} tail>`.elems;
The append function first wraps the list in the Identifiers
non-terminal to be able to use the (..)..
notation, and then projects out the new nested list using the .elems
field. The syntax trees you produce like this are statically correct. Unlike using the [..]..
notation which calls a parser dynamically, this (..)..
notation calls the parser statically and composes correct trees at run-time.
Or perhaps you want to concatenate two identifier lists:
{Identifier "."}+ append({Identifier "."}+ prefix, {Identifier "."}+ postfix)
= (Identifiers) `<{Identifier "."} prefix>.<{Identifier "."}+ postfix>`.elems;
Sometimes you want to concatenate possibly empty sub-lists, this is allowed and the .
separator will be removed automatically:
{Identifier "."}+ append({Identifier "."}+ prefix, {Identifier "."}* postfix)
= (Identifiers) `<{Identifier "."} prefix>.<{Identifier "."}* postfix>`.elems;
So to turn a list[Identifier]
into a {Identifier "."}
you might write this:
{Identifier "."}+ identifiers([Identifier head]) = (Identifiers) `<Identifier head>`.elems;
{Identifier "."}+ identifiers([Identifier head, Identifier sec, *Identifier tail])
= append(insert(head, identifiers([sec, *tail]);
Agreed that this is kind of clumsy and we should maybe prioritize the much easier concrete list syntax templates syntax. We're also open to suggestions for improvement.