diff --git a/Package.resolved b/Package.resolved index a0d669991..ecfc25325 100644 --- a/Package.resolved +++ b/Package.resolved @@ -1,34 +1,41 @@ { - "object": { - "pins": [ - { - "package": "LLVM", - "repositoryURL": "https://github.com/kyouko-taiga/LLVMSwift.git", - "state": { - "branch": "master", - "revision": "58d87e0def9be831da9f9d3ad96bdccfa59982fa", - "version": null - } - }, - { - "package": "swift-argument-parser", - "repositoryURL": "https://github.com/apple/swift-argument-parser.git", - "state": { - "branch": null, - "revision": "6b2aa2748a7881eebb9f84fb10c01293e15b52ca", - "version": "0.5.0" - } - }, - { - "package": "swift-collections", - "repositoryURL": "https://github.com/apple/swift-collections.git", - "state": { - "branch": null, - "revision": "48254824bb4248676bf7ce56014ff57b142b77eb", - "version": "1.0.2" - } + "pins" : [ + { + "identity" : "durian", + "kind" : "remoteSourceControl", + "location" : "https://github.com/val-lang/Durian.git", + "state" : { + "revision" : "63da2be9ba8b92e6a1608ad1a9a609241b1f55cb", + "version" : "1.0.0" } - ] - }, - "version": 1 + }, + { + "identity" : "llvmswift", + "kind" : "remoteSourceControl", + "location" : "https://github.com/kyouko-taiga/LLVMSwift.git", + "state" : { + "branch" : "master", + "revision" : "58d87e0def9be831da9f9d3ad96bdccfa59982fa" + } + }, + { + "identity" : "swift-argument-parser", + "kind" : "remoteSourceControl", + "location" : "https://github.com/apple/swift-argument-parser.git", + "state" : { + "revision" : "6b2aa2748a7881eebb9f84fb10c01293e15b52ca", + "version" : "0.5.0" + } + }, + { + "identity" : "swift-collections", + "kind" : "remoteSourceControl", + "location" : "https://github.com/apple/swift-collections.git", + "state" : { + "revision" : "48254824bb4248676bf7ce56014ff57b142b77eb", + "version" : "1.0.2" + } + } + ], + "version" : 2 } diff --git a/Package.swift b/Package.swift index ae0316555..cc1bfb821 100644 --- a/Package.swift +++ b/Package.swift @@ -22,6 +22,9 @@ let package = Package( .package( url: "https://github.com/kyouko-taiga/LLVMSwift.git", branch: "master"), + .package( + url: "https://github.com/val-lang/Durian.git", + from: "1.0.0"), ], targets: [ @@ -29,7 +32,8 @@ let package = Package( .executableTarget( name: "CLI", dependencies: [ - "Compiler", "Library", + "Compiler", + "Library", .product(name: "ArgumentParser", package: "swift-argument-parser"), ]), @@ -38,15 +42,13 @@ let package = Package( name: "Compiler", dependencies: [ "Utils", - "ParserCombinators", .product(name: "Collections", package: "swift-collections"), .product(name: "LLVM", package: "LLVMSwift"), + .product(name: "Durian", package: "Durian"), ]), .target(name: "Utils"), - .target(name: "ParserCombinators"), - // Test targets. .testTarget( name: "ValTests", diff --git a/Sources/Compiler/Parse/Parser.swift b/Sources/Compiler/Parse/Parser.swift index c874acd88..71eb84ba6 100644 --- a/Sources/Compiler/Parse/Parser.swift +++ b/Sources/Compiler/Parse/Parser.swift @@ -1,4 +1,4 @@ -import ParserCombinators +import Durian import Utils /// # Notes: @@ -64,12 +64,12 @@ public enum Parser { // MARK: Declarations - private static func anyDecl( + private static func anyDecl( _ base: Base - ) -> AnyParserCombinator + ) -> AnyCombinator where Base.Context == ParserContext, Base.Element: DeclID { - AnyParserCombinator(parse: { (context) in + AnyCombinator(parse: { (context) in try base.parse(&context).map(AnyDeclID.init(_:)) }) } @@ -109,8 +109,8 @@ public enum Parser { }) ) - static let namespaceDecl: RecursiveCombinator> = ( - RecursiveCombinator(_namespaceDecl.parse(_:)) + static let namespaceDecl: Recursive> = ( + Recursive(_namespaceDecl.parse(_:)) ) private static let _namespaceDecl = ( @@ -175,8 +175,8 @@ public enum Parser { }) ) - static let productTypeDecl: RecursiveCombinator> = ( - RecursiveCombinator(_productTypeDecl.parse(_:)) + static let productTypeDecl: Recursive> = ( + Recursive(_productTypeDecl.parse(_:)) ) private static let _productTypeDecl = ( @@ -812,7 +812,7 @@ public enum Parser { /// Applies `decl` after having parsed its modifiers. If `decl` fails without committing, /// returns a non-committing failure if no modifier was parsed. - private static func declModifiers( + private static func declModifiers( and decl: Decl ) throws -> Apply< ParserContext, ( @@ -907,18 +907,18 @@ public enum Parser { // MARK: Value expressions - private static func anyExpr( + private static func anyExpr( _ base: Base - ) -> AnyParserCombinator + ) -> AnyCombinator where Base.Context == ParserContext, Base.Element: ExprID { - AnyParserCombinator(parse: { (context) in + AnyCombinator(parse: { (context) in try base.parse(&context).map(AnyExprID.init(_:)) }) } - static let expr: RecursiveCombinator = ( - RecursiveCombinator(infixExpr.parse(_:)) + static let expr: Recursive = ( + Recursive(infixExpr.parse(_:)) ) static let infixExpr = ( @@ -1410,8 +1410,8 @@ public enum Parser { .map({ (context, id) -> MatchCase.Body in .block(id) }) ) - static let conditionalExpr: RecursiveCombinator> = ( - RecursiveCombinator(_conditionalExpr.parse(_:)) + static let conditionalExpr: Recursive> = ( + Recursive(_conditionalExpr.parse(_:)) ) private static let _conditionalExpr = ( @@ -1517,18 +1517,18 @@ public enum Parser { // MARK: Patterns - private static func anyPattern( + private static func anyPattern( _ base: Base - ) -> AnyParserCombinator + ) -> AnyCombinator where Base.Context == ParserContext, Base.Element: PatternID { - AnyParserCombinator(parse: { (context) in + AnyCombinator(parse: { (context) in try base.parse(&context).map(AnyPatternID.init(_:)) }) } - static let pattern: RecursiveCombinator = ( - RecursiveCombinator(_pattern.parse(_:)) + static let pattern: Recursive = ( + Recursive(_pattern.parse(_:)) ) private static let _pattern = ( @@ -1649,18 +1649,18 @@ public enum Parser { // MARK: Statements - private static func anyStmt( + private static func anyStmt( _ base: Base - ) -> AnyParserCombinator + ) -> AnyCombinator where Base.Context == ParserContext, Base.Element: StmtID { - AnyParserCombinator(parse: { (context) in + AnyCombinator(parse: { (context) in try base.parse(&context).map(AnyStmtID.init(_:)) }) } - static let stmt: RecursiveCombinator = ( - RecursiveCombinator(_stmt.parse(_:)) + static let stmt: Recursive = ( + Recursive(_stmt.parse(_:)) ) static let _stmt = ( @@ -1862,18 +1862,18 @@ public enum Parser { // MARK: Type expressions - private static func anyTypeExpr( + private static func anyTypeExpr( _ base: Base - ) -> AnyParserCombinator + ) -> AnyCombinator where Base.Context == ParserContext, Base.Element: TypeExprID { - AnyParserCombinator(parse: { (context) in + AnyCombinator(parse: { (context) in try base.parse(&context).map(AnyTypeExprID.init(_:)) }) } - static let typeExpr: RecursiveCombinator = ( - RecursiveCombinator(unionTypeExpr.parse(_:)) + static let typeExpr: Recursive = ( + Recursive(unionTypeExpr.parse(_:)) ) // static let storedProjectionTypeExpr = ? @@ -2388,7 +2388,7 @@ public enum Parser { extension Parser { /// A combinator that parses tokens with a specific kind. - struct TakeKind: ParserCombinator { + struct TakeKind: Combinator { typealias Context = ParserContext @@ -2404,7 +2404,7 @@ extension Parser { } /// A combinator that parses contextual keywords. - struct ContextualKeyword: ParserCombinator where T.RawValue == String { + struct ContextualKeyword: Combinator where T.RawValue == String { typealias Context = ParserContext @@ -2449,7 +2449,7 @@ extension Parser { /// Creates a combinator that sets the specified flags before applying `base`, and restores them /// to their previous state afterward. - static func settingFlags( + static func settingFlags( _ newFlags: ParserContext.Flags, apply base: Base ) -> Apply @@ -2464,7 +2464,7 @@ extension Parser { } /// Creates a combinator that applies `base` only if its input is not preceeded by whitespaces. - static func withoutLeadingWhitespace( + static func withoutLeadingWhitespace( _ base: Base ) -> Apply where Base.Context == ParserContext @@ -2473,7 +2473,7 @@ extension Parser { } /// Creates a combinator that applies `base` only if its input is not preceeded by newlines. - static func onSameLine( + static func onSameLine( _ base: Base ) -> Apply where Base.Context == ParserContext diff --git a/Sources/Compiler/Parse/ParserContext.swift b/Sources/Compiler/Parse/ParserContext.swift index 3dd0bac82..8ac3158b4 100644 --- a/Sources/Compiler/Parse/ParserContext.swift +++ b/Sources/Compiler/Parse/ParserContext.swift @@ -1,5 +1,5 @@ import DequeModule -import ParserCombinators +import Durian /// A type representing the context of the parser. struct ParserContext { diff --git a/Sources/ParserCombinators/AnyParserCombinator.swift b/Sources/ParserCombinators/AnyParserCombinator.swift deleted file mode 100644 index 0a0772ec3..000000000 --- a/Sources/ParserCombinators/AnyParserCombinator.swift +++ /dev/null @@ -1,22 +0,0 @@ -/// A type-erased parser combinator. -public struct AnyParserCombinator: ParserCombinator { - - private var _parse: (inout Context) throws -> Element? - - /// Creates a new combinator that forwards operations to `base`. - public init(_ base: C) - where C.Context == Context, C.Element == Element - { - self._parse = base.parse(_:) - } - - /// Creates a new combinator that forwards operations to `parse`. - public init(parse: @escaping (inout Context) throws -> Element?) { - self._parse = parse - } - - public func parse(_ context: inout Context) throws -> Element? { - try _parse(&context) - } - -} diff --git a/Sources/ParserCombinators/Apply.swift b/Sources/ParserCombinators/Apply.swift deleted file mode 100644 index df81d88df..000000000 --- a/Sources/ParserCombinators/Apply.swift +++ /dev/null @@ -1,16 +0,0 @@ -/// A combinator that applies a closure. -public struct Apply: ParserCombinator { - - /// The action to apply. - public let action: (inout Context) throws -> Element? - - /// Creates a combinator applying the specified closure. - public init(_ action: @escaping (inout Context) throws -> Element?) { - self.action = action - } - - public func parse(_ context: inout Context) throws -> Element? { - try action(&context) - } - -} diff --git a/Sources/ParserCombinators/Attempt.swift b/Sources/ParserCombinators/Attempt.swift deleted file mode 100644 index 46803071f..000000000 --- a/Sources/ParserCombinators/Attempt.swift +++ /dev/null @@ -1,49 +0,0 @@ -/// A combinator that attempts a parse and backtracks if that produced a hard failure. -public struct Attempt: ParserCombinator -where Base.Context: Restorable -{ - - public typealias Context = Base.Context - - public typealias Element = Base.Element? - - /// The underlying combinator. - public let base: Base - - /// Creates an `Attempt` combinator that wraps `base`. - public init(_ base: Base) { - self.base = base - } - - public func parse(_ context: inout Context) throws -> Element? { - let backup = context.backup() - do { - return .some(try base.parse(&context)) - } catch { - context.restore(from: backup) - return .some(nil) - } - } - - /// Creates a combinator that applies `self` and then `other` without committing unless either - /// `self` or `other` did. - public func andCollapsingSoftFailures( - _ other: Other - ) -> Apply where Other.Context == Context { - Apply({ (context) in - if let a = try self.parse(&context) { - if let b = try other.parse(&context) { - return (a, b) - } else if a == nil { - return nil - } else { - throw HardFailure() - } - } else { - return nil - } - }) - - } - -} diff --git a/Sources/ParserCombinators/Choose.swift b/Sources/ParserCombinators/Choose.swift deleted file mode 100644 index 9588ae3c3..000000000 --- a/Sources/ParserCombinators/Choose.swift +++ /dev/null @@ -1,32 +0,0 @@ -/// A combinator that attempts a parse with a combinator and falls back to another one when the -/// former returns soft failures. -public struct Choose: ParserCombinator -where First.Context == Second.Context, First.Element == Second.Element -{ - - public typealias Context = First.Context - - public typealias Element = First.Element - - /// The first combinator. - public let firstCombinator: First - - /// The second combinator. - public let secondCombinator: Second - - /// Creates a combinator that applies `first`, or backtracks and applies `second` if `first` - /// returned a soft failure. - public init(_ first: First, or second: Second) { - self.firstCombinator = first - self.secondCombinator = second - } - - public func parse(_ context: inout Context) throws -> Element? { - if let result = try firstCombinator.parse(&context) { - return result - } else { - return try secondCombinator.parse(&context) - } - } - -} diff --git a/Sources/ParserCombinators/ChooseN.swift b/Sources/ParserCombinators/ChooseN.swift deleted file mode 100644 index 7831794ad..000000000 --- a/Sources/ParserCombinators/ChooseN.swift +++ /dev/null @@ -1,27 +0,0 @@ -/// A combinator that attempts a parse with multiple combinators until one succeeds. -public struct ChooseN: ParserCombinator { - - public typealias Context = Base.Context - - public typealias Element = Base.Element - - /// The underlying combinators. - public let bases: [Base] - - /// Creates a combinator that applies `bases` sequentially until one returns an element or - /// returns a hard failure. - public init(_ bases: S) where S.Element == Base { - self.bases = Array(bases) - precondition(!self.bases.isEmpty) - } - - public func parse(_ context: inout Context) throws -> Element? { - for base in bases { - if let result = try base.parse(&context) { - return result - } - } - return nil - } - -} diff --git a/Sources/ParserCombinators/Combine.swift b/Sources/ParserCombinators/Combine.swift deleted file mode 100644 index ce05cdbdb..000000000 --- a/Sources/ParserCombinators/Combine.swift +++ /dev/null @@ -1,44 +0,0 @@ -/// A combinator that combines the result of other combinators. -public struct Combine: ParserCombinator -where First.Context == Second.Context -{ - - public typealias Context = First.Context - - public typealias Element = (First.Element, Second.Element) - - /// The first combinator. - public let firstCombinator: First - - /// The second combinator. - public let secondCombinator: Second - - /// Creates a combinator that applies `first` and then `second`. - public init(_ first: First, and second: Second) { - self.firstCombinator = first - self.secondCombinator = second - } - - public func parse(_ context: inout Context) throws -> Element? { - if let a = try firstCombinator.parse(&context) { - if let b = try secondCombinator.parse(&context) { - return (a, b) - } else { - throw HardFailure() - } - } else { - return nil - } - } - - /// Returns a combinator that discards the second result of `self`. - public var first: Apply { - Apply({ (context) in (try parse(&context))?.0 }) - } - - /// Returns a combinator that discards the first result of `self`. - public var second: Apply { - Apply({ (context) in (try parse(&context))?.1 }) - } - -} diff --git a/Sources/ParserCombinators/HardFailure.swift b/Sources/ParserCombinators/HardFailure.swift deleted file mode 100644 index 91625ae65..000000000 --- a/Sources/ParserCombinators/HardFailure.swift +++ /dev/null @@ -1,2 +0,0 @@ -/// A hard parse failure. -public struct HardFailure: Error {} diff --git a/Sources/ParserCombinators/OneOrMany.swift b/Sources/ParserCombinators/OneOrMany.swift deleted file mode 100644 index 4423dc2ca..000000000 --- a/Sources/ParserCombinators/OneOrMany.swift +++ /dev/null @@ -1,30 +0,0 @@ -/// A combinator that applies at least once and then as many times as possible another combinator. -public struct OneOrMany: ParserCombinator { - - public typealias Context = Base.Context - - public typealias Element = [Base.Element] - - /// The underlying combinator. - public let base: Base - - /// Creates a `OneOrMany` combinator that wraps `base`. - public init(_ base: Base) { - self.base = base - } - - public func parse(_ context: inout Context) throws -> Element? { - var elements: [Base.Element] = [] - if let first = try base.parse(&context) { - elements.append(first) - } else { - return nil - } - - while let next = try base.parse(&context) { - elements.append(next) - } - return elements - } - -} diff --git a/Sources/ParserCombinators/ParserCombinator.swift b/Sources/ParserCombinators/ParserCombinator.swift deleted file mode 100644 index 613fedba5..000000000 --- a/Sources/ParserCombinators/ParserCombinator.swift +++ /dev/null @@ -1,79 +0,0 @@ -/// A parser combinator. -public protocol ParserCombinator { - - /// The context from which element are being parsed, typically a stream of tokens. - /// - /// - Requires: `Context` must have value semantics. - associatedtype Context - - /// The element parsed by the combinator. - associatedtype Element - - /// Attempts to parse a result from `context`. - func parse(_ context: inout Context) throws -> Element? - -} - -postfix operator + - -postfix operator * - -extension ParserCombinator { - - /// Creates a combinator that applies `self` and then `other`. - public func and(_ other: Other) -> Combine { - Combine(self, and: other) - } - - /// Creates a combinator that applies `self`, or backtracks and applies `other` if `self` - /// returned a soft failure. - public func or(_ other: Other) -> Choose { - Choose(self, or: other) - } - - /// Creates a combinator that applies `self`, or backtracks and applies `other` if `self` - /// returned any kind of failure. - public func orCatch( - andApply other: Other - ) -> TryCatch { - TryCatch(trying: self, orCatchingAndApplying: other) - } - - /// Creates a combinators that transforms the result of `self`. - public func map( - _ transform: @escaping (inout Context, Element) throws -> T - ) -> Transform { - Transform(base: self, transform: transform) - } - - public static postfix func + (base: Self) -> OneOrMany { - OneOrMany(base) - } - - public static postfix func * (base: Self) -> ZeroOrMany { - ZeroOrMany(base) - } - -} - -/// Creates an `Attempt` combinator that wraps `base`. -public func maybe(_ base: Base) -> Attempt { - Attempt(base) -} - -/// Creates a `ChooseN` combinator that wraps `bases`. -public func oneOf(_ bases: S) -> ChooseN -where S.Element == Base -{ - ChooseN(bases) -} - -/// Creates a `OneOrMany` combinator that wraps `base`. -public func oneOrMany(_ base: Base) -> OneOrMany { - OneOrMany(base) -} - -/// Creates a `ZeroOrMany` combinator that wraps `base`. -public func zeroOrMany(_ base: Base) -> ZeroOrMany { - ZeroOrMany(base) -} diff --git a/Sources/ParserCombinators/RecursiveCombinator.swift b/Sources/ParserCombinators/RecursiveCombinator.swift deleted file mode 100644 index 6de8521c9..000000000 --- a/Sources/ParserCombinators/RecursiveCombinator.swift +++ /dev/null @@ -1,31 +0,0 @@ -/// A combinator that can be used recursively. -public struct RecursiveCombinator: ParserCombinator { - - private final class Definition { - - var make: () -> (inout Context) throws -> Element? - - var parse: ((inout Context) throws -> Element?)? - - init(make: @escaping () -> (inout Context) throws -> Element?) { - self.make = make - } - - } - - /// The definition of the combinator. - private let definition: Definition - - /// Declares combinator that forwards operation to combinator returned by `makeParse`. - public init(_ makeParse: @autoclosure @escaping () -> (inout Context) throws -> Element?) { - self.definition = Definition(make: makeParse) - } - - public func parse(_ context: inout Context) throws -> Element? { - if definition.parse == nil { - definition.parse = definition.make() - } - return try definition.parse!(&context) - } - -} diff --git a/Sources/ParserCombinators/Restorable.swift b/Sources/ParserCombinators/Restorable.swift deleted file mode 100644 index 40d30012f..000000000 --- a/Sources/ParserCombinators/Restorable.swift +++ /dev/null @@ -1,23 +0,0 @@ -/// A type whose notional value can restored. -public protocol Restorable { - - /// An type capturing the saliant parts of `Self`. - associatedtype Backup - - /// Creates a backup of `self`. - func backup() -> Backup - - /// Restore the value of `self` from `backup`. - mutating func restore(from backup: Backup) - -} - -extension Restorable where Backup == Self { - - public func backup() -> Self { self } - - public mutating func restore(from backup: Self) { - self = backup - } - -} diff --git a/Sources/ParserCombinators/Transform.swift b/Sources/ParserCombinators/Transform.swift deleted file mode 100644 index 0012a9071..000000000 --- a/Sources/ParserCombinators/Transform.swift +++ /dev/null @@ -1,20 +0,0 @@ -/// A combinator that transforms the result of another one. -public struct Transform: ParserCombinator { - - public typealias Context = Base.Context - - /// The underlying combinator. - public let base: Base - - /// The closure that is applied to transform `base`'s result. - public let transform: (inout Context, Base.Element) throws -> Element - - public func parse(_ context: inout Context) throws -> Element? { - if let result = try base.parse(&context) { - return try transform(&context, result) - } else { - return nil - } - } - -} diff --git a/Sources/ParserCombinators/TryCatch.swift b/Sources/ParserCombinators/TryCatch.swift deleted file mode 100644 index 9156543e1..000000000 --- a/Sources/ParserCombinators/TryCatch.swift +++ /dev/null @@ -1,35 +0,0 @@ -/// A combinator that attempts a parse with a combinator and falls back to another one after -/// backtracking when the former produces any kind of failure. -public struct TryCatch: ParserCombinator -where First.Context: Restorable, - First.Context == Second.Context, - First.Element == Second.Element -{ - - public typealias Context = First.Context - - public typealias Element = First.Element - - /// The first combinator. - public let first: First - - /// The second combinator. - public let second: Second - - /// Creates a combinator that applies `first`, or backtracks and applies `second` if `first` - /// produced any kind of failure. - public init(trying first: First, orCatchingAndApplying second: Second) { - self.first = first - self.second = second - } - - public func parse(_ context: inout Context) throws -> Element? { - let backup = context.backup() - do { - if let element = try first.parse(&context) { return element } - } catch {} - context.restore(from: backup) - return try second.parse(&context) - } - -} diff --git a/Sources/ParserCombinators/ZeroOrMany.swift b/Sources/ParserCombinators/ZeroOrMany.swift deleted file mode 100644 index d7c5cee3c..000000000 --- a/Sources/ParserCombinators/ZeroOrMany.swift +++ /dev/null @@ -1,24 +0,0 @@ -/// A combinator that as many times as possible another combinator. -public struct ZeroOrMany: ParserCombinator { - - public typealias Context = Base.Context - - public typealias Element = [Base.Element] - - /// The underlying combinator. - public let base: Base - - /// Creates a `ZeroOrMany` combinator that wraps `base`. - public init(_ base: Base) { - self.base = base - } - - public func parse(_ context: inout Context) throws -> Element? { - var elements: [Base.Element] = [] - while let next = try base.parse(&context) { - elements.append(next) - } - return elements - } - -} diff --git a/Tests/ValTests/ParserTests.swift b/Tests/ValTests/ParserTests.swift index d13444a93..2ae0fccad 100644 --- a/Tests/ValTests/ParserTests.swift +++ b/Tests/ValTests/ParserTests.swift @@ -1,5 +1,5 @@ import XCTest -import ParserCombinators +import Durian @testable import Compiler @@ -1671,11 +1671,11 @@ final class ParserTests: XCTestCase { } /// Applies `combinator` on `input`, optionally setting `flags` in the parser context. - func apply( - _ combinator: Combinator, + func apply( + _ combinator: C, on input: SourceFile, flags: ParserContext.Flags? = nil - ) throws -> (element: Combinator.Element?, ast: AST) where Combinator.Context == ParserContext { + ) throws -> (element: C.Element?, ast: AST) where C.Context == ParserContext { var context = ParserContext(ast: AST(), lexer: Lexer(tokenizing: input)) if let f = flags { context.flags = context.flags | f