The -dump-ast flag in SwiftSyntax seems to be outputting a "parse tree" or "concrete syntax tree" where all the syntax is preserved. For example, given the expression "1 + 2", SwiftSyntax will place the "1", "+", and "2" nodes under one parent. In a semantic AST on the other hand, the "1" and "2" nodes will be the children of the "+" operator node. Are there are flags that can help generate a semantic AST? If not, any tips on how I would produce such a tree?
In general, it's not possible to generate a true semantic AST using just SwiftSyntax because the syntax parser doesn't have enough information to complete the tree. For example, the precedence of most operators is defined in the standard library instead of being hardcoded in the compiler, and custom operators can introduce their own precedence groups.
But if you're interested in an approximation specifically for expressions, we use this
SequenceExprFolding algorithm in swift-format to transform the syntax tree into a form that we can use to break and indent terms based on precedence (we hardcode the precedence of the standard operators). This algorithm is a port of the one used in the compiler itself to build the semantic AST from the linear expression token stream.
Thanks for the quick reply. Is it correct to say that SequenceExprFolding will create a reasonable semantic AST, but only if all the operators used in the source code are the ones hardcoded?
Yes for expressions with standard operators, and the algorithm is general enough that if you had specific custom operators or precedence groups you wanted to support, you could manually add them in the
OperatorContext. Otherwise, any operators that it doesn't recognize just get treated with default precedence (which will result in a tree structure that may or may not reflect what you'd get if the code was actually compiled).