File: ParseFunctionDecl.swift

package info (click to toggle)
swiftlang 6.0.3-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 2,519,992 kB
  • sloc: cpp: 9,107,863; ansic: 2,040,022; asm: 1,135,751; python: 296,500; objc: 82,456; f90: 60,502; lisp: 34,951; pascal: 19,946; sh: 18,133; perl: 7,482; ml: 4,937; javascript: 4,117; makefile: 3,840; awk: 3,535; xml: 914; fortran: 619; cs: 573; ruby: 573
file content (100 lines) | stat: -rw-r--r-- 4,178 bytes parent folder | download
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))
    }
}