1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100
|
extension ResourceFunctionSyntax {
static func parse(lexer: inout Lexer, documents: DocumentsSyntax) throws -> ResourceFunctionSyntax {
guard let token = lexer.peek() else {
throw ParseError(description: "`constructor` or identifier expected but got nothing")
}
switch token.kind {
case .constructor:
try lexer.expect(.constructor)
try lexer.expect(.leftParen)
let funcStart = lexer.cursor.nextIndex
let params = try Parser.parseListTrailer(
lexer: &lexer, end: .rightParen
) { docs, lexer in
let start = lexer.cursor.nextIndex
let name = try Identifier.parse(lexer: &lexer)
try lexer.expect(.colon)
let type = try TypeReprSyntax.parse(lexer: &lexer)
return ParameterSyntax(name: name, type: type, textRange: start..<lexer.cursor.nextIndex)
}
return .constructor(
.init(
syntax: NamedFunctionSyntax(
documents: documents,
name: Identifier(text: "constructor", textRange: token.textRange),
function: FunctionSyntax(
parameters: params,
results: .named([]),
textRange: funcStart..<lexer.cursor.nextIndex
)
)
)
)
case .explicitId, .id:
let name = try Identifier.parse(lexer: &lexer)
try lexer.expect(.colon)
let ctor: (SyntaxNode<NamedFunctionSyntax>) -> ResourceFunctionSyntax
if lexer.eat(.static) {
ctor = ResourceFunctionSyntax.static
} else {
ctor = ResourceFunctionSyntax.method
}
let function = try FunctionSyntax.parse(lexer: &lexer)
return ctor(
.init(
syntax:
NamedFunctionSyntax(
documents: documents,
name: name,
function: function
)
)
)
default:
throw ParseError(description: "`constructor` or identifier expected but got \(token.kind)")
}
}
}
extension FunctionSyntax {
static func parse(lexer: inout Lexer) throws -> FunctionSyntax {
func parseParameters(lexer: inout Lexer, leftParen: Bool) throws -> ParameterList {
if leftParen {
try lexer.expect(.leftParen)
}
return try Parser.parseListTrailer(lexer: &lexer, end: .rightParen) { docs, lexer in
let start = lexer.cursor.nextIndex
let name = try Identifier.parse(lexer: &lexer)
try lexer.expect(.colon)
let type = try TypeReprSyntax.parse(lexer: &lexer)
return ParameterSyntax(name: name, type: type, textRange: start..<lexer.cursor.nextIndex)
}
}
let start = lexer.cursor.nextIndex
try lexer.expect(.func)
let params = try parseParameters(lexer: &lexer, leftParen: true)
let results: ResultListSyntax
if lexer.eat(.rArrow) {
if lexer.eat(.leftParen) {
results = .named(try parseParameters(lexer: &lexer, leftParen: false))
} else {
results = try .anon(TypeReprSyntax.parse(lexer: &lexer))
}
} else {
results = .named([])
}
return FunctionSyntax(parameters: params, results: results, textRange: start..<lexer.cursor.nextIndex)
}
}
extension NamedFunctionSyntax {
static func parse(lexer: inout Lexer, documents: DocumentsSyntax) throws -> SyntaxNode<NamedFunctionSyntax> {
let name = try Identifier.parse(lexer: &lexer)
try lexer.expect(.colon)
let function = try FunctionSyntax.parse(lexer: &lexer)
return .init(syntax: NamedFunctionSyntax(documents: documents, name: name, function: function))
}
}
|