File: PrecedenceGroup.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 (139 lines) | stat: -rw-r--r-- 4,675 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
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
//===----------------------------------------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2023 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//

#if swift(>=6)
public import SwiftSyntax
#else
import SwiftSyntax
#endif

/// Names a precedence group.
///
/// TODO: For now, we'll use strings, but we likely want to move this to
/// a general notion of an Identifier.
public typealias PrecedenceGroupName = String

/// The associativity of a precedence group.
public enum Associativity: String, Sendable {
  /// The precedence group is nonassociative, meaning that one must
  /// parenthesize when there are multiple operators in a sequence, e.g.,
  /// if ^ was nonassociative, a ^ b ^ c would need to be disambiguated as
  /// either (a ^ b ) ^ c or a ^ (b ^ c).
  case none

  /// The precedence group is left-associative, meaning that multiple operators
  /// in the same sequence will be parenthesized from the left. This is typical
  /// for arithmetic operators, such that a + b - c is treated as (a + b) - c.
  case left

  /// The precedence group is right-associative, meaning that multiple operators
  /// in the same sequence will be parenthesized from the right. This is used
  /// for assignments, where a = b = c is treated as a = (b = c).
  case right
}

/// Describes the relationship of a precedence group to another precedence
/// group.
public struct PrecedenceRelation: Sendable {
  /// Describes the kind of a precedence relation.
  public enum Kind: Sendable {
    case higherThan
    case lowerThan

    var keyword: Keyword {
      switch self {
      case .higherThan: return .higherThan
      case .lowerThan: return .lowerThan
      }
    }
  }

  /// The relationship to the other group.
  public var kind: Kind

  /// The group name.
  public var groupName: PrecedenceGroupName

  /// The syntax that provides the relation. This specifically refers to the
  /// group name itself, but one can follow the parent pointer to find its
  /// position.
  public var syntax: PrecedenceGroupNameSyntax?

  /// Return a higher-than precedence relation.
  public static func higherThan(
    _ groupName: PrecedenceGroupName,
    syntax: PrecedenceGroupNameSyntax? = nil
  ) -> PrecedenceRelation {
    return .init(kind: .higherThan, groupName: groupName, syntax: syntax)
  }

  /// Return a lower-than precedence relation.
  public static func lowerThan(
    _ groupName: PrecedenceGroupName,
    syntax: PrecedenceGroupNameSyntax? = nil
  ) -> PrecedenceRelation {
    return .init(kind: .lowerThan, groupName: groupName, syntax: syntax)
  }
}

/// Precedence groups are used for parsing sequences of expressions in Swift
/// source code. Each precedence group defines the associativity of the
/// operator and its precedence relative to other precedence groups:
///
///     precedencegroup MultiplicativePrecedence {
///       associativity: left
///       higherThan: AdditivePrecedence
///     }
///
/// Operator declarations then specify which precedence group describes their
/// precedence, e.g.,
///
///     infix operator *: MultiplicationPrecedence
public struct PrecedenceGroup: Sendable {
  /// The name of the group, which must be unique.
  public var name: PrecedenceGroupName

  /// The associativity for the group.
  public var associativity: Associativity = .none

  /// Whether the operators in this precedence group are considered to be
  /// assignment operators.
  public var assignment: Bool = false

  /// The set of relations to other precedence groups that are defined by
  /// this precedence group.
  public var relations: [PrecedenceRelation] = []

  /// The syntax node that describes this precedence group.
  public var syntax: PrecedenceGroupDeclSyntax? = nil

  public init(
    name: PrecedenceGroupName,
    associativity: Associativity = .none,
    assignment: Bool = false,
    relations: [PrecedenceRelation] = [],
    syntax: PrecedenceGroupDeclSyntax? = nil
  ) {
    self.name = name
    self.associativity = associativity
    self.assignment = assignment
    self.relations = relations
    self.syntax = syntax
  }
}

extension PrecedenceGroup: CustomStringConvertible {
  /// The description of a precedence group is the source code that produces it.
  public var description: String {
    (syntax ?? synthesizedSyntax()).description
  }
}