summaryrefslogtreecommitdiff
path: root/toml
diff options
context:
space:
mode:
Diffstat (limited to 'toml')
-rw-r--r--toml/README.md95
-rw-r--r--toml/parser.ts327
-rw-r--r--toml/parser_test.ts263
-rw-r--r--toml/test.ts2
-rw-r--r--toml/testdata/CRLF.toml3
-rw-r--r--toml/testdata/arrayTable.toml12
-rw-r--r--toml/testdata/arrays.toml8
-rw-r--r--toml/testdata/boolean.toml3
-rw-r--r--toml/testdata/cargo.toml56
-rw-r--r--toml/testdata/cargoTest.toml147
-rw-r--r--toml/testdata/datetime.toml8
-rw-r--r--toml/testdata/float.toml23
-rw-r--r--toml/testdata/inlineTable.toml4
-rw-r--r--toml/testdata/integer.toml20
-rw-r--r--toml/testdata/simple.toml4
-rw-r--r--toml/testdata/string.toml30
-rw-r--r--toml/testdata/table.toml13
17 files changed, 1018 insertions, 0 deletions
diff --git a/toml/README.md b/toml/README.md
new file mode 100644
index 000000000..a1acd7466
--- /dev/null
+++ b/toml/README.md
@@ -0,0 +1,95 @@
+# TOML
+
+This module parse TOML files. It follows as much as possible the
+[TOML specs](https://github.com/toml-lang/toml). Be sure to read the supported
+types as not every specs is supported at the moment and the handling in
+TypeScript side is a bit different.
+
+## Supported types and handling
+
+- :heavy_check_mark: [Keys](https://github.com/toml-lang/toml#string)
+- :exclamation: [String](https://github.com/toml-lang/toml#string)
+- :heavy_check_mark:
+ [Multiline String](https://github.com/toml-lang/toml#string)
+- :heavy_check_mark: [Literal String](https://github.com/toml-lang/toml#string)
+- :exclamation: [Integer](https://github.com/toml-lang/toml#integer)
+- :heavy_check_mark: [Float](https://github.com/toml-lang/toml#float)
+- :heavy_check_mark: [Boolean](https://github.com/toml-lang/toml#boolean)
+- :heavy_check_mark:
+ [Offset Date-time](https://github.com/toml-lang/toml#offset-date-time)
+- :heavy_check_mark:
+ [Local Date-time](https://github.com/toml-lang/toml#local-date-time)
+- :heavy_check_mark: [Local Date](https://github.com/toml-lang/toml#local-date)
+- :exclamation: [Local Time](https://github.com/toml-lang/toml#local-time)
+- :heavy_check_mark: [Table](https://github.com/toml-lang/toml#table)
+- :exclamation: [Inline Table](https://github.com/toml-lang/toml#inline-table)
+- :exclamation: [Array of Tables](https://github.com/toml-lang/toml#array-of-tables)
+
+:exclamation: _Supported with warnings see [Warning](#Warning)._
+
+### :warning: Warning
+
+#### String
+
+- Regex : Due to the spec, there is no flag to detect regex properly
+ in a TOML declaration. So the regex is stored as string.
+
+#### Integer
+
+For **Binary** / **Octal** / **Hexadecimal** numbers,
+they are stored as string to be not interpreted as Decimal.
+
+#### Local Time
+
+Because local time does not exist in JavaScript, the local time is stored as a string.
+
+#### Inline Table
+
+Inline tables are supported but nested inline property name are **not**. See below:
+
+```toml
+animal = { type = { name = "pug" } } # Supported
+animal = { type.name = "pug" }
+# not supported. Will output { "animal" : {"type.name":"pug"} }
+```
+
+#### Array of Tables
+
+At the moment only simple declarations like below are supported:
+
+```toml
+[[bin]]
+name = "deno"
+path = "cli/main.rs"
+
+[[bin]]
+name = "deno_core"
+path = "src/foo.rs"
+
+[[nib]]
+name = "node"
+path = "not_found"
+```
+
+will output:
+
+```json
+{
+ "bin": [
+ { "name": "deno", "path": "cli/main.rs" },
+ { "name": "deno_core", "path": "src/foo.rs" }
+ ],
+ "nib": [{ "name": "node", "path": "not_found" }]
+}
+```
+
+## Usage
+
+```ts
+import { parseFile, parse } from "./parser.ts";
+
+const tomlObject = parseFile("file.toml");
+
+const tomlString = 'foo.bar = "Deno"';
+const tomlObject22 = parse(tomlString);
+```
diff --git a/toml/parser.ts b/toml/parser.ts
new file mode 100644
index 000000000..9263f0111
--- /dev/null
+++ b/toml/parser.ts
@@ -0,0 +1,327 @@
+// Copyright 2018-2019 the Deno authors. All rights reserved. MIT license.
+import { existsSync } from "../fs/exists.ts";
+import { deepAssign } from "../util/deep_assign.ts";
+
+class KeyValuePair {
+ key: string;
+ value: unknown;
+}
+
+class ParserGroup {
+ type: string;
+ name: string;
+ arrValues: unknown[] = [];
+ objValues: object = {};
+}
+
+class ParserContext {
+ currentGroup?: ParserGroup;
+ output: object = {};
+}
+
+class Parser {
+ tomlLines: string[];
+ context: ParserContext;
+ constructor(tomlString: string) {
+ this.tomlLines = this._split(tomlString);
+ this.context = new ParserContext();
+ }
+ _sanitize(): void {
+ const out = [];
+ for (let i = 0; i < this.tomlLines.length; i++) {
+ const s = this.tomlLines[i].split("#")[0];
+ if (s !== "") {
+ out.push(s);
+ }
+ }
+ this.tomlLines = out;
+ this._mergeMultilines();
+ }
+
+ _mergeMultilines(): void {
+ function arrayStart(line: string): boolean {
+ const reg = /.*=\s*\[/g;
+ return reg.test(line) && !(line[line.length - 1] === "]");
+ }
+
+ function arrayEnd(line: string): boolean {
+ return line[line.length - 1] === "]";
+ }
+
+ function stringStart(line: string): boolean {
+ const m = line.match(/.*=\s*(?:\"\"\"|''')/);
+ if (!m) {
+ return false;
+ }
+ return !line.endsWith(`"""`) || !line.endsWith(`'''`);
+ }
+
+ function stringEnd(line: string): boolean {
+ return line.endsWith(`'''`) || line.endsWith(`"""`);
+ }
+
+ function isLiteralString(line: string): boolean {
+ return line.match(/'''/) ? true : false;
+ }
+
+ let merged = [],
+ acc = [],
+ isLiteral = false,
+ capture = false,
+ captureType = "",
+ merge = false;
+
+ for (let i = 0; i < this.tomlLines.length; i++) {
+ const line = this.tomlLines[i];
+ const trimmed = line.trim();
+ if (!capture && arrayStart(trimmed)) {
+ capture = true;
+ captureType = "array";
+ } else if (!capture && stringStart(trimmed)) {
+ isLiteral = isLiteralString(trimmed);
+ capture = true;
+ captureType = "string";
+ } else if (capture && arrayEnd(trimmed)) {
+ merge = true;
+ } else if (capture && stringEnd(trimmed)) {
+ merge = true;
+ }
+
+ if (capture) {
+ if (isLiteral) {
+ acc.push(line);
+ } else {
+ acc.push(trimmed);
+ }
+ } else {
+ if (isLiteral) {
+ merged.push(line);
+ } else {
+ merged.push(trimmed);
+ }
+ }
+
+ if (merge) {
+ capture = false;
+ merge = false;
+ if (captureType === "string") {
+ merged.push(
+ acc
+ .join("\n")
+ .replace(/"""/g, '"')
+ .replace(/'''/g, `'`)
+ .replace(/\n/g, "\\n")
+ );
+ isLiteral = false;
+ } else {
+ merged.push(acc.join(""));
+ }
+ captureType = "";
+ acc = [];
+ }
+ }
+ this.tomlLines = merged;
+ }
+ _unflat(keys: string[], values: object = {}, cObj: object = {}): object {
+ let out = {};
+ if (keys.length === 0) {
+ return cObj;
+ } else {
+ if (Object.keys(cObj).length === 0) {
+ cObj = values;
+ }
+ let key = keys.pop();
+ out[key] = cObj;
+ return this._unflat(keys, values, out);
+ }
+ }
+ _groupToOutput(): void {
+ const arrProperty = this.context.currentGroup.name
+ .replace(/"/g, "")
+ .replace(/'/g, "")
+ .split(".");
+ let u = {};
+ if (this.context.currentGroup.type === "array") {
+ u = this._unflat(arrProperty, this.context.currentGroup.arrValues);
+ } else {
+ u = this._unflat(arrProperty, this.context.currentGroup.objValues);
+ }
+ deepAssign(this.context.output, u);
+ delete this.context.currentGroup;
+ }
+ _split(str: string): string[] {
+ let out = [];
+ out.push(...str.split("\n"));
+ return out;
+ }
+ _isGroup(line: string): boolean {
+ const t = line.trim();
+ return t[0] === "[" && t[t.length - 1] === "]";
+ }
+ _isDeclaration(line: string): boolean {
+ return line.split("=").length > 1;
+ }
+ _createGroup(line: string): void {
+ const captureReg = /\[(.*)\]/;
+ if (this.context.currentGroup) {
+ this._groupToOutput();
+ }
+ let g = new ParserGroup();
+ g.name = line.match(captureReg)[1];
+ if (g.name.match(/\[.*\]/)) {
+ g.type = "array";
+ g.name = g.name.match(captureReg)[1];
+ } else {
+ g.type = "object";
+ }
+ this.context.currentGroup = g;
+ }
+ _processDeclaration(line: string): KeyValuePair {
+ let kv = new KeyValuePair();
+ const idx = line.indexOf("=");
+ kv.key = line.substring(0, idx).trim();
+ kv.value = this._parseData(line.slice(idx + 1));
+ return kv;
+ }
+ _parseData(dataString: string): unknown {
+ dataString = dataString.trim();
+ if (this._isDate(dataString)) {
+ return new Date(dataString);
+ }
+ if (this._isLocalTime(dataString)) {
+ return eval(`"${dataString}"`);
+ }
+ if (dataString === "inf" || dataString === "+inf") {
+ return Infinity;
+ }
+ if (dataString === "-inf") {
+ return -Infinity;
+ }
+ if (
+ dataString === "nan" ||
+ dataString === "+nan" ||
+ dataString === "-nan"
+ ) {
+ return NaN;
+ }
+ // inline table
+ if (dataString[0] === "{" && dataString[dataString.length - 1] === "}") {
+ const reg = /([a-zA-Z0-9-_\.]*) (=)/gi;
+ let result;
+ while ((result = reg.exec(dataString))) {
+ let ogVal = result[0];
+ let newVal = ogVal
+ .replace(result[1], `"${result[1]}"`)
+ .replace(result[2], ":");
+ dataString = dataString.replace(ogVal, newVal);
+ }
+ // TODO : unflat if necessary
+ return JSON.parse(dataString);
+ }
+ // If binary / octal / hex
+ if (
+ dataString[0] === "0" &&
+ (dataString[1] === "b" || dataString[1] === "o" || dataString[1] === "x")
+ ) {
+ return dataString;
+ }
+
+ if (this._isParsableNumber(dataString)) {
+ return eval(dataString.replace(/_/g, ""));
+ }
+
+ // Handle First and last EOL for multiline strings
+ if (dataString.startsWith(`"\\n`)) {
+ dataString = dataString.replace(`"\\n`, `"`);
+ } else if (dataString.startsWith(`'\\n`)) {
+ dataString = dataString.replace(`'\\n`, `'`);
+ }
+ if (dataString.endsWith(`\\n"`)) {
+ dataString = dataString.replace(`\\n"`, `"`);
+ } else if (dataString.endsWith(`\\n'`)) {
+ dataString = dataString.replace(`\\n'`, `'`);
+ }
+
+ // dataString = dataString.replace(/\\/, "\\\\");
+
+ return eval(dataString);
+ }
+ _isLocalTime(str: string): boolean {
+ const reg = /(\d{2}):(\d{2}):(\d{2})/;
+ return reg.test(str);
+ }
+ _isParsableNumber(dataString: string): boolean {
+ let d = dataString.replace(/_/g, "");
+ return !isNaN(parseFloat(d));
+ }
+ _isDate(dateStr: string): boolean {
+ const reg = /\d{4}-\d{2}-\d{2}/;
+ return reg.test(dateStr);
+ }
+ _parseLines(): void {
+ for (let i = 0; i < this.tomlLines.length; i++) {
+ const line = this.tomlLines[i];
+
+ // TODO (zekth) Handle unflat of array of tables
+ if (this._isGroup(line)) {
+ // if the current group is an array we push the
+ // parsed objects in it.
+ if (
+ this.context.currentGroup &&
+ this.context.currentGroup.type === "array"
+ ) {
+ this.context.currentGroup.arrValues.push(
+ this.context.currentGroup.objValues
+ );
+ this.context.currentGroup.objValues = {};
+ }
+ // If we need to create a group or to change group
+ if (
+ !this.context.currentGroup ||
+ (this.context.currentGroup &&
+ this.context.currentGroup.name !==
+ line.replace(/\[/g, "").replace(/\]/g, ""))
+ ) {
+ this._createGroup(line);
+ continue;
+ }
+ }
+ if (this._isDeclaration(line)) {
+ let kv = this._processDeclaration(line);
+ if (!this.context.currentGroup) {
+ this.context.output[kv.key] = kv.value;
+ } else {
+ this.context.currentGroup.objValues[kv.key] = kv.value;
+ }
+ }
+ }
+ if (this.context.currentGroup) {
+ if (this.context.currentGroup.type === "array") {
+ this.context.currentGroup.arrValues.push(
+ this.context.currentGroup.objValues
+ );
+ }
+ this._groupToOutput();
+ }
+ }
+ parse(): object {
+ this._sanitize();
+ this._parseLines();
+ return this.context.output;
+ }
+}
+
+export function parse(tomlString: string): object {
+ // File is potentially using EOL CRLF
+ tomlString = tomlString.replace(/\r\n/g, "\n").replace(/\\\n/g, "\n");
+ return new Parser(tomlString).parse();
+}
+
+export function parseFile(filePath: string): object {
+ if (!existsSync(filePath)) {
+ throw new Error("File not found");
+ }
+ const decoder = new TextDecoder();
+ const strFile = decoder.decode(Deno.readFileSync(filePath));
+ return parse(strFile);
+}
diff --git a/toml/parser_test.ts b/toml/parser_test.ts
new file mode 100644
index 000000000..cc6675296
--- /dev/null
+++ b/toml/parser_test.ts
@@ -0,0 +1,263 @@
+// Copyright 2018-2019 the Deno authors. All rights reserved. MIT license.
+import { test } from "../testing/mod.ts";
+import { assertEquals } from "../testing/asserts.ts";
+import { parseFile } from "./parser.ts";
+import * as path from "../fs/path/mod.ts";
+const testFilesDir = path.resolve("toml", "testdata");
+
+test({
+ name: "[TOML] Strings",
+ fn() {
+ const expected = {
+ strings: {
+ str0: "deno",
+ str1: "Roses are not Deno\nViolets are not Deno either",
+ str2: "Roses are not Deno\nViolets are not Deno either",
+ str3: "Roses are not Deno\r\nViolets are not Deno either",
+ str4: 'this is a "quote"',
+ str5: "The quick brown\nfox jumps over\nthe lazy dog.",
+ str6: "The quick brown\nfox jumps over\nthe lazy dog.",
+ lines:
+ "The first newline is\ntrimmed in raw strings.\n All other whitespace\n is preserved."
+ }
+ };
+ const actual = parseFile(path.join(testFilesDir, "string.toml"));
+ assertEquals(actual, expected);
+ }
+});
+
+test({
+ name: "[TOML] CRLF",
+ fn() {
+ const expected = { boolean: { bool1: true, bool2: false } };
+ const actual = parseFile(path.join(testFilesDir, "CRLF.toml"));
+ assertEquals(actual, expected);
+ }
+});
+
+test({
+ name: "[TOML] Boolean",
+ fn() {
+ const expected = { boolean: { bool1: true, bool2: false } };
+ const actual = parseFile(path.join(testFilesDir, "boolean.toml"));
+ assertEquals(actual, expected);
+ }
+});
+
+test({
+ name: "[TOML] Integer",
+ fn() {
+ const expected = {
+ integer: {
+ int1: 99,
+ int2: 42,
+ int3: 0,
+ int4: -17,
+ int5: 1000,
+ int6: 5349221,
+ int7: 12345,
+ hex1: "0xDEADBEEF",
+ hex2: "0xdeadbeef",
+ hex3: "0xdead_beef",
+ oct1: "0o01234567",
+ oct2: "0o755",
+ bin1: "0b11010110"
+ }
+ };
+ const actual = parseFile(path.join(testFilesDir, "integer.toml"));
+ assertEquals(actual, expected);
+ }
+});
+
+test({
+ name: "[TOML] Float",
+ fn() {
+ const expected = {
+ float: {
+ flt1: 1.0,
+ flt2: 3.1415,
+ flt3: -0.01,
+ flt4: 5e22,
+ flt5: 1e6,
+ flt6: -2e-2,
+ flt7: 6.626e-34,
+ flt8: 224_617.445_991_228,
+ sf1: Infinity,
+ sf2: Infinity,
+ sf3: -Infinity,
+ sf4: NaN,
+ sf5: NaN,
+ sf6: NaN
+ }
+ };
+ const actual = parseFile(path.join(testFilesDir, "float.toml"));
+ assertEquals(actual, expected);
+ }
+});
+
+test({
+ name: "[TOML] Arrays",
+ fn() {
+ const expected = {
+ arrays: {
+ data: [["gamma", "delta"], [1, 2]],
+ hosts: ["alpha", "omega"]
+ }
+ };
+ const actual = parseFile(path.join(testFilesDir, "arrays.toml"));
+ assertEquals(actual, expected);
+ }
+});
+
+test({
+ name: "[TOML] Table",
+ fn() {
+ const expected = {
+ deeply: {
+ nested: {
+ object: {
+ in: {
+ the: {
+ toml: {
+ name: "Tom Preston-Werner"
+ }
+ }
+ }
+ }
+ }
+ },
+ servers: {
+ alpha: {
+ ip: "10.0.0.1",
+ dc: "eqdc10"
+ },
+ beta: {
+ ip: "10.0.0.2",
+ dc: "eqdc20"
+ }
+ }
+ };
+ const actual = parseFile(path.join(testFilesDir, "table.toml"));
+ assertEquals(actual, expected);
+ }
+});
+
+test({
+ name: "[TOML] Simple",
+ fn() {
+ const expected = {
+ deno: "is",
+ not: "[node]",
+ regex: "<ic*s*>",
+ NANI: "何?!"
+ };
+ const actual = parseFile(path.join(testFilesDir, "simple.toml"));
+ assertEquals(actual, expected);
+ }
+});
+
+test({
+ name: "[TOML] Datetime",
+ fn() {
+ const expected = {
+ datetime: {
+ odt1: new Date("1979-05-27T07:32:00Z"),
+ odt2: new Date("1979-05-27T00:32:00-07:00"),
+ odt3: new Date("1979-05-27T00:32:00.999999-07:00"),
+ odt4: new Date("1979-05-27 07:32:00Z"),
+ ld1: new Date("1979-05-27"),
+ lt1: "07:32:00",
+ lt2: "00:32:00.999999"
+ }
+ };
+ const actual = parseFile(path.join(testFilesDir, "datetime.toml"));
+ assertEquals(actual, expected);
+ }
+});
+
+test({
+ name: "[TOML] Inline Table",
+ fn() {
+ const expected = {
+ inlinetable: {
+ name: {
+ first: "Tom",
+ last: "Preston-Werner"
+ },
+ point: {
+ x: 1,
+ y: 2
+ },
+ animal: {
+ type: {
+ name: "pug"
+ }
+ }
+ }
+ };
+ const actual = parseFile(path.join(testFilesDir, "inlineTable.toml"));
+ assertEquals(actual, expected);
+ }
+});
+
+test({
+ name: "[TOML] Array of Tables",
+ fn() {
+ const expected = {
+ bin: [
+ { name: "deno", path: "cli/main.rs" },
+ { name: "deno_core", path: "src/foo.rs" }
+ ],
+ nib: [{ name: "node", path: "not_found" }]
+ };
+ const actual = parseFile(path.join(testFilesDir, "arrayTable.toml"));
+ assertEquals(actual, expected);
+ }
+});
+
+test({
+ name: "[TOML] Cargo",
+ fn() {
+ /* eslint-disable @typescript-eslint/camelcase */
+ const expected = {
+ workspace: { members: ["./", "core"] },
+ bin: [{ name: "deno", path: "cli/main.rs" }],
+ package: { name: "deno", version: "0.3.4", edition: "2018" },
+ dependencies: {
+ deno_core: { path: "./core" },
+ ansi_term: "0.11.0",
+ atty: "0.2.11",
+ dirs: "1.0.5",
+ flatbuffers: "0.5.0",
+ futures: "0.1.25",
+ getopts: "0.2.18",
+ http: "0.1.16",
+ hyper: "0.12.24",
+ "hyper-rustls": "0.16.0",
+ "integer-atomics": "1.0.2",
+ lazy_static: "1.3.0",
+ libc: "0.2.49",
+ log: "0.4.6",
+ rand: "0.6.5",
+ regex: "1.1.0",
+ remove_dir_all: "0.5.1",
+ ring: "0.14.6",
+ rustyline: "3.0.0",
+ serde_json: "1.0.38",
+ "source-map-mappings": "0.5.0",
+ tempfile: "3.0.7",
+ tokio: "0.1.15",
+ "tokio-executor": "0.1.6",
+ "tokio-fs": "0.1.5",
+ "tokio-io": "0.1.11",
+ "tokio-process": "0.2.3",
+ "tokio-threadpool": "0.1.11",
+ url: "1.7.2"
+ },
+ target: { "cfg(windows)": { dependencies: { winapi: "0.3.6" } } }
+ };
+ /* eslint-enable @typescript-eslint/camelcase */
+ const actual = parseFile(path.join(testFilesDir, "cargo.toml"));
+ assertEquals(actual, expected);
+ }
+});
diff --git a/toml/test.ts b/toml/test.ts
new file mode 100644
index 000000000..16be28c8d
--- /dev/null
+++ b/toml/test.ts
@@ -0,0 +1,2 @@
+// Copyright 2018-2019 the Deno authors. All rights reserved. MIT license.
+import "./parser_test.ts";
diff --git a/toml/testdata/CRLF.toml b/toml/testdata/CRLF.toml
new file mode 100644
index 000000000..92264888a
--- /dev/null
+++ b/toml/testdata/CRLF.toml
@@ -0,0 +1,3 @@
+[boolean]
+bool1 = true
+bool2 = false \ No newline at end of file
diff --git a/toml/testdata/arrayTable.toml b/toml/testdata/arrayTable.toml
new file mode 100644
index 000000000..3788b7e7c
--- /dev/null
+++ b/toml/testdata/arrayTable.toml
@@ -0,0 +1,12 @@
+
+[[bin]]
+name = "deno"
+path = "cli/main.rs"
+
+[[bin]]
+name = "deno_core"
+path = "src/foo.rs"
+
+[[nib]]
+name = "node"
+path = "not_found" \ No newline at end of file
diff --git a/toml/testdata/arrays.toml b/toml/testdata/arrays.toml
new file mode 100644
index 000000000..5d5913d0c
--- /dev/null
+++ b/toml/testdata/arrays.toml
@@ -0,0 +1,8 @@
+[arrays]
+data = [ ["gamma", "delta"], [1, 2] ]
+
+# Line breaks are OK when inside arrays
+hosts = [
+ "alpha",
+ "omega"
+]
diff --git a/toml/testdata/boolean.toml b/toml/testdata/boolean.toml
new file mode 100644
index 000000000..92264888a
--- /dev/null
+++ b/toml/testdata/boolean.toml
@@ -0,0 +1,3 @@
+[boolean]
+bool1 = true
+bool2 = false \ No newline at end of file
diff --git a/toml/testdata/cargo.toml b/toml/testdata/cargo.toml
new file mode 100644
index 000000000..5402d10a4
--- /dev/null
+++ b/toml/testdata/cargo.toml
@@ -0,0 +1,56 @@
+# Copyright 2018-2019 the Deno authors. All rights reserved. MIT license.
+# Dummy package info required by `cargo fetch`.
+# Use tools/sync_third_party.py to install deps after editing this file.
+# Deno does not build with cargo. Deno uses a build system called gn.
+# See build_extra/rust/BUILD.gn for the manually built configuration of rust
+# crates.
+
+[workspace]
+members = [
+ "./",
+ "core",
+]
+
+[[bin]]
+name = "deno"
+path = "cli/main.rs"
+
+[package]
+name = "deno"
+version = "0.3.4"
+edition = "2018"
+
+[dependencies]
+deno_core = { path = "./core" }
+
+ansi_term = "0.11.0"
+atty = "0.2.11"
+dirs = "1.0.5"
+flatbuffers = "0.5.0"
+futures = "0.1.25"
+getopts = "0.2.18"
+http = "0.1.16"
+hyper = "0.12.24"
+hyper-rustls = "0.16.0"
+integer-atomics = "1.0.2"
+lazy_static = "1.3.0"
+libc = "0.2.49"
+log = "0.4.6"
+rand = "0.6.5"
+regex = "1.1.0"
+remove_dir_all = "0.5.1"
+ring = "0.14.6"
+rustyline = "3.0.0"
+serde_json = "1.0.38"
+source-map-mappings = "0.5.0"
+tempfile = "3.0.7"
+tokio = "0.1.15"
+tokio-executor = "0.1.6"
+tokio-fs = "0.1.5"
+tokio-io = "0.1.11"
+tokio-process = "0.2.3"
+tokio-threadpool = "0.1.11"
+url = "1.7.2"
+
+[target.'cfg(windows)'.dependencies]
+winapi = "0.3.6" \ No newline at end of file
diff --git a/toml/testdata/cargoTest.toml b/toml/testdata/cargoTest.toml
new file mode 100644
index 000000000..47e7f6e4d
--- /dev/null
+++ b/toml/testdata/cargoTest.toml
@@ -0,0 +1,147 @@
+# This is a TOML document.
+
+title = "TOML Example"
+
+[deeply.nested.object.in.the.toml]
+name = "Tom Preston-Werner"
+dob = 2009-05-27T07:32:00
+
+[database]
+server = "192.168.1.1"
+ports = [ 8001, 8001, 8002 ]
+connection_max = 5000
+enabled = true
+
+[servers]
+
+ # Indentation (tabs and/or spaces) is allowed but not required
+ [servers.alpha]
+ ip = "10.0.0.1"
+ dc = "eqdc10"
+
+ [servers.beta]
+ ip = "10.0.0.2"
+ dc = "eqdc10"
+
+[clients]
+data = [ ["gamma", "delta"], [1, 2] ]
+
+# Line breaks are OK when inside arrays
+hosts = [
+ "alpha",
+ "omega"
+]
+
+[strings]
+str0 = "deno"
+str1 = """
+Roses are red
+ Violets are blue"""
+# On a Unix system, the above multi-line string will most likely be the same as:
+str2 = "Roses are red\nViolets are blue"
+
+# On a Windows system, it will most likely be equivalent to:
+str3 = "Roses are red\r\nViolets are blue"
+str4 = "The quick brown fox jumps over the lazy dog."
+str5 = "this is a \"quote\""
+
+str5 = """
+The quick brown \
+
+
+ fox jumps over \
+ the lazy dog."""
+
+str6 = """\
+ The quick brown \
+ fox jumps over \
+ the lazy dog.\
+ """
+lines = '''
+The first newline is
+trimmed in raw strings.
+ All other whitespace
+ is preserved.
+'''
+
+[Integer]
+int1 = +99
+int2 = 42
+int3 = 0
+int4 = -17
+int5 = 1_000
+int6 = 5_349_221
+int7 = 1_2_3_4_5 # VALID but discouraged
+
+# hexadecimal with prefix `0x`
+hex1 = 0xDEADBEEF
+hex2 = 0xdeadbeef
+hex3 = 0xdead_beef
+
+# octal with prefix `0o`
+oct1 = 0o01234567
+oct2 = 0o755 # useful for Unix file permissions
+
+# binary with prefix `0b`
+bin1 = 0b11010110
+
+[Date-Time]
+odt1 = 1979-05-27T07:32:00Z
+odt2 = 1979-05-27T00:32:00-07:00
+odt3 = 1979-05-27T00:32:00.999999-07:00
+odt4 = 1979-05-27 07:32:00Z
+ld1 = 1979-05-27
+lt1 = 07:32:00 #buggy
+lt2 = 00:32:00.999999 #buggy
+
+[boolean]
+bool1 = true
+bool2 = false
+
+[float]
+# fractional
+flt1 = +1.0
+flt2 = 3.1415
+flt3 = -0.01
+
+# exponent
+flt4 = 5e+22
+flt5 = 1e6
+flt6 = -2E-2
+
+# both
+flt7 = 6.626e-34
+flt8 = 224_617.445_991_228
+# infinity
+sf1 = inf # positive infinity
+sf2 = +inf # positive infinity
+sf3 = -inf # negative infinity
+
+# not a number
+sf4 = nan # actual sNaN/qNaN encoding is implementation specific
+sf5 = +nan # same as `nan`
+sf6 = -nan # valid, actual encoding is implementation specific
+
+[Table]
+name = { first = "Tom", last = "Preston-Werner" }
+point = { x = 1, y = 2 }
+animal = { type.name = "pug" }
+
+[[fruit]]
+ name = "apple"
+
+ [fruit.physical]
+ color = "red"
+ shape = "round"
+
+ [[fruit.variety]]
+ name = "red delicious"
+
+ [[fruit.variety]]
+ name = "granny smith"
+
+[[fruit]]
+ name = "banana"
+
+ [[fruit.variety]]
+ name = "plantain"
diff --git a/toml/testdata/datetime.toml b/toml/testdata/datetime.toml
new file mode 100644
index 000000000..b21924793
--- /dev/null
+++ b/toml/testdata/datetime.toml
@@ -0,0 +1,8 @@
+[datetime]
+odt1 = 1979-05-27T07:32:00Z
+odt2 = 1979-05-27T00:32:00-07:00
+odt3 = 1979-05-27T00:32:00.999999-07:00
+odt4 = 1979-05-27 07:32:00Z
+ld1 = 1979-05-27
+lt1 = 07:32:00
+lt2 = 00:32:00.999999
diff --git a/toml/testdata/float.toml b/toml/testdata/float.toml
new file mode 100644
index 000000000..92f0b6d17
--- /dev/null
+++ b/toml/testdata/float.toml
@@ -0,0 +1,23 @@
+[float]
+# fractional
+flt1 = +1.0
+flt2 = 3.1415
+flt3 = -0.01
+
+# exponent
+flt4 = 5e+22
+flt5 = 1e6
+flt6 = -2E-2
+
+# both
+flt7 = 6.626e-34
+flt8 = 224_617.445_991_228
+# infinity
+sf1 = inf # positive infinity
+sf2 = +inf # positive infinity
+sf3 = -inf # negative infinity
+
+# not a number
+sf4 = nan # actual sNaN/qNaN encoding is implementation specific
+sf5 = +nan # same as `nan`
+sf6 = -nan # valid, actual encoding is implementation specific \ No newline at end of file
diff --git a/toml/testdata/inlineTable.toml b/toml/testdata/inlineTable.toml
new file mode 100644
index 000000000..1a7e55c52
--- /dev/null
+++ b/toml/testdata/inlineTable.toml
@@ -0,0 +1,4 @@
+[inlinetable]
+name = { first = "Tom", last = "Preston-Werner" }
+point = { x = 1, y = 2 }
+animal = { type = { name = "pug" } } \ No newline at end of file
diff --git a/toml/testdata/integer.toml b/toml/testdata/integer.toml
new file mode 100644
index 000000000..3bd781e8f
--- /dev/null
+++ b/toml/testdata/integer.toml
@@ -0,0 +1,20 @@
+[integer]
+int1 = +99
+int2 = 42
+int3 = 0
+int4 = -17
+int5 = 1_000
+int6 = 5_349_221
+int7 = 1_2_3_4_5 # VALID but discouraged
+
+# hexadecimal with prefix `0x`
+hex1 = 0xDEADBEEF
+hex2 = 0xdeadbeef
+hex3 = 0xdead_beef
+
+# octal with prefix `0o`
+oct1 = 0o01234567
+oct2 = 0o755 # useful for Unix file permissions
+
+# binary with prefix `0b`
+bin1 = 0b11010110 \ No newline at end of file
diff --git a/toml/testdata/simple.toml b/toml/testdata/simple.toml
new file mode 100644
index 000000000..aac44714e
--- /dev/null
+++ b/toml/testdata/simple.toml
@@ -0,0 +1,4 @@
+deno = "is"
+not = "[node]"
+regex = '<\i\c*\s*>'
+NANI = '何?!' \ No newline at end of file
diff --git a/toml/testdata/string.toml b/toml/testdata/string.toml
new file mode 100644
index 000000000..f811824eb
--- /dev/null
+++ b/toml/testdata/string.toml
@@ -0,0 +1,30 @@
+[strings]
+str0 = "deno"
+str1 = """
+Roses are not Deno
+ Violets are not Deno either"""
+# On a Unix system, the above multi-line string will most likely be the same as:
+str2 = "Roses are not Deno\nViolets are not Deno either"
+
+# On a Windows system, it will most likely be equivalent to:
+str3 = "Roses are not Deno\r\nViolets are not Deno either"
+str4 = "this is a \"quote\""
+
+str5 = """
+The quick brown \
+
+
+ fox jumps over \
+ the lazy dog."""
+
+str6 = """\
+ The quick brown \
+ fox jumps over \
+ the lazy dog.\
+ """
+lines = '''
+The first newline is
+trimmed in raw strings.
+ All other whitespace
+ is preserved.
+''' \ No newline at end of file
diff --git a/toml/testdata/table.toml b/toml/testdata/table.toml
new file mode 100644
index 000000000..7008e6fb0
--- /dev/null
+++ b/toml/testdata/table.toml
@@ -0,0 +1,13 @@
+[deeply.nested.object.in.the.toml]
+name = "Tom Preston-Werner"
+
+[servers]
+
+ # Indentation (tabs and/or spaces) is allowed but not required
+ [servers.alpha]
+ ip = "10.0.0.1"
+ dc = "eqdc10"
+
+ [servers.beta]
+ ip = "10.0.0.2"
+ dc = "eqdc20" \ No newline at end of file