mirror of
https://github.com/cirruslabs/tart.git
synced 2026-10-02 04:01:12 +02:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f9001304c8 | ||
|
|
4e20ea8f72 | ||
|
|
678ce0a55a | ||
|
|
8273ae66e1 | ||
|
|
4a9316a377 | ||
|
|
6321d547cf | ||
|
|
f241e21614 | ||
|
|
0eca923604 | ||
|
|
87f29cc11f | ||
|
|
90d1393137 | ||
|
|
625d431d10 |
+1
-1
@@ -6,6 +6,6 @@ export VERSION="${CIRRUS_TAG:-0}"
|
||||
|
||||
mkdir -p .ci/pkg/
|
||||
cp .build/arm64-apple-macosx/debug/tart .ci/pkg/
|
||||
pkgbuild --root .ci/pkg --version $VERSION --install-location /usr/local/bin/ --identifier com.github.cirruslabs.tart --sign "Developer ID Installer: Fedor Korotkov (9M2P8L4D89)" "./dist/Tart-$VERSION.pkg"
|
||||
pkgbuild --root .ci/pkg --version $VERSION --install-location /usr/local/bin/ --identifier com.github.cirruslabs.tart --sign "Developer ID Installer: Cirrus Labs, Inc. (9M2P8L4D89)" "./dist/Tart-$VERSION.pkg"
|
||||
xcrun notarytool submit "./dist/Tart-$VERSION.pkg" --keychain-profile "notarytool" --wait
|
||||
xcrun stapler staple "./dist/Tart-$VERSION.pkg"
|
||||
|
||||
+1
-1
@@ -22,7 +22,7 @@ task:
|
||||
macos_instance:
|
||||
image: ghcr.io/cirruslabs/macos-ventura-xcode:latest
|
||||
env:
|
||||
MACOS_CERTIFICATE: ENCRYPTED[8a6930a8c1286e7e536ea41b7647ea40e99174ad15e9cfcc753754fea55a619b355415629dff515b54a8921643e314e5]
|
||||
MACOS_CERTIFICATE: ENCRYPTED[552b9d275d1c2bdbc1bff778b104a8f9a53cbd0d59344d4b7f6d0ca3c811a5cefb97bef9ba0ef31c219cb07bdacdd2c2]
|
||||
AC_PASSWORD: ENCRYPTED[4a761023e7e06fe2eb350c8b6e8e7ca961af193cb9ba47605f25f1d353abc3142606f412e405be48fd897a78787ea8c2]
|
||||
GITHUB_TOKEN: ENCRYPTED[!98ace8259c6024da912c14d5a3c5c6aac186890a8d4819fad78f3e0c41a4e0cd3a2537dd6e91493952fb056fa434be7c!]
|
||||
GORELEASER_KEY: ENCRYPTED[!9b80b6ef684ceaf40edd4c7af93014ee156c8aba7e6e5795f41c482729887b5c31f36b651491d790f1f668670888d9fd!]
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
github: [cirruslabs]
|
||||
+27
-9
@@ -1,14 +1,5 @@
|
||||
{
|
||||
"pins" : [
|
||||
{
|
||||
"identity" : "antlr4",
|
||||
"kind" : "remoteSourceControl",
|
||||
"location" : "https://github.com/antlr/antlr4",
|
||||
"state" : {
|
||||
"branch" : "4.10.1",
|
||||
"revision" : "44d87bc1d130c88aa452894aa5f7e2f710f68253"
|
||||
}
|
||||
},
|
||||
{
|
||||
"identity" : "async-http-client",
|
||||
"kind" : "remoteSourceControl",
|
||||
@@ -54,6 +45,15 @@
|
||||
"version" : "1.0.2"
|
||||
}
|
||||
},
|
||||
{
|
||||
"identity" : "swift-case-paths",
|
||||
"kind" : "remoteSourceControl",
|
||||
"location" : "https://github.com/pointfreeco/swift-case-paths",
|
||||
"state" : {
|
||||
"revision" : "ce9c0d897db8a840c39de64caaa9b60119cf4be8",
|
||||
"version" : "0.8.1"
|
||||
}
|
||||
},
|
||||
{
|
||||
"identity" : "swift-log",
|
||||
"kind" : "remoteSourceControl",
|
||||
@@ -117,6 +117,15 @@
|
||||
"version" : "1.0.2"
|
||||
}
|
||||
},
|
||||
{
|
||||
"identity" : "swift-parsing",
|
||||
"kind" : "remoteSourceControl",
|
||||
"location" : "https://github.com/pointfreeco/swift-parsing",
|
||||
"state" : {
|
||||
"revision" : "28d32e9ace1c4c43f5e5a177be837a202494c2d5",
|
||||
"version" : "0.9.2"
|
||||
}
|
||||
},
|
||||
{
|
||||
"identity" : "swiftdate",
|
||||
"kind" : "remoteSourceControl",
|
||||
@@ -125,6 +134,15 @@
|
||||
"revision" : "6190d0cefff3013e77ed567e6b074f324e5c5bf5",
|
||||
"version" : "6.3.1"
|
||||
}
|
||||
},
|
||||
{
|
||||
"identity" : "xctest-dynamic-overlay",
|
||||
"kind" : "remoteSourceControl",
|
||||
"location" : "https://github.com/pointfreeco/xctest-dynamic-overlay",
|
||||
"state" : {
|
||||
"revision" : "50a70a9d3583fe228ce672e8923010c8df2deddd",
|
||||
"version" : "0.2.1"
|
||||
}
|
||||
}
|
||||
],
|
||||
"version" : 2
|
||||
|
||||
+4
-3
@@ -12,10 +12,10 @@ let package = Package(
|
||||
dependencies: [
|
||||
.package(url: "https://github.com/apple/swift-argument-parser", from: "1.1.2"),
|
||||
.package(url: "https://github.com/mhdhejazi/Dynamic", branch: "master"),
|
||||
.package(url: "https://github.com/pointfreeco/swift-parsing", from: "0.9.2"),
|
||||
.package(url: "https://github.com/swift-server/async-http-client", from: "1.11.4"),
|
||||
.package(url: "https://github.com/apple/swift-algorithms", from: "1.0.0"),
|
||||
.package(url: "https://github.com/malcommac/SwiftDate", from: "6.3.1"),
|
||||
.package(url: "https://github.com/antlr/antlr4", revision: "4.10.1")
|
||||
.package(url: "https://github.com/malcommac/SwiftDate", from: "6.3.1")
|
||||
],
|
||||
targets: [
|
||||
.executableTarget(name: "tart", dependencies: [
|
||||
@@ -23,9 +23,10 @@ let package = Package(
|
||||
.product(name: "ArgumentParser", package: "swift-argument-parser"),
|
||||
.product(name: "AsyncHTTPClient", package: "async-http-client"),
|
||||
.product(name: "Dynamic", package: "Dynamic"),
|
||||
.product(name: "Parsing", package: "swift-parsing"),
|
||||
.product(name: "SwiftDate", package: "SwiftDate"),
|
||||
.product(name: "Antlr4", package: "Antlr4"),
|
||||
]),
|
||||
.testTarget(name: "TartTests", dependencies: ["tart"])
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
@@ -238,8 +238,8 @@ This invocation calls the `tart pull` implicitly (if the image is not being pres
|
||||
<details>
|
||||
<summary>Why Tart is free and open sourced?</summary>
|
||||
|
||||
Tart is a relatively small project, and it didn't feel right to try to monetize it.
|
||||
Apple did all the heavy lifting with their `Virtualization.Framework`.
|
||||
Apple did all the heavy lifting with their `Virtualization.Framework` and it just felt right to develop Tart in the open.
|
||||
Please consider [becoming a sponsor](https://github.com/sponsors/cirruslabs) if you find Tart saving a substantial amount of money on licensing and engineering hours for your company.
|
||||
</details>
|
||||
|
||||
<details>
|
||||
@@ -268,3 +268,21 @@ This invocation calls the `tart pull` implicitly (if the image is not being pres
|
||||
Tart is limited by functionality of Apple's `Virtualization.Framework`. At the moment `Virtualization.Framework`
|
||||
doesn't support nested virtualization.
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary>Changing the default NAT subnet</summary>
|
||||
|
||||
To change the default network to `192.168.77.1`:
|
||||
|
||||
```
|
||||
sudo defaults write /Library/Preferences/SystemConfiguration/com.apple.vmnet.plist Shared_Net_Address -string 192.168.77.1
|
||||
```
|
||||
|
||||
Note that even through a network would normally be specified as `192.168.77.0`, the [vmnet framework](https://developer.apple.com/documentation/vmnet) seems to treat this as a starting address too and refuses to pick up such network-like values.
|
||||
|
||||
The default subnet mask `255.255.255.0` should suffice for most use-cases, however, you can also change it to `255.255.0.0`, for example:
|
||||
|
||||
```
|
||||
sudo defaults write /Library/Preferences/SystemConfiguration/com.apple.vmnet.plist Shared_Net_Mask -string 255.255.0.0
|
||||
```
|
||||
</details>
|
||||
|
||||
@@ -4,5 +4,7 @@
|
||||
<dict>
|
||||
<key>com.apple.security.virtualization</key>
|
||||
<true/>
|
||||
<key>com.apple.vm.networking</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
||||
</plist>
|
||||
|
||||
@@ -34,6 +34,11 @@ struct Clone: AsyncParsableCommand {
|
||||
let sourceVM = try VMStorageHelper.open(sourceName)
|
||||
|
||||
let tmpVMDir = try VMDirectory.temporary()
|
||||
|
||||
// Lock the temporary VM directory to prevent it's garbage collection
|
||||
let tmpVMDirLock = try FileLock(lockURL: tmpVMDir.baseURL)
|
||||
try tmpVMDirLock.lock()
|
||||
|
||||
try await withTaskCancellationHandler(operation: {
|
||||
let lock = try FileLock(lockURL: Config().tartHomeDir)
|
||||
try lock.lock()
|
||||
|
||||
@@ -27,6 +27,11 @@ struct Create: AsyncParsableCommand {
|
||||
func run() async throws {
|
||||
do {
|
||||
let tmpVMDir = try VMDirectory.temporary()
|
||||
|
||||
// Lock the temporary VM directory to prevent it's garbage collection
|
||||
let tmpVMDirLock = try FileLock(lockURL: tmpVMDir.baseURL)
|
||||
try tmpVMDirLock.lock()
|
||||
|
||||
try await withTaskCancellationHandler(operation: {
|
||||
if let fromIPSW = fromIPSW {
|
||||
if fromIPSW == "latest" {
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
import ArgumentParser
|
||||
import Foundation
|
||||
|
||||
struct Rename: AsyncParsableCommand {
|
||||
static var configuration = CommandConfiguration(abstract: "Rename a VM")
|
||||
|
||||
@Argument(help: "VM name")
|
||||
var name: String
|
||||
|
||||
@Argument(help: "new VM name")
|
||||
var newName: String
|
||||
|
||||
func validate() throws {
|
||||
if newName.contains("/") {
|
||||
throw ValidationError("<new-name> should be a local name")
|
||||
}
|
||||
}
|
||||
|
||||
func run() async throws {
|
||||
do {
|
||||
let localStorage = VMStorageLocal()
|
||||
|
||||
if !localStorage.exists(name) {
|
||||
throw ValidationError("failed to rename a non-existent VM: \(name)")
|
||||
}
|
||||
|
||||
if localStorage.exists(newName) {
|
||||
throw ValidationError("failed to rename VM \(name), target VM \(name) already exists, delete it first!")
|
||||
}
|
||||
|
||||
try localStorage.rename(name, newName)
|
||||
|
||||
Foundation.exit(0)
|
||||
} catch {
|
||||
print(error)
|
||||
|
||||
Foundation.exit(1)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -47,15 +47,28 @@ struct Run: AsyncParsableCommand {
|
||||
@Option(help: ArgumentHelp("""
|
||||
Additional directory shares with an optional read-only specifier\n(e.g. --dir=\"build:~/src/build\" --dir=\"sources:~/src/sources:ro\")
|
||||
""", discussion: """
|
||||
Requires host to be macOS 13.0 (Ventura) or newer.
|
||||
All shared directories are automatically mounted to "/Volumes/My Shared Files" directory on macOS,
|
||||
while on Linux you have to do it manually: "mount -t virtiofs com.apple.virtio-fs.automount /mount/point".
|
||||
For macOS guests, they must be running macOS 13.0 (Ventura) or newer.
|
||||
""", valueName: "name:path[:ro]"))
|
||||
var dir: [String] = []
|
||||
|
||||
@Option(help: ArgumentHelp("""
|
||||
Use bridged networking instead of the default shared (NAT) networking \n(e.g. --net-bridged=en0 or --net-bridged=\"Wi-Fi\")
|
||||
""", discussion: """
|
||||
Specify "list" as an interface name (--net-bridged=list) to list the available bridged interfaces.
|
||||
""", valueName: "interface name"))
|
||||
var netBridged: String?
|
||||
|
||||
func validate() throws {
|
||||
if vnc && vncExperimental {
|
||||
throw ValidationError("--vnc and --vnc-experimental are mutually exclusive")
|
||||
}
|
||||
|
||||
if withSoftnet && netBridged != nil {
|
||||
throw ValidationError("--with-softnet and --net-bridged are mutually exclusive")
|
||||
}
|
||||
}
|
||||
|
||||
@MainActor
|
||||
@@ -63,7 +76,7 @@ struct Run: AsyncParsableCommand {
|
||||
let vmDir = try VMStorageLocal().open(name)
|
||||
vm = try VM(
|
||||
vmDir: vmDir,
|
||||
withSoftnet: withSoftnet,
|
||||
network: userSpecifiedNetwork(vmDir: vmDir) ?? NetworkShared(),
|
||||
additionalDiskAttachments: additionalDiskAttachments(),
|
||||
directoryShares: directoryShares()
|
||||
)
|
||||
@@ -123,11 +136,53 @@ struct Run: AsyncParsableCommand {
|
||||
}
|
||||
}
|
||||
|
||||
func userSpecifiedNetwork(vmDir: VMDirectory) throws -> Network? {
|
||||
if withSoftnet {
|
||||
let config = try VMConfig.init(fromURL: vmDir.configURL)
|
||||
|
||||
return try Softnet(vmMACAddress: config.macAddress.string)
|
||||
}
|
||||
|
||||
if let netBridged = netBridged {
|
||||
let matchingInterfaces = VZBridgedNetworkInterface.networkInterfaces.filter { interface in
|
||||
interface.identifier == netBridged || interface.localizedDisplayName == netBridged
|
||||
}
|
||||
|
||||
if matchingInterfaces.isEmpty {
|
||||
let available = bridgeInterfaces().joined(separator: ", ")
|
||||
throw ValidationError("no bridge interfaces matched \"\(netBridged)\", "
|
||||
+ "available interfaces: \(available)")
|
||||
}
|
||||
|
||||
if matchingInterfaces.count > 1 {
|
||||
throw ValidationError("more than one bridge interface matched \"\(netBridged)\", "
|
||||
+ "consider refining the search criteria")
|
||||
}
|
||||
|
||||
return NetworkBridged(interface: matchingInterfaces.first!)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func bridgeInterfaces() -> [String] {
|
||||
VZBridgedNetworkInterface.networkInterfaces.map { interface in
|
||||
var bridgeDescription = interface.identifier
|
||||
|
||||
if let localizedDisplayName = interface.localizedDisplayName {
|
||||
bridgeDescription += " (or \"\(localizedDisplayName)\")"
|
||||
}
|
||||
|
||||
return bridgeDescription
|
||||
}
|
||||
}
|
||||
|
||||
func additionalDiskAttachments() throws -> [VZDiskImageStorageDeviceAttachment] {
|
||||
var result: [VZDiskImageStorageDeviceAttachment] = []
|
||||
let readOnlySuffix = ":ro"
|
||||
let expandedDiskPaths = disk.map { NSString(string:$0).expandingTildeInPath }
|
||||
|
||||
for rawDisk in disk {
|
||||
for rawDisk in expandedDiskPaths {
|
||||
if rawDisk.hasSuffix(readOnlySuffix) {
|
||||
result.append(try VZDiskImageStorageDeviceAttachment(
|
||||
url: URL(fileURLWithPath: String(rawDisk.prefix(rawDisk.count - readOnlySuffix.count))),
|
||||
@@ -166,7 +221,7 @@ struct Run: AsyncParsableCommand {
|
||||
|
||||
let (name, path) = (String(splits[0]), String(splits[1]))
|
||||
|
||||
result.append(DirectoryShare(name: name, path: URL(fileURLWithPath: path), readOnly: readOnly))
|
||||
result.append(DirectoryShare(name: name, path: URL(fileURLWithPath: NSString(string: path).expandingTildeInPath), readOnly: readOnly))
|
||||
}
|
||||
|
||||
return result
|
||||
|
||||
@@ -3,6 +3,7 @@ import Foundation
|
||||
struct Config {
|
||||
let tartHomeDir: URL
|
||||
let tartCacheDir: URL
|
||||
let tartTmpDir: URL
|
||||
|
||||
init() throws {
|
||||
var tartHomeDir: URL
|
||||
@@ -14,11 +15,27 @@ struct Config {
|
||||
.homeDirectoryForCurrentUser
|
||||
.appendingPathComponent(".tart", isDirectory: true)
|
||||
}
|
||||
|
||||
self.tartHomeDir = tartHomeDir
|
||||
tartCacheDir = tartHomeDir.appendingPathComponent("cache", isDirectory: true)
|
||||
|
||||
tartCacheDir = tartHomeDir.appendingPathComponent("cache", isDirectory: true)
|
||||
try FileManager.default.createDirectory(at: tartCacheDir, withIntermediateDirectories: true)
|
||||
|
||||
tartTmpDir = tartHomeDir.appendingPathComponent("tmp", isDirectory: true)
|
||||
try FileManager.default.createDirectory(at: tartTmpDir, withIntermediateDirectories: true)
|
||||
}
|
||||
|
||||
func gc() throws {
|
||||
for entry in try FileManager.default.contentsOfDirectory(at: tartTmpDir,
|
||||
includingPropertiesForKeys: [], options: []) {
|
||||
let lock = try FileLock(lockURL: entry)
|
||||
if try !lock.trylock() {
|
||||
continue
|
||||
}
|
||||
|
||||
try FileManager.default.removeItem(at: entry)
|
||||
|
||||
try lock.unlock()
|
||||
}
|
||||
}
|
||||
|
||||
static func jsonEncoder() -> JSONEncoder {
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
import Virtualization
|
||||
|
||||
protocol Network {
|
||||
func attachment() -> VZNetworkDeviceAttachment
|
||||
func run() throws
|
||||
func stop() throws
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
import Foundation
|
||||
import Virtualization
|
||||
|
||||
class NetworkBridged: Network {
|
||||
let interface: VZBridgedNetworkInterface
|
||||
|
||||
init(interface: VZBridgedNetworkInterface) {
|
||||
self.interface = interface
|
||||
}
|
||||
|
||||
func attachment() -> VZNetworkDeviceAttachment {
|
||||
VZBridgedNetworkDeviceAttachment(interface: interface)
|
||||
}
|
||||
|
||||
func run() throws {
|
||||
// no-op, only used for Softnet
|
||||
}
|
||||
|
||||
func stop() throws {
|
||||
// no-op, only used for Softnet
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
import Foundation
|
||||
import Virtualization
|
||||
|
||||
class NetworkShared: Network {
|
||||
func attachment() -> VZNetworkDeviceAttachment {
|
||||
VZNATNetworkDeviceAttachment()
|
||||
}
|
||||
|
||||
func run() throws {
|
||||
// no-op, only used for Softnet
|
||||
}
|
||||
|
||||
func stop() throws {
|
||||
// no-op, only used for Softnet
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,11 @@
|
||||
import Foundation
|
||||
import Virtualization
|
||||
|
||||
enum SoftnetError: Error {
|
||||
case InitializationFailed(why: String)
|
||||
}
|
||||
|
||||
class Softnet {
|
||||
class Softnet: Network {
|
||||
private let process = Process()
|
||||
|
||||
let vmFD: Int32
|
||||
@@ -57,4 +58,9 @@ class Softnet {
|
||||
throw SoftnetError.InitializationFailed(why: "setsockopt(SO_SNDBUF) returned \(ret)")
|
||||
}
|
||||
}
|
||||
|
||||
func attachment() -> VZNetworkDeviceAttachment {
|
||||
let fh = FileHandle.init(fileDescriptor: vmFD)
|
||||
return VZFileHandleNetworkDeviceAttachment(fileHandle: fh)
|
||||
}
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
token literal names:
|
||||
null
|
||||
':'
|
||||
'/'
|
||||
'.'
|
||||
'@'
|
||||
'-'
|
||||
'_'
|
||||
null
|
||||
null
|
||||
|
||||
token symbolic names:
|
||||
null
|
||||
null
|
||||
null
|
||||
null
|
||||
null
|
||||
null
|
||||
null
|
||||
DIGIT
|
||||
LETTER
|
||||
|
||||
rule names:
|
||||
root
|
||||
host
|
||||
port
|
||||
namespace
|
||||
namespace_component
|
||||
reference
|
||||
tag
|
||||
separator
|
||||
name
|
||||
|
||||
|
||||
atn:
|
||||
[4, 1, 8, 85, 2, 0, 7, 0, 2, 1, 7, 1, 2, 2, 7, 2, 2, 3, 7, 3, 2, 4, 7, 4, 2, 5, 7, 5, 2, 6, 7, 6, 2, 7, 7, 7, 2, 8, 7, 8, 1, 0, 1, 0, 1, 0, 3, 0, 22, 8, 0, 1, 0, 1, 0, 1, 0, 3, 0, 27, 8, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 5, 1, 34, 8, 1, 10, 1, 12, 1, 37, 9, 1, 1, 2, 4, 2, 40, 8, 2, 11, 2, 12, 2, 41, 1, 3, 1, 3, 1, 3, 5, 3, 47, 8, 3, 10, 3, 12, 3, 50, 9, 3, 1, 4, 1, 4, 3, 4, 54, 8, 4, 4, 4, 56, 8, 4, 11, 4, 12, 4, 57, 1, 5, 1, 5, 1, 5, 1, 5, 1, 5, 1, 5, 1, 5, 3, 5, 67, 8, 5, 1, 6, 1, 6, 1, 6, 1, 6, 5, 6, 73, 8, 6, 10, 6, 12, 6, 76, 9, 6, 1, 7, 1, 7, 1, 8, 4, 8, 81, 8, 8, 11, 8, 12, 8, 82, 1, 8, 0, 0, 9, 0, 2, 4, 6, 8, 10, 12, 14, 16, 0, 2, 2, 0, 3, 3, 5, 6, 1, 0, 7, 8, 85, 0, 18, 1, 0, 0, 0, 2, 30, 1, 0, 0, 0, 4, 39, 1, 0, 0, 0, 6, 43, 1, 0, 0, 0, 8, 55, 1, 0, 0, 0, 10, 66, 1, 0, 0, 0, 12, 68, 1, 0, 0, 0, 14, 77, 1, 0, 0, 0, 16, 80, 1, 0, 0, 0, 18, 21, 3, 2, 1, 0, 19, 20, 5, 1, 0, 0, 20, 22, 3, 4, 2, 0, 21, 19, 1, 0, 0, 0, 21, 22, 1, 0, 0, 0, 22, 23, 1, 0, 0, 0, 23, 24, 5, 2, 0, 0, 24, 26, 3, 6, 3, 0, 25, 27, 3, 10, 5, 0, 26, 25, 1, 0, 0, 0, 26, 27, 1, 0, 0, 0, 27, 28, 1, 0, 0, 0, 28, 29, 5, 0, 0, 1, 29, 1, 1, 0, 0, 0, 30, 35, 3, 16, 8, 0, 31, 32, 5, 3, 0, 0, 32, 34, 3, 16, 8, 0, 33, 31, 1, 0, 0, 0, 34, 37, 1, 0, 0, 0, 35, 33, 1, 0, 0, 0, 35, 36, 1, 0, 0, 0, 36, 3, 1, 0, 0, 0, 37, 35, 1, 0, 0, 0, 38, 40, 5, 7, 0, 0, 39, 38, 1, 0, 0, 0, 40, 41, 1, 0, 0, 0, 41, 39, 1, 0, 0, 0, 41, 42, 1, 0, 0, 0, 42, 5, 1, 0, 0, 0, 43, 48, 3, 8, 4, 0, 44, 45, 5, 2, 0, 0, 45, 47, 3, 8, 4, 0, 46, 44, 1, 0, 0, 0, 47, 50, 1, 0, 0, 0, 48, 46, 1, 0, 0, 0, 48, 49, 1, 0, 0, 0, 49, 7, 1, 0, 0, 0, 50, 48, 1, 0, 0, 0, 51, 53, 3, 16, 8, 0, 52, 54, 3, 14, 7, 0, 53, 52, 1, 0, 0, 0, 53, 54, 1, 0, 0, 0, 54, 56, 1, 0, 0, 0, 55, 51, 1, 0, 0, 0, 56, 57, 1, 0, 0, 0, 57, 55, 1, 0, 0, 0, 57, 58, 1, 0, 0, 0, 58, 9, 1, 0, 0, 0, 59, 60, 5, 1, 0, 0, 60, 67, 3, 12, 6, 0, 61, 62, 5, 4, 0, 0, 62, 63, 3, 16, 8, 0, 63, 64, 5, 1, 0, 0, 64, 65, 3, 16, 8, 0, 65, 67, 1, 0, 0, 0, 66, 59, 1, 0, 0, 0, 66, 61, 1, 0, 0, 0, 67, 11, 1, 0, 0, 0, 68, 74, 3, 16, 8, 0, 69, 70, 3, 14, 7, 0, 70, 71, 3, 16, 8, 0, 71, 73, 1, 0, 0, 0, 72, 69, 1, 0, 0, 0, 73, 76, 1, 0, 0, 0, 74, 72, 1, 0, 0, 0, 74, 75, 1, 0, 0, 0, 75, 13, 1, 0, 0, 0, 76, 74, 1, 0, 0, 0, 77, 78, 7, 0, 0, 0, 78, 15, 1, 0, 0, 0, 79, 81, 7, 1, 0, 0, 80, 79, 1, 0, 0, 0, 81, 82, 1, 0, 0, 0, 82, 80, 1, 0, 0, 0, 82, 83, 1, 0, 0, 0, 83, 17, 1, 0, 0, 0, 10, 21, 26, 35, 41, 48, 53, 57, 66, 74, 82]
|
||||
@@ -1,14 +0,0 @@
|
||||
T__0=1
|
||||
T__1=2
|
||||
T__2=3
|
||||
T__3=4
|
||||
T__4=5
|
||||
T__5=6
|
||||
DIGIT=7
|
||||
LETTER=8
|
||||
':'=1
|
||||
'/'=2
|
||||
'.'=3
|
||||
'@'=4
|
||||
'-'=5
|
||||
'_'=6
|
||||
@@ -1,154 +0,0 @@
|
||||
// Generated from Reference.g4 by ANTLR 4.10.1
|
||||
|
||||
import Antlr4
|
||||
|
||||
|
||||
/**
|
||||
* This class provides an empty implementation of {@link ReferenceListener},
|
||||
* which can be extended to create a listener which only needs to handle a subset
|
||||
* of the available methods.
|
||||
*/
|
||||
open class ReferenceBaseListener: ReferenceListener {
|
||||
public init() { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
open func enterRoot(_ ctx: ReferenceParser.RootContext) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
open func exitRoot(_ ctx: ReferenceParser.RootContext) { }
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
open func enterHost(_ ctx: ReferenceParser.HostContext) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
open func exitHost(_ ctx: ReferenceParser.HostContext) { }
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
open func enterPort(_ ctx: ReferenceParser.PortContext) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
open func exitPort(_ ctx: ReferenceParser.PortContext) { }
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
open func enterNamespace(_ ctx: ReferenceParser.NamespaceContext) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
open func exitNamespace(_ ctx: ReferenceParser.NamespaceContext) { }
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
open func enterNamespace_component(_ ctx: ReferenceParser.Namespace_componentContext) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
open func exitNamespace_component(_ ctx: ReferenceParser.Namespace_componentContext) { }
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
open func enterReference(_ ctx: ReferenceParser.ReferenceContext) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
open func exitReference(_ ctx: ReferenceParser.ReferenceContext) { }
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
open func enterTag(_ ctx: ReferenceParser.TagContext) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
open func exitTag(_ ctx: ReferenceParser.TagContext) { }
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
open func enterSeparator(_ ctx: ReferenceParser.SeparatorContext) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
open func exitSeparator(_ ctx: ReferenceParser.SeparatorContext) { }
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
open func enterName(_ ctx: ReferenceParser.NameContext) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
open func exitName(_ ctx: ReferenceParser.NameContext) { }
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
open func enterEveryRule(_ ctx: ParserRuleContext) throws { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
open func exitEveryRule(_ ctx: ParserRuleContext) throws { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
open func visitTerminal(_ node: TerminalNode) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
open func visitErrorNode(_ node: ErrorNode) { }
|
||||
}
|
||||
@@ -1,41 +0,0 @@
|
||||
token literal names:
|
||||
null
|
||||
':'
|
||||
'/'
|
||||
'.'
|
||||
'@'
|
||||
'-'
|
||||
'_'
|
||||
null
|
||||
null
|
||||
|
||||
token symbolic names:
|
||||
null
|
||||
null
|
||||
null
|
||||
null
|
||||
null
|
||||
null
|
||||
null
|
||||
DIGIT
|
||||
LETTER
|
||||
|
||||
rule names:
|
||||
T__0
|
||||
T__1
|
||||
T__2
|
||||
T__3
|
||||
T__4
|
||||
T__5
|
||||
DIGIT
|
||||
LETTER
|
||||
|
||||
channel names:
|
||||
DEFAULT_TOKEN_CHANNEL
|
||||
HIDDEN
|
||||
|
||||
mode names:
|
||||
DEFAULT_MODE
|
||||
|
||||
atn:
|
||||
[4, 0, 8, 33, 6, -1, 2, 0, 7, 0, 2, 1, 7, 1, 2, 2, 7, 2, 2, 3, 7, 3, 2, 4, 7, 4, 2, 5, 7, 5, 2, 6, 7, 6, 2, 7, 7, 7, 1, 0, 1, 0, 1, 1, 1, 1, 1, 2, 1, 2, 1, 3, 1, 3, 1, 4, 1, 4, 1, 5, 1, 5, 1, 6, 1, 6, 1, 7, 1, 7, 0, 0, 8, 1, 1, 3, 2, 5, 3, 7, 4, 9, 5, 11, 6, 13, 7, 15, 8, 1, 0, 2, 1, 0, 48, 57, 2, 0, 65, 90, 97, 122, 32, 0, 1, 1, 0, 0, 0, 0, 3, 1, 0, 0, 0, 0, 5, 1, 0, 0, 0, 0, 7, 1, 0, 0, 0, 0, 9, 1, 0, 0, 0, 0, 11, 1, 0, 0, 0, 0, 13, 1, 0, 0, 0, 0, 15, 1, 0, 0, 0, 1, 17, 1, 0, 0, 0, 3, 19, 1, 0, 0, 0, 5, 21, 1, 0, 0, 0, 7, 23, 1, 0, 0, 0, 9, 25, 1, 0, 0, 0, 11, 27, 1, 0, 0, 0, 13, 29, 1, 0, 0, 0, 15, 31, 1, 0, 0, 0, 17, 18, 5, 58, 0, 0, 18, 2, 1, 0, 0, 0, 19, 20, 5, 47, 0, 0, 20, 4, 1, 0, 0, 0, 21, 22, 5, 46, 0, 0, 22, 6, 1, 0, 0, 0, 23, 24, 5, 64, 0, 0, 24, 8, 1, 0, 0, 0, 25, 26, 5, 45, 0, 0, 26, 10, 1, 0, 0, 0, 27, 28, 5, 95, 0, 0, 28, 12, 1, 0, 0, 0, 29, 30, 7, 0, 0, 0, 30, 14, 1, 0, 0, 0, 31, 32, 7, 1, 0, 0, 32, 16, 1, 0, 0, 0, 1, 0, 0]
|
||||
@@ -1,90 +0,0 @@
|
||||
// Generated from Reference.g4 by ANTLR 4.10.1
|
||||
import Antlr4
|
||||
|
||||
open class ReferenceLexer: Lexer {
|
||||
|
||||
internal static var _decisionToDFA: [DFA] = {
|
||||
var decisionToDFA = [DFA]()
|
||||
let length = ReferenceLexer._ATN.getNumberOfDecisions()
|
||||
for i in 0..<length {
|
||||
decisionToDFA.append(DFA(ReferenceLexer._ATN.getDecisionState(i)!, i))
|
||||
}
|
||||
return decisionToDFA
|
||||
}()
|
||||
|
||||
internal static let _sharedContextCache = PredictionContextCache()
|
||||
|
||||
public
|
||||
static let T__0=1, T__1=2, T__2=3, T__3=4, T__4=5, T__5=6, DIGIT=7, LETTER=8
|
||||
|
||||
public
|
||||
static let channelNames: [String] = [
|
||||
"DEFAULT_TOKEN_CHANNEL", "HIDDEN"
|
||||
]
|
||||
|
||||
public
|
||||
static let modeNames: [String] = [
|
||||
"DEFAULT_MODE"
|
||||
]
|
||||
|
||||
public
|
||||
static let ruleNames: [String] = [
|
||||
"T__0", "T__1", "T__2", "T__3", "T__4", "T__5", "DIGIT", "LETTER"
|
||||
]
|
||||
|
||||
private static let _LITERAL_NAMES: [String?] = [
|
||||
nil, "':'", "'/'", "'.'", "'@'", "'-'", "'_'"
|
||||
]
|
||||
private static let _SYMBOLIC_NAMES: [String?] = [
|
||||
nil, nil, nil, nil, nil, nil, nil, "DIGIT", "LETTER"
|
||||
]
|
||||
public
|
||||
static let VOCABULARY = Vocabulary(_LITERAL_NAMES, _SYMBOLIC_NAMES)
|
||||
|
||||
|
||||
override open
|
||||
func getVocabulary() -> Vocabulary {
|
||||
return ReferenceLexer.VOCABULARY
|
||||
}
|
||||
|
||||
public
|
||||
required init(_ input: CharStream) {
|
||||
RuntimeMetaData.checkVersion("4.10.1", RuntimeMetaData.VERSION)
|
||||
super.init(input)
|
||||
_interp = LexerATNSimulator(self, ReferenceLexer._ATN, ReferenceLexer._decisionToDFA, ReferenceLexer._sharedContextCache)
|
||||
}
|
||||
|
||||
override open
|
||||
func getGrammarFileName() -> String { return "Reference.g4" }
|
||||
|
||||
override open
|
||||
func getRuleNames() -> [String] { return ReferenceLexer.ruleNames }
|
||||
|
||||
override open
|
||||
func getSerializedATN() -> [Int] { return ReferenceLexer._serializedATN }
|
||||
|
||||
override open
|
||||
func getChannelNames() -> [String] { return ReferenceLexer.channelNames }
|
||||
|
||||
override open
|
||||
func getModeNames() -> [String] { return ReferenceLexer.modeNames }
|
||||
|
||||
override open
|
||||
func getATN() -> ATN { return ReferenceLexer._ATN }
|
||||
|
||||
static let _serializedATN:[Int] = [
|
||||
4,0,8,33,6,-1,2,0,7,0,2,1,7,1,2,2,7,2,2,3,7,3,2,4,7,4,2,5,7,5,2,6,7,6,
|
||||
2,7,7,7,1,0,1,0,1,1,1,1,1,2,1,2,1,3,1,3,1,4,1,4,1,5,1,5,1,6,1,6,1,7,1,
|
||||
7,0,0,8,1,1,3,2,5,3,7,4,9,5,11,6,13,7,15,8,1,0,2,1,0,48,57,2,0,65,90,97,
|
||||
122,32,0,1,1,0,0,0,0,3,1,0,0,0,0,5,1,0,0,0,0,7,1,0,0,0,0,9,1,0,0,0,0,11,
|
||||
1,0,0,0,0,13,1,0,0,0,0,15,1,0,0,0,1,17,1,0,0,0,3,19,1,0,0,0,5,21,1,0,0,
|
||||
0,7,23,1,0,0,0,9,25,1,0,0,0,11,27,1,0,0,0,13,29,1,0,0,0,15,31,1,0,0,0,
|
||||
17,18,5,58,0,0,18,2,1,0,0,0,19,20,5,47,0,0,20,4,1,0,0,0,21,22,5,46,0,0,
|
||||
22,6,1,0,0,0,23,24,5,64,0,0,24,8,1,0,0,0,25,26,5,45,0,0,26,10,1,0,0,0,
|
||||
27,28,5,95,0,0,28,12,1,0,0,0,29,30,7,0,0,0,30,14,1,0,0,0,31,32,7,1,0,0,
|
||||
32,16,1,0,0,0,1,0,0
|
||||
]
|
||||
|
||||
public
|
||||
static let _ATN: ATN = try! ATNDeserializer().deserialize(_serializedATN)
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
T__0=1
|
||||
T__1=2
|
||||
T__2=3
|
||||
T__3=4
|
||||
T__4=5
|
||||
T__5=6
|
||||
DIGIT=7
|
||||
LETTER=8
|
||||
':'=1
|
||||
'/'=2
|
||||
'.'=3
|
||||
'@'=4
|
||||
'-'=5
|
||||
'_'=6
|
||||
@@ -1,117 +0,0 @@
|
||||
// Generated from Reference.g4 by ANTLR 4.10.1
|
||||
import Antlr4
|
||||
|
||||
/**
|
||||
* This interface defines a complete listener for a parse tree produced by
|
||||
* {@link ReferenceParser}.
|
||||
*/
|
||||
public protocol ReferenceListener: ParseTreeListener {
|
||||
/**
|
||||
* Enter a parse tree produced by {@link ReferenceParser#root}.
|
||||
- Parameters:
|
||||
- ctx: the parse tree
|
||||
*/
|
||||
func enterRoot(_ ctx: ReferenceParser.RootContext)
|
||||
/**
|
||||
* Exit a parse tree produced by {@link ReferenceParser#root}.
|
||||
- Parameters:
|
||||
- ctx: the parse tree
|
||||
*/
|
||||
func exitRoot(_ ctx: ReferenceParser.RootContext)
|
||||
/**
|
||||
* Enter a parse tree produced by {@link ReferenceParser#host}.
|
||||
- Parameters:
|
||||
- ctx: the parse tree
|
||||
*/
|
||||
func enterHost(_ ctx: ReferenceParser.HostContext)
|
||||
/**
|
||||
* Exit a parse tree produced by {@link ReferenceParser#host}.
|
||||
- Parameters:
|
||||
- ctx: the parse tree
|
||||
*/
|
||||
func exitHost(_ ctx: ReferenceParser.HostContext)
|
||||
/**
|
||||
* Enter a parse tree produced by {@link ReferenceParser#port}.
|
||||
- Parameters:
|
||||
- ctx: the parse tree
|
||||
*/
|
||||
func enterPort(_ ctx: ReferenceParser.PortContext)
|
||||
/**
|
||||
* Exit a parse tree produced by {@link ReferenceParser#port}.
|
||||
- Parameters:
|
||||
- ctx: the parse tree
|
||||
*/
|
||||
func exitPort(_ ctx: ReferenceParser.PortContext)
|
||||
/**
|
||||
* Enter a parse tree produced by {@link ReferenceParser#namespace}.
|
||||
- Parameters:
|
||||
- ctx: the parse tree
|
||||
*/
|
||||
func enterNamespace(_ ctx: ReferenceParser.NamespaceContext)
|
||||
/**
|
||||
* Exit a parse tree produced by {@link ReferenceParser#namespace}.
|
||||
- Parameters:
|
||||
- ctx: the parse tree
|
||||
*/
|
||||
func exitNamespace(_ ctx: ReferenceParser.NamespaceContext)
|
||||
/**
|
||||
* Enter a parse tree produced by {@link ReferenceParser#namespace_component}.
|
||||
- Parameters:
|
||||
- ctx: the parse tree
|
||||
*/
|
||||
func enterNamespace_component(_ ctx: ReferenceParser.Namespace_componentContext)
|
||||
/**
|
||||
* Exit a parse tree produced by {@link ReferenceParser#namespace_component}.
|
||||
- Parameters:
|
||||
- ctx: the parse tree
|
||||
*/
|
||||
func exitNamespace_component(_ ctx: ReferenceParser.Namespace_componentContext)
|
||||
/**
|
||||
* Enter a parse tree produced by {@link ReferenceParser#reference}.
|
||||
- Parameters:
|
||||
- ctx: the parse tree
|
||||
*/
|
||||
func enterReference(_ ctx: ReferenceParser.ReferenceContext)
|
||||
/**
|
||||
* Exit a parse tree produced by {@link ReferenceParser#reference}.
|
||||
- Parameters:
|
||||
- ctx: the parse tree
|
||||
*/
|
||||
func exitReference(_ ctx: ReferenceParser.ReferenceContext)
|
||||
/**
|
||||
* Enter a parse tree produced by {@link ReferenceParser#tag}.
|
||||
- Parameters:
|
||||
- ctx: the parse tree
|
||||
*/
|
||||
func enterTag(_ ctx: ReferenceParser.TagContext)
|
||||
/**
|
||||
* Exit a parse tree produced by {@link ReferenceParser#tag}.
|
||||
- Parameters:
|
||||
- ctx: the parse tree
|
||||
*/
|
||||
func exitTag(_ ctx: ReferenceParser.TagContext)
|
||||
/**
|
||||
* Enter a parse tree produced by {@link ReferenceParser#separator}.
|
||||
- Parameters:
|
||||
- ctx: the parse tree
|
||||
*/
|
||||
func enterSeparator(_ ctx: ReferenceParser.SeparatorContext)
|
||||
/**
|
||||
* Exit a parse tree produced by {@link ReferenceParser#separator}.
|
||||
- Parameters:
|
||||
- ctx: the parse tree
|
||||
*/
|
||||
func exitSeparator(_ ctx: ReferenceParser.SeparatorContext)
|
||||
/**
|
||||
* Enter a parse tree produced by {@link ReferenceParser#name}.
|
||||
- Parameters:
|
||||
- ctx: the parse tree
|
||||
*/
|
||||
func enterName(_ ctx: ReferenceParser.NameContext)
|
||||
/**
|
||||
* Exit a parse tree produced by {@link ReferenceParser#name}.
|
||||
- Parameters:
|
||||
- ctx: the parse tree
|
||||
*/
|
||||
func exitName(_ ctx: ReferenceParser.NameContext)
|
||||
}
|
||||
@@ -1,781 +0,0 @@
|
||||
// Generated from Reference.g4 by ANTLR 4.10.1
|
||||
import Antlr4
|
||||
|
||||
open class ReferenceParser: Parser {
|
||||
|
||||
internal static var _decisionToDFA: [DFA] = {
|
||||
var decisionToDFA = [DFA]()
|
||||
let length = ReferenceParser._ATN.getNumberOfDecisions()
|
||||
for i in 0..<length {
|
||||
decisionToDFA.append(DFA(ReferenceParser._ATN.getDecisionState(i)!, i))
|
||||
}
|
||||
return decisionToDFA
|
||||
}()
|
||||
|
||||
internal static let _sharedContextCache = PredictionContextCache()
|
||||
|
||||
public
|
||||
enum Tokens: Int {
|
||||
case EOF = -1, T__0 = 1, T__1 = 2, T__2 = 3, T__3 = 4, T__4 = 5, T__5 = 6,
|
||||
DIGIT = 7, LETTER = 8
|
||||
}
|
||||
|
||||
public
|
||||
static let RULE_root = 0, RULE_host = 1, RULE_port = 2, RULE_namespace = 3,
|
||||
RULE_namespace_component = 4, RULE_reference = 5, RULE_tag = 6,
|
||||
RULE_separator = 7, RULE_name = 8
|
||||
|
||||
public
|
||||
static let ruleNames: [String] = [
|
||||
"root", "host", "port", "namespace", "namespace_component", "reference",
|
||||
"tag", "separator", "name"
|
||||
]
|
||||
|
||||
private static let _LITERAL_NAMES: [String?] = [
|
||||
nil, "':'", "'/'", "'.'", "'@'", "'-'", "'_'"
|
||||
]
|
||||
private static let _SYMBOLIC_NAMES: [String?] = [
|
||||
nil, nil, nil, nil, nil, nil, nil, "DIGIT", "LETTER"
|
||||
]
|
||||
public
|
||||
static let VOCABULARY = Vocabulary(_LITERAL_NAMES, _SYMBOLIC_NAMES)
|
||||
|
||||
override open
|
||||
func getGrammarFileName() -> String { return "Reference.g4" }
|
||||
|
||||
override open
|
||||
func getRuleNames() -> [String] { return ReferenceParser.ruleNames }
|
||||
|
||||
override open
|
||||
func getSerializedATN() -> [Int] { return ReferenceParser._serializedATN }
|
||||
|
||||
override open
|
||||
func getATN() -> ATN { return ReferenceParser._ATN }
|
||||
|
||||
|
||||
override open
|
||||
func getVocabulary() -> Vocabulary {
|
||||
return ReferenceParser.VOCABULARY
|
||||
}
|
||||
|
||||
override public
|
||||
init(_ input:TokenStream) throws {
|
||||
RuntimeMetaData.checkVersion("4.10.1", RuntimeMetaData.VERSION)
|
||||
try super.init(input)
|
||||
_interp = ParserATNSimulator(self,ReferenceParser._ATN,ReferenceParser._decisionToDFA, ReferenceParser._sharedContextCache)
|
||||
}
|
||||
|
||||
|
||||
public class RootContext: ParserRuleContext {
|
||||
open
|
||||
func host() -> HostContext? {
|
||||
return getRuleContext(HostContext.self, 0)
|
||||
}
|
||||
open
|
||||
func namespace() -> NamespaceContext? {
|
||||
return getRuleContext(NamespaceContext.self, 0)
|
||||
}
|
||||
open
|
||||
func EOF() -> TerminalNode? {
|
||||
return getToken(ReferenceParser.Tokens.EOF.rawValue, 0)
|
||||
}
|
||||
open
|
||||
func port() -> PortContext? {
|
||||
return getRuleContext(PortContext.self, 0)
|
||||
}
|
||||
open
|
||||
func reference() -> ReferenceContext? {
|
||||
return getRuleContext(ReferenceContext.self, 0)
|
||||
}
|
||||
override open
|
||||
func getRuleIndex() -> Int {
|
||||
return ReferenceParser.RULE_root
|
||||
}
|
||||
override open
|
||||
func enterRule(_ listener: ParseTreeListener) {
|
||||
if let listener = listener as? ReferenceListener {
|
||||
listener.enterRoot(self)
|
||||
}
|
||||
}
|
||||
override open
|
||||
func exitRule(_ listener: ParseTreeListener) {
|
||||
if let listener = listener as? ReferenceListener {
|
||||
listener.exitRoot(self)
|
||||
}
|
||||
}
|
||||
}
|
||||
@discardableResult
|
||||
open func root() throws -> RootContext {
|
||||
var _localctx: RootContext
|
||||
_localctx = RootContext(_ctx, getState())
|
||||
try enterRule(_localctx, 0, ReferenceParser.RULE_root)
|
||||
var _la: Int = 0
|
||||
defer {
|
||||
try! exitRule()
|
||||
}
|
||||
do {
|
||||
try enterOuterAlt(_localctx, 1)
|
||||
setState(18)
|
||||
try host()
|
||||
setState(21)
|
||||
try _errHandler.sync(self)
|
||||
_la = try _input.LA(1)
|
||||
if (//closure
|
||||
{ () -> Bool in
|
||||
let testSet: Bool = _la == ReferenceParser.Tokens.T__0.rawValue
|
||||
return testSet
|
||||
}()) {
|
||||
setState(19)
|
||||
try match(ReferenceParser.Tokens.T__0.rawValue)
|
||||
setState(20)
|
||||
try port()
|
||||
|
||||
}
|
||||
|
||||
setState(23)
|
||||
try match(ReferenceParser.Tokens.T__1.rawValue)
|
||||
setState(24)
|
||||
try namespace()
|
||||
setState(26)
|
||||
try _errHandler.sync(self)
|
||||
_la = try _input.LA(1)
|
||||
if (//closure
|
||||
{ () -> Bool in
|
||||
let testSet: Bool = _la == ReferenceParser.Tokens.T__0.rawValue || _la == ReferenceParser.Tokens.T__3.rawValue
|
||||
return testSet
|
||||
}()) {
|
||||
setState(25)
|
||||
try reference()
|
||||
|
||||
}
|
||||
|
||||
setState(28)
|
||||
try match(ReferenceParser.Tokens.EOF.rawValue)
|
||||
|
||||
}
|
||||
catch ANTLRException.recognition(let re) {
|
||||
_localctx.exception = re
|
||||
_errHandler.reportError(self, re)
|
||||
try _errHandler.recover(self, re)
|
||||
}
|
||||
|
||||
return _localctx
|
||||
}
|
||||
|
||||
public class HostContext: ParserRuleContext {
|
||||
open
|
||||
func name() -> [NameContext] {
|
||||
return getRuleContexts(NameContext.self)
|
||||
}
|
||||
open
|
||||
func name(_ i: Int) -> NameContext? {
|
||||
return getRuleContext(NameContext.self, i)
|
||||
}
|
||||
override open
|
||||
func getRuleIndex() -> Int {
|
||||
return ReferenceParser.RULE_host
|
||||
}
|
||||
override open
|
||||
func enterRule(_ listener: ParseTreeListener) {
|
||||
if let listener = listener as? ReferenceListener {
|
||||
listener.enterHost(self)
|
||||
}
|
||||
}
|
||||
override open
|
||||
func exitRule(_ listener: ParseTreeListener) {
|
||||
if let listener = listener as? ReferenceListener {
|
||||
listener.exitHost(self)
|
||||
}
|
||||
}
|
||||
}
|
||||
@discardableResult
|
||||
open func host() throws -> HostContext {
|
||||
var _localctx: HostContext
|
||||
_localctx = HostContext(_ctx, getState())
|
||||
try enterRule(_localctx, 2, ReferenceParser.RULE_host)
|
||||
var _la: Int = 0
|
||||
defer {
|
||||
try! exitRule()
|
||||
}
|
||||
do {
|
||||
try enterOuterAlt(_localctx, 1)
|
||||
setState(30)
|
||||
try name()
|
||||
setState(35)
|
||||
try _errHandler.sync(self)
|
||||
_la = try _input.LA(1)
|
||||
while (//closure
|
||||
{ () -> Bool in
|
||||
let testSet: Bool = _la == ReferenceParser.Tokens.T__2.rawValue
|
||||
return testSet
|
||||
}()) {
|
||||
setState(31)
|
||||
try match(ReferenceParser.Tokens.T__2.rawValue)
|
||||
setState(32)
|
||||
try name()
|
||||
|
||||
|
||||
setState(37)
|
||||
try _errHandler.sync(self)
|
||||
_la = try _input.LA(1)
|
||||
}
|
||||
|
||||
}
|
||||
catch ANTLRException.recognition(let re) {
|
||||
_localctx.exception = re
|
||||
_errHandler.reportError(self, re)
|
||||
try _errHandler.recover(self, re)
|
||||
}
|
||||
|
||||
return _localctx
|
||||
}
|
||||
|
||||
public class PortContext: ParserRuleContext {
|
||||
open
|
||||
func DIGIT() -> [TerminalNode] {
|
||||
return getTokens(ReferenceParser.Tokens.DIGIT.rawValue)
|
||||
}
|
||||
open
|
||||
func DIGIT(_ i:Int) -> TerminalNode? {
|
||||
return getToken(ReferenceParser.Tokens.DIGIT.rawValue, i)
|
||||
}
|
||||
override open
|
||||
func getRuleIndex() -> Int {
|
||||
return ReferenceParser.RULE_port
|
||||
}
|
||||
override open
|
||||
func enterRule(_ listener: ParseTreeListener) {
|
||||
if let listener = listener as? ReferenceListener {
|
||||
listener.enterPort(self)
|
||||
}
|
||||
}
|
||||
override open
|
||||
func exitRule(_ listener: ParseTreeListener) {
|
||||
if let listener = listener as? ReferenceListener {
|
||||
listener.exitPort(self)
|
||||
}
|
||||
}
|
||||
}
|
||||
@discardableResult
|
||||
open func port() throws -> PortContext {
|
||||
var _localctx: PortContext
|
||||
_localctx = PortContext(_ctx, getState())
|
||||
try enterRule(_localctx, 4, ReferenceParser.RULE_port)
|
||||
var _la: Int = 0
|
||||
defer {
|
||||
try! exitRule()
|
||||
}
|
||||
do {
|
||||
try enterOuterAlt(_localctx, 1)
|
||||
setState(39)
|
||||
try _errHandler.sync(self)
|
||||
_la = try _input.LA(1)
|
||||
repeat {
|
||||
setState(38)
|
||||
try match(ReferenceParser.Tokens.DIGIT.rawValue)
|
||||
|
||||
|
||||
setState(41);
|
||||
try _errHandler.sync(self)
|
||||
_la = try _input.LA(1)
|
||||
} while (//closure
|
||||
{ () -> Bool in
|
||||
let testSet: Bool = _la == ReferenceParser.Tokens.DIGIT.rawValue
|
||||
return testSet
|
||||
}())
|
||||
|
||||
}
|
||||
catch ANTLRException.recognition(let re) {
|
||||
_localctx.exception = re
|
||||
_errHandler.reportError(self, re)
|
||||
try _errHandler.recover(self, re)
|
||||
}
|
||||
|
||||
return _localctx
|
||||
}
|
||||
|
||||
public class NamespaceContext: ParserRuleContext {
|
||||
open
|
||||
func namespace_component() -> [Namespace_componentContext] {
|
||||
return getRuleContexts(Namespace_componentContext.self)
|
||||
}
|
||||
open
|
||||
func namespace_component(_ i: Int) -> Namespace_componentContext? {
|
||||
return getRuleContext(Namespace_componentContext.self, i)
|
||||
}
|
||||
override open
|
||||
func getRuleIndex() -> Int {
|
||||
return ReferenceParser.RULE_namespace
|
||||
}
|
||||
override open
|
||||
func enterRule(_ listener: ParseTreeListener) {
|
||||
if let listener = listener as? ReferenceListener {
|
||||
listener.enterNamespace(self)
|
||||
}
|
||||
}
|
||||
override open
|
||||
func exitRule(_ listener: ParseTreeListener) {
|
||||
if let listener = listener as? ReferenceListener {
|
||||
listener.exitNamespace(self)
|
||||
}
|
||||
}
|
||||
}
|
||||
@discardableResult
|
||||
open func namespace() throws -> NamespaceContext {
|
||||
var _localctx: NamespaceContext
|
||||
_localctx = NamespaceContext(_ctx, getState())
|
||||
try enterRule(_localctx, 6, ReferenceParser.RULE_namespace)
|
||||
var _la: Int = 0
|
||||
defer {
|
||||
try! exitRule()
|
||||
}
|
||||
do {
|
||||
try enterOuterAlt(_localctx, 1)
|
||||
setState(43)
|
||||
try namespace_component()
|
||||
setState(48)
|
||||
try _errHandler.sync(self)
|
||||
_la = try _input.LA(1)
|
||||
while (//closure
|
||||
{ () -> Bool in
|
||||
let testSet: Bool = _la == ReferenceParser.Tokens.T__1.rawValue
|
||||
return testSet
|
||||
}()) {
|
||||
setState(44)
|
||||
try match(ReferenceParser.Tokens.T__1.rawValue)
|
||||
setState(45)
|
||||
try namespace_component()
|
||||
|
||||
|
||||
setState(50)
|
||||
try _errHandler.sync(self)
|
||||
_la = try _input.LA(1)
|
||||
}
|
||||
|
||||
}
|
||||
catch ANTLRException.recognition(let re) {
|
||||
_localctx.exception = re
|
||||
_errHandler.reportError(self, re)
|
||||
try _errHandler.recover(self, re)
|
||||
}
|
||||
|
||||
return _localctx
|
||||
}
|
||||
|
||||
public class Namespace_componentContext: ParserRuleContext {
|
||||
open
|
||||
func name() -> [NameContext] {
|
||||
return getRuleContexts(NameContext.self)
|
||||
}
|
||||
open
|
||||
func name(_ i: Int) -> NameContext? {
|
||||
return getRuleContext(NameContext.self, i)
|
||||
}
|
||||
open
|
||||
func separator() -> [SeparatorContext] {
|
||||
return getRuleContexts(SeparatorContext.self)
|
||||
}
|
||||
open
|
||||
func separator(_ i: Int) -> SeparatorContext? {
|
||||
return getRuleContext(SeparatorContext.self, i)
|
||||
}
|
||||
override open
|
||||
func getRuleIndex() -> Int {
|
||||
return ReferenceParser.RULE_namespace_component
|
||||
}
|
||||
override open
|
||||
func enterRule(_ listener: ParseTreeListener) {
|
||||
if let listener = listener as? ReferenceListener {
|
||||
listener.enterNamespace_component(self)
|
||||
}
|
||||
}
|
||||
override open
|
||||
func exitRule(_ listener: ParseTreeListener) {
|
||||
if let listener = listener as? ReferenceListener {
|
||||
listener.exitNamespace_component(self)
|
||||
}
|
||||
}
|
||||
}
|
||||
@discardableResult
|
||||
open func namespace_component() throws -> Namespace_componentContext {
|
||||
var _localctx: Namespace_componentContext
|
||||
_localctx = Namespace_componentContext(_ctx, getState())
|
||||
try enterRule(_localctx, 8, ReferenceParser.RULE_namespace_component)
|
||||
var _la: Int = 0
|
||||
defer {
|
||||
try! exitRule()
|
||||
}
|
||||
do {
|
||||
try enterOuterAlt(_localctx, 1)
|
||||
setState(55)
|
||||
try _errHandler.sync(self)
|
||||
_la = try _input.LA(1)
|
||||
repeat {
|
||||
setState(51)
|
||||
try name()
|
||||
setState(53)
|
||||
try _errHandler.sync(self)
|
||||
_la = try _input.LA(1)
|
||||
if (//closure
|
||||
{ () -> Bool in
|
||||
let testSet: Bool = { () -> Bool in
|
||||
let testArray: [Int] = [_la, ReferenceParser.Tokens.T__2.rawValue,ReferenceParser.Tokens.T__4.rawValue,ReferenceParser.Tokens.T__5.rawValue]
|
||||
return Utils.testBitLeftShiftArray(testArray, 0)
|
||||
}()
|
||||
return testSet
|
||||
}()) {
|
||||
setState(52)
|
||||
try separator()
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
setState(57);
|
||||
try _errHandler.sync(self)
|
||||
_la = try _input.LA(1)
|
||||
} while (//closure
|
||||
{ () -> Bool in
|
||||
let testSet: Bool = _la == ReferenceParser.Tokens.DIGIT.rawValue || _la == ReferenceParser.Tokens.LETTER.rawValue
|
||||
return testSet
|
||||
}())
|
||||
|
||||
}
|
||||
catch ANTLRException.recognition(let re) {
|
||||
_localctx.exception = re
|
||||
_errHandler.reportError(self, re)
|
||||
try _errHandler.recover(self, re)
|
||||
}
|
||||
|
||||
return _localctx
|
||||
}
|
||||
|
||||
public class ReferenceContext: ParserRuleContext {
|
||||
open
|
||||
func tag() -> TagContext? {
|
||||
return getRuleContext(TagContext.self, 0)
|
||||
}
|
||||
open
|
||||
func name() -> [NameContext] {
|
||||
return getRuleContexts(NameContext.self)
|
||||
}
|
||||
open
|
||||
func name(_ i: Int) -> NameContext? {
|
||||
return getRuleContext(NameContext.self, i)
|
||||
}
|
||||
override open
|
||||
func getRuleIndex() -> Int {
|
||||
return ReferenceParser.RULE_reference
|
||||
}
|
||||
override open
|
||||
func enterRule(_ listener: ParseTreeListener) {
|
||||
if let listener = listener as? ReferenceListener {
|
||||
listener.enterReference(self)
|
||||
}
|
||||
}
|
||||
override open
|
||||
func exitRule(_ listener: ParseTreeListener) {
|
||||
if let listener = listener as? ReferenceListener {
|
||||
listener.exitReference(self)
|
||||
}
|
||||
}
|
||||
}
|
||||
@discardableResult
|
||||
open func reference() throws -> ReferenceContext {
|
||||
var _localctx: ReferenceContext
|
||||
_localctx = ReferenceContext(_ctx, getState())
|
||||
try enterRule(_localctx, 10, ReferenceParser.RULE_reference)
|
||||
defer {
|
||||
try! exitRule()
|
||||
}
|
||||
do {
|
||||
setState(66)
|
||||
try _errHandler.sync(self)
|
||||
switch (ReferenceParser.Tokens(rawValue: try _input.LA(1))!) {
|
||||
case .T__0:
|
||||
try enterOuterAlt(_localctx, 1)
|
||||
setState(59)
|
||||
try match(ReferenceParser.Tokens.T__0.rawValue)
|
||||
setState(60)
|
||||
try tag()
|
||||
|
||||
|
||||
break
|
||||
|
||||
case .T__3:
|
||||
try enterOuterAlt(_localctx, 2)
|
||||
setState(61)
|
||||
try match(ReferenceParser.Tokens.T__3.rawValue)
|
||||
setState(62)
|
||||
try name()
|
||||
setState(63)
|
||||
try match(ReferenceParser.Tokens.T__0.rawValue)
|
||||
setState(64)
|
||||
try name()
|
||||
|
||||
|
||||
break
|
||||
default:
|
||||
throw ANTLRException.recognition(e: NoViableAltException(self))
|
||||
}
|
||||
}
|
||||
catch ANTLRException.recognition(let re) {
|
||||
_localctx.exception = re
|
||||
_errHandler.reportError(self, re)
|
||||
try _errHandler.recover(self, re)
|
||||
}
|
||||
|
||||
return _localctx
|
||||
}
|
||||
|
||||
public class TagContext: ParserRuleContext {
|
||||
open
|
||||
func name() -> [NameContext] {
|
||||
return getRuleContexts(NameContext.self)
|
||||
}
|
||||
open
|
||||
func name(_ i: Int) -> NameContext? {
|
||||
return getRuleContext(NameContext.self, i)
|
||||
}
|
||||
open
|
||||
func separator() -> [SeparatorContext] {
|
||||
return getRuleContexts(SeparatorContext.self)
|
||||
}
|
||||
open
|
||||
func separator(_ i: Int) -> SeparatorContext? {
|
||||
return getRuleContext(SeparatorContext.self, i)
|
||||
}
|
||||
override open
|
||||
func getRuleIndex() -> Int {
|
||||
return ReferenceParser.RULE_tag
|
||||
}
|
||||
override open
|
||||
func enterRule(_ listener: ParseTreeListener) {
|
||||
if let listener = listener as? ReferenceListener {
|
||||
listener.enterTag(self)
|
||||
}
|
||||
}
|
||||
override open
|
||||
func exitRule(_ listener: ParseTreeListener) {
|
||||
if let listener = listener as? ReferenceListener {
|
||||
listener.exitTag(self)
|
||||
}
|
||||
}
|
||||
}
|
||||
@discardableResult
|
||||
open func tag() throws -> TagContext {
|
||||
var _localctx: TagContext
|
||||
_localctx = TagContext(_ctx, getState())
|
||||
try enterRule(_localctx, 12, ReferenceParser.RULE_tag)
|
||||
var _la: Int = 0
|
||||
defer {
|
||||
try! exitRule()
|
||||
}
|
||||
do {
|
||||
try enterOuterAlt(_localctx, 1)
|
||||
setState(68)
|
||||
try name()
|
||||
setState(74)
|
||||
try _errHandler.sync(self)
|
||||
_la = try _input.LA(1)
|
||||
while (//closure
|
||||
{ () -> Bool in
|
||||
let testSet: Bool = { () -> Bool in
|
||||
let testArray: [Int] = [_la, ReferenceParser.Tokens.T__2.rawValue,ReferenceParser.Tokens.T__4.rawValue,ReferenceParser.Tokens.T__5.rawValue]
|
||||
return Utils.testBitLeftShiftArray(testArray, 0)
|
||||
}()
|
||||
return testSet
|
||||
}()) {
|
||||
setState(69)
|
||||
try separator()
|
||||
setState(70)
|
||||
try name()
|
||||
|
||||
|
||||
setState(76)
|
||||
try _errHandler.sync(self)
|
||||
_la = try _input.LA(1)
|
||||
}
|
||||
|
||||
}
|
||||
catch ANTLRException.recognition(let re) {
|
||||
_localctx.exception = re
|
||||
_errHandler.reportError(self, re)
|
||||
try _errHandler.recover(self, re)
|
||||
}
|
||||
|
||||
return _localctx
|
||||
}
|
||||
|
||||
public class SeparatorContext: ParserRuleContext {
|
||||
override open
|
||||
func getRuleIndex() -> Int {
|
||||
return ReferenceParser.RULE_separator
|
||||
}
|
||||
override open
|
||||
func enterRule(_ listener: ParseTreeListener) {
|
||||
if let listener = listener as? ReferenceListener {
|
||||
listener.enterSeparator(self)
|
||||
}
|
||||
}
|
||||
override open
|
||||
func exitRule(_ listener: ParseTreeListener) {
|
||||
if let listener = listener as? ReferenceListener {
|
||||
listener.exitSeparator(self)
|
||||
}
|
||||
}
|
||||
}
|
||||
@discardableResult
|
||||
open func separator() throws -> SeparatorContext {
|
||||
var _localctx: SeparatorContext
|
||||
_localctx = SeparatorContext(_ctx, getState())
|
||||
try enterRule(_localctx, 14, ReferenceParser.RULE_separator)
|
||||
var _la: Int = 0
|
||||
defer {
|
||||
try! exitRule()
|
||||
}
|
||||
do {
|
||||
try enterOuterAlt(_localctx, 1)
|
||||
setState(77)
|
||||
_la = try _input.LA(1)
|
||||
if (!(//closure
|
||||
{ () -> Bool in
|
||||
let testSet: Bool = { () -> Bool in
|
||||
let testArray: [Int] = [_la, ReferenceParser.Tokens.T__2.rawValue,ReferenceParser.Tokens.T__4.rawValue,ReferenceParser.Tokens.T__5.rawValue]
|
||||
return Utils.testBitLeftShiftArray(testArray, 0)
|
||||
}()
|
||||
return testSet
|
||||
}())) {
|
||||
try _errHandler.recoverInline(self)
|
||||
}
|
||||
else {
|
||||
_errHandler.reportMatch(self)
|
||||
try consume()
|
||||
}
|
||||
|
||||
}
|
||||
catch ANTLRException.recognition(let re) {
|
||||
_localctx.exception = re
|
||||
_errHandler.reportError(self, re)
|
||||
try _errHandler.recover(self, re)
|
||||
}
|
||||
|
||||
return _localctx
|
||||
}
|
||||
|
||||
public class NameContext: ParserRuleContext {
|
||||
open
|
||||
func LETTER() -> [TerminalNode] {
|
||||
return getTokens(ReferenceParser.Tokens.LETTER.rawValue)
|
||||
}
|
||||
open
|
||||
func LETTER(_ i:Int) -> TerminalNode? {
|
||||
return getToken(ReferenceParser.Tokens.LETTER.rawValue, i)
|
||||
}
|
||||
open
|
||||
func DIGIT() -> [TerminalNode] {
|
||||
return getTokens(ReferenceParser.Tokens.DIGIT.rawValue)
|
||||
}
|
||||
open
|
||||
func DIGIT(_ i:Int) -> TerminalNode? {
|
||||
return getToken(ReferenceParser.Tokens.DIGIT.rawValue, i)
|
||||
}
|
||||
override open
|
||||
func getRuleIndex() -> Int {
|
||||
return ReferenceParser.RULE_name
|
||||
}
|
||||
override open
|
||||
func enterRule(_ listener: ParseTreeListener) {
|
||||
if let listener = listener as? ReferenceListener {
|
||||
listener.enterName(self)
|
||||
}
|
||||
}
|
||||
override open
|
||||
func exitRule(_ listener: ParseTreeListener) {
|
||||
if let listener = listener as? ReferenceListener {
|
||||
listener.exitName(self)
|
||||
}
|
||||
}
|
||||
}
|
||||
@discardableResult
|
||||
open func name() throws -> NameContext {
|
||||
var _localctx: NameContext
|
||||
_localctx = NameContext(_ctx, getState())
|
||||
try enterRule(_localctx, 16, ReferenceParser.RULE_name)
|
||||
var _la: Int = 0
|
||||
defer {
|
||||
try! exitRule()
|
||||
}
|
||||
do {
|
||||
var _alt:Int
|
||||
try enterOuterAlt(_localctx, 1)
|
||||
setState(80);
|
||||
try _errHandler.sync(self)
|
||||
_alt = 1;
|
||||
repeat {
|
||||
switch (_alt) {
|
||||
case 1:
|
||||
setState(79)
|
||||
_la = try _input.LA(1)
|
||||
if (!(//closure
|
||||
{ () -> Bool in
|
||||
let testSet: Bool = _la == ReferenceParser.Tokens.DIGIT.rawValue || _la == ReferenceParser.Tokens.LETTER.rawValue
|
||||
return testSet
|
||||
}())) {
|
||||
try _errHandler.recoverInline(self)
|
||||
}
|
||||
else {
|
||||
_errHandler.reportMatch(self)
|
||||
try consume()
|
||||
}
|
||||
|
||||
|
||||
break
|
||||
default:
|
||||
throw ANTLRException.recognition(e: NoViableAltException(self))
|
||||
}
|
||||
setState(82);
|
||||
try _errHandler.sync(self)
|
||||
_alt = try getInterpreter().adaptivePredict(_input,9,_ctx)
|
||||
} while (_alt != 2 && _alt != ATN.INVALID_ALT_NUMBER)
|
||||
|
||||
}
|
||||
catch ANTLRException.recognition(let re) {
|
||||
_localctx.exception = re
|
||||
_errHandler.reportError(self, re)
|
||||
try _errHandler.recover(self, re)
|
||||
}
|
||||
|
||||
return _localctx
|
||||
}
|
||||
|
||||
static let _serializedATN:[Int] = [
|
||||
4,1,8,85,2,0,7,0,2,1,7,1,2,2,7,2,2,3,7,3,2,4,7,4,2,5,7,5,2,6,7,6,2,7,7,
|
||||
7,2,8,7,8,1,0,1,0,1,0,3,0,22,8,0,1,0,1,0,1,0,3,0,27,8,0,1,0,1,0,1,1,1,
|
||||
1,1,1,5,1,34,8,1,10,1,12,1,37,9,1,1,2,4,2,40,8,2,11,2,12,2,41,1,3,1,3,
|
||||
1,3,5,3,47,8,3,10,3,12,3,50,9,3,1,4,1,4,3,4,54,8,4,4,4,56,8,4,11,4,12,
|
||||
4,57,1,5,1,5,1,5,1,5,1,5,1,5,1,5,3,5,67,8,5,1,6,1,6,1,6,1,6,5,6,73,8,6,
|
||||
10,6,12,6,76,9,6,1,7,1,7,1,8,4,8,81,8,8,11,8,12,8,82,1,8,0,0,9,0,2,4,6,
|
||||
8,10,12,14,16,0,2,2,0,3,3,5,6,1,0,7,8,85,0,18,1,0,0,0,2,30,1,0,0,0,4,39,
|
||||
1,0,0,0,6,43,1,0,0,0,8,55,1,0,0,0,10,66,1,0,0,0,12,68,1,0,0,0,14,77,1,
|
||||
0,0,0,16,80,1,0,0,0,18,21,3,2,1,0,19,20,5,1,0,0,20,22,3,4,2,0,21,19,1,
|
||||
0,0,0,21,22,1,0,0,0,22,23,1,0,0,0,23,24,5,2,0,0,24,26,3,6,3,0,25,27,3,
|
||||
10,5,0,26,25,1,0,0,0,26,27,1,0,0,0,27,28,1,0,0,0,28,29,5,0,0,1,29,1,1,
|
||||
0,0,0,30,35,3,16,8,0,31,32,5,3,0,0,32,34,3,16,8,0,33,31,1,0,0,0,34,37,
|
||||
1,0,0,0,35,33,1,0,0,0,35,36,1,0,0,0,36,3,1,0,0,0,37,35,1,0,0,0,38,40,5,
|
||||
7,0,0,39,38,1,0,0,0,40,41,1,0,0,0,41,39,1,0,0,0,41,42,1,0,0,0,42,5,1,0,
|
||||
0,0,43,48,3,8,4,0,44,45,5,2,0,0,45,47,3,8,4,0,46,44,1,0,0,0,47,50,1,0,
|
||||
0,0,48,46,1,0,0,0,48,49,1,0,0,0,49,7,1,0,0,0,50,48,1,0,0,0,51,53,3,16,
|
||||
8,0,52,54,3,14,7,0,53,52,1,0,0,0,53,54,1,0,0,0,54,56,1,0,0,0,55,51,1,0,
|
||||
0,0,56,57,1,0,0,0,57,55,1,0,0,0,57,58,1,0,0,0,58,9,1,0,0,0,59,60,5,1,0,
|
||||
0,60,67,3,12,6,0,61,62,5,4,0,0,62,63,3,16,8,0,63,64,5,1,0,0,64,65,3,16,
|
||||
8,0,65,67,1,0,0,0,66,59,1,0,0,0,66,61,1,0,0,0,67,11,1,0,0,0,68,74,3,16,
|
||||
8,0,69,70,3,14,7,0,70,71,3,16,8,0,71,73,1,0,0,0,72,69,1,0,0,0,73,76,1,
|
||||
0,0,0,74,72,1,0,0,0,74,75,1,0,0,0,75,13,1,0,0,0,76,74,1,0,0,0,77,78,7,
|
||||
0,0,0,78,15,1,0,0,0,79,81,7,1,0,0,80,79,1,0,0,0,81,82,1,0,0,0,82,80,1,
|
||||
0,0,0,82,83,1,0,0,0,83,17,1,0,0,0,10,21,26,35,41,48,53,57,66,74,82
|
||||
]
|
||||
|
||||
public
|
||||
static let _ATN = try! ATNDeserializer().deserialize(_serializedATN)
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
all: clean
|
||||
antlr -o Generated -Dlanguage=Swift Reference.g4
|
||||
|
||||
clean:
|
||||
rm -rf Generated
|
||||
@@ -1,13 +0,0 @@
|
||||
grammar Reference;
|
||||
|
||||
root: host (':' port)? '/' namespace reference? EOF;
|
||||
host: name ('.' name)*;
|
||||
port: DIGIT+;
|
||||
namespace: namespace_component ('/' namespace_component)*;
|
||||
namespace_component: (name separator?)+;
|
||||
reference: (':' tag) | ('@' name ':' name);
|
||||
tag: name (separator name)*;
|
||||
separator: '.' | '-' | '_';
|
||||
name: (LETTER | DIGIT)+;
|
||||
DIGIT: [0-9];
|
||||
LETTER: [A-Za-z];
|
||||
@@ -1,5 +1,5 @@
|
||||
import Foundation
|
||||
import Antlr4
|
||||
import Parsing
|
||||
|
||||
struct Reference: Comparable, Hashable, CustomStringConvertible {
|
||||
enum ReferenceType: Comparable {
|
||||
@@ -46,39 +46,6 @@ struct Reference: Comparable, Hashable, CustomStringConvertible {
|
||||
}
|
||||
}
|
||||
|
||||
class ReferenceCollector: ReferenceBaseListener {
|
||||
var host: String? = nil
|
||||
var port: String? = nil
|
||||
var namespace: String? = nil
|
||||
var reference: String? = nil
|
||||
|
||||
override func exitHost(_ ctx: ReferenceParser.HostContext) {
|
||||
host = ctx.getText()
|
||||
}
|
||||
|
||||
override func exitPort(_ ctx: ReferenceParser.PortContext) {
|
||||
port = ctx.getText()
|
||||
}
|
||||
|
||||
override func exitNamespace(_ ctx: ReferenceParser.NamespaceContext) {
|
||||
namespace = ctx.getText()
|
||||
}
|
||||
|
||||
override func exitReference(_ ctx: ReferenceParser.ReferenceContext) {
|
||||
reference = ctx.getText()
|
||||
}
|
||||
}
|
||||
|
||||
class ErrorCollector: BaseErrorListener {
|
||||
var error: String? = nil
|
||||
|
||||
override func syntaxError<T>(_ recognizer: Recognizer<T>, _ offendingSymbol: AnyObject?, _ line: Int, _ charPositionInLine: Int, _ msg: String, _ e: AnyObject?) {
|
||||
if error == nil {
|
||||
error = "\(msg) (character \(charPositionInLine + 1))"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct RemoteName: Comparable, Hashable, CustomStringConvertible {
|
||||
var host: String
|
||||
var namespace: String
|
||||
@@ -91,40 +58,51 @@ struct RemoteName: Comparable, Hashable, CustomStringConvertible {
|
||||
}
|
||||
|
||||
init(_ name: String) throws {
|
||||
let errorCollector = ErrorCollector()
|
||||
let inputStream = ANTLRInputStream(Array(name.unicodeScalars), name.count)
|
||||
let lexer = ReferenceLexer(inputStream)
|
||||
lexer.removeErrorListeners()
|
||||
lexer.addErrorListener(errorCollector)
|
||||
let csNormal = [
|
||||
UInt8(ascii: "a")...UInt8(ascii: "z"),
|
||||
UInt8(ascii: "A")...UInt8(ascii: "Z"),
|
||||
UInt8(ascii: "0")...UInt8(ascii: "9"),
|
||||
].asCharacterSet().union(CharacterSet(charactersIn: "_-."))
|
||||
|
||||
let tokenStream = CommonTokenStream(lexer)
|
||||
let parser = try ReferenceParser(tokenStream)
|
||||
parser.removeErrorListeners()
|
||||
parser.addErrorListener(errorCollector)
|
||||
let csHex = [
|
||||
UInt8(ascii: "a")...UInt8(ascii: "f"),
|
||||
UInt8(ascii: "0")...UInt8(ascii: "9"),
|
||||
].asCharacterSet()
|
||||
|
||||
let referenceCollector = ReferenceCollector()
|
||||
try ParseTreeWalker().walk(referenceCollector, try parser.root())
|
||||
|
||||
if let error = errorCollector.error {
|
||||
throw RuntimeError("failed to parse remote name: \(error)")
|
||||
}
|
||||
|
||||
host = referenceCollector.host!
|
||||
if let port = referenceCollector.port {
|
||||
host += ":" + port
|
||||
}
|
||||
namespace = referenceCollector.namespace!
|
||||
if let reference = referenceCollector.reference {
|
||||
if reference.starts(with: "@sha256:") {
|
||||
self.reference = Reference(digest: String(reference.dropFirst(1)))
|
||||
} else if reference.starts(with: ":") {
|
||||
self.reference = Reference(tag: String(reference.dropFirst(1)))
|
||||
} else {
|
||||
throw RuntimeError("failed to parse remote name: unknown reference format")
|
||||
let parser = Parse {
|
||||
Consumed {
|
||||
csNormal
|
||||
Optionally {
|
||||
":"
|
||||
Digits()
|
||||
}
|
||||
}
|
||||
} else {
|
||||
self.reference = Reference(tag: "latest")
|
||||
"/"
|
||||
csNormal.union(CharacterSet(charactersIn: "/"))
|
||||
Optionally {
|
||||
OneOf {
|
||||
Parse {
|
||||
":"
|
||||
csNormal.map {
|
||||
Reference(tag: String($0))
|
||||
}
|
||||
}
|
||||
Parse {
|
||||
"@sha256:"
|
||||
csHex.map {
|
||||
Reference(digest: "sha256:" + String($0))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
End()
|
||||
}
|
||||
|
||||
let result = try parser.parse(name)
|
||||
|
||||
host = String(result.0)
|
||||
namespace = String(result.1)
|
||||
reference = result.2 ?? Reference(tag: "latest")
|
||||
}
|
||||
|
||||
static func <(lhs: RemoteName, rhs: RemoteName) -> Bool {
|
||||
|
||||
@@ -17,6 +17,7 @@ struct Root: AsyncParsableCommand {
|
||||
Pull.self,
|
||||
Push.self,
|
||||
Prune.self,
|
||||
Rename.self,
|
||||
Delete.self,
|
||||
])
|
||||
|
||||
@@ -36,6 +37,9 @@ struct Root: AsyncParsableCommand {
|
||||
do {
|
||||
var command = try parseAsRoot()
|
||||
|
||||
// Run garbage-collection before each command (shouldn't take too long)
|
||||
try Config().gc()
|
||||
|
||||
if var asyncCommand = command as? AsyncParsableCommand {
|
||||
try await asyncCommand.run()
|
||||
} else {
|
||||
|
||||
+11
-27
@@ -34,10 +34,10 @@ class VM: NSObject, VZVirtualMachineDelegate, ObservableObject {
|
||||
// VM's config
|
||||
var config: VMConfig
|
||||
|
||||
var softnet: Softnet? = nil
|
||||
var network: Network
|
||||
|
||||
init(vmDir: VMDirectory,
|
||||
withSoftnet: Bool = false,
|
||||
network: Network = NetworkShared(),
|
||||
additionalDiskAttachments: [VZDiskImageStorageDeviceAttachment] = [],
|
||||
directoryShares: [DirectoryShare] = []
|
||||
) throws {
|
||||
@@ -49,13 +49,10 @@ class VM: NSObject, VZVirtualMachineDelegate, ObservableObject {
|
||||
}
|
||||
|
||||
// Initialize the virtual machine and its configuration
|
||||
if withSoftnet {
|
||||
softnet = try Softnet(vmMACAddress: config.macAddress.string)
|
||||
}
|
||||
|
||||
self.network = network
|
||||
let configuration = try Self.craftConfiguration(diskURL: vmDir.diskURL,
|
||||
nvramURL: vmDir.nvramURL, vmConfig: config,
|
||||
softnet: softnet, additionalDiskAttachments: additionalDiskAttachments,
|
||||
network: network, additionalDiskAttachments: additionalDiskAttachments,
|
||||
directoryShares: directoryShares)
|
||||
virtualMachine = VZVirtualMachine(configuration: configuration)
|
||||
|
||||
@@ -114,7 +111,7 @@ class VM: NSObject, VZVirtualMachineDelegate, ObservableObject {
|
||||
vmDir: VMDirectory,
|
||||
ipswURL: URL?,
|
||||
diskSizeGB: UInt16,
|
||||
withSoftnet: Bool = false,
|
||||
network: Network = NetworkShared(),
|
||||
additionalDiskAttachments: [VZDiskImageStorageDeviceAttachment] = []
|
||||
) async throws {
|
||||
let ipswURL = ipswURL != nil ? ipswURL! : try await VM.retrieveLatestIPSW();
|
||||
@@ -149,12 +146,9 @@ class VM: NSObject, VZVirtualMachineDelegate, ObservableObject {
|
||||
try config.save(toURL: vmDir.configURL)
|
||||
|
||||
// Initialize the virtual machine and its configuration
|
||||
if withSoftnet {
|
||||
softnet = try Softnet(vmMACAddress: config.macAddress.string)
|
||||
}
|
||||
|
||||
self.network = network
|
||||
let configuration = try Self.craftConfiguration(diskURL: vmDir.diskURL, nvramURL: vmDir.nvramURL,
|
||||
vmConfig: config, softnet: softnet,
|
||||
vmConfig: config, network: network,
|
||||
additionalDiskAttachments: additionalDiskAttachments,
|
||||
directoryShares: [])
|
||||
virtualMachine = VZVirtualMachine(configuration: configuration)
|
||||
@@ -193,9 +187,7 @@ class VM: NSObject, VZVirtualMachineDelegate, ObservableObject {
|
||||
}
|
||||
|
||||
func run(_ recovery: Bool) async throws {
|
||||
if let softnet = softnet {
|
||||
try softnet.run()
|
||||
}
|
||||
try network.run()
|
||||
|
||||
DispatchQueue.main.sync {
|
||||
Task {
|
||||
@@ -225,16 +217,14 @@ class VM: NSObject, VZVirtualMachineDelegate, ObservableObject {
|
||||
}
|
||||
}
|
||||
|
||||
if let softnet = softnet {
|
||||
try softnet.stop();
|
||||
}
|
||||
try network.stop()
|
||||
}
|
||||
|
||||
static func craftConfiguration(
|
||||
diskURL: URL,
|
||||
nvramURL: URL,
|
||||
vmConfig: VMConfig,
|
||||
softnet: Softnet? = nil,
|
||||
network: Network = NetworkShared(),
|
||||
additionalDiskAttachments: [VZDiskImageStorageDeviceAttachment],
|
||||
directoryShares: [DirectoryShare]
|
||||
) throws -> VZVirtualMachineConfiguration {
|
||||
@@ -268,13 +258,7 @@ class VM: NSObject, VZVirtualMachineDelegate, ObservableObject {
|
||||
|
||||
// Networking
|
||||
let vio = VZVirtioNetworkDeviceConfiguration()
|
||||
|
||||
if let softnet = softnet {
|
||||
let fh = FileHandle.init(fileDescriptor: softnet.vmFD)
|
||||
vio.attachment = VZFileHandleNetworkDeviceAttachment(fileHandle: fh)
|
||||
} else {
|
||||
vio.attachment = VZNATNetworkDeviceAttachment()
|
||||
}
|
||||
vio.attachment = network.attachment()
|
||||
vio.macAddress = vmConfig.macAddress
|
||||
configuration.networkDevices = [vio]
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@ struct VMDirectory: Prunable {
|
||||
}
|
||||
|
||||
static func temporary() throws -> VMDirectory {
|
||||
let tmpDir = FileManager.default.temporaryDirectory.appendingPathComponent(UUID().uuidString)
|
||||
let tmpDir = try Config().tartTmpDir.appendingPathComponent(UUID().uuidString)
|
||||
try FileManager.default.createDirectory(at: tmpDir, withIntermediateDirectories: false)
|
||||
|
||||
return VMDirectory(baseURL: tmpDir)
|
||||
|
||||
@@ -32,6 +32,10 @@ class VMStorageLocal {
|
||||
_ = try FileManager.default.replaceItemAt(vmURL(name), withItemAt: from.baseURL)
|
||||
}
|
||||
|
||||
func rename(_ name: String, _ newName: String) throws {
|
||||
_ = try FileManager.default.replaceItemAt(vmURL(newName), withItemAt: vmURL(name))
|
||||
}
|
||||
|
||||
func delete(_ name: String) throws {
|
||||
try FileManager.default.removeItem(at: vmURL(name))
|
||||
}
|
||||
|
||||
@@ -150,14 +150,20 @@ class VMStorageOCI: PrunableStorage {
|
||||
if !exists(digestName) {
|
||||
let tmpVMDir = try VMDirectory.temporary()
|
||||
|
||||
// Lock the temporary VM directory to prevent it's garbage collection
|
||||
let tmpVMDirLock = try FileLock(lockURL: tmpVMDir.baseURL)
|
||||
try tmpVMDirLock.lock()
|
||||
|
||||
// Try to reclaim some cache space if we know the VM size in advance
|
||||
if let uncompressedDiskSize = manifest.uncompressedDiskSize() {
|
||||
let requiredCapacityBytes = UInt64(uncompressedDiskSize + 128 * 1024 * 1024)
|
||||
|
||||
let attrs = try Config().tartCacheDir.resourceValues(forKeys: [.volumeAvailableCapacityForImportantUsageKey])
|
||||
let availableCapacityBytes = UInt64(attrs.volumeAvailableCapacityForImportantUsage!)
|
||||
let attrs = try Config().tartCacheDir.resourceValues(forKeys: [.volumeAvailableCapacityForImportantUsageKey, .volumeAvailableCapacityKey])
|
||||
let availableCapacityBytes = max(UInt64(attrs.volumeAvailableCapacityForImportantUsage!), UInt64(attrs.volumeAvailableCapacity!))
|
||||
|
||||
if availableCapacityBytes < requiredCapacityBytes {
|
||||
// There is a suspicious that occasionally capacity is returned as zero which can't be true.
|
||||
// Let's validate to avoid unnecessary pruning.
|
||||
if 0 < availableCapacityBytes && availableCapacityBytes < requiredCapacityBytes {
|
||||
try Prune.pruneReclaim(reclaimBytes: requiredCapacityBytes - availableCapacityBytes)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -44,8 +44,4 @@ final class RemoteNameTests: XCTestCase {
|
||||
// Port must be specified when ":" is used
|
||||
XCTAssertEqual(try? RemoteName("127.0.0.1:/a/b").host, nil)
|
||||
}
|
||||
|
||||
func testNoPathTraversal() throws {
|
||||
XCTAssertEqual(try? RemoteName("ghcr.io/a/../b/c:latest"), nil)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user