Swift AST written in Swift. Part 4 of ∞

Alexey Demedeckiy
2 min readMar 21, 2017

--

In previous part I have discussed let and var declrartions grammar. As I discovered, grammar reflects not all syntax restrictions of the language.

In this part I will discover structure of function declaration. Let’s start from looking at formal grammar definition:

Single root declaration is good. It also contains a lot of subreferenses, let’s look into them more carefully.

First of all, let’s flatten this definition as much sa possible. Function head can be replaced with it’s own content, as no variance presented in its definition.

Second, function signature can be simplified by modeling parameter-clause as [Parameter]. throws and rethrows can be modeled as single optional enum.

After all simplification, function-declaration can be expressed like this:

struct FunctionDeclaration {
let attributes: [Attribute]
let modifiers: [DeclarationModifier]
let name: FunctionName
let genericParamters: GenericParameterClause?
let parameters: [Parameter]
let throwBehavior: ThrowsModifier?
let result: FunctionResult?
let `where`: GenericWhereClause?
let body: CodeBlock?
}

A lot of optionals here. FunctionName is the first extra definition. In Swift, function can represent regular method or operator body. Only change is grammar of FunctionName. As usual, we will model it as enum:

enum FunctionName {
case identifier(Identifier)
case `operator`(Operator)
}

Now we will cover Parameter definition. There is 3 possible options for single paramter.

  1. With default value
  2. With variadic length (aka ellipsis)
  3. Simplest form without modifiers.

In other words we can optionally have one of two modifiers.

struct Parameter {
let externalName: Identifier?
let localName: Identifier
let type: TypeAnnotation
let modifier: ParameterModifier?
}
enum ParameterModifier {
case `default`(Expression)
case ellipsis
}

So minimal representation of this would be just local name and type.

Next stop for us is definition of throwing. Function can be declared with throw or rethrow or without any. Again it looks like optional choice from 2 options.

enum ThrowsModifier {
case `throws`, `rethrows`
}

Last piece of FunctionDeclaration is a function result. It is simple Type in most cases, but we can specify custom attributes for it (do you know some examples?) so I will model it as struct:

struct FunctionResult {
let attributes: [Attribute]
let type: Type
}

Thats it.

Looks like function declaration is not so scary, or I become “bit of an expert in this things” © Daddy Pig.

In next part I will build enum declaration model. I will try to keep this articles short and focused, and publish them more often.

Thank you for your time and interest in this area.

--

--