diff --git a/builder.ts b/builder.ts index 9c26b4876..e925cbed2 100755 --- a/builder.ts +++ b/builder.ts @@ -4,9 +4,9 @@ const { TreeNode } = require("./products/TreeNode.js") const { TypeScriptRewriter } = require("./products/TypeScriptRewriter.js") const { Disk } = require("./products/Disk.node.js") const { Utils } = require("./products/Utils.js") -const { HandGrammarProgram } = require("./products/GrammarLanguage.js") +const { HandParsersProgram } = require("./products/Parsers.js") const { TestRacer } = require("./products/TestRacer.js") -const { GrammarCompiler } = require("./products/GrammarCompiler.js") +const { ParsersCompiler } = require("./products/ParsersCompiler.js") const path = require("path") const fs = require("fs") const { execSync } = require("child_process") @@ -16,7 +16,7 @@ const prettierConfig = require("./package.json").prettier import { scrollNotationTypes } from "./products/scrollNotationTypes" // todo: remove? -const registeredExtensions: scrollNotationTypes.stringMap = { js: "//", maia: "doc.tooling ", ts: "//", grammar: "tooling ", gram: "tooling " } +const registeredExtensions: scrollNotationTypes.stringMap = { js: "//", maia: "doc.tooling ", ts: "//", parsers: "tooling ", gram: "tooling " } class Builder extends TreeNode { private _typeScriptToJavascript(sourceCode: string, forBrowser = false) { @@ -187,10 +187,10 @@ class Builder extends TreeNode { this._buildTsc(Disk.read(__filename), path.join(__dirname, "builder.js")) } - makeGrammarFileTestTree(grammarPath: scrollNotationTypes.grammarFilePath) { - // todo: can we ditch these dual tests at some point? ideally Grammar should be bootstrapped correct? + makeParsersFileTestTree(parsersPath: scrollNotationTypes.parsersFilePath) { + // todo: can we ditch these dual tests at some point? ideally Parsers should be bootstrapped correct? const testTree: any = {} - const checkGrammarFile = (equal: Function, program: any) => { + const checkParsersFile = (equal: Function, program: any) => { // Act const errs = program.getAllErrors() if (errs.length) console.log(errs.join("\n")) @@ -198,12 +198,12 @@ class Builder extends TreeNode { equal(errs.length, 0, "should be no errors") } - const handGrammarProgram = new HandGrammarProgram(Disk.read(grammarPath)) + const handParsersProgram = new HandParsersProgram(Disk.read(parsersPath)) - testTree[`grammarCheckOf${grammarPath}`] = (equal: Function) => checkGrammarFile(equal, GrammarCompiler.compileGrammarAndCreateProgram(grammarPath, path.join(__dirname, "langs", "grammar", "grammar.grammar"))) - testTree[`handGrammarCheckOf${grammarPath}`] = (equal: Function) => checkGrammarFile(equal, handGrammarProgram) + testTree[`parsersCheckOf${parsersPath}`] = (equal: Function) => checkParsersFile(equal, ParsersCompiler.compileParsersAndCreateProgram(parsersPath, path.join(__dirname, "langs", "parsers", "parsers.parsers"))) + testTree[`handParsersCheckOf${parsersPath}`] = (equal: Function) => checkParsersFile(equal, handParsersProgram) - Object.assign(testTree, handGrammarProgram.examplesToTestBlocks()) + Object.assign(testTree, handParsersProgram.examplesToTestBlocks()) return testTree } @@ -251,14 +251,14 @@ class Builder extends TreeNode { } produceAllLangs() { - const langs = `arrow chuck dug dumbdown fire fruit grammar hakon jibberish jibjab numbers poop project stamp stump swarm`.split(" ") + const langs = `arrow chuck dug dumbdown fire fruit parsers hakon jibberish jibjab numbers poop project stamp stump swarm`.split(" ") langs.forEach(lang => this.produceLang(lang)) } produceLang(langName: string) { - const newFilePath = path.join(__dirname, "langs", langName, `${langName}.grammar`) - GrammarCompiler.compileGrammarForBrowser(newFilePath, this._getProductFolder(), true) - GrammarCompiler.compileGrammarForNodeJs(newFilePath, this._getProductFolder(), true, ".") + const newFilePath = path.join(__dirname, "langs", langName, `${langName}.parsers`) + ParsersCompiler.compileParsersForBrowser(newFilePath, this._getProductFolder(), true) + ParsersCompiler.compileParsersForNodeJs(newFilePath, this._getProductFolder(), true, ".") } private _getProductsTree() { @@ -266,10 +266,10 @@ class Builder extends TreeNode { } buildJibJab() { - const combined = GrammarCompiler.combineFiles([__dirname + "/langs/jibberish/jibberish.grammar", __dirname + "/langs/jibjab/jibjab.gram"]) - const path = __dirname + "/langs/jibjab/jibjab.grammar" + const combined = ParsersCompiler.combineFiles([__dirname + "/langs/jibberish/jibberish.parsers", __dirname + "/langs/jibjab/jibjab.gram"]) + const path = __dirname + "/langs/jibjab/jibjab.parsers" combined.toDisk(path) - GrammarCompiler.formatFileInPlace(path, __dirname + "/langs/grammar/grammar.grammar") + ParsersCompiler.formatFileInPlace(path, __dirname + "/langs/parsers/parsers.parsers") } _getProductFolder() { @@ -297,7 +297,7 @@ class Builder extends TreeNode { const fileTestTree: any = {} - allTestFiles.filter(file => file.endsWith(".grammar")).forEach(file => (fileTestTree[file] = this.makeGrammarFileTestTree(file))) + allTestFiles.filter(file => file.endsWith(".parsers")).forEach(file => (fileTestTree[file] = this.makeParsersFileTestTree(file))) allTestFiles.filter(file => file.endsWith(".test.js") || file.endsWith(".test.ts")).forEach(file => (fileTestTree[file] = require(file).testTree)) @@ -314,7 +314,7 @@ treeNode swim testRacer treeFileSystem -grammar +parsers utils treeComponentFramework`.split("\n") const fileTree = {} diff --git a/designer/DesignerApp.ts b/designer/DesignerApp.ts index 5f8cb1591..54c028c59 100644 --- a/designer/DesignerApp.ts +++ b/designer/DesignerApp.ts @@ -1,10 +1,10 @@ const { AbstractTreeComponentParser, TreeComponentFrameworkDebuggerComponent, AbstractGithubTriangleComponent } = require("../products/TreeComponentFramework.node.js") const { TreeNode } = require("../products/TreeNode.js") const { Utils } = require("../products/Utils.js") -const { HandGrammarProgram, GrammarBackedNode, UnknownGrammarProgram } = require("../products/GrammarLanguage.js") -const { GrammarCodeMirrorMode } = require("../products/GrammarCodeMirrorMode.js") +const { HandParsersProgram, ParserBackedNode, UnknownParsersProgram } = require("../products/Parsers.js") +const { ParsersCodeMirrorMode } = require("../products/ParsersCodeMirrorMode.js") -declare var grammarParser: any +declare var parsersParser: any // todo: get typings in here. declare var CodeMirror: any @@ -49,14 +49,14 @@ class DesignerApp extends AbstractTreeComponentParser { this.willowBrowser.setHtmlOfElementWithIdHack("explainResultsDiv", this._toIceTray(this.program)) } - inferPrefixGrammarCommand() { - this.setGrammarCode(new UnknownGrammarProgram(this.getCodeValue()).inferGrammarFileForAKeywordLanguage("inferredLanguage")) - this._onGrammarKeyup() + inferPrefixParsersCommand() { + this.setParsersCode(new UnknownParsersProgram(this.getCodeValue()).inferParsersFileForAKeywordLanguage("inferredLanguage")) + this._onParsersKeyup() } synthesizeProgramCommand() { - const grammarProgram = new HandGrammarProgram(this.getGrammarCode()) - this.setCodeCode(grammarProgram.rootParserDefinition.synthesizeNode().join("\n")) + const parsersProgram = new HandParsersProgram(this.getParsersCode()) + this.setCodeCode(parsersProgram.rootParserDefinition.synthesizeNode().join("\n")) this._onCodeKeyUp() } @@ -68,34 +68,34 @@ class DesignerApp extends AbstractTreeComponentParser { async fetchAndLoadScrollSDKShippedLanguageCommand(name: string) { const samplePath = `/langs/${name}/sample.${name}` - const grammarPath = `/langs/${name}/${name}.grammar` + const parsersPath = `/langs/${name}/${name}.parsers` const willowBrowser = this.willowBrowser - const grammar = await willowBrowser.httpGetUrl(grammarPath) + const parsers = await willowBrowser.httpGetUrl(parsersPath) const sample = await willowBrowser.httpGetUrl(samplePath) - this._setGrammarAndCode(grammar.text, sample.text) + this._setParsersAndCode(parsers.text, sample.text) } - async fetchAndLoadGrammarFromUrlCommand(url: string, programUrl: string) { + async fetchAndLoadParsersFromUrlCommand(url: string, programUrl: string) { const willowBrowser = this.willowBrowser - const grammar = await willowBrowser.httpGetUrl(url) - const grammarProgram = new HandGrammarProgram(grammar.text) - const rootNodeDef = grammarProgram.rootParserDefinition + const parsers = await willowBrowser.httpGetUrl(url) + const parsersProgram = new HandParsersProgram(parsers.text) + const rootNodeDef = parsersProgram.rootParserDefinition let sample = rootNodeDef.getNode("example").childrenToString() if (programUrl) { sample = await willowBrowser.httpGetUrl(programUrl) sample = sample.text } - this._setGrammarAndCode(grammar.text, sample) + this._setParsersAndCode(parsers.text, sample) } // TODO: ADD TESTS!!!!! async downloadBundleCommand() { - const grammarProgram = new HandGrammarProgram(this.getGrammarCode()) - const bundle = grammarProgram.toBundle() - const languageName = grammarProgram.extensionName + const parsersProgram = new HandParsersProgram(this.getParsersCode()) + const bundle = parsersProgram.toBundle() + const languageName = parsersProgram.extensionName return this._makeZipBundle(languageName + ".zip", bundle) } @@ -138,21 +138,21 @@ class DesignerApp extends AbstractTreeComponentParser { } /// - public languages = "newlang hakon stump dumbdown arrow dug iris fire chuck fruit swarm project stamp grammar config jibberish numbers poop".split(" ") + public languages = "newlang parsers hakon stump dumbdown arrow dug iris fire chuck fruit swarm project stamp config jibberish numbers poop".split(" ") public program: any - public grammarProgram: any + public parsersProgram: any _localStorageKeys = { - grammarConsole: "grammarConsole", + parsersConsole: "parsersConsole", codeConsole: "codeConsole" } - private grammarInstance: any + private parsersInstance: any private codeInstance: any - private _grammarParser: any - private _cachedGrammarCode: string + private _parsersParser: any + private _cachedParsersCode: string private codeWidgets: any[] = [] @@ -169,15 +169,15 @@ class DesignerApp extends AbstractTreeComponentParser { await this.fetchAndLoadScrollSDKShippedLanguageCommand(standard) return true } else if (fromUrl) { - console.log(`Loading grammar from '${fromUrl}'....`) - await this.fetchAndLoadGrammarFromUrlCommand(fromUrl, programUrl) + console.log(`Loading parsers from '${fromUrl}'....`) + await this.fetchAndLoadParsersFromUrlCommand(fromUrl, programUrl) return true } else { - const grammarCode = deepLink.getNode("grammar") + const parsersCode = deepLink.getNode("parsers") const sampleCode = deepLink.getNode("sample") - if (grammarCode && sampleCode) { + if (parsersCode && sampleCode) { console.log("Loading custom from deep link....") - this._setGrammarAndCode(grammarCode.childrenToString(), sampleCode.childrenToString()) + this._setParsersAndCode(parsersCode.childrenToString(), sampleCode.childrenToString()) return true } } @@ -188,8 +188,9 @@ class DesignerApp extends AbstractTreeComponentParser { history.replaceState(null, null, " ") } - _onGrammarKeyup() { - this._grammarDidUpdate() + _onParsersKeyup() { + this._updateLocalStorage() + this._parsersDidUpdate() this._onCodeKeyUp() // Hack to break CM cache: if (true) { @@ -203,13 +204,13 @@ class DesignerApp extends AbstractTreeComponentParser { this._bindTreeComponentFrameworkCommandListenersOnBody() this.renderAndGetRenderReport(this.willowBrowser.getBodyStumpNode()) - this.grammarInstance = new GrammarCodeMirrorMode("grammar", () => grammarParser, undefined, CodeMirror).register().fromTextAreaWithAutocomplete(document.getElementById("grammarConsole"), { lineWrapping: true }) + this.parsersInstance = new ParsersCodeMirrorMode("parsers", () => parsersParser, undefined, CodeMirror).register().fromTextAreaWithAutocomplete(document.getElementById("parsersConsole"), { lineWrapping: true }) - this.grammarInstance.on("keyup", () => { - this._onGrammarKeyup() + this.parsersInstance.on("keyup", () => { + this._onParsersKeyup() }) - this.codeInstance = new GrammarCodeMirrorMode("custom", () => this._getGrammarParser(), undefined, CodeMirror).register().fromTextAreaWithAutocomplete(document.getElementById("codeConsole"), { lineWrapping: true }) + this.codeInstance = new ParsersCodeMirrorMode("custom", () => this._getParsersParser(), undefined, CodeMirror).register().fromTextAreaWithAutocomplete(document.getElementById("codeConsole"), { lineWrapping: true }) this.codeInstance.on("keyup", () => this._onCodeKeyUp()) @@ -218,12 +219,12 @@ class DesignerApp extends AbstractTreeComponentParser { if (!wasLoadedFromDeepLink) await this._restoreFromLocalStorage() } - getGrammarCode() { - return this.grammarInstance.getValue() + getParsersCode() { + return this.parsersInstance.getValue() } - setGrammarCode(code: string) { - this.grammarInstance.setValue(code) + setParsersCode(code: string) { + this.parsersInstance.setValue(code) } setCodeCode(code: string) { @@ -236,40 +237,40 @@ class DesignerApp extends AbstractTreeComponentParser { private async _restoreFromLocalStorage() { console.log("Restoring from local storage....") - const grammarCode: any = localStorage.getItem(this._localStorageKeys.grammarConsole) + const parsersCode: any = localStorage.getItem(this._localStorageKeys.parsersConsole) const code = localStorage.getItem(this._localStorageKeys.codeConsole) - if (typeof grammarCode === "string" && typeof code === "string") this._setGrammarAndCode(grammarCode, code) + if (typeof parsersCode === "string" && typeof code === "string") this._setParsersAndCode(parsersCode, code) - return grammarCode || code + return parsersCode || code } private _updateLocalStorage() { - localStorage.setItem(this._localStorageKeys.grammarConsole, this.getGrammarCode()) + localStorage.setItem(this._localStorageKeys.parsersConsole, this.getParsersCode()) localStorage.setItem(this._localStorageKeys.codeConsole, this.getCodeValue()) this._updateShareLink() // todo: where to put this? console.log("Local storage updated...") } - private _getGrammarErrors(grammarCode: string) { - return new grammarParser(grammarCode).getAllErrors() + private _getParsersErrors(parsersCode: string) { + return new parsersParser(parsersCode).getAllErrors() } - private _getGrammarParser() { - let currentGrammarCode = this.getGrammarCode() + private _getParsersParser() { + let currentParsersCode = this.getParsersCode() - if (!this._grammarParser || currentGrammarCode !== this._cachedGrammarCode) { + if (!this._parsersParser || currentParsersCode !== this._cachedParsersCode) { try { - const grammarErrors = this._getGrammarErrors(currentGrammarCode) - this._grammarParser = new HandGrammarProgram(currentGrammarCode).compileAndReturnRootParser() - this._cachedGrammarCode = currentGrammarCode + const parsersErrors = this._getParsersErrors(currentParsersCode) + this._parsersParser = new HandParsersProgram(currentParsersCode).compileAndReturnRootParser() + this._cachedParsersCode = currentParsersCode this.willowBrowser.setHtmlOfElementWithIdHack("otherErrorsDiv") } catch (err) { console.error(err) this.willowBrowser.setHtmlOfElementWithIdHack("otherErrorsDiv", err) } } - return this._grammarParser + return this._parsersParser } protected onCommandError(err: any) { @@ -277,14 +278,13 @@ class DesignerApp extends AbstractTreeComponentParser { this.willowBrowser.setHtmlOfElementWithIdHack("otherErrorsDiv", err) } - private _grammarDidUpdate() { - const grammarCode = this.getGrammarCode() - this._updateLocalStorage() - this.grammarProgram = new grammarParser(grammarCode) - const errs = this.grammarProgram.getAllErrors().map((err: any) => err.toObject()) - this.willowBrowser.setHtmlOfElementWithIdHack("grammarErrorsConsole", errs.length ? new TreeNode(errs).toFormattedTable(200) : "0 errors") - const grammarProgram = new HandGrammarProgram(this.grammarInstance.getValue()) - const readme = new dumbdownParser(grammarProgram.toReadMe()).compile() + private _parsersDidUpdate() { + const parsersCode = this.getParsersCode() + this.parsersProgram = new parsersParser(parsersCode) + const errs = this.parsersProgram.getAllErrors().map((err: any) => err.toObject()) + this.willowBrowser.setHtmlOfElementWithIdHack("parsersErrorsConsole", errs.length ? new TreeNode(errs).toFormattedTable(200) : "0 errors") + const parsersProgram = new HandParsersProgram(this.parsersInstance.getValue()) + const readme = new dumbdownParser(parsersProgram.toReadMe()).compile() this.willowBrowser.setHtmlOfElementWithIdHack("readmeComponent", readme) } @@ -298,7 +298,7 @@ class DesignerApp extends AbstractTreeComponentParser { toShareLink() { const tree = new TreeNode() - tree.appendLineAndChildren("grammar", this.getGrammarCode()) + tree.appendLineAndChildren("parsers", this.getParsersCode()) tree.appendLineAndChildren("sample", this.getCodeValue()) return "#" + encodeURIComponent(tree.asString) } @@ -307,10 +307,10 @@ class DesignerApp extends AbstractTreeComponentParser { const { willowBrowser } = this const code = this.getCodeValue() this._updateLocalStorage() - const grammarParser = this._getGrammarParser() + const parsersParser = this._getParsersParser() const that = this - this.program = new grammarParser(code) + this.program = new parsersParser(code) const errs = this.program.scopeErrors.concat(this.program.getAllErrors()) willowBrowser.setHtmlOfElementWithIdHack("codeErrorsConsole", errs.length ? new TreeNode(errs.map((err: any) => err.toObject())).toFormattedTable(200) : "0 errors") @@ -343,11 +343,11 @@ class DesignerApp extends AbstractTreeComponentParser { if (willowBrowser.getElementById("executeCommand").checked) this.executeCommand() } - _setGrammarAndCode(grammar: string, code: string) { - this.setGrammarCode(grammar) + _setParsersAndCode(parsers: string, code: string) { + this.setParsersCode(parsers) this.setCodeCode(code) this._clearHash() - this._grammarDidUpdate() + this._parsersDidUpdate() this._clearResults() this._onCodeKeyUp() } @@ -455,7 +455,7 @@ class samplesComponent extends AbstractTreeComponentParser { ) .join("\n span | \n") return `p - span Example Languages + span Examples ${langs}` } } @@ -534,19 +534,16 @@ class tableComponent extends AbstractTreeComponentParser { return `table tr td - span Grammar for your Tree Language - a Infer Prefix Grammar - clickCommand inferPrefixGrammarCommand - span | - a Download Bundle - clickCommand downloadBundleCommand - span | + span Your Parsers   + a Infer Prefix Parsers + clickCommand inferPrefixParsersCommand + span |   a Synthesize Program clickCommand synthesizeProgramCommand textarea - id grammarConsole + id parsersConsole td - span Source Code in your Language + span Your Program input type checkbox id executeCommand @@ -568,13 +565,13 @@ class tableComponent extends AbstractTreeComponentParser { id codeConsole tr td - div Grammar Errors + div Parser Errors pre - id grammarErrorsConsole + id parsersErrorsConsole div id readmeComponent td - div Language Errors + div Program Errors pre id codeErrorsConsole textarea @@ -594,7 +591,7 @@ class tableComponent extends AbstractTreeComponentParser { class headerComponent extends AbstractTreeComponentParser { _getTitle() { - return `Scroll Designer` + return `Parser Designer` } toHakonCode() { return `#logo @@ -636,8 +633,8 @@ class headerComponent extends AbstractTreeComponentParser { div id helpSection style display: none; - p This is a simple web IDE for designing and building Tree Languages. To build a Tree Language, you write code in a "grammar language" in the textarea on the left. You can then write code in your new language in the textarea on the right. You instantly get syntax highlighting, autocomplete, type/cell checking, suggested corrections, and more. - p Click "Newlang" to create a New Language, or explore/edit existing languages. In dev tools, you can access the parsed trees below as "app.grammarProgram" and program at "app.program". We also have a work-in-progress Tutorial for creating new Tree Languages using Grammar.` + p This is a simple web IDE for designing and building languages on top of Scroll Notation. To build a language, you write Parsers in the textarea on the left. You can then write code in your new language in the textarea on the right. You instantly get syntax highlighting, autocomplete, type/cell checking, suggested corrections, and more. + p Click "Newlang" to create a New Language, or explore/edit existing languages. In dev tools, you can access the parsed trees below as "app.parsersProgram" and program at "app.program". We also have a work-in-progress Tutorial for creating new languages using Parsers.` } } diff --git a/designer/index.html b/designer/index.html index d6a7951c0..bb9db0129 100644 --- a/designer/index.html +++ b/designer/index.html @@ -1,6 +1,6 @@ - Scroll Designer + Parser Designer @@ -13,11 +13,11 @@ - - + + - + diff --git a/designer/readme.scroll b/designer/readme.scroll index feb6a25a8..1d15a5e73 100644 --- a/designer/readme.scroll +++ b/designer/readme.scroll @@ -1,6 +1,6 @@ title Designer -This is the folder containing the source code for the Scroll Designer web app. +This is the folder containing the source code for the Parser Designer web app. Try it Now https://sdk.scroll.pub/designer/ diff --git a/disk/Disk.node.ts b/disk/Disk.node.ts index 8579b54e8..0e8a6f7e5 100644 --- a/disk/Disk.node.ts +++ b/disk/Disk.node.ts @@ -151,7 +151,7 @@ class Disk { return map } /** - * Take an object like {".gitignore" : "ignore/", "grammar/root.grammar": "foo"} + * Take an object like {".gitignore" : "ignore/", "parsers/root.parsers": "foo"} * and recreate on the filesystem as files and folders. Each key is 1 file. * */ static writeObjectToDisk = (baseFolder: string, obj: any) => { diff --git a/favicon.ico b/favicon.ico new file mode 100644 index 000000000..1f9baf6e2 Binary files /dev/null and b/favicon.ico differ diff --git a/grammar/readme.scroll b/grammar/readme.scroll deleted file mode 100644 index a2940d210..000000000 --- a/grammar/readme.scroll +++ /dev/null @@ -1,5 +0,0 @@ -title Grammar TypeScript Implementation - -This folder contains Grammar implemented in TypeScript. - -See the folder `langs/grammar/` for documentation on Grammar. diff --git a/kitchen/readme.scroll b/kitchen/readme.scroll index 6a4d42862..e6776c0ce 100644 --- a/kitchen/readme.scroll +++ b/kitchen/readme.scroll @@ -2,7 +2,7 @@ title Kitchen Kitchen is a simple ExpressJS app used by Scroll Developers. -With Kitchen you can run Scroll Notation sandbox, Scroll Designer, and other tools locally. +With Kitchen you can run Scroll Notation sandbox, Parser Designer, and other tools locally. ? How do I start it? code diff --git a/langs/arrow/arrow.grammar b/langs/arrow/arrow.parsers similarity index 93% rename from langs/arrow/arrow.grammar rename to langs/arrow/arrow.parsers index 944940a9c..9198bc4f1 100644 --- a/langs/arrow/arrow.grammar +++ b/langs/arrow/arrow.parsers @@ -36,7 +36,7 @@ commentParser crux Comment boolean suggestInAutocomplete false arrowParser - description A demonstration prefix Tree Language showing how in the future Scroll Notation will be used for simpler and more intelligent APIs. + description A demonstration prefix Language showing how in the future Scroll Notation will be used for simpler and more intelligent APIs. root inScope chargeParser commentParser catchAllParser errorParser diff --git a/langs/chuck/chuck.grammar b/langs/chuck/chuck.parsers similarity index 85% rename from langs/chuck/chuck.grammar rename to langs/chuck/chuck.parsers index de4e85d92..2c07ae246 100644 --- a/langs/chuck/chuck.grammar +++ b/langs/chuck/chuck.parsers @@ -8,7 +8,7 @@ floatCell // Line Parsers chuckParser - description A useless demo Tree Language inspired by Forth that tests postfix notation. + description A useless demo Language inspired by Forth that tests postfix notation. root inScope abstractOperatorParser onlyNumbersParser abstractOperatorParser diff --git a/langs/config/config.grammar b/langs/config/config.parsers similarity index 74% rename from langs/config/config.grammar rename to langs/config/config.parsers index dbdfd9a1f..23ff5116e 100644 --- a/langs/config/config.grammar +++ b/langs/config/config.parsers @@ -9,7 +9,7 @@ keywordCell // Line Parsers configParser - description A simple Tree Language for config files. Stores recursive maps with keys as strings and values as strings. + description A simple Language for config files. Stores recursive maps with keys as strings and values as strings. root catchAllParser pairParser pairParser diff --git a/langs/dug/dug.grammar b/langs/dug/dug.parsers similarity index 95% rename from langs/dug/dug.grammar rename to langs/dug/dug.parsers index 394fc934e..a2fc86d50 100644 --- a/langs/dug/dug.grammar +++ b/langs/dug/dug.parsers @@ -16,7 +16,7 @@ numberCell // Line Parsers dugParser root - description A demonstration prefix Tree Language that compiles to JSON. + description A demonstration prefix Language that compiles to JSON. inScope abstractValueParser catchAllParser errorParser javascript diff --git a/langs/dug/sample.dug b/langs/dug/sample.dug index eaa09e3f7..6d5acd645 100644 --- a/langs/dug/sample.dug +++ b/langs/dug/sample.dug @@ -4,7 +4,7 @@ object version string 30.0.0 description - string Simplify your code with Scroll Notation. This scrollsdk package includes a Scroll Notation parser, compiler-compiler, and virtual machine for Tree Languages, as well as sample languages, implemented in TypeScript. + string Simplify your code with Scroll Notation. This scrollsdk package includes a Scroll Notation parser, compiler-compiler, and virtual machine for Languages, as well as sample languages, implemented in TypeScript. prettier object useTabs diff --git a/langs/dumbdown/dumbdown.grammar b/langs/dumbdown/dumbdown.parsers similarity index 95% rename from langs/dumbdown/dumbdown.grammar rename to langs/dumbdown/dumbdown.parsers index c8ec627c4..92c052526 100644 --- a/langs/dumbdown/dumbdown.grammar +++ b/langs/dumbdown/dumbdown.parsers @@ -17,7 +17,7 @@ errorParser baseParser errorParser dumbdownParser extensions dd dumbdown - description A Tree Language that compiles to HTML. An alternative to Markdown. + description A Language that compiles to HTML. An alternative to Markdown. root inScope abstractTopLevelParser blankLineParser catchAllParser quickParagraphParser @@ -28,7 +28,7 @@ dumbdownParser paragraph It compiles to HTML. Blank lines get turned into brs. - link https://notation.scroll.pub Dumbdown is a Tree Language. + link https://notation.scroll.pub Dumbdown is a Language. list - It has lists - Too! diff --git a/langs/dumbdown/readme.scroll b/langs/dumbdown/readme.scroll index 1d2db4f42..a25b251bb 100644 --- a/langs/dumbdown/readme.scroll +++ b/langs/dumbdown/readme.scroll @@ -1,6 +1,6 @@ title Dumbdown - The dumb alternative to markdown -The dialect of Dumbdown included in the ScrollSDK project is used as a demonstration and to autogenerate readmes from Grammars. +The dialect of Dumbdown included in the ScrollSDK project is used as a demonstration and to autogenerate readmes from Parsers. Dumbdown spawned an official project: Scroll https://github.com/breck7/scroll Scroll diff --git a/langs/dumbdown/sample.dumbdown b/langs/dumbdown/sample.dumbdown index 117c76fff..f33328ca1 100644 --- a/langs/dumbdown/sample.dumbdown +++ b/langs/dumbdown/sample.dumbdown @@ -13,7 +13,7 @@ code list - Dumbdown supports lists - - Dumbdown is a demonstration Tree Language from the Scroll Notation Lab + - Dumbdown is a demonstration Language from the Scroll Notation Lab - This is a very early version - Dumbdown is released to the public domain - If you want to make it better, please do! \ No newline at end of file diff --git a/langs/fire/fire.grammar b/langs/fire/fire.parsers similarity index 98% rename from langs/fire/fire.grammar rename to langs/fire/fire.parsers index 2fac9e807..7a2bdcedb 100644 --- a/langs/fire/fire.grammar +++ b/langs/fire/fire.parsers @@ -46,7 +46,7 @@ leftAnyCell // Line Parsers fireParser root - description A useless prefix Tree Language that compiles to Javascript for testing Scroll Notation features. + description A useless prefix Language that compiles to Javascript for testing Scroll Notation features. compilesTo js inScope hashbangParser abstractTerminalParser abstractNonTerminalParser catchAllParser errorParser diff --git a/langs/fruit/fruit.grammar b/langs/fruit/fruit.parsers similarity index 100% rename from langs/fruit/fruit.grammar rename to langs/fruit/fruit.parsers diff --git a/langs/hakon/hakon.grammar b/langs/hakon/hakon.parsers similarity index 98% rename from langs/hakon/hakon.grammar rename to langs/hakon/hakon.parsers index 6b46e90b6..a77ca508d 100644 --- a/langs/hakon/hakon.grammar +++ b/langs/hakon/hakon.parsers @@ -31,7 +31,7 @@ commentCell hakonParser root // todo Add variables? - description A prefix Tree Language that compiles to CSS + description A prefix Language that compiles to CSS compilesTo css inScope commentParser catchAllParser selectorParser diff --git a/langs/iris/iris.grammar b/langs/iris/iris.parsers similarity index 91% rename from langs/iris/iris.grammar rename to langs/iris/iris.parsers index 45802ce6f..691fcd01b 100644 --- a/langs/iris/iris.grammar +++ b/langs/iris/iris.parsers @@ -26,7 +26,7 @@ speciesCell // Line Parsers irisParser - description An ssv Tree Language autogenerated from the Iris CSV file. + description An ssv Language autogenerated from the Iris CSV file. root inScope commentParser headerParser catchAllParser rowParser diff --git a/langs/jibberish/jibberish.node.js b/langs/jibberish/jibberish.node.js index a55ce21e0..5fa4c6d7b 100644 --- a/langs/jibberish/jibberish.node.js +++ b/langs/jibberish/jibberish.node.js @@ -1 +1 @@ -module.exports = require("../../products/GrammarCompiler.js").GrammarCompiler.compileGrammarFileAtPathAndReturnRootParser(__dirname + "/jibberish.grammar") +module.exports = require("../../products/ParsersCompiler.js").ParsersCompiler.compileParsersFileAtPathAndReturnRootParser(__dirname + "/jibberish.parsers") diff --git a/langs/jibberish/jibberish.grammar b/langs/jibberish/jibberish.parsers similarity index 97% rename from langs/jibberish/jibberish.grammar rename to langs/jibberish/jibberish.parsers index 1098f3239..539f89c44 100644 --- a/langs/jibberish/jibberish.grammar +++ b/langs/jibberish/jibberish.parsers @@ -17,7 +17,7 @@ opSymbolCell // Line Parsers jibberishParser root - description A useless Tree Language built for testing Scroll Notation code. + description A useless Language built for testing Scroll Notation code. javascript execute() { return 42 diff --git a/langs/jibjab/jibjab.node.js b/langs/jibjab/jibjab.node.js index 5587c347e..d28ff5d88 100644 --- a/langs/jibjab/jibjab.node.js +++ b/langs/jibjab/jibjab.node.js @@ -1 +1 @@ -module.exports = require("../../products/GrammarCompiler.js").GrammarCompiler.compileGrammarFileAtPathAndReturnRootParser(__dirname + "/jibjab.grammar") +module.exports = require("../../products/ParsersCompiler.js").ParsersCompiler.compileParsersFileAtPathAndReturnRootParser(__dirname + "/jibjab.parsers") diff --git a/langs/jibjab/jibjab.grammar b/langs/jibjab/jibjab.parsers similarity index 97% rename from langs/jibjab/jibjab.grammar rename to langs/jibjab/jibjab.parsers index 7215e9791..44b81798b 100644 --- a/langs/jibjab/jibjab.grammar +++ b/langs/jibjab/jibjab.parsers @@ -19,7 +19,7 @@ commentCell // Line Parsers jibberishParser root - description A useless Tree Language built for testing Scroll Notation code. + description A useless Language built for testing Scroll Notation code. javascript execute() { return 42 diff --git a/langs/newlang/newlang.grammar b/langs/newlang/newlang.parsers similarity index 80% rename from langs/newlang/newlang.grammar rename to langs/newlang/newlang.parsers index 30155a19e..780add188 100644 --- a/langs/newlang/newlang.grammar +++ b/langs/newlang/newlang.parsers @@ -8,7 +8,7 @@ keywordCell // Line Parsers newlangParser root - description This is the basic root node for your new prefix Tree Language. + description This is the basic root node for your new prefix Language. catchAllParser catchAllErrorParser inScope helloParser helloParser diff --git a/langs/numbers/numbers.grammar b/langs/numbers/numbers.parsers similarity index 96% rename from langs/numbers/numbers.grammar rename to langs/numbers/numbers.parsers index ddcf3a350..94c94ce9c 100644 --- a/langs/numbers/numbers.grammar +++ b/langs/numbers/numbers.parsers @@ -23,7 +23,7 @@ operatorCell // Line Parsers numbersParser root - description A useless Tree Language for testing Scroll Notation features. + description A useless Language for testing Scroll Notation features. inScope abstractArithmeticReducerParser commentParser hashBangParser catchAllParser errorParser javascript diff --git a/langs/grammar/grammar.grammar b/langs/parsers/parsers.parsers similarity index 97% rename from langs/grammar/grammar.grammar rename to langs/parsers/parsers.parsers index 2656d0bef..d03b0369d 100755 --- a/langs/grammar/grammar.grammar +++ b/langs/parsers/parsers.parsers @@ -1,4 +1,4 @@ -// todo Add imports parsers, along with source maps, so we can correctly support grammars split across multiple files, and better enable grammars from compositions of reusable bits? +// todo Add imports parsers, along with source maps, so we can correctly support parsers split across multiple files, and better enable parsers from compositions of reusable bits? // todo Do error checking for if you have a firstwordCellType, cells, and/or catchAllCellType with same name. // todo Add enumOption root level type? // todo compile cells. add javascript property. move getRunTimeEnumOptions to cells. @@ -98,12 +98,12 @@ commentCell highlightScope comment // Line Parsers -grammarParser +parsersParser root - description Grammar is a Tree Language for creating new Tree Languages. By creating a grammar file you get a parser, a type checker, syntax highlighting, autocomplete, a compiler, and virtual machine for executing your new language. Grammar uses both postfix and prefix language features. + description Parsers is a language for creating new languages on top of Scroll Notation. By creating a parsers file you get a parser, a type checker, syntax highlighting, autocomplete, a compiler, and virtual machine for executing your new language. Parsers uses both postfix and prefix language features. catchAllParser catchAllErrorParser - extensions grammar gram - example A grammar that parses anything: + extensions parsers gram + example A parsers that parses anything: latinParser root catchAllParser anyParser @@ -112,7 +112,7 @@ grammarParser version 5.0.0 inScope slashCommentParser blankLineParser cellTypeDefinitionParser parserDefinitionParser blankLineParser - description Blank lines are OK in Grammar. + description Blank lines are OK in Parsers. cells blankCell pattern ^$ tags doNotSynthesize diff --git a/langs/grammar/readme.scroll b/langs/parsers/readme.scroll similarity index 77% rename from langs/grammar/readme.scroll rename to langs/parsers/readme.scroll index 6dd026b92..2fd4d7a25 100644 --- a/langs/grammar/readme.scroll +++ b/langs/parsers/readme.scroll @@ -2,15 +2,15 @@ import ../../header.scroll permalink index.html copyButtons -title Grammar: A language for making languages +title Scroll Parsers: A language for making languages startColumns 2 -? What is Grammar? -Grammar is a language for making languages. +? What is Parsers? +Parsers is a language for making languages. ? Can you show me an example? -Below is some code written in Grammar to create a simple language called *Panda*. +Below is some code written in Parsers to create a simple language called *Panda*. code pandaParser @@ -23,27 +23,27 @@ code cells operatorCell catchAllCellType intCell -The Grammar code can generate a parser that parses statements like `+ 1 2 5 10` and `- 10 2`. +The Parsers code can generate a parser that parses statements like `+ 1 2 5 10` and `- 10 2`. ? What is a longer description? -Grammar is a Tree Language for generating parsers for other Tree Languages. The parsers not only allow parsing of those languages but also can include code written in a host language (such as Javascript) for compiling and/or runtime interpreting of these languages. +Parsers is a language built on Scroll Notation for building other languages built on Scroll Notation. The parsers not only allow parsing of those languages but also can include code written in a host language (such as Javascript) for compiling and/or runtime interpreting of these languages. ? Can I try it online? -Yes! The Scroll Designer is an online tool for writing Grammar code to build languages right in your browser. - https://sdk.scroll.pub/designer/ Scroll Designer +Yes! The Parser Designer is an online tool for writing Parsers code to build languages right in your browser. + https://sdk.scroll.pub/designer/ Parser Designer endColumns -# Grammar Roadmap +# Parsers Roadmap id roadmap -The following major features are likely to be added to a future version of Grammar: +The following major features are likely to be added to a future version of Parsers: style text-align: center; startColumns 2 ## Import statements -- Turning Grammar into a 2 pass language where the first pass resolves any imports +- Turning Parsers into a 2 pass language where the first pass resolves any imports - Imports will leverage the existing import code used by Scroll for posix style paths - Other protocols may be supported such as `https://` imports and perhaps something like `node_modules://` @@ -64,20 +64,20 @@ startColumns 2 - A common pattern in languages is to have different scopes for the first line of the file. For example, shebang lines in executable scripts or header lines in CSV files. We might want to create a way to have certain parsers inScope for line 0 and out of scope the rest of the lines. ## LSP Support -- We should move away from TreeComponentFramework and the Designer App code base and move efforts toward having languages written in Grammar get an LSP implementation for free. +- We should move away from TreeComponentFramework and the Designer App code base and move efforts toward having languages written in Parsers get an LSP implementation for free. ## BNF Parsing -- It's worth exploring using Grammar to also generate parsers for BNF languages. +- It's worth exploring using Parsers to also generate parsers for BNF languages. ## Upgrading to CodeMirror Version 6 - It may be worth it to upgrade the CodeMirror Mode Code to Code Mirror Version 6. endColumns -# Grammar Release Notes +# Parsers Release Notes id releaseNotes -Here's a list of the notable changes in Grammar: +Here's a list of the notable changes in Parsers: style text-align: center; startColumns 2 diff --git a/langs/grammar/sample.grammar b/langs/parsers/sample.parsers similarity index 100% rename from langs/grammar/sample.grammar rename to langs/parsers/sample.parsers diff --git a/langs/poop/poop.grammar b/langs/poop/poop.parsers similarity index 83% rename from langs/poop/poop.grammar rename to langs/poop/poop.parsers index c2a7931df..1d60ae69b 100644 --- a/langs/poop/poop.grammar +++ b/langs/poop/poop.parsers @@ -21,9 +21,9 @@ eventTypeCell // Line parsers poopParser - description POOP is the Programming Option for Overtired Parents. It is a Tree Language for sleep deprived parents to log their child's bathroom, feeding, and sleep events and compile them to CSV. You can use POOP with computers or pen and paper. Each line records an event, a time, and optionally notes. POOP is an anyfix language. You can put the time first or the event type first. You can write the actual symbols, or, if it is 3am, you can just use some of the natural medium to record the event type. + description POOP is the Programming Option for Overtired Parents. It is a Language for sleep deprived parents to log their child's bathroom, feeding, and sleep events and compile them to CSV. You can use POOP with computers or pen and paper. Each line records an event, a time, and optionally notes. POOP is an anyfix language. You can put the time first or the event type first. You can write the actual symbols, or, if it is 3am, you can just use some of the natural medium to record the event type. root - tags nonPrefixGrammar + tags nonPrefixParsers compilesTo csv javascript compile() { diff --git a/langs/poop/readme.scroll b/langs/poop/readme.scroll index 35e4bc6b9..b1d997e3a 100755 --- a/langs/poop/readme.scroll +++ b/langs/poop/readme.scroll @@ -3,7 +3,7 @@ title poop Readme Try it now https://sdk.scroll.pub/designer/#standard%20poop -POOP is the *Programming Option for Overtired Parents*. It is a Tree Language for sleep deprived parents to log their child's bathroom, feeding, and sleep events. You can use POOP with computers or pen and paper. Each line records an event, a time, and optionally notes. +POOP is the *Programming Option for Overtired Parents*. It is a Language for sleep deprived parents to log their child's bathroom, feeding, and sleep events. You can use POOP with computers or pen and paper. Each line records an event, a time, and optionally notes. POOP is an anyfix language. You can put the time first or the event type first. You can write the actual symbols with pen or pencil, or, if it is 3am, you can just use some of the natural medium to record the event type. @@ -40,4 +40,4 @@ code This readme was auto-generated using the ScrollSDK https://github.com/breck7/scrollsdk ScrollSDK -๐Ÿ’ฉ is just for fun, a demonstration Tree Language. ๐Ÿ’ฉ is hereby dumped into the public domain. +๐Ÿ’ฉ is just for fun, a demonstration Language. ๐Ÿ’ฉ is hereby dumped into the public domain. diff --git a/langs/project/project.grammar b/langs/project/project.parsers similarity index 97% rename from langs/project/project.grammar rename to langs/project/project.parsers index ff3e52ec2..b9494a5c4 100755 --- a/langs/project/project.grammar +++ b/langs/project/project.parsers @@ -11,7 +11,7 @@ fileConstantCell projectParser root version 2.0.0 - description A prefix Tree Language for project dependency management in Javascript and Typescript. + description A prefix Language for project dependency management in Javascript and Typescript. javascript getScriptPathsInCorrectDependencyOrder() { const cloned = this.clone() diff --git a/langs/project/readme.scroll b/langs/project/readme.scroll index 9cd19f160..1c6674f66 100644 --- a/langs/project/readme.scroll +++ b/langs/project/readme.scroll @@ -1,4 +1,4 @@ -title A Tree Language for project dependency management. +title A Language for project dependency management. Helps with building and serving Javascript and TypeScript projects. diff --git a/langs/readme.scroll b/langs/readme.scroll index e2522fcfe..b67350506 100644 --- a/langs/readme.scroll +++ b/langs/readme.scroll @@ -1,9 +1,9 @@ title Langs -This folder contains numerous Tree Languages. +This folder contains numerous languages. Some of these languages are just for demonstration and testing purposes. Some of them are usable. The recommended way to use the languages in the folder is to search the top level `products/` folder and use the compiled Javascript directly. -The usuable languages include Stamp, Hakon, Stump, Swarm, Grammar and Dumbdown. +The usuable languages include Parsers, Stamp, Hakon, Stump, and Swarm. diff --git a/langs/stamp/readme.scroll b/langs/stamp/readme.scroll index 09b839841..68ef03dfa 100644 --- a/langs/stamp/readme.scroll +++ b/langs/stamp/readme.scroll @@ -11,7 +11,7 @@ code data # My Readme -You can also play with writing your own stamp files by hand in this web IDE to see autocomplete, type checking, and the full grammar. +You can also play with writing your own stamp files by hand in this web IDE to see autocomplete, type checking, and the parsers. https://sdk.scroll.pub/designer/#standard%20stamp web IDE # QuickStart: How to use Stamp in Node @@ -67,7 +67,7 @@ The current options for this situation are: # Alternatives Considered - Wikipedia list of archive formats https://en.wikipedia.org/wiki/List_of_archive_formats -- ptar full featured, but difference is the file output is a custom format (not a Tree Language) +- ptar full featured, but difference is the file output is a custom format (not a Language) https://github.com/jtvaughan/ptar ptar - shar old school method that has the major security flaw of potentially running any shell command https://en.wikipedia.org/wiki/Shar shar diff --git a/langs/stamp/stamp.grammar b/langs/stamp/stamp.parsers similarity index 97% rename from langs/stamp/stamp.grammar rename to langs/stamp/stamp.parsers index 0e7a6e45f..151069716 100644 --- a/langs/stamp/stamp.grammar +++ b/langs/stamp/stamp.parsers @@ -21,7 +21,7 @@ keywordCell // Line parsers stampParser root - description A prefix Tree Language for creating distributable text template files that expand to folders and files. + description A prefix Language for creating distributable text template files that expand to folders and files. catchAllParser errorParser javascript async executeSeries(parentDir) { diff --git a/langs/stump/stump.grammar b/langs/stump/stump.parsers similarity index 99% rename from langs/stump/stump.grammar rename to langs/stump/stump.parsers index e52da8ec4..414ca68a0 100644 --- a/langs/stump/stump.grammar +++ b/langs/stump/stump.parsers @@ -26,7 +26,7 @@ bernKeywordCell // Line parsers stumpParser root - description A prefix Tree Language that compiles to HTML. + description A prefix Language that compiles to HTML. catchAllParser errorParser inScope htmlTagParser blankLineParser example diff --git a/langs/swarm/nodeSample.swarm b/langs/swarm/nodeSample.swarm index be8a7018d..381173f21 100644 --- a/langs/swarm/nodeSample.swarm +++ b/langs/swarm/nodeSample.swarm @@ -1,7 +1,7 @@ #! /usr/bin/env node /usr/local/bin/scrollsdk test swarmNodeSample arrange - require ../../products/GrammarLanguage.js HandGrammarProgram + require ../../products/Parsers.js HandParsersProgram constructWithParagraph testlangParser root diff --git a/langs/swarm/swarm.grammar b/langs/swarm/swarm.parsers similarity index 99% rename from langs/swarm/swarm.grammar rename to langs/swarm/swarm.parsers index d232556cd..14cf62edc 100755 --- a/langs/swarm/swarm.grammar +++ b/langs/swarm/swarm.parsers @@ -44,7 +44,7 @@ typeOfOptionCell // Line parsers swarmParser root - description A prefix Tree Language for unit testing of classes. + description A prefix Language for unit testing of classes. inScope hashbangParser arrangeParser abstractTestBlockParser catchAllParser errorParser javascript diff --git a/langs/zin/zin.grammar b/langs/zin/zin.parsers similarity index 100% rename from langs/zin/zin.grammar rename to langs/zin/zin.parsers diff --git a/package.json b/package.json index 299bf157a..005d0c4b8 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "scrollsdk", - "version": "78.0.0", + "version": "80.0.0", "description": "This npm package includes the Scroll Notation class, the Scroll Parser compiler-compiler, a Scroll IDE, and more, all implemented in TypeScript.", "types": "./built/scrollsdk.node.d.ts", "main": "./products/TreeNode.js", @@ -16,9 +16,9 @@ }, "files": [ "products/Disk.node.js", - "products/grammar.nodejs.js", - "products/GrammarCompiler.js", - "products/GrammarLanguage.js", + "products/parsers.nodejs.js", + "products/ParsersCompiler.js", + "products/Parsers.js", "products/hakon.nodejs.js", "products/Path.js", "products/stamp.nodejs.js", @@ -58,4 +58,4 @@ "prettier": "^2.8.7", "superagent": "^8.0.9" } -} +} \ No newline at end of file diff --git a/grammar/GrammarLanguage.compiled.test.ts b/parsers/Parsers.compiled.test.ts similarity index 58% rename from grammar/GrammarLanguage.compiled.test.ts rename to parsers/Parsers.compiled.test.ts index f03a943d1..57d949f75 100755 --- a/grammar/GrammarLanguage.compiled.test.ts +++ b/parsers/Parsers.compiled.test.ts @@ -5,36 +5,36 @@ const path = require("path") const { TestRacer } = require("../products/TestRacer.js") const { Disk } = require("../products/Disk.node.js") const { TreeNode } = require("../products/TreeNode.js") -const { HandGrammarProgram, UnknownGrammarProgram } = require("../products/GrammarLanguage.js") -const { GrammarCompiler } = require("../products/GrammarCompiler.js") +const { HandParsersProgram, UnknownParsersProgram } = require("../products/Parsers.js") +const { ParsersCompiler } = require("../products/ParsersCompiler.js") const testTree: scrollNotationTypes.testTree = {} // todo: turn prettier off for test running? seems like it might increase test time from 2s to 5s... -// todo: setup: make vms dir. cleanup? delete grammar file when done? +// todo: setup: make vms dir. cleanup? delete parsers file when done? const outputDir = path.join(__dirname, "..", "ignore", "vms") const langsDir = path.join(__dirname, "..", "langs") Disk.mkdir(outputDir) -const makeProgram = (grammarCode: string, code: string) => { - const grammarProgram = new HandGrammarProgram(grammarCode) - const rootParser = grammarProgram.compileAndReturnRootParser() +const makeProgram = (parsersCode: string, code: string) => { + const parsersProgram = new HandParsersProgram(parsersCode) + const rootParser = parsersProgram.compileAndReturnRootParser() return new rootParser(code) } -testTree.grammar = equal => { +testTree.parsers = equal => { // Arrange - const grammarGrammarPath = path.join(langsDir, "grammar", "grammar.grammar") + const parsersParsersPath = path.join(langsDir, "parsers", "parsers.parsers") try { - const tempFilePath = GrammarCompiler.compileGrammarForNodeJs(grammarGrammarPath, outputDir, false) + const tempFilePath = ParsersCompiler.compileParsersForNodeJs(parsersParsersPath, outputDir, false) // Act - const grammar = require(tempFilePath) + const parsers = require(tempFilePath) // Assert - equal(!!new grammar(), true, "it compiled") + equal(!!new parsers(), true, "it compiled") } catch (err) { console.error(err) } finally { @@ -47,9 +47,9 @@ testTree.compileAll = equal => { langs.split(" ").map(name => { try { // Act - const grammarPath = path.join(langsDir, name, `${name}.grammar`) - const grammarCode = TreeNode.fromDisk(grammarPath) - const tempFilePath = GrammarCompiler.compileGrammarForNodeJs(grammarPath, outputDir, false) + const parsersPath = path.join(langsDir, name, `${name}.parsers`) + const parsersCode = TreeNode.fromDisk(parsersPath) + const tempFilePath = ParsersCompiler.compileParsersForNodeJs(parsersPath, outputDir, false) const rootClass = require(tempFilePath) // Assert @@ -57,7 +57,7 @@ testTree.compileAll = equal => { // Act // todo: should we have an example node for all langs? - const exampleProgram = grammarCode.getNode("grammar example") + const exampleProgram = parsersCode.getNode("parsers example") if (exampleProgram) { const testProgram = new rootClass(exampleProgram.childrenToString()) // todo: should we then execute it? compile it? @@ -78,7 +78,7 @@ testTree.compileAll = equal => { testTree.jibberish = equal => { // Arrange try { - const tempFilePath = GrammarCompiler.compileGrammarForNodeJs(path.join(langsDir, `jibberish/jibberish.grammar`), outputDir, false) + const tempFilePath = ParsersCompiler.compileParsersForNodeJs(path.join(langsDir, `jibberish/jibberish.parsers`), outputDir, false) // Act const jibberish = require(tempFilePath) @@ -99,11 +99,11 @@ testTree.jibberish = equal => { testTree.numbers = equal => { // Arrange - const numbersGrammarPath = path.join(langsDir, `numbers/numbers.grammar`) - const numbersGrammarCode = Disk.read(numbersGrammarPath) - const makeNumbersRunTimeProgram = (code: string) => makeProgram(numbersGrammarCode, code) + const numbersParsersPath = path.join(langsDir, `numbers/numbers.parsers`) + const numbersParsersCode = Disk.read(numbersParsersPath) + const makeNumbersRunTimeProgram = (code: string) => makeProgram(numbersParsersCode, code) try { - const tempFilePath = GrammarCompiler.compileGrammarForNodeJs(numbersGrammarPath, outputDir, false) + const tempFilePath = ParsersCompiler.compileParsersForNodeJs(numbersParsersPath, outputDir, false) // Act const numbers = require(tempFilePath) @@ -136,15 +136,15 @@ testTree.numbers = equal => { } } -testTree.predictGrammarFile = equal => { +testTree.predictParsersFile = equal => { // Arrange - const input = Disk.read(path.join(__dirname, "UnknownGrammar.sample.tree")) + const input = Disk.read(path.join(__dirname, "UnknownParsers.sample.tree")) // Act - const grammarFile = new UnknownGrammarProgram(input).inferGrammarFileForAKeywordLanguage("foobar") + const parsersFile = new UnknownParsersProgram(input).inferParsersFileForAKeywordLanguage("foobar") // Assert - equal(grammarFile, Disk.read(path.join(__dirname, "UnknownGrammar.expected.grammar")), "predicted grammar correct") + equal(parsersFile, Disk.read(path.join(__dirname, "UnknownParsers.expected.parsers")), "predicted parsers correct") } testTree.emojis = equal => { @@ -155,32 +155,32 @@ testTree.emojis = equal => { ๐Ÿ’ฉ` // Act - const grammarFile = new UnknownGrammarProgram(source).inferGrammarFileForAKeywordLanguage("emojiLang") + const parsersFile = new UnknownParsersProgram(source).inferParsersFileForAKeywordLanguage("emojiLang") // Assert - equal(grammarFile, Disk.read(path.join(__dirname, "UnknownGrammar.expectedEmoji.grammar")), "predicted emoji grammar correct") + equal(parsersFile, Disk.read(path.join(__dirname, "UnknownParsers.expectedEmoji.parsers")), "predicted emoji parsers correct") } const langs = Disk.dir(langsDir) langs.forEach((name: string) => { const folder = path.join(langsDir, `${name}`) if (!Disk.isDir(folder)) return - testTree[`${name}InferPrefixGrammar`] = equal => { + testTree[`${name}InferPrefixParsers`] = equal => { // Arrange const samplePath = path.join(langsDir, name, `sample.${name}`) const sampleCode = TreeNode.fromDisk(samplePath).toString() // todo: cleanup - if (Disk.read(path.join(langsDir, name, `${name}.grammar`)).includes("nonPrefixGrammar")) return equal(true, true, `skipped ${name} beause not prefix grammar`) + if (Disk.read(path.join(langsDir, name, `${name}.parsers`)).includes("nonPrefixParsers")) return equal(true, true, `skipped ${name} beause not prefix parsers`) // Act - const inferredPrefixGrammarCode = new UnknownGrammarProgram(sampleCode).inferGrammarFileForAKeywordLanguage("foobar") - const inferredPrefixGrammarProgram = new HandGrammarProgram(inferredPrefixGrammarCode) - const rootParser = inferredPrefixGrammarProgram.compileAndReturnRootParser() - const programParsedWithInferredGrammar = new rootParser(sampleCode) + const inferredPrefixParsersCode = new UnknownParsersProgram(sampleCode).inferParsersFileForAKeywordLanguage("foobar") + const inferredPrefixParsersProgram = new HandParsersProgram(inferredPrefixParsersCode) + const rootParser = inferredPrefixParsersProgram.compileAndReturnRootParser() + const programParsedWithInferredParsers = new rootParser(sampleCode) // Assert - equal(inferredPrefixGrammarProgram.getAllErrors().length, 0, `no errors in inferred grammar program for language ${name}`) - equal(programParsedWithInferredGrammar.getAllErrors().length, 0, `no errors in program from inferred grammar for ${name}`) + equal(inferredPrefixParsersProgram.getAllErrors().length, 0, `no errors in inferred parsers program for language ${name}`) + equal(programParsedWithInferredParsers.getAllErrors().length, 0, `no errors in program from inferred parsers for ${name}`) } }) diff --git a/grammar/GrammarLanguage.test.ts b/parsers/Parsers.test.ts similarity index 79% rename from grammar/GrammarLanguage.test.ts rename to parsers/Parsers.test.ts index 2423dd874..f7184d76c 100755 --- a/grammar/GrammarLanguage.test.ts +++ b/parsers/Parsers.test.ts @@ -6,27 +6,27 @@ import { scrollNotationTypes } from "../products/scrollNotationTypes" const { Disk } = require("../products/Disk.node.js") const { TestRacer } = require("../products/TestRacer.js") -const { HandGrammarProgram } = require("../products/GrammarLanguage.js") +const { HandParsersProgram } = require("../products/Parsers.js") const path = require("path") const jibberishRootDir = path.join(__dirname, "..", "langs", "jibberish") -const numbersPath = path.join(__dirname, "..", "langs", "numbers", "numbers.grammar") -const numbersGrammar = Disk.read(numbersPath) -const arrowPath = path.join(__dirname, "..", "langs", "arrow", "arrow.grammar") -const arrowGrammar = Disk.read(arrowPath) -const hakonPath = path.join(__dirname, "..", "langs", "hakon", "hakon.grammar") -const hakonGrammar = Disk.read(hakonPath) -const grammarGrammarPath = path.join(__dirname, "..", "langs", "grammar", "grammar.grammar") -const grammarGrammar = Disk.read(grammarGrammarPath) -const jibberishGrammarPath = path.join(jibberishRootDir, "jibberish.grammar") -const jibberishGrammarCode = Disk.read(jibberishGrammarPath) -const poopGrammarPath = path.join(__dirname, "..", "langs", "poop", "poop.grammar") +const numbersPath = path.join(__dirname, "..", "langs", "numbers", "numbers.parsers") +const numbersParsers = Disk.read(numbersPath) +const arrowPath = path.join(__dirname, "..", "langs", "arrow", "arrow.parsers") +const arrowParsers = Disk.read(arrowPath) +const hakonPath = path.join(__dirname, "..", "langs", "hakon", "hakon.parsers") +const hakonParsers = Disk.read(hakonPath) +const parsersParsersPath = path.join(__dirname, "..", "langs", "parsers", "parsers.parsers") +const parsersParsers = Disk.read(parsersParsersPath) +const jibberishParsersPath = path.join(jibberishRootDir, "jibberish.parsers") +const jibberishParsersCode = Disk.read(jibberishParsersPath) +const poopParsersPath = path.join(__dirname, "..", "langs", "poop", "poop.parsers") const testTree: scrollNotationTypes.testTree = {} testTree.emptyProgram = equal => { // Arrange/Act/Assert - const program = new HandGrammarProgram() + const program = new HandParsersProgram() const errs = program.getAllErrors() // Assert @@ -34,63 +34,63 @@ testTree.emptyProgram = equal => { equal(errs.length, 0, "should be no errors") } -testTree.grammarLangBasics = equal => { +testTree.parsersLangBasics = equal => { // Arrange/Act - const grammarProgram = new HandGrammarProgram(jibberishGrammarCode) - const errs = grammarProgram.getAllErrors() + const parsersProgram = new HandParsersProgram(jibberishParsersCode) + const errs = parsersProgram.getAllErrors() // Assert if (errs.length) console.log(errs.map((err: any) => err.message)) equal(errs.length, 0, "should be no errors") } -const makeGrammarProgram = (code: string) => makeProgram(grammarGrammar, code) +const makeParsersProgram = (code: string) => makeProgram(parsersParsers, code) const makeJibberishProgram = (code: string) => { - const grammarCode = Disk.read(jibberishGrammarPath) - return makeProgram(grammarCode, code) + const parsersCode = Disk.read(jibberishParsersPath) + return makeProgram(parsersCode, code) } const makePoopProgram = (code: string) => { - const grammarCode = Disk.read(poopGrammarPath) - return makeProgram(grammarCode, code) + const parsersCode = Disk.read(poopParsersPath) + return makeProgram(parsersCode, code) } -const makeIrisProgram = (code: string) => makeProgram(Disk.read(path.normalize(__dirname + "/../langs/iris/iris.grammar")), code) +const makeIrisProgram = (code: string) => makeProgram(Disk.read(path.normalize(__dirname + "/../langs/iris/iris.parsers")), code) -const makeNumbersProgram = (code: string) => makeProgram(numbersGrammar, code) +const makeNumbersProgram = (code: string) => makeProgram(numbersParsers, code) -const makeProgram = (grammarCode: string, code: string) => { - const grammarProgram = new HandGrammarProgram(grammarCode) - const rootParser = grammarProgram.compileAndReturnRootParser() +const makeProgram = (parsersCode: string, code: string) => { + const parsersProgram = new HandParsersProgram(parsersCode) + const rootParser = parsersProgram.compileAndReturnRootParser() return new rootParser(code) } testTree.trainAndPredict = equal => { // Arrange/Act - const grammarProgram = new HandGrammarProgram(hakonGrammar) - const hakonParser = grammarProgram.compileAndReturnRootParser() + const parsersProgram = new HandParsersProgram(hakonParsers) + const hakonParser = parsersProgram.compileAndReturnRootParser() const testBlankProgram = new hakonParser() - const handGrammarProgram = testBlankProgram.handGrammarProgram - const examples = handGrammarProgram.getNodesByGlobPath("* example").map((node: any) => node.childrenToString()) - const model = grammarProgram.trainModel(examples) + const handParsersProgram = testBlankProgram.handParsersProgram + const examples = handParsersProgram.getNodesByGlobPath("* example").map((node: any) => node.childrenToString()) + const model = parsersProgram.trainModel(examples) // Assert - const predictions = handGrammarProgram.predictChildren(model, testBlankProgram) + const predictions = handParsersProgram.predictChildren(model, testBlankProgram) equal(predictions[0].id, "selectorParser") // Act const bodyNode = testBlankProgram.appendLine("body") // Assert - const predictions2 = handGrammarProgram.predictChildren(model, bodyNode) + const predictions2 = handParsersProgram.predictChildren(model, bodyNode) equal(predictions2[0].id, "propertyParser") // Act const fontSizeNode = testBlankProgram.appendLine("font-size") // Assert - const predictions3 = handGrammarProgram.predictParents(model, fontSizeNode) + const predictions3 = handParsersProgram.predictParents(model, fontSizeNode) equal(predictions3[0].id, "selectorParser") } @@ -107,7 +107,7 @@ testTree.jibberish = equal => { equal(errs.length, 0, `should be 0 errors`) if (errs.length) console.log(errs.map((err: any) => err.message)) - const parserDef = program.handGrammarProgram.parserFamilyTree.getNode("abstractTopLevelParser nodeWithConstsParser nodeExpandsConstsParser") + const parserDef = program.handParsersProgram.parserFamilyTree.getNode("abstractTopLevelParser nodeWithConstsParser nodeExpandsConstsParser") equal(parserDef.toString(), "nodeExpandsConstsParser", "family tree works") @@ -120,7 +120,7 @@ testTree.jibberish = equal => { equal(fooNode.parserId, "fooParser") equal(constNode.parserId, "nodeWithConstsParser") equal(constNode.definition.ancestorParserIdsArray.join(" "), "abstractTopLevelParser nodeWithConstsParser") - equal(constNode.definition.greeting, "hello world", "constants are also present on grammar definition nodes") + equal(constNode.definition.greeting, "hello world", "constants are also present on parsers definition nodes") // Assert equal(constNode.greeting, "hello world", "constant strings should work") @@ -177,12 +177,12 @@ langs.forEach((lang: string) => { const folder = path.normalize(`${__dirname}/../langs/${lang}`) if (!Disk.isDir(folder)) return testTree[`${lang}SimTest`] = equal => { - const grammarCode = Disk.read(path.normalize(`${folder}/${lang}.grammar`)) - const grammarProgram = new HandGrammarProgram(grammarCode) - const rootParser = grammarProgram.compileAndReturnRootParser() + const parsersCode = Disk.read(path.normalize(`${folder}/${lang}.parsers`)) + const parsersProgram = new HandParsersProgram(parsersCode) + const rootParser = parsersProgram.compileAndReturnRootParser() // Act - const simulatedProgram = grammarProgram.rootParserDefinition.synthesizeNode().join("\n") + const simulatedProgram = parsersProgram.rootParserDefinition.synthesizeNode().join("\n") // Assert const errors = new rootParser(simulatedProgram).getAllErrors() @@ -219,10 +219,10 @@ testTree.jibberishErrors = equal => { testTree.toTypeScriptInterface = equal => { // Arrange - const grammarProgram = new HandGrammarProgram(arrowGrammar).compileAndReturnRootParser() + const parsersProgram = new HandParsersProgram(arrowParsers).compileAndReturnRootParser() // Act // Assert equal( - new grammarProgram().definition.toTypeScriptInterface(), + new parsersProgram().definition.toTypeScriptInterface(), `// A credit card charge interface chargeParser { amount: any @@ -297,8 +297,8 @@ hueParser extends abstractColorPropertiesParser saturationParser extends abstractColorPropertiesParser` - const grammarProgram = makeGrammarProgram(normalCode) - const formatted = grammarProgram.format().toString() + const parsersProgram = makeParsersProgram(normalCode) + const formatted = parsersProgram.format().toString() equal(formatted, normalCode, "code is already in formatted form") } @@ -325,7 +325,7 @@ h1Parser crux html.h1 extends abstractHtmlParser` // Act/Assert - equal(makeGrammarProgram(unsortedCode).format().toString(), sortedCode, "code was fixed") + equal(makeParsersProgram(unsortedCode).format().toString(), sortedCode, "code was fixed") } testTree.cokeRegression = equal => { @@ -415,7 +415,7 @@ com testTree.extraWord = equal => { // Arrange - const program = makeGrammarProgram(`foobarParser + const program = makeParsersProgram(`foobarParser root foo2`) // Act/Assert @@ -429,7 +429,7 @@ testTree.extraWord = equal => { testTree.autocompleteAdditionalWords = equal => { // Arrange - const program = makeGrammarProgram(`fooCell + const program = makeParsersProgram(`fooCell highlightScope comme`) // Act/Assert @@ -438,7 +438,7 @@ testTree.autocompleteAdditionalWords = equal => { testTree.autocompleteAdvanced = equal => { // Arrange - const program = makeGrammarProgram(`latinParser + const program = makeParsersProgram(`latinParser root catchAllParser anyParser inScope faveNumberParser @@ -491,8 +491,8 @@ testTree.blobParsers = equal => { testTree.sublimeSyntaxFile = equal => { // Arrange/Act - const grammarProgram = new HandGrammarProgram(jibberishGrammarCode) - const code = grammarProgram.toSublimeSyntaxFile() + const parsersProgram = new HandParsersProgram(jibberishParsersCode) + const code = parsersProgram.toSublimeSyntaxFile() // Assert equal(code.includes("scope:"), true) @@ -500,8 +500,8 @@ testTree.sublimeSyntaxFile = equal => { testTree.toStumpString = equal => { // Arrange/Act - const grammarProgram = new HandGrammarProgram(arrowGrammar).compileAndReturnRootParser() - const code = new grammarProgram().definition.getParserDefinitionByParserId("chargeParser").toStumpString() + const parsersProgram = new HandParsersProgram(arrowParsers).compileAndReturnRootParser() + const code = new parsersProgram().definition.getParserDefinitionByParserId("chargeParser").toStumpString() const expected = `div label amount input @@ -535,7 +535,7 @@ div // todo: reenable once we have the requirement of at least 1 root node // testTree.requiredParsers = equal => { // // Arrange/Act -// const path = grammarGrammarPath +// const path = parsersParsersPath // const anyProgram = makeProgram( // readFileSync(path, "utf8"), // `cellType word @@ -548,9 +548,9 @@ div // equal(errs.length, 1) // } -testTree.minimumGrammar = equal => { +testTree.minimumParsers = equal => { // Arrange/Act - const rootParser = new HandGrammarProgram( + const rootParser = new HandParsersProgram( `anyLangParser root catchAllParser anyParser @@ -559,23 +559,23 @@ anyParser anyCell` ).compileAndReturnRootParser() const program = new rootParser() - const handGrammarProgram = program.handGrammarProgram + const handParsersProgram = program.handParsersProgram // Assert - let errors = handGrammarProgram.getAllErrors() + let errors = handParsersProgram.getAllErrors() equal(errors.length, 0) errors = program.getAllErrors() equal(errors.length, 0) // Arrange/Act/Assert - const constructor = new HandGrammarProgram().compileAndReturnRootParser() + const constructor = new HandParsersProgram().compileAndReturnRootParser() const errs = new constructor("foobar").getAllErrors() equal(errs.length, 0) } testTree.rootCatchAllParser = equal => { // Arrange - const abcLang = new HandGrammarProgram(`abcParser + const abcLang = new HandParsersProgram(`abcParser root`).compileAndReturnRootParser() // Act/Assert @@ -584,7 +584,7 @@ testTree.rootCatchAllParser = equal => { equal(program.toCellTypeTree(), "extraWordCell", "one word") // Arrange - const abcLangWithErrors = new HandGrammarProgram(`abcParser + const abcLangWithErrors = new HandParsersProgram(`abcParser root catchAllParser errorParser errorParser @@ -596,16 +596,16 @@ errorParser testTree.blankParserId = equal => { // Arrange - const abcLang = new HandGrammarProgram(`parser `).compileAndReturnRootParser() + const abcLang = new HandParsersProgram(`parser `).compileAndReturnRootParser() // Act/Assert equal(new abcLang("foobar").getAllErrors().length, 0) } -testTree.grammarWithLoop = equal => { +testTree.parsersWithLoop = equal => { // Arrange/Act/Assert try { - const rootParser = new HandGrammarProgram( + const rootParser = new HandParsersProgram( `langWithLoopParser root catchAllParser nodeAParser @@ -622,7 +622,7 @@ anyCell` new rootParser("nodeA") equal(false, true, "Should have thrown error") } catch (err) { - equal(err.toString().includes("Loop"), true, `Expected correct error thrown when grammar. Got: ${err.toString()}`) + equal(err.toString().includes("Loop"), true, `Expected correct error thrown when parsers. Got: ${err.toString()}`) } } @@ -646,7 +646,7 @@ extendsAbstract 2`) testTree.updateParserIds = equal => { // Arrange/Act - const anyProgram = makeGrammarProgram(`someLangParser + const anyProgram = makeParsersProgram(`someLangParser root foobarCell regex test`) @@ -666,16 +666,16 @@ foobarCell testTree.toNodeJsJavascript = equal => { // Arrange - let program = new HandGrammarProgram(grammarGrammar) + let program = new HandParsersProgram(parsersParsers) // Act let compiledParser = program.toNodeJsJavascript() // Assert equal(typeof compiledParser, "string") } -testTree.invalidGrammarRegression = equal => { +testTree.invalidParsersRegression = equal => { // Arrange - let program = new HandGrammarProgram(`oldStyle something + let program = new HandParsersProgram(`oldStyle something root`) // Act let compiledParser = program.toNodeJsJavascript() @@ -685,20 +685,20 @@ testTree.invalidGrammarRegression = equal => { testTree.bundler = equal => { // Arrange - const jibberishGrammarProgram = new HandGrammarProgram(jibberishGrammarCode) + const jibberishParsersProgram = new HandParsersProgram(jibberishParsersCode) // Act - const bundle = jibberishGrammarProgram.toBundle() + const bundle = jibberishParsersProgram.toBundle() // Assert equal(bundle["readme.md"].includes("Installing"), true) } -const jibberishGrammarProgram = new HandGrammarProgram(jibberishGrammarCode) -Object.assign(testTree, jibberishGrammarProgram.examplesToTestBlocks()) +const jibberishParsersProgram = new HandParsersProgram(jibberishParsersCode) +Object.assign(testTree, jibberishParsersProgram.examplesToTestBlocks()) // Arrange/Act -const badGrammarProgram = new HandGrammarProgram( +const badParsersProgram = new HandParsersProgram( `badParser root inScope addParser @@ -711,7 +711,7 @@ addParser keywordCell intCell` ) -Object.assign(testTree, badGrammarProgram.examplesToTestBlocks(undefined, `InvalidWord at line 9 cell 2. "B" does not fit in cellType "intCell".`)) +Object.assign(testTree, badParsersProgram.examplesToTestBlocks(undefined, `InvalidWord at line 9 cell 2. "B" does not fit in cellType "intCell".`)) /*NODE_JS_ONLY*/ if (!module.parent) TestRacer.testSingleFile(__filename, testTree) diff --git a/grammar/GrammarLanguage.ts b/parsers/Parsers.ts similarity index 81% rename from grammar/GrammarLanguage.ts rename to parsers/Parsers.ts index 65f0b0804..bcedb35f0 100644 --- a/grammar/GrammarLanguage.ts +++ b/parsers/Parsers.ts @@ -4,7 +4,7 @@ const { TreeNode, TreeWord, ExtendibleTreeNode, AbstractExtendibleTreeNode } = r import { scrollNotationTypes } from "../products/scrollNotationTypes" interface AbstractRuntimeProgramConstructorInterface { - new (code?: string): GrammarBackedNode + new (code?: string): ParserBackedNode } declare type parserInfo = { firstWordMap: { [firstWord: string]: parserDefinitionParser }; regexTests: scrollNotationTypes.regexTestDef[] } @@ -13,8 +13,8 @@ declare type parserInfo = { firstWordMap: { [firstWord: string]: parserDefinitio const GlobalNamespaceAdditions: scrollNotationTypes.stringMap = { Utils: "Utils.js", TreeNode: "TreeNode.js", - HandGrammarProgram: "GrammarLanguage.js", - GrammarBackedNode: "GrammarLanguage.js" + HandParsersProgram: "Parsers.js", + ParserBackedNode: "Parsers.js" } interface SimplePredictionModel { @@ -23,7 +23,7 @@ interface SimplePredictionModel { indexToId: { [index: number]: string } } -enum GrammarConstantsCompiler { +enum ParsersConstantsCompiler { stringTemplate = "stringTemplate", // replacement instructions indentCharacter = "indentCharacter", catchAllCellDelimiter = "catchAllCellDelimiter", @@ -32,7 +32,7 @@ enum GrammarConstantsCompiler { closeChildren = "closeChildren" } -enum GrammarConstantsMisc { +enum ParsersConstantsMisc { doNotSynthesize = "doNotSynthesize" } @@ -47,14 +47,14 @@ enum PreludeCellTypeIds { intCell = "intCell" } -enum GrammarConstantsConstantTypes { +enum ParsersConstantsConstantTypes { boolean = "boolean", string = "string", int = "int", float = "float" } -enum GrammarBundleFiles { +enum ParsersBundleFiles { package = "package.json", readme = "readme.md", indexHtml = "index.html", @@ -62,13 +62,13 @@ enum GrammarBundleFiles { testJs = "test.js" } -enum GrammarCellParser { +enum ParsersCellParser { prefix = "prefix", postfix = "postfix", omnifix = "omnifix" } -enum GrammarConstants { +enum ParsersConstants { // node types extensions = "extensions", comment = "//", @@ -76,7 +76,7 @@ enum GrammarConstants { parser = "parser", cellType = "cellType", - grammarFileExtension = "grammar", + parsersFileExtension = "parsers", abstractParserPrefix = "abstract", parserSuffix = "Parser", @@ -154,16 +154,16 @@ class TypedWord extends TreeWord { } // todo: can we merge these methods into base TreeNode and ditch this class? -abstract class GrammarBackedNode extends TreeNode { - private _definition: AbstractParserDefinitionParser | HandGrammarProgram | parserDefinitionParser - get definition(): AbstractParserDefinitionParser | HandGrammarProgram | parserDefinitionParser { +abstract class ParserBackedNode extends TreeNode { + private _definition: AbstractParserDefinitionParser | HandParsersProgram | parserDefinitionParser + get definition(): AbstractParserDefinitionParser | HandParsersProgram | parserDefinitionParser { if (this._definition) return this._definition - this._definition = this.isRoot() ? this.handGrammarProgram : this.parent.definition.getParserDefinitionByParserId(this.constructor.name) + this._definition = this.isRoot() ? this.handParsersProgram : this.parent.definition.getParserDefinitionByParserId(this.constructor.name) return this._definition } - get rootGrammarTree() { + get rootParsersTree() { return this.definition.root } @@ -172,7 +172,7 @@ abstract class GrammarBackedNode extends TreeNode { } private _nodeIndex: { - [parserId: string]: GrammarBackedNode[] + [parserId: string]: ParserBackedNode[] } protected get nodeIndex() { @@ -194,7 +194,7 @@ abstract class GrammarBackedNode extends TreeNode { protected _makeNodeIndex(startAt = 0) { if (!this._nodeIndex || !startAt) this._nodeIndex = {} - const nodes = this._getChildrenArray() as GrammarBackedNode[] + const nodes = this._getChildrenArray() as ParserBackedNode[] const newIndex = this._nodeIndex const length = nodes.length @@ -209,7 +209,7 @@ abstract class GrammarBackedNode extends TreeNode { return newIndex } - getChildInstancesOfParserId(parserId: scrollNotationTypes.parserId): GrammarBackedNode[] { + getChildInstancesOfParserId(parserId: scrollNotationTypes.parserId): ParserBackedNode[] { return this.nodeIndex[parserId] || [] } @@ -250,14 +250,14 @@ abstract class GrammarBackedNode extends TreeNode { return cell ? cell.getAutoCompleteWords(partialWord) : [] } - // note: this is overwritten by the root node of a runtime grammar program. + // note: this is overwritten by the root node of a runtime parsers program. // some of the magic that makes this all work. but maybe there's a better way. - get handGrammarProgram(): HandGrammarProgram { - if (this.isRoot()) throw new Error(`Root node without getHandGrammarProgram defined.`) - return (this.root).handGrammarProgram + get handParsersProgram(): HandParsersProgram { + if (this.isRoot()) throw new Error(`Root node without getHandParsersProgram defined.`) + return (this.root).handParsersProgram } - getRunTimeEnumOptions(cell: AbstractGrammarBackedCell): string[] { + getRunTimeEnumOptions(cell: AbstractParsersBackedCell): string[] { return undefined } @@ -266,7 +266,7 @@ abstract class GrammarBackedNode extends TreeNode { if (!parserOrder.length) return this const orderMap: scrollNotationTypes.stringMap = {} parserOrder.forEach((word, index) => (orderMap[word] = index)) - this.sort(Utils.makeSortByFn((runtimeNode: GrammarBackedNode) => orderMap[runtimeNode.definition.parserIdFromDefinition])) + this.sort(Utils.makeSortByFn((runtimeNode: ParserBackedNode) => orderMap[runtimeNode.definition.parserIdFromDefinition])) return this } @@ -280,7 +280,7 @@ abstract class GrammarBackedNode extends TreeNode { get programAsCells() { // todo: what is this? - return this.topDownArray.map((node: GrammarBackedNode) => { + return this.topDownArray.map((node: ParserBackedNode) => { const cells = node.parsedCells let indents = node.getIndentLevel() - 1 while (indents) { @@ -297,7 +297,7 @@ abstract class GrammarBackedNode extends TreeNode { get allTypedWords() { const words: TypedWord[] = [] - this.topDownArray.forEach((node: GrammarBackedNode) => node.wordTypes.forEach((cell, index) => words.push(new TypedWord(node, index, cell.cellTypeId)))) + this.topDownArray.forEach((node: ParserBackedNode) => node.wordTypes.forEach((cell, index) => words.push(new TypedWord(node, index, cell.cellTypeId)))) return words } @@ -306,7 +306,7 @@ abstract class GrammarBackedNode extends TreeNode { } findAllNodesWithParser(parserId: scrollNotationTypes.parserId) { - return this.topDownArray.filter((node: GrammarBackedNode) => node.definition.parserIdFromDefinition === parserId) + return this.topDownArray.filter((node: ParserBackedNode) => node.definition.parserIdFromDefinition === parserId) } toCellTypeTree() { @@ -333,7 +333,7 @@ abstract class GrammarBackedNode extends TreeNode { ).toFormattedTable(maxColumnWidth) } - // Helper method for selecting potential parsers needed to update grammar file. + // Helper method for selecting potential parsers needed to update parsers file. get invalidParsers() { return Array.from( new Set( @@ -380,7 +380,7 @@ abstract class GrammarBackedNode extends TreeNode { getAutocompleteResultsAt(lineIndex: scrollNotationTypes.positiveInt, charIndex: scrollNotationTypes.positiveInt) { const lineNode = this.nodeAtLine(lineIndex) || this - const nodeInScope = lineNode.getNodeInScopeAtCharIndex(charIndex) + const nodeInScope = lineNode.getNodeInScopeAtCharIndex(charIndex) // todo: add more tests // todo: second param this.childrenToString() @@ -397,7 +397,7 @@ abstract class GrammarBackedNode extends TreeNode { } private _sortWithParentParsersUpTop() { - const familyTree = new HandGrammarProgram(this.toString()).parserFamilyTree + const familyTree = new HandParsersProgram(this.toString()).parserFamilyTree const rank: scrollNotationTypes.stringMap = {} familyTree.topDownArray.forEach((node, index) => { rank[node.getWord(0)] = index @@ -468,12 +468,12 @@ abstract class GrammarBackedNode extends TreeNode { getParserUsage(filepath = "") { // returns a report on what parsers from its language the program uses const usage = new TreeNode() - const handGrammarProgram = this.handGrammarProgram - handGrammarProgram.validConcreteAndAbstractParserDefinitions.forEach((def: AbstractParserDefinitionParser) => { + const handParsersProgram = this.handParsersProgram + handParsersProgram.validConcreteAndAbstractParserDefinitions.forEach((def: AbstractParserDefinitionParser) => { const requiredCellTypeIds = def.cellParser.getRequiredCellTypeIds() usage.appendLine([def.parserIdFromDefinition, "line-id", "parser", requiredCellTypeIds.join(" ")].join(" ")) }) - this.topDownArray.forEach((node: GrammarBackedNode, lineNumber: number) => { + this.topDownArray.forEach((node: ParserBackedNode, lineNumber: number) => { const stats = usage.getNode(node.parserId) stats.appendLine([filepath + "-" + lineNumber, node.words.join(" ")].join(" ")) }) @@ -481,23 +481,23 @@ abstract class GrammarBackedNode extends TreeNode { } toHighlightScopeTree() { - return this.topDownArray.map((child: GrammarBackedNode) => child.indentation + child.getLineHighlightScopes()).join("\n") + return this.topDownArray.map((child: ParserBackedNode) => child.indentation + child.getLineHighlightScopes()).join("\n") } toDefinitionLineNumberTree() { - return this.topDownArray.map((child: GrammarBackedNode) => child.definition.lineNumber + " " + child.indentation + child.cellDefinitionLineNumbers.join(" ")).join("\n") + return this.topDownArray.map((child: ParserBackedNode) => child.definition.lineNumber + " " + child.indentation + child.cellDefinitionLineNumbers.join(" ")).join("\n") } get asCellTypeTreeWithParserIds() { - return this.topDownArray.map((child: GrammarBackedNode) => child.constructor.name + this.wordBreakSymbol + child.indentation + child.lineCellTypes).join("\n") + return this.topDownArray.map((child: ParserBackedNode) => child.constructor.name + this.wordBreakSymbol + child.indentation + child.lineCellTypes).join("\n") } toPreludeCellTypeTreeWithParserIds() { - return this.topDownArray.map((child: GrammarBackedNode) => child.constructor.name + this.wordBreakSymbol + child.indentation + child.getLineCellPreludeTypes()).join("\n") + return this.topDownArray.map((child: ParserBackedNode) => child.constructor.name + this.wordBreakSymbol + child.indentation + child.getLineCellPreludeTypes()).join("\n") } get asTreeWithParsers() { - return this.topDownArray.map((child: GrammarBackedNode) => child.constructor.name + this.wordBreakSymbol + child.indentation + child.getLine()).join("\n") + return this.topDownArray.map((child: ParserBackedNode) => child.constructor.name + this.wordBreakSymbol + child.indentation + child.getLine()).join("\n") } getCellHighlightScopeAtPosition(lineIndex: number, wordIndex: number): scrollNotationTypes.highlightScope | undefined { @@ -537,26 +537,26 @@ abstract class GrammarBackedNode extends TreeNode { private get singleParserUsedTwiceErrors() { const errors: scrollNotationTypes.TreeError[] = [] - const parent = this.parent as GrammarBackedNode + const parent = this.parent as ParserBackedNode const hits = parent.getChildInstancesOfParserId(this.definition.id) if (hits.length > 1) hits.forEach((node, index) => { - if (node === this) errors.push(new ParserUsedMultipleTimesError(node)) + if (node === this) errors.push(new ParserUsedMultipleTimesError(node)) }) return errors } private get uniqueLineAppearsTwiceErrors() { const errors: scrollNotationTypes.TreeError[] = [] - const parent = this.parent as GrammarBackedNode + const parent = this.parent as ParserBackedNode const hits = parent.getChildInstancesOfParserId(this.definition.id) if (hits.length > 1) { const set = new Set() hits.forEach((node, index) => { const line = node.getLine() - if (set.has(line)) errors.push(new ParserUsedMultipleTimesError(node)) + if (set.has(line)) errors.push(new ParserUsedMultipleTimesError(node)) set.add(line) }) } @@ -578,7 +578,7 @@ abstract class GrammarBackedNode extends TreeNode { return this.cellErrors.concat(this.scopeErrors) } - get parsedCells(): AbstractGrammarBackedCell[] { + get parsedCells(): AbstractParsersBackedCell[] { return this.definition.cellParser.getCellArray(this) } @@ -606,7 +606,7 @@ abstract class GrammarBackedNode extends TreeNode { } protected _getCompiledIndentation() { - const indentCharacter = this.definition._getCompilerObject()[GrammarConstantsCompiler.indentCharacter] + const indentCharacter = this.definition._getCompilerObject()[ParsersConstantsCompiler.indentCharacter] const indent = this.indentation return indentCharacter !== undefined ? indentCharacter.repeat(indent.length) : indent } @@ -623,21 +623,21 @@ abstract class GrammarBackedNode extends TreeNode { protected _getCompiledLine() { const compiler = this.definition._getCompilerObject() - const catchAllCellDelimiter = compiler[GrammarConstantsCompiler.catchAllCellDelimiter] - const str = compiler[GrammarConstantsCompiler.stringTemplate] + const catchAllCellDelimiter = compiler[ParsersConstantsCompiler.catchAllCellDelimiter] + const str = compiler[ParsersConstantsCompiler.stringTemplate] return str !== undefined ? Utils.formatStr(str, catchAllCellDelimiter, Object.assign(this._getFields(), this.cells)) : this.getLine() } protected get listDelimiter() { - return this.definition._getFromExtended(GrammarConstants.listDelimiter) + return this.definition._getFromExtended(ParsersConstants.listDelimiter) } protected get contentKey() { - return this.definition._getFromExtended(GrammarConstants.contentKey) + return this.definition._getFromExtended(ParsersConstants.contentKey) } protected get childrenKey() { - return this.definition._getFromExtended(GrammarConstants.childrenKey) + return this.definition._getFromExtended(ParsersConstants.childrenKey) } protected get childrenAreTextBlob() { @@ -645,7 +645,7 @@ abstract class GrammarBackedNode extends TreeNode { } protected get isArrayElement() { - return this.definition._hasFromExtended(GrammarConstants.uniqueFirstWord) ? false : !this.definition.isSingle + return this.definition._hasFromExtended(ParsersConstants.uniqueFirstWord) ? false : !this.definition.isSingle } get list() { @@ -702,7 +702,7 @@ abstract class GrammarBackedNode extends TreeNode { get typedMap() { const obj: scrollNotationTypes.stringMap = {} - this.forEach((node: GrammarBackedNode) => { + this.forEach((node: ParserBackedNode) => { if (!node._shouldSerialize) return true const tuple = node.typedTuple @@ -726,9 +726,9 @@ abstract class GrammarBackedNode extends TreeNode { if (def.isTerminalParser()) return indent + compiledLine const compiler = def._getCompilerObject() - const openChildrenString = compiler[GrammarConstantsCompiler.openChildren] || "" - const closeChildrenString = compiler[GrammarConstantsCompiler.closeChildren] || "" - const childJoinCharacter = compiler[GrammarConstantsCompiler.joinChildrenWith] || "\n" + const openChildrenString = compiler[ParsersConstantsCompiler.openChildren] || "" + const closeChildrenString = compiler[ParsersConstantsCompiler.closeChildren] || "" + const childJoinCharacter = compiler[ParsersConstantsCompiler.joinChildrenWith] || "\n" const compiledChildren = this.map(child => child.compile()).join(childJoinCharacter) @@ -752,7 +752,7 @@ ${indent}${closeChildrenString}` } } -class BlobParser extends GrammarBackedNode { +class BlobParser extends ParserBackedNode { createParserCombinator() { return new TreeNode.ParserCombinator(BlobParser, {}) } @@ -763,7 +763,7 @@ class BlobParser extends GrammarBackedNode { } // todo: can we remove this? hard to extend. -class UnknownParserNode extends GrammarBackedNode { +class UnknownParserNode extends ParserBackedNode { createParserCombinator() { return new TreeNode.ParserCombinator(UnknownParserNode, {}) } @@ -776,8 +776,8 @@ class UnknownParserNode extends GrammarBackedNode { /* A cell contains a word but also the type information for that word. */ -abstract class AbstractGrammarBackedCell { - constructor(node: GrammarBackedNode, index: scrollNotationTypes.int, typeDef: cellTypeDefinitionParser, cellTypeId: string, isCatchAll: boolean, parserDefinitionParser: AbstractParserDefinitionParser) { +abstract class AbstractParsersBackedCell { + constructor(node: ParserBackedNode, index: scrollNotationTypes.int, typeDef: cellTypeDefinitionParser, cellTypeId: string, isCatchAll: boolean, parserDefinitionParser: AbstractParserDefinitionParser) { this._typeDef = typeDef this._node = node this._isCatchAll = isCatchAll @@ -794,7 +794,7 @@ abstract class AbstractGrammarBackedCell { return this._typeDef.lineNumber } - private _node: GrammarBackedNode + private _node: ParserBackedNode protected _index: scrollNotationTypes.int private _typeDef: cellTypeDefinitionParser private _isCatchAll: boolean @@ -820,15 +820,15 @@ abstract class AbstractGrammarBackedCell { } get min() { - return this.cellTypeDefinition.get(GrammarConstants.min) || "0" + return this.cellTypeDefinition.get(ParsersConstants.min) || "0" } get max() { - return this.cellTypeDefinition.get(GrammarConstants.max) || "100" + return this.cellTypeDefinition.get(ParsersConstants.max) || "100" } get placeholder() { - return this.cellTypeDefinition.get(GrammarConstants.examples) || "" + return this.cellTypeDefinition.get(ParsersConstants.examples) || "" } abstract get parsed(): T @@ -840,7 +840,7 @@ abstract class AbstractGrammarBackedCell { getAutoCompleteWords(partialWord: string = "") { const cellDef = this.cellTypeDefinition - let words = cellDef ? cellDef._getAutocompleteWordOptions(this.getNode().root) : [] + let words = cellDef ? cellDef._getAutocompleteWordOptions(this.getNode().root) : [] const runTimeOptions = this.getNode().getRunTimeEnumOptions(this) if (runTimeOptions) words = runTimeOptions.concat(words) @@ -857,7 +857,7 @@ abstract class AbstractGrammarBackedCell { synthesizeCell(seed = Date.now()): string { // todo: cleanup const cellDef = this.cellTypeDefinition - const enumOptions = cellDef._getFromExtended(GrammarConstants.enum) + const enumOptions = cellDef._getFromExtended(ParsersConstants.enum) if (enumOptions) return Utils.getRandomString(1, enumOptions.split(" ")) return this._synthesizeCell(seed) @@ -865,7 +865,7 @@ abstract class AbstractGrammarBackedCell { _getStumpEnumInput(crux: string): string { const cellDef = this.cellTypeDefinition - const enumOptions = cellDef._getFromExtended(GrammarConstants.enum) + const enumOptions = cellDef._getFromExtended(ParsersConstants.enum) if (!enumOptions) return undefined const options = new TreeNode( enumOptions @@ -904,7 +904,7 @@ ${options.toString(1)}` const runTimeOptions = this.getNode().getRunTimeEnumOptions(this) const word = this.getWord() if (runTimeOptions) return runTimeOptions.includes(word) - return this.cellTypeDefinition.isValid(word, this.getNode().root) && this._isValid() + return this.cellTypeDefinition.isValid(word, this.getNode().root) && this._isValid() } getErrorIfAny(): scrollNotationTypes.TreeError { @@ -916,7 +916,7 @@ ${options.toString(1)}` } } -class GrammarBitCell extends AbstractGrammarBackedCell { +class ParsersBitCell extends AbstractParsersBackedCell { _isValid() { const word = this.getWord() return word === "0" || word === "1" @@ -938,7 +938,7 @@ class GrammarBitCell extends AbstractGrammarBackedCell { } } -abstract class GrammarNumericCell extends AbstractGrammarBackedCell { +abstract class ParsersNumericCell extends AbstractParsersBackedCell { _toStumpInput(crux: string): string { return `input name ${crux} @@ -949,7 +949,7 @@ abstract class GrammarNumericCell extends AbstractGrammarBackedCell { } } -class GrammarIntCell extends GrammarNumericCell { +class ParsersIntCell extends ParsersNumericCell { _isValid() { const word = this.getWord() const num = parseInt(word) @@ -975,7 +975,7 @@ class GrammarIntCell extends GrammarNumericCell { static parserFunctionName = "parseInt" } -class GrammarFloatCell extends GrammarNumericCell { +class ParsersFloatCell extends ParsersNumericCell { _isValid() { const word = this.getWord() const num = parseFloat(word) @@ -1000,9 +1000,9 @@ class GrammarFloatCell extends GrammarNumericCell { static parserFunctionName = "parseFloat" } -// ErrorCellType => grammar asks for a '' cell type here but the grammar does not specify a '' cell type. (todo: bring in didyoumean?) +// ErrorCellType => parsers asks for a '' cell type here but the parsers does not specify a '' cell type. (todo: bring in didyoumean?) -class GrammarBoolCell extends AbstractGrammarBackedCell { +class ParsersBoolCell extends AbstractParsersBackedCell { private _trues = new Set(["1", "true", "t", "yes"]) private _falses = new Set(["0", "false", "f", "no"]) @@ -1032,13 +1032,13 @@ class GrammarBoolCell extends AbstractGrammarBackedCell { } } -class GrammarAnyCell extends AbstractGrammarBackedCell { +class ParsersAnyCell extends AbstractParsersBackedCell { _isValid() { return true } _synthesizeCell() { - const examples = this.cellTypeDefinition._getFromExtended(GrammarConstants.examples) + const examples = this.cellTypeDefinition._getFromExtended(ParsersConstants.examples) if (examples) return Utils.getRandomString(1, examples.split(" ")) return this._parserDefinitionParser.parserIdFromDefinition + "-" + this.constructor.name } @@ -1052,7 +1052,7 @@ class GrammarAnyCell extends AbstractGrammarBackedCell { } } -class GrammarKeywordCell extends GrammarAnyCell { +class ParsersKeywordCell extends ParsersAnyCell { static defaultHighlightScope = "keyword" _synthesizeCell() { @@ -1060,13 +1060,13 @@ class GrammarKeywordCell extends GrammarAnyCell { } } -class GrammarExtraWordCellTypeCell extends AbstractGrammarBackedCell { +class ParsersExtraWordCellTypeCell extends AbstractParsersBackedCell { _isValid() { return false } synthesizeCell() { - throw new Error(`Trying to synthesize a GrammarExtraWordCellTypeCell`) + throw new Error(`Trying to synthesize a ParsersExtraWordCellTypeCell`) return this._synthesizeCell() } @@ -1083,13 +1083,13 @@ class GrammarExtraWordCellTypeCell extends AbstractGrammarBackedCell { } } -class GrammarUnknownCellTypeCell extends AbstractGrammarBackedCell { +class ParsersUnknownCellTypeCell extends AbstractParsersBackedCell { _isValid() { return false } synthesizeCell() { - throw new Error(`Trying to synthesize an GrammarUnknownCellTypeCell`) + throw new Error(`Trying to synthesize an ParsersUnknownCellTypeCell`) return this._synthesizeCell() } @@ -1107,10 +1107,10 @@ class GrammarUnknownCellTypeCell extends AbstractGrammarBackedCell { } abstract class AbstractTreeError implements scrollNotationTypes.TreeError { - constructor(node: GrammarBackedNode) { + constructor(node: ParserBackedNode) { this._node = node } - private _node: GrammarBackedNode // todo: would it ever be a TreeNode? + private _node: ParserBackedNode // todo: would it ever be a TreeNode? getLineIndex(): scrollNotationTypes.positiveInt { return this.lineNumber - 1 @@ -1150,12 +1150,12 @@ abstract class AbstractTreeError implements scrollNotationTypes.TreeError { } get parserId(): string { - return (this.getNode()).definition.parserIdFromDefinition + return (this.getNode()).definition.parserIdFromDefinition } private _getCodeMirrorLineWidgetElementCellTypeHints() { const el = document.createElement("div") - el.appendChild(document.createTextNode(this.getIndent() + (this.getNode()).definition.lineHints)) + el.appendChild(document.createTextNode(this.getIndent() + (this.getNode()).definition.lineHints)) el.className = "LintCellTypeHints" return el } @@ -1183,7 +1183,7 @@ abstract class AbstractTreeError implements scrollNotationTypes.TreeError { } getExtension() { - return this.getNode().handGrammarProgram.extensionName + return this.getNode().handParsersProgram.extensionName } getNode() { @@ -1229,7 +1229,7 @@ abstract class AbstractTreeError implements scrollNotationTypes.TreeError { } abstract class AbstractCellError extends AbstractTreeError { - constructor(cell: AbstractGrammarBackedCell) { + constructor(cell: AbstractParsersBackedCell) { super(cell.getNode()) this._cell = cell } @@ -1249,7 +1249,7 @@ abstract class AbstractCellError extends AbstractTreeError { ) } - private _cell: AbstractGrammarBackedCell + private _cell: AbstractParsersBackedCell } class UnknownParserError extends AbstractTreeError { @@ -1265,7 +1265,7 @@ class UnknownParserError extends AbstractTreeError { const parentNode = node.parent return Utils.didYouMean( node.firstWord, - (parentNode).getAutocompleteResults("", 0).map(option => option.text) + (parentNode).getAutocompleteResults("", 0).map(option => option.text) ) } @@ -1306,7 +1306,7 @@ class BlankLineError extends UnknownParserError { } class MissingRequiredParserError extends AbstractTreeError { - constructor(node: GrammarBackedNode, missingParserId: scrollNotationTypes.firstWord) { + constructor(node: ParserBackedNode, missingParserId: scrollNotationTypes.firstWord) { super(node) this._missingParserId = missingParserId } @@ -1348,7 +1348,7 @@ class LineAppearsMultipleTimesError extends AbstractTreeError { class UnknownCellTypeError extends AbstractCellError { get message(): string { - return super.message + ` No cellType "${this.cell.cellTypeId}" found. Language grammar for "${this.getExtension()}" may need to be fixed.` + return super.message + ` No cellType "${this.cell.cellTypeId}" found. Language parsers for "${this.getExtension()}" may need to be fixed.` } } @@ -1400,11 +1400,11 @@ class MissingWordError extends AbstractCellError { // todo: add standard types, enum types, from disk types -abstract class AbstractGrammarWordTestParser extends TreeNode { - abstract isValid(str: string, programRootNode?: GrammarBackedNode): boolean +abstract class AbstractParsersWordTestParser extends TreeNode { + abstract isValid(str: string, programRootNode?: ParserBackedNode): boolean } -class GrammarRegexTestParser extends AbstractGrammarWordTestParser { +class ParsersRegexTestParser extends AbstractParsersWordTestParser { private _regex: RegExp isValid(str: string) { @@ -1413,7 +1413,7 @@ class GrammarRegexTestParser extends AbstractGrammarWordTestParser { } } -class GrammarReservedWordsTestParser extends AbstractGrammarWordTestParser { +class ParsersReservedWordsTestParser extends AbstractParsersWordTestParser { private _set: Set isValid(str: string) { @@ -1423,8 +1423,8 @@ class GrammarReservedWordsTestParser extends AbstractGrammarWordTestParser { } // todo: remove in favor of custom word type constructors -class EnumFromCellTypesTestParser extends AbstractGrammarWordTestParser { - _getEnumFromCellTypes(programRootNode: GrammarBackedNode): scrollNotationTypes.stringMap { +class EnumFromCellTypesTestParser extends AbstractParsersWordTestParser { + _getEnumFromCellTypes(programRootNode: ParserBackedNode): scrollNotationTypes.stringMap { const cellTypeIds = this.getWordsFrom(1) const enumGroup = cellTypeIds.join(" ") // note: hack where we store it on the program. otherwise has global effects. @@ -1445,12 +1445,12 @@ class EnumFromCellTypesTestParser extends AbstractGrammarWordTestParser { } // todo: remove - isValid(str: string, programRootNode: GrammarBackedNode) { + isValid(str: string, programRootNode: ParserBackedNode) { return this._getEnumFromCellTypes(programRootNode)[str] === true } } -class GrammarEnumTestNode extends AbstractGrammarWordTestParser { +class ParsersEnumTestNode extends AbstractParsersWordTestParser { private _map: scrollNotationTypes.stringMap isValid(str: string) { @@ -1467,17 +1467,17 @@ class GrammarEnumTestNode extends AbstractGrammarWordTestParser { class cellTypeDefinitionParser extends AbstractExtendibleTreeNode { createParserCombinator() { const types: scrollNotationTypes.stringMap = {} - types[GrammarConstants.regex] = GrammarRegexTestParser - types[GrammarConstants.reservedWords] = GrammarReservedWordsTestParser - types[GrammarConstants.enumFromCellTypes] = EnumFromCellTypesTestParser - types[GrammarConstants.enum] = GrammarEnumTestNode - types[GrammarConstants.highlightScope] = TreeNode - types[GrammarConstants.comment] = TreeNode - types[GrammarConstants.examples] = TreeNode - types[GrammarConstants.min] = TreeNode - types[GrammarConstants.max] = TreeNode - types[GrammarConstants.description] = TreeNode - types[GrammarConstants.extends] = TreeNode + types[ParsersConstants.regex] = ParsersRegexTestParser + types[ParsersConstants.reservedWords] = ParsersReservedWordsTestParser + types[ParsersConstants.enumFromCellTypes] = EnumFromCellTypesTestParser + types[ParsersConstants.enum] = ParsersEnumTestNode + types[ParsersConstants.highlightScope] = TreeNode + types[ParsersConstants.comment] = TreeNode + types[ParsersConstants.examples] = TreeNode + types[ParsersConstants.min] = TreeNode + types[ParsersConstants.max] = TreeNode + types[ParsersConstants.description] = TreeNode + types[ParsersConstants.extends] = TreeNode return new TreeNode.ParserCombinator(undefined, types) } @@ -1486,7 +1486,7 @@ class cellTypeDefinitionParser extends AbstractExtendibleTreeNode { } get idToNodeMap() { - return (this.parent).cellTypeDefinitions + return (this.parent).cellTypeDefinitions } getGetter(wordIndex: number) { @@ -1506,8 +1506,8 @@ class cellTypeDefinitionParser extends AbstractExtendibleTreeNode { // `this.getWordsFrom(${requireds.length + 1})` // todo: cleanup typings. todo: remove this hidden logic. have a "baseType" property? - getCellConstructor(): typeof AbstractGrammarBackedCell { - return this.preludeKind || GrammarAnyCell + getCellConstructor(): typeof AbstractParsersBackedCell { + return this.preludeKind || ParsersAnyCell } get preludeKind() { @@ -1526,44 +1526,44 @@ class cellTypeDefinitionParser extends AbstractExtendibleTreeNode { } get highlightScope(): string | undefined { - const hs = this._getFromExtended(GrammarConstants.highlightScope) + const hs = this._getFromExtended(ParsersConstants.highlightScope) if (hs) return hs const preludeKind = this.preludeKind if (preludeKind) return preludeKind.defaultHighlightScope } _getEnumOptions() { - const enumNode = this._getNodeFromExtended(GrammarConstants.enum) + const enumNode = this._getNodeFromExtended(ParsersConstants.enum) if (!enumNode) return undefined // we sort by longest first to capture longest match first. todo: add test - const options = Object.keys((enumNode.getNode(GrammarConstants.enum)).getOptions()) + const options = Object.keys((enumNode.getNode(ParsersConstants.enum)).getOptions()) options.sort((a, b) => b.length - a.length) return options } - private _getEnumFromCellTypeOptions(program: GrammarBackedNode) { - const node = this._getNodeFromExtended(GrammarConstants.enumFromCellTypes) - return node ? Object.keys((node.getNode(GrammarConstants.enumFromCellTypes))._getEnumFromCellTypes(program)) : undefined + private _getEnumFromCellTypeOptions(program: ParserBackedNode) { + const node = this._getNodeFromExtended(ParsersConstants.enumFromCellTypes) + return node ? Object.keys((node.getNode(ParsersConstants.enumFromCellTypes))._getEnumFromCellTypes(program)) : undefined } - _getAutocompleteWordOptions(program: GrammarBackedNode): string[] { + _getAutocompleteWordOptions(program: ParserBackedNode): string[] { return this._getEnumOptions() || this._getEnumFromCellTypeOptions(program) || [] } get regexString() { // todo: enum const enumOptions = this._getEnumOptions() - return this._getFromExtended(GrammarConstants.regex) || (enumOptions ? "(?:" + enumOptions.join("|") + ")" : "[^ ]*") + return this._getFromExtended(ParsersConstants.regex) || (enumOptions ? "(?:" + enumOptions.join("|") + ")" : "[^ ]*") } private _getAllTests() { - return this._getChildrenByParserInExtended(AbstractGrammarWordTestParser) + return this._getChildrenByParserInExtended(AbstractParsersWordTestParser) } - isValid(str: string, programRootNode: GrammarBackedNode) { - return this._getAllTests().every(node => (node).isValid(str, programRootNode)) + isValid(str: string, programRootNode: ParserBackedNode) { + return this._getAllTests().every(node => (node).isValid(str, programRootNode)) } get cellTypeId(): scrollNotationTypes.cellTypeId { @@ -1579,7 +1579,7 @@ abstract class AbstractCellParser { } get catchAllCellTypeId(): scrollNotationTypes.cellTypeId | undefined { - return this._definition._getFromExtended(GrammarConstants.catchAllCellType) + return this._definition._getFromExtended(ParsersConstants.catchAllCellType) } // todo: improve layout (use bold?) @@ -1594,7 +1594,7 @@ abstract class AbstractCellParser { private _requiredCellTypeIds: string[] getRequiredCellTypeIds(): scrollNotationTypes.cellTypeId[] { if (!this._requiredCellTypeIds) { - const parameters = this._definition._getFromExtended(GrammarConstants.cells) + const parameters = this._definition._getFromExtended(ParsersConstants.cells) this._requiredCellTypeIds = parameters ? parameters.split(" ") : [] } return this._requiredCellTypeIds @@ -1608,15 +1608,15 @@ abstract class AbstractCellParser { return cellIndex >= numberOfRequiredCells } - getCellArray(node: GrammarBackedNode = undefined): AbstractGrammarBackedCell[] { + getCellArray(node: ParserBackedNode = undefined): AbstractParsersBackedCell[] { const wordCount = node ? node.words.length : 0 const def = this._definition - const grammarProgram = def.languageDefinitionProgram + const parsersProgram = def.languageDefinitionProgram const requiredCellTypeIds = this.getRequiredCellTypeIds() const numberOfRequiredCells = requiredCellTypeIds.length const actualWordCountOrRequiredCellCount = Math.max(wordCount, numberOfRequiredCells) - const cells: AbstractGrammarBackedCell[] = [] + const cells: AbstractParsersBackedCell[] = [] // A for loop instead of map because "numberOfCellsToFill" can be longer than words.length for (let cellIndex = 0; cellIndex < actualWordCountOrRequiredCellCount; cellIndex++) { @@ -1624,15 +1624,15 @@ abstract class AbstractCellParser { let cellTypeId = isCatchAll ? this.catchAllCellTypeId : this._getCellTypeId(cellIndex, requiredCellTypeIds, wordCount) - let cellTypeDefinition = grammarProgram.getCellTypeDefinitionById(cellTypeId) + let cellTypeDefinition = parsersProgram.getCellTypeDefinitionById(cellTypeId) let cellConstructor if (cellTypeDefinition) cellConstructor = cellTypeDefinition.getCellConstructor() - else if (cellTypeId) cellConstructor = GrammarUnknownCellTypeCell + else if (cellTypeId) cellConstructor = ParsersUnknownCellTypeCell else { - cellConstructor = GrammarExtraWordCellTypeCell + cellConstructor = ParsersExtraWordCellTypeCell cellTypeId = PreludeCellTypeIds.extraWordCell - cellTypeDefinition = grammarProgram.getCellTypeDefinitionById(cellTypeId) + cellTypeDefinition = parsersProgram.getCellTypeDefinitionById(cellTypeId) } const anyCellConstructor = cellConstructor @@ -1656,15 +1656,15 @@ class PostfixCellParser extends AbstractCellParser { } class OmnifixCellParser extends AbstractCellParser { - getCellArray(node: GrammarBackedNode = undefined): AbstractGrammarBackedCell[] { - const cells: AbstractGrammarBackedCell[] = [] + getCellArray(node: ParserBackedNode = undefined): AbstractParsersBackedCell[] { + const cells: AbstractParsersBackedCell[] = [] const def = this._definition - const program = (node ? node.root : undefined) - const grammarProgram = def.languageDefinitionProgram + const program = (node ? node.root : undefined) + const parsersProgram = def.languageDefinitionProgram const words = node ? node.words : [] - const requiredCellTypeDefs = this.getRequiredCellTypeIds().map(cellTypeId => grammarProgram.getCellTypeDefinitionById(cellTypeId)) + const requiredCellTypeDefs = this.getRequiredCellTypeIds().map(cellTypeId => parsersProgram.getCellTypeDefinitionById(cellTypeId)) const catchAllCellTypeId = this.catchAllCellTypeId - const catchAllCellTypeDef = catchAllCellTypeId && grammarProgram.getCellTypeDefinitionById(catchAllCellTypeId) + const catchAllCellTypeDef = catchAllCellTypeId && parsersProgram.getCellTypeDefinitionById(catchAllCellTypeId) words.forEach((word, wordIndex) => { let cellConstructor: any @@ -1683,7 +1683,7 @@ class OmnifixCellParser extends AbstractCellParser { cells.push(new cellConstructor(node, wordIndex, catchAllCellTypeDef, catchAllCellTypeId, true, def)) return true } - cells.push(new GrammarUnknownCellTypeCell(node, wordIndex, undefined, undefined, false, def)) + cells.push(new ParsersUnknownCellTypeCell(node, wordIndex, undefined, undefined, false, def)) }) const wordCount = words.length requiredCellTypeDefs.forEach((cellTypeDef, index) => { @@ -1695,17 +1695,17 @@ class OmnifixCellParser extends AbstractCellParser { } } -class GrammarExampleParser extends TreeNode {} +class ParsersExampleParser extends TreeNode {} -class GrammarCompilerParser extends TreeNode { +class ParsersCompilerParser extends TreeNode { createParserCombinator() { const types = [ - GrammarConstantsCompiler.stringTemplate, - GrammarConstantsCompiler.indentCharacter, - GrammarConstantsCompiler.catchAllCellDelimiter, - GrammarConstantsCompiler.joinChildrenWith, - GrammarConstantsCompiler.openChildren, - GrammarConstantsCompiler.closeChildren + ParsersConstantsCompiler.stringTemplate, + ParsersConstantsCompiler.indentCharacter, + ParsersConstantsCompiler.catchAllCellDelimiter, + ParsersConstantsCompiler.joinChildrenWith, + ParsersConstantsCompiler.openChildren, + ParsersConstantsCompiler.closeChildren ] const map: scrollNotationTypes.firstWordToParserMap = {} types.forEach(type => { @@ -1739,8 +1739,8 @@ abstract class AbstractParserConstantParser extends TreeNode { } } -class GrammarParserConstantInt extends AbstractParserConstantParser {} -class GrammarParserConstantString extends AbstractParserConstantParser { +class ParsersParserConstantInt extends AbstractParserConstantParser {} +class ParsersParserConstantString extends AbstractParserConstantParser { get constantValueAsJsText() { return "`" + Utils.escapeBackTicks(this.constantValue) + "`" } @@ -1749,62 +1749,62 @@ class GrammarParserConstantString extends AbstractParserConstantParser { return this.length ? this.childrenToString() : this.getWordsFrom(2).join(" ") } } -class GrammarParserConstantFloat extends AbstractParserConstantParser {} -class GrammarParserConstantBoolean extends AbstractParserConstantParser {} +class ParsersParserConstantFloat extends AbstractParserConstantParser {} +class ParsersParserConstantBoolean extends AbstractParserConstantParser {} abstract class AbstractParserDefinitionParser extends AbstractExtendibleTreeNode { createParserCombinator() { // todo: some of these should just be on nonRootNodes const types = [ - GrammarConstants.frequency, - GrammarConstants.inScope, - GrammarConstants.cells, - GrammarConstants.extends, - GrammarConstants.description, - GrammarConstants.catchAllParser, - GrammarConstants.catchAllCellType, - GrammarConstants.cellParser, - GrammarConstants.extensions, - GrammarConstants.version, - GrammarConstants.sortTemplate, - GrammarConstants.tags, - GrammarConstants.crux, - GrammarConstants.cruxFromId, - GrammarConstants.listDelimiter, - GrammarConstants.contentKey, - GrammarConstants.childrenKey, - GrammarConstants.uniqueFirstWord, - GrammarConstants.uniqueLine, - GrammarConstants.pattern, - GrammarConstants.baseParser, - GrammarConstants.required, - GrammarConstants.root, - GrammarConstants._extendsJsClass, - GrammarConstants._rootNodeJsHeader, - GrammarConstants.javascript, - GrammarConstants.compilesTo, - GrammarConstants.javascript, - GrammarConstants.single, - GrammarConstants.comment + ParsersConstants.frequency, + ParsersConstants.inScope, + ParsersConstants.cells, + ParsersConstants.extends, + ParsersConstants.description, + ParsersConstants.catchAllParser, + ParsersConstants.catchAllCellType, + ParsersConstants.cellParser, + ParsersConstants.extensions, + ParsersConstants.version, + ParsersConstants.sortTemplate, + ParsersConstants.tags, + ParsersConstants.crux, + ParsersConstants.cruxFromId, + ParsersConstants.listDelimiter, + ParsersConstants.contentKey, + ParsersConstants.childrenKey, + ParsersConstants.uniqueFirstWord, + ParsersConstants.uniqueLine, + ParsersConstants.pattern, + ParsersConstants.baseParser, + ParsersConstants.required, + ParsersConstants.root, + ParsersConstants._extendsJsClass, + ParsersConstants._rootNodeJsHeader, + ParsersConstants.javascript, + ParsersConstants.compilesTo, + ParsersConstants.javascript, + ParsersConstants.single, + ParsersConstants.comment ] const map: scrollNotationTypes.firstWordToParserMap = {} types.forEach(type => { map[type] = TreeNode }) - map[GrammarConstantsConstantTypes.boolean] = GrammarParserConstantBoolean - map[GrammarConstantsConstantTypes.int] = GrammarParserConstantInt - map[GrammarConstantsConstantTypes.string] = GrammarParserConstantString - map[GrammarConstantsConstantTypes.float] = GrammarParserConstantFloat - map[GrammarConstants.compilerParser] = GrammarCompilerParser - map[GrammarConstants.example] = GrammarExampleParser - return new TreeNode.ParserCombinator(undefined, map, [{ regex: HandGrammarProgram.parserFullRegex, parser: parserDefinitionParser }]) + map[ParsersConstantsConstantTypes.boolean] = ParsersParserConstantBoolean + map[ParsersConstantsConstantTypes.int] = ParsersParserConstantInt + map[ParsersConstantsConstantTypes.string] = ParsersParserConstantString + map[ParsersConstantsConstantTypes.float] = ParsersParserConstantFloat + map[ParsersConstants.compilerParser] = ParsersCompilerParser + map[ParsersConstants.example] = ParsersExampleParser + return new TreeNode.ParserCombinator(undefined, map, [{ regex: HandParsersProgram.parserFullRegex, parser: parserDefinitionParser }]) } get sortSpec() { const sortSections = new Map() const sortIndices = new Map() - const sortTemplate = this.get(GrammarConstants.sortTemplate) + const sortTemplate = this.get(ParsersConstants.sortTemplate) if (!sortTemplate) return { sortSections, sortIndices } sortTemplate.split(" ").forEach((section, sectionIndex) => section.split(" ").forEach(word => sortSections.set(word, sectionIndex))) @@ -1849,7 +1849,7 @@ ${properties.join("\n")} } get idWithoutSuffix() { - return this.id.replace(HandGrammarProgram.parserSuffixRegex, "") + return this.id.replace(HandParsersProgram.parserSuffixRegex, "") } get constantsObject() { @@ -1866,8 +1866,8 @@ ${properties.join("\n")} return obj } - get examples(): GrammarExampleParser[] { - return this._getChildrenByParserInExtended(GrammarExampleParser) + get examples(): ParsersExampleParser[] { + return this._getChildrenByParserInExtended(ParsersExampleParser) } get parserIdFromDefinition(): scrollNotationTypes.parserId { @@ -1884,15 +1884,15 @@ ${properties.join("\n")} } _isAbstract() { - return this.id.startsWith(GrammarConstants.abstractParserPrefix) + return this.id.startsWith(ParsersConstants.abstractParserPrefix) } get cruxIfAny(): string { - return this.get(GrammarConstants.crux) || (this._hasFromExtended(GrammarConstants.cruxFromId) ? this.idWithoutSuffix : undefined) + return this.get(ParsersConstants.crux) || (this._hasFromExtended(ParsersConstants.cruxFromId) ? this.idWithoutSuffix : undefined) } get regexMatch() { - return this.get(GrammarConstants.pattern) + return this.get(ParsersConstants.pattern) } get firstCellEnumOptions() { @@ -1900,13 +1900,13 @@ ${properties.join("\n")} return firstCellDef ? firstCellDef._getEnumOptions() : undefined } - get languageDefinitionProgram(): HandGrammarProgram { - return this.root + get languageDefinitionProgram(): HandParsersProgram { + return this.root } protected get customJavascriptMethods(): scrollNotationTypes.javascriptCode { - const hasJsCode = this.has(GrammarConstants.javascript) - return hasJsCode ? this.getNode(GrammarConstants.javascript).childrenToString() : "" + const hasJsCode = this.has(ParsersConstants.javascript) + return hasJsCode ? this.getNode(ParsersConstants.javascript).childrenToString() : "" } private _cache_firstWordToNodeDefMap: { [firstWord: string]: parserDefinitionParser } @@ -1922,11 +1922,11 @@ ${properties.join("\n")} } private _getMyCellTypeDefs() { - const requiredCells = this.get(GrammarConstants.cells) + const requiredCells = this.get(ParsersConstants.cells) if (!requiredCells) return [] - const grammarProgram = this.languageDefinitionProgram + const parsersProgram = this.languageDefinitionProgram return requiredCells.split(" ").map(cellTypeId => { - const cellTypeDef = grammarProgram.getCellTypeDefinitionById(cellTypeId) + const cellTypeDef = parsersProgram.getCellTypeDefinitionById(cellTypeId) if (!cellTypeDef) throw new Error(`No cellType "${cellTypeId}" found`) return cellTypeDef }) @@ -1935,11 +1935,11 @@ ${properties.join("\n")} // todo: what happens when you have a cell getter and constant with same name? private get cellGettersAndParserConstants() { // todo: add cellType parsings - const grammarProgram = this.languageDefinitionProgram + const parsersProgram = this.languageDefinitionProgram const getters = this._getMyCellTypeDefs().map((cellTypeDef, index) => cellTypeDef.getGetter(index)) - const catchAllCellTypeId = this.get(GrammarConstants.catchAllCellType) - if (catchAllCellTypeId) getters.push(grammarProgram.getCellTypeDefinitionById(catchAllCellTypeId).getCatchAllGetter(getters.length)) + const catchAllCellTypeId = this.get(ParsersConstants.catchAllCellType) + if (catchAllCellTypeId) getters.push(parsersProgram.getCellTypeDefinitionById(catchAllCellTypeId).getCatchAllGetter(getters.length)) // Constants Object.values(this._getUniqueConstantNodes(false)).forEach(node => getters.push(node.getGetter())) @@ -1983,7 +1983,7 @@ ${properties.join("\n")} } _getMyInScopeParserIds(target: AbstractParserDefinitionParser = this): scrollNotationTypes.parserId[] { - const parsersNode = target.getNode(GrammarConstants.inScope) + const parsersNode = target.getNode(ParsersConstants.inScope) const scopedDefinitionIds = target.myScopedParserDefinitions.map(def => def.id) return parsersNode ? parsersNode.getWordsFrom(1).concat(scopedDefinitionIds) : scopedDefinitionIds } @@ -1996,17 +1996,17 @@ ${properties.join("\n")} } get isSingle() { - const hit = this._getNodeFromExtended(GrammarConstants.single) - return hit && hit.get(GrammarConstants.single) !== "false" + const hit = this._getNodeFromExtended(ParsersConstants.single) + return hit && hit.get(ParsersConstants.single) !== "false" } get isUniqueLine() { - const hit = this._getNodeFromExtended(GrammarConstants.uniqueLine) - return hit && hit.get(GrammarConstants.uniqueLine) !== "false" + const hit = this._getNodeFromExtended(ParsersConstants.uniqueLine) + return hit && hit.get(ParsersConstants.uniqueLine) !== "false" } isRequired(): boolean { - return this._hasFromExtended(GrammarConstants.required) + return this._hasFromExtended(ParsersConstants.required) } getParserDefinitionByParserId(parserId: scrollNotationTypes.parserId): AbstractParserDefinitionParser { @@ -2035,16 +2035,16 @@ ${properties.join("\n")} } private get _languageRootNode() { - return (this.root).rootParserDefinition + return (this.root).rootParserDefinition } private _isErrorParser() { - return this.get(GrammarConstants.baseParser) === GrammarConstants.errorParser + return this.get(ParsersConstants.baseParser) === ParsersConstants.errorParser } _isBlobParser() { // Do not check extended classes. Only do once. - return this._getFromExtended(GrammarConstants.baseParser) === GrammarConstants.blobParser + return this._getFromExtended(ParsersConstants.baseParser) === ParsersConstants.blobParser } private get errorMethodToJavascript(): scrollNotationTypes.javascriptCode { @@ -2095,7 +2095,7 @@ ${properties.join("\n")} private get catchAllParserToJavascript(): scrollNotationTypes.javascriptCode { if (this._isBlobParser()) return "this._getBlobParserCatchAllParser()" - const parserId = this.get(GrammarConstants.catchAllParser) + const parserId = this.get(ParsersConstants.catchAllParser) if (!parserId) return "" const nodeDef = this.getParserDefinitionByParserId(parserId) return nodeDef.generatedClassName @@ -2106,9 +2106,9 @@ ${properties.join("\n")} const thisClassName = this.generatedClassName if (this._amIRoot()) { - components.push(`static cachedHandGrammarProgramRoot = new HandGrammarProgram(\`${Utils.escapeBackTicks(this.parent.toString().replace(/\\/g, "\\\\"))}\`) - get handGrammarProgram() { - return this.constructor.cachedHandGrammarProgramRoot + components.push(`static cachedHandParsersProgramRoot = new HandParsersProgram(\`${Utils.escapeBackTicks(this.parent.toString().replace(/\\/g, "\\\\"))}\`) + get handParsersProgram() { + return this.constructor.cachedHandParsersProgramRoot }`) components.push(`static rootParser = ${thisClassName}`) @@ -2121,18 +2121,18 @@ ${properties.join("\n")} private _getExtendsClassName() { // todo: this is hopefully a temporary line in place for now for the case where you want your base class to extend something other than another treeclass - const hardCodedExtend = this.get(GrammarConstants._extendsJsClass) + const hardCodedExtend = this.get(ParsersConstants._extendsJsClass) if (hardCodedExtend) return hardCodedExtend const extendedDef = this._getExtendedParent() - return extendedDef ? extendedDef.generatedClassName : "GrammarBackedNode" + return extendedDef ? extendedDef.generatedClassName : "ParserBackedNode" } _getCompilerObject(): scrollNotationTypes.stringMap { let obj: { [key: string]: string } = {} - const items = this._getChildrenByParserInExtended(GrammarCompilerParser) + const items = this._getChildrenByParserInExtended(ParsersCompilerParser) items.reverse() // Last definition wins. - items.forEach((node: GrammarCompilerParser) => { + items.forEach((node: ParsersCompilerParser) => { obj = Object.assign(obj, node.toObject()) // todo: what about multiline strings? }) return obj @@ -2149,7 +2149,7 @@ ${properties.join("\n")} } isTerminalParser() { - return !this._getFromExtended(GrammarConstants.inScope) && !this._getFromExtended(GrammarConstants.catchAllParser) + return !this._getFromExtended(ParsersConstants.inScope) && !this._getFromExtended(ParsersConstants.catchAllParser) } private get sublimeMatchLine() { @@ -2178,7 +2178,7 @@ ${properties.join("\n")} const captures = requiredCellTypeIds .map((cellTypeId, index) => { const cellTypeDefinition = program.getCellTypeDefinitionById(cellTypeId) // todo: cleanup - if (!cellTypeDefinition) throw new Error(`No ${GrammarConstants.cellType} ${cellTypeId} found`) // todo: standardize error/capture error at grammar time + if (!cellTypeDefinition) throw new Error(`No ${ParsersConstants.cellType} ${cellTypeId} found`) // todo: standardize error/capture error at parsers time return ` ${index + 1}: ${(cellTypeDefinition.highlightScope || defaultHighlightScope) + "." + cellTypeDefinition.cellTypeId}` }) .join("\n") @@ -2228,11 +2228,11 @@ ${captures} } get description(): string { - return this._getFromExtended(GrammarConstants.description) || "" + return this._getFromExtended(ParsersConstants.description) || "" } get frequency() { - const val = this._getFromExtended(GrammarConstants.frequency) + const val = this._getFromExtended(ParsersConstants.frequency) return val ? parseFloat(val) : 0 } @@ -2273,8 +2273,8 @@ ${cells.toString(1)}` private _shouldSynthesize(def: AbstractParserDefinitionParser, parserChain: string[]) { if (def._isErrorParser() || def._isAbstract()) return false if (parserChain.includes(def.id)) return false - const tags = def.get(GrammarConstants.tags) - if (tags && tags.includes(GrammarConstantsMisc.doNotSynthesize)) return false + const tags = def.get(ParsersConstants.tags) + if (tags && tags.includes(ParsersConstantsMisc.doNotSynthesize)) return false return true } @@ -2327,7 +2327,7 @@ ${cells.toString(1)}` // todo: refactor synthesizeNode(nodeCount = 1, indentCount = -1, parsersAlreadySynthesized: string[] = [], seed = Date.now()) { let inScopeParserIds = this._getInScopeParserIds() - const catchAllParserId = this._getFromExtended(GrammarConstants.catchAllParser) + const catchAllParserId = this._getFromExtended(ParsersConstants.catchAllParser) if (catchAllParserId) inScopeParserIds.push(catchAllParserId) const thisId = this.id if (!parsersAlreadySynthesized.includes(thisId)) parsersAlreadySynthesized.push(thisId) @@ -2352,9 +2352,9 @@ ${cells.toString(1)}` get cellParser() { if (!this._cellParser) { - const cellParsingStrategy = this._getFromExtended(GrammarConstants.cellParser) - if (cellParsingStrategy === GrammarCellParser.postfix) this._cellParser = new PostfixCellParser(this) - else if (cellParsingStrategy === GrammarCellParser.omnifix) this._cellParser = new OmnifixCellParser(this) + const cellParsingStrategy = this._getFromExtended(ParsersConstants.cellParser) + if (cellParsingStrategy === ParsersCellParser.postfix) this._cellParser = new PostfixCellParser(this) + else if (cellParsingStrategy === ParsersCellParser.omnifix) this._cellParser = new OmnifixCellParser(this) else this._cellParser = new PrefixCellParser(this) } return this._cellParser @@ -2364,28 +2364,28 @@ ${cells.toString(1)}` // todo: remove? class parserDefinitionParser extends AbstractParserDefinitionParser {} -// HandGrammarProgram is a constructor that takes a grammar file, and builds a new +// HandParsersProgram is a constructor that takes a parsers file, and builds a new // constructor for new language that takes files in that language to execute, compile, etc. -class HandGrammarProgram extends AbstractParserDefinitionParser { +class HandParsersProgram extends AbstractParserDefinitionParser { createParserCombinator() { const map: scrollNotationTypes.stringMap = {} - map[GrammarConstants.comment] = TreeNode + map[ParsersConstants.comment] = TreeNode return new TreeNode.ParserCombinator(UnknownParserNode, map, [ - { regex: HandGrammarProgram.blankLineRegex, parser: TreeNode }, - { regex: HandGrammarProgram.parserFullRegex, parser: parserDefinitionParser }, - { regex: HandGrammarProgram.cellTypeFullRegex, parser: cellTypeDefinitionParser } + { regex: HandParsersProgram.blankLineRegex, parser: TreeNode }, + { regex: HandParsersProgram.parserFullRegex, parser: parserDefinitionParser }, + { regex: HandParsersProgram.cellTypeFullRegex, parser: cellTypeDefinitionParser } ]) } - static makeParserId = (str: string) => Utils._replaceNonAlphaNumericCharactersWithCharCodes(str).replace(HandGrammarProgram.parserSuffixRegex, "") + GrammarConstants.parserSuffix - static makeCellTypeId = (str: string) => Utils._replaceNonAlphaNumericCharactersWithCharCodes(str).replace(HandGrammarProgram.cellTypeSuffixRegex, "") + GrammarConstants.cellTypeSuffix + static makeParserId = (str: string) => Utils._replaceNonAlphaNumericCharactersWithCharCodes(str).replace(HandParsersProgram.parserSuffixRegex, "") + ParsersConstants.parserSuffix + static makeCellTypeId = (str: string) => Utils._replaceNonAlphaNumericCharactersWithCharCodes(str).replace(HandParsersProgram.cellTypeSuffixRegex, "") + ParsersConstants.cellTypeSuffix - static parserSuffixRegex = new RegExp(GrammarConstants.parserSuffix + "$") - static parserFullRegex = new RegExp("^[a-zA-Z0-9_]+" + GrammarConstants.parserSuffix + "$") + static parserSuffixRegex = new RegExp(ParsersConstants.parserSuffix + "$") + static parserFullRegex = new RegExp("^[a-zA-Z0-9_]+" + ParsersConstants.parserSuffix + "$") static blankLineRegex = new RegExp("^$") - static cellTypeSuffixRegex = new RegExp(GrammarConstants.cellTypeSuffix + "$") - static cellTypeFullRegex = new RegExp("^[a-zA-Z0-9_]+" + GrammarConstants.cellTypeSuffix + "$") + static cellTypeSuffixRegex = new RegExp(ParsersConstants.cellTypeSuffix + "$") + static cellTypeFullRegex = new RegExp("^[a-zA-Z0-9_]+" + ParsersConstants.cellTypeSuffix + "$") private _cache_rootParser: any // rootParser @@ -2430,9 +2430,9 @@ class HandGrammarProgram extends AbstractParserDefinitionParser { }) programs.forEach(code => { const exampleProgram = new rootParser(code) - exampleProgram.topDownArray.forEach((node: GrammarBackedNode) => { + exampleProgram.topDownArray.forEach((node: ParserBackedNode) => { const nodeIndex = idToIndex[node.definition.id] - const parentNode = node.parent + const parentNode = node.parent if (!nodeIndex) return undefined if (parentNode.isRoot()) matrix[0][nodeIndex]++ else { @@ -2464,19 +2464,19 @@ class HandGrammarProgram extends AbstractParserDefinitionParser { return predictions } - predictChildren(model: SimplePredictionModel, node: GrammarBackedNode) { + predictChildren(model: SimplePredictionModel, node: ParserBackedNode) { return this._mapPredictions(this._predictChildren(model, node), model) } - predictParents(model: SimplePredictionModel, node: GrammarBackedNode) { + predictParents(model: SimplePredictionModel, node: ParserBackedNode) { return this._mapPredictions(this._predictParents(model, node), model) } - private _predictChildren(model: SimplePredictionModel, node: GrammarBackedNode) { + private _predictChildren(model: SimplePredictionModel, node: ParserBackedNode) { return model.matrix[node.isRoot() ? 0 : model.idToIndex[node.definition.id]] } - private _predictParents(model: SimplePredictionModel, node: GrammarBackedNode) { + private _predictParents(model: SimplePredictionModel, node: ParserBackedNode) { if (node.isRoot()) return [] const nodeIndex = model.idToIndex[node.definition.id] return model.matrix.map(row => row[nodeIndex]) @@ -2503,7 +2503,7 @@ class HandGrammarProgram extends AbstractParserDefinitionParser { return vm.runInThisContext(code) } catch (err) { // todo: figure out best error pattern here for debugging - console.log(`Error in compiled grammar code for language "${this.grammarName}"`) + console.log(`Error in compiled parsers code for language "${this.parsersName}"`) // console.log(new TreeNode(code).toStringWithLineNumbers()) console.log(err) throw err @@ -2588,7 +2588,7 @@ paragraph This readme was auto-generated using the const example = rootNodeDef.examples[0] const sampleCode = example ? example.childrenToString() : "" - files[GrammarBundleFiles.package] = JSON.stringify( + files[ParsersBundleFiles.package] = JSON.stringify( { name: languageName, private: true, @@ -2599,7 +2599,7 @@ paragraph This readme was auto-generated using the null, 2 ) - files[GrammarBundleFiles.readme] = this.toReadMe() + files[ParsersBundleFiles.readme] = this.toReadMe() const testCode = `const program = new ${languageName}(sampleCode) const errors = program.getAllErrors() @@ -2609,13 +2609,13 @@ if (errors.length) const nodePath = `${languageName}.node.js` files[nodePath] = this.toNodeJsJavascript() - files[GrammarBundleFiles.indexJs] = `module.exports = require("./${nodePath}")` + files[ParsersBundleFiles.indexJs] = `module.exports = require("./${nodePath}")` const browserPath = `${languageName}.browser.js` files[browserPath] = this.toBrowserJavascript() - files[GrammarBundleFiles.indexHtml] = ` + files[ParsersBundleFiles.indexHtml] = ` - + + files[ParsersBundleFiles.indexHtml] = ` - + ` const samplePath = "sample." + this.extensionName files[samplePath] = sampleCode.toString() - files[GrammarBundleFiles.testJs] = `const ${languageName} = require("./index.js") + files[ParsersBundleFiles.testJs] = `const ${languageName} = require("./index.js") /*keep-line*/ const sampleCode = require("fs").readFileSync("${samplePath}", "utf8") ${testCode}` return files } get targetExtension() { - return this.rootParserDefinition.get(GrammarConstants.compilesTo) + return this.rootParserDefinition.get(ParsersConstants.compilesTo) } get cellTypeDefinitions() { if (this._cache_cellTypes) return this._cache_cellTypes @@ -2171,7 +2171,7 @@ ${testCode}` return this.getChildrenByParser(parserDefinitionParser).filter(node => node._hasValidParserId()) } get lastRootParserDefinitionNode() { - return this.findLast(def => def instanceof AbstractParserDefinitionParser && def.has(GrammarConstants.root) && def._hasValidParserId()) + return this.findLast(def => def instanceof AbstractParserDefinitionParser && def.has(ParsersConstants.root) && def._hasValidParserId()) } _initRootParserDefinitionNode() { if (this._cache_rootParserNode) return @@ -2179,9 +2179,9 @@ ${testCode}` // By default, have a very permissive basic root node. // todo: whats the best design pattern to use for this sort of thing? if (!this._cache_rootParserNode) { - this._cache_rootParserNode = this.concat(`${GrammarConstants.DefaultRootParser} - ${GrammarConstants.root} - ${GrammarConstants.catchAllParser} ${GrammarConstants.BlobParser}`)[0] + this._cache_rootParserNode = this.concat(`${ParsersConstants.DefaultRootParser} + ${ParsersConstants.root} + ${ParsersConstants.catchAllParser} ${ParsersConstants.BlobParser}`)[0] this._addDefaultCatchAllBlobParser() } } @@ -2193,11 +2193,11 @@ ${testCode}` if (this._addedCatchAll) return this._addedCatchAll = true delete this._cache_parserDefinitionParsers - this.concat(`${GrammarConstants.BlobParser} - ${GrammarConstants.baseParser} ${GrammarConstants.blobParser}`) + this.concat(`${ParsersConstants.BlobParser} + ${ParsersConstants.baseParser} ${ParsersConstants.blobParser}`) } get extensionName() { - return this.grammarName + return this.parsersName } get id() { return this.rootParserId @@ -2205,14 +2205,14 @@ ${testCode}` get rootParserId() { return this.rootParserDefinition.parserIdFromDefinition } - get grammarName() { - return this.rootParserId.replace(HandGrammarProgram.parserSuffixRegex, "") + get parsersName() { + return this.rootParserId.replace(HandParsersProgram.parserSuffixRegex, "") } _getMyInScopeParserIds() { return super._getMyInScopeParserIds(this.rootParserDefinition) } _getInScopeParserIds() { - const parsersNode = this.rootParserDefinition.getNode(GrammarConstants.inScope) + const parsersNode = this.rootParserDefinition.getNode(ParsersConstants.inScope) return parsersNode ? parsersNode.getWordsFrom(1) : [] } makeProgramParserDefinitionCache() { @@ -2228,7 +2228,7 @@ ${testCode}` return this._cached_rootParser } get fileExtensions() { - return this.rootParserDefinition.get(GrammarConstants.extensions) ? this.rootParserDefinition.get(GrammarConstants.extensions).split(" ").join(",") : this.extensionName + return this.rootParserDefinition.get(ParsersConstants.extensions) ? this.rootParserDefinition.get(ParsersConstants.extensions).split(" ").join(",") : this.extensionName } toNodeJsJavascript(scrollsdkProductsPath = "scrollsdk/products") { return this._rootNodeDefToJavascriptClass(scrollsdkProductsPath, true).trim() @@ -2241,7 +2241,7 @@ ${testCode}` // todo: throw if there is no root node defined const parserClasses = defs.map(def => def.asJavascriptClass).join("\n\n") const rootDef = this.rootParserDefinition - const rootNodeJsHeader = forNodeJs && rootDef._getConcatBlockStringFromExtended(GrammarConstants._rootNodeJsHeader) + const rootNodeJsHeader = forNodeJs && rootDef._getConcatBlockStringFromExtended(ParsersConstants._rootNodeJsHeader) const rootName = rootDef.generatedClassName if (!rootName) throw new Error(`Root Node Type Has No Name`) let exportScript = "" @@ -2259,7 +2259,7 @@ ${rootName}` }) .join("\n") } - // todo: we can expose the previous "constants" export, if needed, via the grammar, which we preserve. + // todo: we can expose the previous "constants" export, if needed, via the parsers, which we preserve. return `{ ${nodeJsImports} ${rootNodeJsHeader ? rootNodeJsHeader : ""} @@ -2293,35 +2293,35 @@ ${includes} ${parserContexts}` } } -HandGrammarProgram.makeParserId = str => Utils._replaceNonAlphaNumericCharactersWithCharCodes(str).replace(HandGrammarProgram.parserSuffixRegex, "") + GrammarConstants.parserSuffix -HandGrammarProgram.makeCellTypeId = str => Utils._replaceNonAlphaNumericCharactersWithCharCodes(str).replace(HandGrammarProgram.cellTypeSuffixRegex, "") + GrammarConstants.cellTypeSuffix -HandGrammarProgram.parserSuffixRegex = new RegExp(GrammarConstants.parserSuffix + "$") -HandGrammarProgram.parserFullRegex = new RegExp("^[a-zA-Z0-9_]+" + GrammarConstants.parserSuffix + "$") -HandGrammarProgram.blankLineRegex = new RegExp("^$") -HandGrammarProgram.cellTypeSuffixRegex = new RegExp(GrammarConstants.cellTypeSuffix + "$") -HandGrammarProgram.cellTypeFullRegex = new RegExp("^[a-zA-Z0-9_]+" + GrammarConstants.cellTypeSuffix + "$") -HandGrammarProgram._languages = {} -HandGrammarProgram._parsers = {} +HandParsersProgram.makeParserId = str => Utils._replaceNonAlphaNumericCharactersWithCharCodes(str).replace(HandParsersProgram.parserSuffixRegex, "") + ParsersConstants.parserSuffix +HandParsersProgram.makeCellTypeId = str => Utils._replaceNonAlphaNumericCharactersWithCharCodes(str).replace(HandParsersProgram.cellTypeSuffixRegex, "") + ParsersConstants.cellTypeSuffix +HandParsersProgram.parserSuffixRegex = new RegExp(ParsersConstants.parserSuffix + "$") +HandParsersProgram.parserFullRegex = new RegExp("^[a-zA-Z0-9_]+" + ParsersConstants.parserSuffix + "$") +HandParsersProgram.blankLineRegex = new RegExp("^$") +HandParsersProgram.cellTypeSuffixRegex = new RegExp(ParsersConstants.cellTypeSuffix + "$") +HandParsersProgram.cellTypeFullRegex = new RegExp("^[a-zA-Z0-9_]+" + ParsersConstants.cellTypeSuffix + "$") +HandParsersProgram._languages = {} +HandParsersProgram._parsers = {} const PreludeKinds = {} -PreludeKinds[PreludeCellTypeIds.anyCell] = GrammarAnyCell -PreludeKinds[PreludeCellTypeIds.keywordCell] = GrammarKeywordCell -PreludeKinds[PreludeCellTypeIds.floatCell] = GrammarFloatCell -PreludeKinds[PreludeCellTypeIds.numberCell] = GrammarFloatCell -PreludeKinds[PreludeCellTypeIds.bitCell] = GrammarBitCell -PreludeKinds[PreludeCellTypeIds.boolCell] = GrammarBoolCell -PreludeKinds[PreludeCellTypeIds.intCell] = GrammarIntCell -class UnknownGrammarProgram extends TreeNode { - _inferRootNodeForAPrefixLanguage(grammarName) { - grammarName = HandGrammarProgram.makeParserId(grammarName) - const rootNode = new TreeNode(`${grammarName} - ${GrammarConstants.root}`) - // note: right now we assume 1 global cellTypeMap and parserMap per grammar. But we may have scopes in the future? +PreludeKinds[PreludeCellTypeIds.anyCell] = ParsersAnyCell +PreludeKinds[PreludeCellTypeIds.keywordCell] = ParsersKeywordCell +PreludeKinds[PreludeCellTypeIds.floatCell] = ParsersFloatCell +PreludeKinds[PreludeCellTypeIds.numberCell] = ParsersFloatCell +PreludeKinds[PreludeCellTypeIds.bitCell] = ParsersBitCell +PreludeKinds[PreludeCellTypeIds.boolCell] = ParsersBoolCell +PreludeKinds[PreludeCellTypeIds.intCell] = ParsersIntCell +class UnknownParsersProgram extends TreeNode { + _inferRootNodeForAPrefixLanguage(parsersName) { + parsersName = HandParsersProgram.makeParserId(parsersName) + const rootNode = new TreeNode(`${parsersName} + ${ParsersConstants.root}`) + // note: right now we assume 1 global cellTypeMap and parserMap per parsers. But we may have scopes in the future? const rootNodeNames = this.getFirstWords() .filter(identity => identity) - .map(word => HandGrammarProgram.makeParserId(word)) + .map(word => HandParsersProgram.makeParserId(word)) rootNode .nodeAt(0) - .touchNode(GrammarConstants.inScope) + .touchNode(ParsersConstants.inScope) .setWordsFrom(1, Array.from(new Set(rootNodeNames))) return rootNode } @@ -2330,7 +2330,7 @@ class UnknownGrammarProgram extends TreeNode { for (let node of clone.getTopDownArrayIterator()) { const firstWordIsAnInteger = !!node.firstWord.match(/^\d+$/) const parentFirstWord = node.parent.firstWord - if (firstWordIsAnInteger && parentFirstWord) node.setFirstWord(HandGrammarProgram.makeParserId(parentFirstWord + UnknownGrammarProgram._childSuffix)) + if (firstWordIsAnInteger && parentFirstWord) node.setFirstWord(HandParsersProgram.makeParserId(parentFirstWord + UnknownParsersProgram._childSuffix)) } } _getKeywordMaps(clone) { @@ -2347,10 +2347,10 @@ class UnknownGrammarProgram extends TreeNode { } _inferParserDef(firstWord, globalCellTypeMap, childFirstWords, instances) { const edgeSymbol = this.edgeSymbol - const parserId = HandGrammarProgram.makeParserId(firstWord) + const parserId = HandParsersProgram.makeParserId(firstWord) const nodeDefNode = new TreeNode(parserId).nodeAt(0) - const childParserIds = childFirstWords.map(word => HandGrammarProgram.makeParserId(word)) - if (childParserIds.length) nodeDefNode.touchNode(GrammarConstants.inScope).setWordsFrom(1, childParserIds) + const childParserIds = childFirstWords.map(word => HandParsersProgram.makeParserId(word)) + if (childParserIds.length) nodeDefNode.touchNode(ParsersConstants.inScope).setWordsFrom(1, childParserIds) const cellsForAllInstances = instances .map(line => line.content) .filter(identity => identity) @@ -2377,29 +2377,29 @@ class UnknownGrammarProgram extends TreeNode { cellTypeIds.pop() } } - const needsCruxProperty = !firstWord.endsWith(UnknownGrammarProgram._childSuffix + GrammarConstants.parserSuffix) // todo: cleanup - if (needsCruxProperty) nodeDefNode.set(GrammarConstants.crux, firstWord) - if (catchAllCellType) nodeDefNode.set(GrammarConstants.catchAllCellType, catchAllCellType) + const needsCruxProperty = !firstWord.endsWith(UnknownParsersProgram._childSuffix + ParsersConstants.parserSuffix) // todo: cleanup + if (needsCruxProperty) nodeDefNode.set(ParsersConstants.crux, firstWord) + if (catchAllCellType) nodeDefNode.set(ParsersConstants.catchAllCellType, catchAllCellType) const cellLine = cellTypeIds.slice() cellLine.unshift(PreludeCellTypeIds.keywordCell) - if (cellLine.length > 0) nodeDefNode.set(GrammarConstants.cells, cellLine.join(edgeSymbol)) - //if (!catchAllCellType && cellTypeIds.length === 1) nodeDefNode.set(GrammarConstants.cells, cellTypeIds[0]) + if (cellLine.length > 0) nodeDefNode.set(ParsersConstants.cells, cellLine.join(edgeSymbol)) + //if (!catchAllCellType && cellTypeIds.length === 1) nodeDefNode.set(ParsersConstants.cells, cellTypeIds[0]) // Todo: add conditional frequencies return nodeDefNode.parent.toString() } - // inferGrammarFileForAnSSVLanguage(grammarName: string): string { - // grammarName = HandGrammarProgram.makeParserId(grammarName) - // const rootNode = new TreeNode(`${grammarName} - // ${GrammarConstants.root}`) - // // note: right now we assume 1 global cellTypeMap and parserMap per grammar. But we may have scopes in the future? - // const rootNodeNames = this.getFirstWords().map(word => HandGrammarProgram.makeParserId(word)) + // inferParsersFileForAnSSVLanguage(parsersName: string): string { + // parsersName = HandParsersProgram.makeParserId(parsersName) + // const rootNode = new TreeNode(`${parsersName} + // ${ParsersConstants.root}`) + // // note: right now we assume 1 global cellTypeMap and parserMap per parsers. But we may have scopes in the future? + // const rootNodeNames = this.getFirstWords().map(word => HandParsersProgram.makeParserId(word)) // rootNode // .nodeAt(0) - // .touchNode(GrammarConstants.inScope) + // .touchNode(ParsersConstants.inScope) // .setWordsFrom(1, Array.from(new Set(rootNodeNames))) // return rootNode // } - inferGrammarFileForAKeywordLanguage(grammarName) { + inferParsersFileForAKeywordLanguage(parsersName) { const clone = this.clone() this._renameIntegerKeywords(clone) const { keywordsToChildKeywords, keywordsToNodeInstances } = this._getKeywordMaps(clone) @@ -2411,13 +2411,13 @@ class UnknownGrammarProgram extends TreeNode { const cellTypeDefs = [] globalCellTypeMap.forEach((def, id) => cellTypeDefs.push(def ? def : id)) const nodeBreakSymbol = this.nodeBreakSymbol - return this._formatCode([this._inferRootNodeForAPrefixLanguage(grammarName).toString(), cellTypeDefs.join(nodeBreakSymbol), parserDefs.join(nodeBreakSymbol)].filter(identity => identity).join("\n")) + return this._formatCode([this._inferRootNodeForAPrefixLanguage(parsersName).toString(), cellTypeDefs.join(nodeBreakSymbol), parserDefs.join(nodeBreakSymbol)].filter(identity => identity).join("\n")) } _formatCode(code) { // todo: make this run in browser too if (!this.isNodeJs()) return code - const grammarProgram = new HandGrammarProgram(TreeNode.fromDisk(__dirname + "/../langs/grammar/grammar.grammar")) - const rootParser = grammarProgram.compileAndReturnRootParser() + const parsersProgram = new HandParsersProgram(TreeNode.fromDisk(__dirname + "/../langs/parsers/parsers.parsers")) + const rootParser = parsersProgram.compileAndReturnRootParser() const program = new rootParser(code) return program.format().toString() } @@ -2448,13 +2448,13 @@ class UnknownGrammarProgram extends TreeNode { const enumLimit = 30 if (instanceCount > 1 && maxCellsOnLine === 1 && allValues.length > asSet.size && asSet.size < enumLimit) return { - cellTypeId: HandGrammarProgram.makeCellTypeId(firstWord), - cellTypeDefinition: `${HandGrammarProgram.makeCellTypeId(firstWord)} + cellTypeId: HandParsersProgram.makeCellTypeId(firstWord), + cellTypeDefinition: `${HandParsersProgram.makeCellTypeId(firstWord)} enum ${values.join(edgeSymbol)}` } return { cellTypeId: PreludeCellTypeIds.anyCell } } } -UnknownGrammarProgram._childSuffix = "Child" +UnknownParsersProgram._childSuffix = "Child" -module.exports = { GrammarConstants, PreludeCellTypeIds, HandGrammarProgram, GrammarBackedNode, UnknownParserError, UnknownGrammarProgram } +module.exports = { ParsersConstants, PreludeCellTypeIds, HandParsersProgram, ParserBackedNode, UnknownParserError, UnknownParsersProgram } diff --git a/products/GrammarLanguage.browser.js b/products/Parsers.ts.browser.js similarity index 80% rename from products/GrammarLanguage.browser.js rename to products/Parsers.ts.browser.js index a4d7a557c..91ea36b9b 100644 --- a/products/GrammarLanguage.browser.js +++ b/products/Parsers.ts.browser.js @@ -2,22 +2,22 @@ const GlobalNamespaceAdditions = { Utils: "Utils.js", TreeNode: "TreeNode.js", - HandGrammarProgram: "GrammarLanguage.js", - GrammarBackedNode: "GrammarLanguage.js" + HandParsersProgram: "Parsers.js", + ParserBackedNode: "Parsers.js" } -var GrammarConstantsCompiler -;(function (GrammarConstantsCompiler) { - GrammarConstantsCompiler["stringTemplate"] = "stringTemplate" - GrammarConstantsCompiler["indentCharacter"] = "indentCharacter" - GrammarConstantsCompiler["catchAllCellDelimiter"] = "catchAllCellDelimiter" - GrammarConstantsCompiler["openChildren"] = "openChildren" - GrammarConstantsCompiler["joinChildrenWith"] = "joinChildrenWith" - GrammarConstantsCompiler["closeChildren"] = "closeChildren" -})(GrammarConstantsCompiler || (GrammarConstantsCompiler = {})) -var GrammarConstantsMisc -;(function (GrammarConstantsMisc) { - GrammarConstantsMisc["doNotSynthesize"] = "doNotSynthesize" -})(GrammarConstantsMisc || (GrammarConstantsMisc = {})) +var ParsersConstantsCompiler +;(function (ParsersConstantsCompiler) { + ParsersConstantsCompiler["stringTemplate"] = "stringTemplate" + ParsersConstantsCompiler["indentCharacter"] = "indentCharacter" + ParsersConstantsCompiler["catchAllCellDelimiter"] = "catchAllCellDelimiter" + ParsersConstantsCompiler["openChildren"] = "openChildren" + ParsersConstantsCompiler["joinChildrenWith"] = "joinChildrenWith" + ParsersConstantsCompiler["closeChildren"] = "closeChildren" +})(ParsersConstantsCompiler || (ParsersConstantsCompiler = {})) +var ParsersConstantsMisc +;(function (ParsersConstantsMisc) { + ParsersConstantsMisc["doNotSynthesize"] = "doNotSynthesize" +})(ParsersConstantsMisc || (ParsersConstantsMisc = {})) var PreludeCellTypeIds ;(function (PreludeCellTypeIds) { PreludeCellTypeIds["anyCell"] = "anyCell" @@ -29,88 +29,88 @@ var PreludeCellTypeIds PreludeCellTypeIds["boolCell"] = "boolCell" PreludeCellTypeIds["intCell"] = "intCell" })(PreludeCellTypeIds || (PreludeCellTypeIds = {})) -var GrammarConstantsConstantTypes -;(function (GrammarConstantsConstantTypes) { - GrammarConstantsConstantTypes["boolean"] = "boolean" - GrammarConstantsConstantTypes["string"] = "string" - GrammarConstantsConstantTypes["int"] = "int" - GrammarConstantsConstantTypes["float"] = "float" -})(GrammarConstantsConstantTypes || (GrammarConstantsConstantTypes = {})) -var GrammarBundleFiles -;(function (GrammarBundleFiles) { - GrammarBundleFiles["package"] = "package.json" - GrammarBundleFiles["readme"] = "readme.md" - GrammarBundleFiles["indexHtml"] = "index.html" - GrammarBundleFiles["indexJs"] = "index.js" - GrammarBundleFiles["testJs"] = "test.js" -})(GrammarBundleFiles || (GrammarBundleFiles = {})) -var GrammarCellParser -;(function (GrammarCellParser) { - GrammarCellParser["prefix"] = "prefix" - GrammarCellParser["postfix"] = "postfix" - GrammarCellParser["omnifix"] = "omnifix" -})(GrammarCellParser || (GrammarCellParser = {})) -var GrammarConstants -;(function (GrammarConstants) { +var ParsersConstantsConstantTypes +;(function (ParsersConstantsConstantTypes) { + ParsersConstantsConstantTypes["boolean"] = "boolean" + ParsersConstantsConstantTypes["string"] = "string" + ParsersConstantsConstantTypes["int"] = "int" + ParsersConstantsConstantTypes["float"] = "float" +})(ParsersConstantsConstantTypes || (ParsersConstantsConstantTypes = {})) +var ParsersBundleFiles +;(function (ParsersBundleFiles) { + ParsersBundleFiles["package"] = "package.json" + ParsersBundleFiles["readme"] = "readme.md" + ParsersBundleFiles["indexHtml"] = "index.html" + ParsersBundleFiles["indexJs"] = "index.js" + ParsersBundleFiles["testJs"] = "test.js" +})(ParsersBundleFiles || (ParsersBundleFiles = {})) +var ParsersCellParser +;(function (ParsersCellParser) { + ParsersCellParser["prefix"] = "prefix" + ParsersCellParser["postfix"] = "postfix" + ParsersCellParser["omnifix"] = "omnifix" +})(ParsersCellParser || (ParsersCellParser = {})) +var ParsersConstants +;(function (ParsersConstants) { // node types - GrammarConstants["extensions"] = "extensions" - GrammarConstants["comment"] = "//" - GrammarConstants["version"] = "version" - GrammarConstants["parser"] = "parser" - GrammarConstants["cellType"] = "cellType" - GrammarConstants["grammarFileExtension"] = "grammar" - GrammarConstants["abstractParserPrefix"] = "abstract" - GrammarConstants["parserSuffix"] = "Parser" - GrammarConstants["cellTypeSuffix"] = "Cell" + ParsersConstants["extensions"] = "extensions" + ParsersConstants["comment"] = "//" + ParsersConstants["version"] = "version" + ParsersConstants["parser"] = "parser" + ParsersConstants["cellType"] = "cellType" + ParsersConstants["parsersFileExtension"] = "parsers" + ParsersConstants["abstractParserPrefix"] = "abstract" + ParsersConstants["parserSuffix"] = "Parser" + ParsersConstants["cellTypeSuffix"] = "Cell" // error check time - GrammarConstants["regex"] = "regex" - GrammarConstants["reservedWords"] = "reservedWords" - GrammarConstants["enumFromCellTypes"] = "enumFromCellTypes" - GrammarConstants["enum"] = "enum" - GrammarConstants["examples"] = "examples" - GrammarConstants["min"] = "min" - GrammarConstants["max"] = "max" + ParsersConstants["regex"] = "regex" + ParsersConstants["reservedWords"] = "reservedWords" + ParsersConstants["enumFromCellTypes"] = "enumFromCellTypes" + ParsersConstants["enum"] = "enum" + ParsersConstants["examples"] = "examples" + ParsersConstants["min"] = "min" + ParsersConstants["max"] = "max" // baseParsers - GrammarConstants["baseParser"] = "baseParser" - GrammarConstants["blobParser"] = "blobParser" - GrammarConstants["errorParser"] = "errorParser" + ParsersConstants["baseParser"] = "baseParser" + ParsersConstants["blobParser"] = "blobParser" + ParsersConstants["errorParser"] = "errorParser" // parse time - GrammarConstants["extends"] = "extends" - GrammarConstants["root"] = "root" - GrammarConstants["crux"] = "crux" - GrammarConstants["cruxFromId"] = "cruxFromId" - GrammarConstants["pattern"] = "pattern" - GrammarConstants["inScope"] = "inScope" - GrammarConstants["cells"] = "cells" - GrammarConstants["listDelimiter"] = "listDelimiter" - GrammarConstants["contentKey"] = "contentKey" - GrammarConstants["childrenKey"] = "childrenKey" - GrammarConstants["uniqueFirstWord"] = "uniqueFirstWord" - GrammarConstants["catchAllCellType"] = "catchAllCellType" - GrammarConstants["cellParser"] = "cellParser" - GrammarConstants["catchAllParser"] = "catchAllParser" - GrammarConstants["constants"] = "constants" - GrammarConstants["required"] = "required" - GrammarConstants["single"] = "single" - GrammarConstants["uniqueLine"] = "uniqueLine" - GrammarConstants["tags"] = "tags" - GrammarConstants["_extendsJsClass"] = "_extendsJsClass" - GrammarConstants["_rootNodeJsHeader"] = "_rootNodeJsHeader" + ParsersConstants["extends"] = "extends" + ParsersConstants["root"] = "root" + ParsersConstants["crux"] = "crux" + ParsersConstants["cruxFromId"] = "cruxFromId" + ParsersConstants["pattern"] = "pattern" + ParsersConstants["inScope"] = "inScope" + ParsersConstants["cells"] = "cells" + ParsersConstants["listDelimiter"] = "listDelimiter" + ParsersConstants["contentKey"] = "contentKey" + ParsersConstants["childrenKey"] = "childrenKey" + ParsersConstants["uniqueFirstWord"] = "uniqueFirstWord" + ParsersConstants["catchAllCellType"] = "catchAllCellType" + ParsersConstants["cellParser"] = "cellParser" + ParsersConstants["catchAllParser"] = "catchAllParser" + ParsersConstants["constants"] = "constants" + ParsersConstants["required"] = "required" + ParsersConstants["single"] = "single" + ParsersConstants["uniqueLine"] = "uniqueLine" + ParsersConstants["tags"] = "tags" + ParsersConstants["_extendsJsClass"] = "_extendsJsClass" + ParsersConstants["_rootNodeJsHeader"] = "_rootNodeJsHeader" // default catchAll parser - GrammarConstants["BlobParser"] = "BlobParser" - GrammarConstants["DefaultRootParser"] = "DefaultRootParser" + ParsersConstants["BlobParser"] = "BlobParser" + ParsersConstants["DefaultRootParser"] = "DefaultRootParser" // code - GrammarConstants["javascript"] = "javascript" + ParsersConstants["javascript"] = "javascript" // compile time - GrammarConstants["compilerParser"] = "compiler" - GrammarConstants["compilesTo"] = "compilesTo" + ParsersConstants["compilerParser"] = "compiler" + ParsersConstants["compilesTo"] = "compilesTo" // develop time - GrammarConstants["description"] = "description" - GrammarConstants["example"] = "example" - GrammarConstants["sortTemplate"] = "sortTemplate" - GrammarConstants["frequency"] = "frequency" - GrammarConstants["highlightScope"] = "highlightScope" -})(GrammarConstants || (GrammarConstants = {})) + ParsersConstants["description"] = "description" + ParsersConstants["example"] = "example" + ParsersConstants["sortTemplate"] = "sortTemplate" + ParsersConstants["frequency"] = "frequency" + ParsersConstants["highlightScope"] = "highlightScope" +})(ParsersConstants || (ParsersConstants = {})) class TypedWord extends TreeWord { constructor(node, cellIndex, type) { super(node, cellIndex) @@ -124,13 +124,13 @@ class TypedWord extends TreeWord { } } // todo: can we merge these methods into base TreeNode and ditch this class? -class GrammarBackedNode extends TreeNode { +class ParserBackedNode extends TreeNode { get definition() { if (this._definition) return this._definition - this._definition = this.isRoot() ? this.handGrammarProgram : this.parent.definition.getParserDefinitionByParserId(this.constructor.name) + this._definition = this.isRoot() ? this.handParsersProgram : this.parent.definition.getParserDefinitionByParserId(this.constructor.name) return this._definition } - get rootGrammarTree() { + get rootParsersTree() { return this.definition.root } getAutocompleteResults(partialWord, cellIndex) { @@ -197,11 +197,11 @@ class GrammarBackedNode extends TreeNode { const cell = this.parsedCells[cellIndex] return cell ? cell.getAutoCompleteWords(partialWord) : [] } - // note: this is overwritten by the root node of a runtime grammar program. + // note: this is overwritten by the root node of a runtime parsers program. // some of the magic that makes this all work. but maybe there's a better way. - get handGrammarProgram() { - if (this.isRoot()) throw new Error(`Root node without getHandGrammarProgram defined.`) - return this.root.handGrammarProgram + get handParsersProgram() { + if (this.isRoot()) throw new Error(`Root node without getHandParsersProgram defined.`) + return this.root.handParsersProgram } getRunTimeEnumOptions(cell) { return undefined @@ -269,7 +269,7 @@ class GrammarBackedNode extends TreeNode { }) ).toFormattedTable(maxColumnWidth) } - // Helper method for selecting potential parsers needed to update grammar file. + // Helper method for selecting potential parsers needed to update parsers file. get invalidParsers() { return Array.from( new Set( @@ -326,7 +326,7 @@ class GrammarBackedNode extends TreeNode { } } _sortWithParentParsersUpTop() { - const familyTree = new HandGrammarProgram(this.toString()).parserFamilyTree + const familyTree = new HandParsersProgram(this.toString()).parserFamilyTree const rank = {} familyTree.topDownArray.forEach((node, index) => { rank[node.getWord(0)] = index @@ -389,8 +389,8 @@ class GrammarBackedNode extends TreeNode { getParserUsage(filepath = "") { // returns a report on what parsers from its language the program uses const usage = new TreeNode() - const handGrammarProgram = this.handGrammarProgram - handGrammarProgram.validConcreteAndAbstractParserDefinitions.forEach(def => { + const handParsersProgram = this.handParsersProgram + handParsersProgram.validConcreteAndAbstractParserDefinitions.forEach(def => { const requiredCellTypeIds = def.cellParser.getRequiredCellTypeIds() usage.appendLine([def.parserIdFromDefinition, "line-id", "parser", requiredCellTypeIds.join(" ")].join(" ")) }) @@ -498,7 +498,7 @@ class GrammarBackedNode extends TreeNode { return this.parsedCells.map(cell => cell.definitionLineNumber) } _getCompiledIndentation() { - const indentCharacter = this.definition._getCompilerObject()[GrammarConstantsCompiler.indentCharacter] + const indentCharacter = this.definition._getCompilerObject()[ParsersConstantsCompiler.indentCharacter] const indent = this.indentation return indentCharacter !== undefined ? indentCharacter.repeat(indent.length) : indent } @@ -513,24 +513,24 @@ class GrammarBackedNode extends TreeNode { } _getCompiledLine() { const compiler = this.definition._getCompilerObject() - const catchAllCellDelimiter = compiler[GrammarConstantsCompiler.catchAllCellDelimiter] - const str = compiler[GrammarConstantsCompiler.stringTemplate] + const catchAllCellDelimiter = compiler[ParsersConstantsCompiler.catchAllCellDelimiter] + const str = compiler[ParsersConstantsCompiler.stringTemplate] return str !== undefined ? Utils.formatStr(str, catchAllCellDelimiter, Object.assign(this._getFields(), this.cells)) : this.getLine() } get listDelimiter() { - return this.definition._getFromExtended(GrammarConstants.listDelimiter) + return this.definition._getFromExtended(ParsersConstants.listDelimiter) } get contentKey() { - return this.definition._getFromExtended(GrammarConstants.contentKey) + return this.definition._getFromExtended(ParsersConstants.contentKey) } get childrenKey() { - return this.definition._getFromExtended(GrammarConstants.childrenKey) + return this.definition._getFromExtended(ParsersConstants.childrenKey) } get childrenAreTextBlob() { return this.definition._isBlobParser() } get isArrayElement() { - return this.definition._hasFromExtended(GrammarConstants.uniqueFirstWord) ? false : !this.definition.isSingle + return this.definition._hasFromExtended(ParsersConstants.uniqueFirstWord) ? false : !this.definition.isSingle } get list() { return this.listDelimiter ? this.content.split(this.listDelimiter) : super.list @@ -592,9 +592,9 @@ class GrammarBackedNode extends TreeNode { const compiledLine = this._getCompiledLine() if (def.isTerminalParser()) return indent + compiledLine const compiler = def._getCompilerObject() - const openChildrenString = compiler[GrammarConstantsCompiler.openChildren] || "" - const closeChildrenString = compiler[GrammarConstantsCompiler.closeChildren] || "" - const childJoinCharacter = compiler[GrammarConstantsCompiler.joinChildrenWith] || "\n" + const openChildrenString = compiler[ParsersConstantsCompiler.openChildren] || "" + const closeChildrenString = compiler[ParsersConstantsCompiler.closeChildren] || "" + const childJoinCharacter = compiler[ParsersConstantsCompiler.joinChildrenWith] || "\n" const compiledChildren = this.map(child => child.compile()).join(childJoinCharacter) return `${indent + compiledLine}${openChildrenString} ${compiledChildren} @@ -614,7 +614,7 @@ ${indent}${closeChildrenString}` return cells } } -class BlobParser extends GrammarBackedNode { +class BlobParser extends ParserBackedNode { createParserCombinator() { return new TreeNode.ParserCombinator(BlobParser, {}) } @@ -623,7 +623,7 @@ class BlobParser extends GrammarBackedNode { } } // todo: can we remove this? hard to extend. -class UnknownParserNode extends GrammarBackedNode { +class UnknownParserNode extends ParserBackedNode { createParserCombinator() { return new TreeNode.ParserCombinator(UnknownParserNode, {}) } @@ -634,7 +634,7 @@ class UnknownParserNode extends GrammarBackedNode { /* A cell contains a word but also the type information for that word. */ -class AbstractGrammarBackedCell { +class AbstractParsersBackedCell { constructor(node, index, typeDef, cellTypeId, isCatchAll, parserDefinitionParser) { this._typeDef = typeDef this._node = node @@ -662,13 +662,13 @@ class AbstractGrammarBackedCell { return this._isCatchAll } get min() { - return this.cellTypeDefinition.get(GrammarConstants.min) || "0" + return this.cellTypeDefinition.get(ParsersConstants.min) || "0" } get max() { - return this.cellTypeDefinition.get(GrammarConstants.max) || "100" + return this.cellTypeDefinition.get(ParsersConstants.max) || "100" } get placeholder() { - return this.cellTypeDefinition.get(GrammarConstants.examples) || "" + return this.cellTypeDefinition.get(ParsersConstants.examples) || "" } get highlightScope() { const definition = this.cellTypeDefinition @@ -690,13 +690,13 @@ class AbstractGrammarBackedCell { synthesizeCell(seed = Date.now()) { // todo: cleanup const cellDef = this.cellTypeDefinition - const enumOptions = cellDef._getFromExtended(GrammarConstants.enum) + const enumOptions = cellDef._getFromExtended(ParsersConstants.enum) if (enumOptions) return Utils.getRandomString(1, enumOptions.split(" ")) return this._synthesizeCell(seed) } _getStumpEnumInput(crux) { const cellDef = this.cellTypeDefinition - const enumOptions = cellDef._getFromExtended(GrammarConstants.enum) + const enumOptions = cellDef._getFromExtended(ParsersConstants.enum) if (!enumOptions) return undefined const options = new TreeNode( enumOptions @@ -736,8 +736,8 @@ ${options.toString(1)}` return word === undefined || word === "" ? new MissingWordError(this) : new InvalidWordError(this) } } -AbstractGrammarBackedCell.parserFunctionName = "" -class GrammarBitCell extends AbstractGrammarBackedCell { +AbstractParsersBackedCell.parserFunctionName = "" +class ParsersBitCell extends AbstractParsersBackedCell { _isValid() { const word = this.getWord() return word === "0" || word === "1" @@ -753,8 +753,8 @@ class GrammarBitCell extends AbstractGrammarBackedCell { return !!parseInt(word) } } -GrammarBitCell.defaultHighlightScope = "constant.numeric" -class GrammarNumericCell extends AbstractGrammarBackedCell { +ParsersBitCell.defaultHighlightScope = "constant.numeric" +class ParsersNumericCell extends AbstractParsersBackedCell { _toStumpInput(crux) { return `input name ${crux} @@ -764,7 +764,7 @@ class GrammarNumericCell extends AbstractGrammarBackedCell { max ${this.max}` } } -class GrammarIntCell extends GrammarNumericCell { +class ParsersIntCell extends ParsersNumericCell { _isValid() { const word = this.getWord() const num = parseInt(word) @@ -782,9 +782,9 @@ class GrammarIntCell extends GrammarNumericCell { return parseInt(word) } } -GrammarIntCell.defaultHighlightScope = "constant.numeric.integer" -GrammarIntCell.parserFunctionName = "parseInt" -class GrammarFloatCell extends GrammarNumericCell { +ParsersIntCell.defaultHighlightScope = "constant.numeric.integer" +ParsersIntCell.parserFunctionName = "parseInt" +class ParsersFloatCell extends ParsersNumericCell { _isValid() { const word = this.getWord() const num = parseFloat(word) @@ -801,10 +801,10 @@ class GrammarFloatCell extends GrammarNumericCell { return parseFloat(word) } } -GrammarFloatCell.defaultHighlightScope = "constant.numeric.float" -GrammarFloatCell.parserFunctionName = "parseFloat" -// ErrorCellType => grammar asks for a '' cell type here but the grammar does not specify a '' cell type. (todo: bring in didyoumean?) -class GrammarBoolCell extends AbstractGrammarBackedCell { +ParsersFloatCell.defaultHighlightScope = "constant.numeric.float" +ParsersFloatCell.parserFunctionName = "parseFloat" +// ErrorCellType => parsers asks for a '' cell type here but the parsers does not specify a '' cell type. (todo: bring in didyoumean?) +class ParsersBoolCell extends AbstractParsersBackedCell { constructor() { super(...arguments) this._trues = new Set(["1", "true", "t", "yes"]) @@ -829,13 +829,13 @@ class GrammarBoolCell extends AbstractGrammarBackedCell { return this._trues.has(word.toLowerCase()) } } -GrammarBoolCell.defaultHighlightScope = "constant.numeric" -class GrammarAnyCell extends AbstractGrammarBackedCell { +ParsersBoolCell.defaultHighlightScope = "constant.numeric" +class ParsersAnyCell extends AbstractParsersBackedCell { _isValid() { return true } _synthesizeCell() { - const examples = this.cellTypeDefinition._getFromExtended(GrammarConstants.examples) + const examples = this.cellTypeDefinition._getFromExtended(ParsersConstants.examples) if (examples) return Utils.getRandomString(1, examples.split(" ")) return this._parserDefinitionParser.parserIdFromDefinition + "-" + this.constructor.name } @@ -846,18 +846,18 @@ class GrammarAnyCell extends AbstractGrammarBackedCell { return this.getWord() } } -class GrammarKeywordCell extends GrammarAnyCell { +class ParsersKeywordCell extends ParsersAnyCell { _synthesizeCell() { return this._parserDefinitionParser.cruxIfAny } } -GrammarKeywordCell.defaultHighlightScope = "keyword" -class GrammarExtraWordCellTypeCell extends AbstractGrammarBackedCell { +ParsersKeywordCell.defaultHighlightScope = "keyword" +class ParsersExtraWordCellTypeCell extends AbstractParsersBackedCell { _isValid() { return false } synthesizeCell() { - throw new Error(`Trying to synthesize a GrammarExtraWordCellTypeCell`) + throw new Error(`Trying to synthesize a ParsersExtraWordCellTypeCell`) return this._synthesizeCell() } _synthesizeCell() { @@ -870,12 +870,12 @@ class GrammarExtraWordCellTypeCell extends AbstractGrammarBackedCell { return new ExtraWordError(this) } } -class GrammarUnknownCellTypeCell extends AbstractGrammarBackedCell { +class ParsersUnknownCellTypeCell extends AbstractParsersBackedCell { _isValid() { return false } synthesizeCell() { - throw new Error(`Trying to synthesize an GrammarUnknownCellTypeCell`) + throw new Error(`Trying to synthesize an ParsersUnknownCellTypeCell`) return this._synthesizeCell() } _synthesizeCell() { @@ -950,7 +950,7 @@ class AbstractTreeError { return this.getNode().getLine() } getExtension() { - return this.getNode().handGrammarProgram.extensionName + return this.getNode().handParsersProgram.extensionName } getNode() { return this._node @@ -1079,7 +1079,7 @@ class LineAppearsMultipleTimesError extends AbstractTreeError { } class UnknownCellTypeError extends AbstractCellError { get message() { - return super.message + ` No cellType "${this.cell.cellTypeId}" found. Language grammar for "${this.getExtension()}" may need to be fixed.` + return super.message + ` No cellType "${this.cell.cellTypeId}" found. Language parsers for "${this.getExtension()}" may need to be fixed.` } } class InvalidWordError extends AbstractCellError { @@ -1118,21 +1118,21 @@ class MissingWordError extends AbstractCellError { } } // todo: add standard types, enum types, from disk types -class AbstractGrammarWordTestParser extends TreeNode {} -class GrammarRegexTestParser extends AbstractGrammarWordTestParser { +class AbstractParsersWordTestParser extends TreeNode {} +class ParsersRegexTestParser extends AbstractParsersWordTestParser { isValid(str) { if (!this._regex) this._regex = new RegExp("^" + this.content + "$") return !!str.match(this._regex) } } -class GrammarReservedWordsTestParser extends AbstractGrammarWordTestParser { +class ParsersReservedWordsTestParser extends AbstractParsersWordTestParser { isValid(str) { if (!this._set) this._set = new Set(this.content.split(" ")) return !this._set.has(str) } } // todo: remove in favor of custom word type constructors -class EnumFromCellTypesTestParser extends AbstractGrammarWordTestParser { +class EnumFromCellTypesTestParser extends AbstractParsersWordTestParser { _getEnumFromCellTypes(programRootNode) { const cellTypeIds = this.getWordsFrom(1) const enumGroup = cellTypeIds.join(" ") @@ -1156,7 +1156,7 @@ class EnumFromCellTypesTestParser extends AbstractGrammarWordTestParser { return this._getEnumFromCellTypes(programRootNode)[str] === true } } -class GrammarEnumTestNode extends AbstractGrammarWordTestParser { +class ParsersEnumTestNode extends AbstractParsersWordTestParser { isValid(str) { // enum c c++ java return !!this.getOptions()[str] @@ -1169,17 +1169,17 @@ class GrammarEnumTestNode extends AbstractGrammarWordTestParser { class cellTypeDefinitionParser extends AbstractExtendibleTreeNode { createParserCombinator() { const types = {} - types[GrammarConstants.regex] = GrammarRegexTestParser - types[GrammarConstants.reservedWords] = GrammarReservedWordsTestParser - types[GrammarConstants.enumFromCellTypes] = EnumFromCellTypesTestParser - types[GrammarConstants.enum] = GrammarEnumTestNode - types[GrammarConstants.highlightScope] = TreeNode - types[GrammarConstants.comment] = TreeNode - types[GrammarConstants.examples] = TreeNode - types[GrammarConstants.min] = TreeNode - types[GrammarConstants.max] = TreeNode - types[GrammarConstants.description] = TreeNode - types[GrammarConstants.extends] = TreeNode + types[ParsersConstants.regex] = ParsersRegexTestParser + types[ParsersConstants.reservedWords] = ParsersReservedWordsTestParser + types[ParsersConstants.enumFromCellTypes] = EnumFromCellTypesTestParser + types[ParsersConstants.enum] = ParsersEnumTestNode + types[ParsersConstants.highlightScope] = TreeNode + types[ParsersConstants.comment] = TreeNode + types[ParsersConstants.examples] = TreeNode + types[ParsersConstants.min] = TreeNode + types[ParsersConstants.max] = TreeNode + types[ParsersConstants.description] = TreeNode + types[ParsersConstants.extends] = TreeNode return new TreeNode.ParserCombinator(undefined, types) } get id() { @@ -1203,7 +1203,7 @@ class cellTypeDefinitionParser extends AbstractExtendibleTreeNode { // `this.getWordsFrom(${requireds.length + 1})` // todo: cleanup typings. todo: remove this hidden logic. have a "baseType" property? getCellConstructor() { - return this.preludeKind || GrammarAnyCell + return this.preludeKind || ParsersAnyCell } get preludeKind() { return PreludeKinds[this.getWord(0)] || PreludeKinds[this._getExtendedCellTypeId()] @@ -1218,22 +1218,22 @@ class cellTypeDefinitionParser extends AbstractExtendibleTreeNode { return arr[arr.length - 1].id } get highlightScope() { - const hs = this._getFromExtended(GrammarConstants.highlightScope) + const hs = this._getFromExtended(ParsersConstants.highlightScope) if (hs) return hs const preludeKind = this.preludeKind if (preludeKind) return preludeKind.defaultHighlightScope } _getEnumOptions() { - const enumNode = this._getNodeFromExtended(GrammarConstants.enum) + const enumNode = this._getNodeFromExtended(ParsersConstants.enum) if (!enumNode) return undefined // we sort by longest first to capture longest match first. todo: add test - const options = Object.keys(enumNode.getNode(GrammarConstants.enum).getOptions()) + const options = Object.keys(enumNode.getNode(ParsersConstants.enum).getOptions()) options.sort((a, b) => b.length - a.length) return options } _getEnumFromCellTypeOptions(program) { - const node = this._getNodeFromExtended(GrammarConstants.enumFromCellTypes) - return node ? Object.keys(node.getNode(GrammarConstants.enumFromCellTypes)._getEnumFromCellTypes(program)) : undefined + const node = this._getNodeFromExtended(ParsersConstants.enumFromCellTypes) + return node ? Object.keys(node.getNode(ParsersConstants.enumFromCellTypes)._getEnumFromCellTypes(program)) : undefined } _getAutocompleteWordOptions(program) { return this._getEnumOptions() || this._getEnumFromCellTypeOptions(program) || [] @@ -1241,10 +1241,10 @@ class cellTypeDefinitionParser extends AbstractExtendibleTreeNode { get regexString() { // todo: enum const enumOptions = this._getEnumOptions() - return this._getFromExtended(GrammarConstants.regex) || (enumOptions ? "(?:" + enumOptions.join("|") + ")" : "[^ ]*") + return this._getFromExtended(ParsersConstants.regex) || (enumOptions ? "(?:" + enumOptions.join("|") + ")" : "[^ ]*") } _getAllTests() { - return this._getChildrenByParserInExtended(AbstractGrammarWordTestParser) + return this._getChildrenByParserInExtended(AbstractParsersWordTestParser) } isValid(str, programRootNode) { return this._getAllTests().every(node => node.isValid(str, programRootNode)) @@ -1258,7 +1258,7 @@ class AbstractCellParser { this._definition = definition } get catchAllCellTypeId() { - return this._definition._getFromExtended(GrammarConstants.catchAllCellType) + return this._definition._getFromExtended(ParsersConstants.catchAllCellType) } // todo: improve layout (use bold?) get lineHints() { @@ -1268,7 +1268,7 @@ class AbstractCellParser { } getRequiredCellTypeIds() { if (!this._requiredCellTypeIds) { - const parameters = this._definition._getFromExtended(GrammarConstants.cells) + const parameters = this._definition._getFromExtended(ParsersConstants.cells) this._requiredCellTypeIds = parameters ? parameters.split(" ") : [] } return this._requiredCellTypeIds @@ -1282,7 +1282,7 @@ class AbstractCellParser { getCellArray(node = undefined) { const wordCount = node ? node.words.length : 0 const def = this._definition - const grammarProgram = def.languageDefinitionProgram + const parsersProgram = def.languageDefinitionProgram const requiredCellTypeIds = this.getRequiredCellTypeIds() const numberOfRequiredCells = requiredCellTypeIds.length const actualWordCountOrRequiredCellCount = Math.max(wordCount, numberOfRequiredCells) @@ -1291,14 +1291,14 @@ class AbstractCellParser { for (let cellIndex = 0; cellIndex < actualWordCountOrRequiredCellCount; cellIndex++) { const isCatchAll = this._isCatchAllCell(cellIndex, numberOfRequiredCells, wordCount) let cellTypeId = isCatchAll ? this.catchAllCellTypeId : this._getCellTypeId(cellIndex, requiredCellTypeIds, wordCount) - let cellTypeDefinition = grammarProgram.getCellTypeDefinitionById(cellTypeId) + let cellTypeDefinition = parsersProgram.getCellTypeDefinitionById(cellTypeId) let cellConstructor if (cellTypeDefinition) cellConstructor = cellTypeDefinition.getCellConstructor() - else if (cellTypeId) cellConstructor = GrammarUnknownCellTypeCell + else if (cellTypeId) cellConstructor = ParsersUnknownCellTypeCell else { - cellConstructor = GrammarExtraWordCellTypeCell + cellConstructor = ParsersExtraWordCellTypeCell cellTypeId = PreludeCellTypeIds.extraWordCell - cellTypeDefinition = grammarProgram.getCellTypeDefinitionById(cellTypeId) + cellTypeDefinition = parsersProgram.getCellTypeDefinitionById(cellTypeId) } const anyCellConstructor = cellConstructor cells[cellIndex] = new anyCellConstructor(node, cellIndex, cellTypeDefinition, cellTypeId, isCatchAll, def) @@ -1321,11 +1321,11 @@ class OmnifixCellParser extends AbstractCellParser { const cells = [] const def = this._definition const program = node ? node.root : undefined - const grammarProgram = def.languageDefinitionProgram + const parsersProgram = def.languageDefinitionProgram const words = node ? node.words : [] - const requiredCellTypeDefs = this.getRequiredCellTypeIds().map(cellTypeId => grammarProgram.getCellTypeDefinitionById(cellTypeId)) + const requiredCellTypeDefs = this.getRequiredCellTypeIds().map(cellTypeId => parsersProgram.getCellTypeDefinitionById(cellTypeId)) const catchAllCellTypeId = this.catchAllCellTypeId - const catchAllCellTypeDef = catchAllCellTypeId && grammarProgram.getCellTypeDefinitionById(catchAllCellTypeId) + const catchAllCellTypeDef = catchAllCellTypeId && parsersProgram.getCellTypeDefinitionById(catchAllCellTypeId) words.forEach((word, wordIndex) => { let cellConstructor for (let index = 0; index < requiredCellTypeDefs.length; index++) { @@ -1343,7 +1343,7 @@ class OmnifixCellParser extends AbstractCellParser { cells.push(new cellConstructor(node, wordIndex, catchAllCellTypeDef, catchAllCellTypeId, true, def)) return true } - cells.push(new GrammarUnknownCellTypeCell(node, wordIndex, undefined, undefined, false, def)) + cells.push(new ParsersUnknownCellTypeCell(node, wordIndex, undefined, undefined, false, def)) }) const wordCount = words.length requiredCellTypeDefs.forEach((cellTypeDef, index) => { @@ -1353,16 +1353,16 @@ class OmnifixCellParser extends AbstractCellParser { return cells } } -class GrammarExampleParser extends TreeNode {} -class GrammarCompilerParser extends TreeNode { +class ParsersExampleParser extends TreeNode {} +class ParsersCompilerParser extends TreeNode { createParserCombinator() { const types = [ - GrammarConstantsCompiler.stringTemplate, - GrammarConstantsCompiler.indentCharacter, - GrammarConstantsCompiler.catchAllCellDelimiter, - GrammarConstantsCompiler.joinChildrenWith, - GrammarConstantsCompiler.openChildren, - GrammarConstantsCompiler.closeChildren + ParsersConstantsCompiler.stringTemplate, + ParsersConstantsCompiler.indentCharacter, + ParsersConstantsCompiler.catchAllCellDelimiter, + ParsersConstantsCompiler.joinChildrenWith, + ParsersConstantsCompiler.openChildren, + ParsersConstantsCompiler.closeChildren ] const map = {} types.forEach(type => { @@ -1390,8 +1390,8 @@ class AbstractParserConstantParser extends TreeNode { return JSON.parse(this.constantValueAsJsText) } } -class GrammarParserConstantInt extends AbstractParserConstantParser {} -class GrammarParserConstantString extends AbstractParserConstantParser { +class ParsersParserConstantInt extends AbstractParserConstantParser {} +class ParsersParserConstantString extends AbstractParserConstantParser { get constantValueAsJsText() { return "`" + Utils.escapeBackTicks(this.constantValue) + "`" } @@ -1399,59 +1399,59 @@ class GrammarParserConstantString extends AbstractParserConstantParser { return this.length ? this.childrenToString() : this.getWordsFrom(2).join(" ") } } -class GrammarParserConstantFloat extends AbstractParserConstantParser {} -class GrammarParserConstantBoolean extends AbstractParserConstantParser {} +class ParsersParserConstantFloat extends AbstractParserConstantParser {} +class ParsersParserConstantBoolean extends AbstractParserConstantParser {} class AbstractParserDefinitionParser extends AbstractExtendibleTreeNode { createParserCombinator() { // todo: some of these should just be on nonRootNodes const types = [ - GrammarConstants.frequency, - GrammarConstants.inScope, - GrammarConstants.cells, - GrammarConstants.extends, - GrammarConstants.description, - GrammarConstants.catchAllParser, - GrammarConstants.catchAllCellType, - GrammarConstants.cellParser, - GrammarConstants.extensions, - GrammarConstants.version, - GrammarConstants.sortTemplate, - GrammarConstants.tags, - GrammarConstants.crux, - GrammarConstants.cruxFromId, - GrammarConstants.listDelimiter, - GrammarConstants.contentKey, - GrammarConstants.childrenKey, - GrammarConstants.uniqueFirstWord, - GrammarConstants.uniqueLine, - GrammarConstants.pattern, - GrammarConstants.baseParser, - GrammarConstants.required, - GrammarConstants.root, - GrammarConstants._extendsJsClass, - GrammarConstants._rootNodeJsHeader, - GrammarConstants.javascript, - GrammarConstants.compilesTo, - GrammarConstants.javascript, - GrammarConstants.single, - GrammarConstants.comment + ParsersConstants.frequency, + ParsersConstants.inScope, + ParsersConstants.cells, + ParsersConstants.extends, + ParsersConstants.description, + ParsersConstants.catchAllParser, + ParsersConstants.catchAllCellType, + ParsersConstants.cellParser, + ParsersConstants.extensions, + ParsersConstants.version, + ParsersConstants.sortTemplate, + ParsersConstants.tags, + ParsersConstants.crux, + ParsersConstants.cruxFromId, + ParsersConstants.listDelimiter, + ParsersConstants.contentKey, + ParsersConstants.childrenKey, + ParsersConstants.uniqueFirstWord, + ParsersConstants.uniqueLine, + ParsersConstants.pattern, + ParsersConstants.baseParser, + ParsersConstants.required, + ParsersConstants.root, + ParsersConstants._extendsJsClass, + ParsersConstants._rootNodeJsHeader, + ParsersConstants.javascript, + ParsersConstants.compilesTo, + ParsersConstants.javascript, + ParsersConstants.single, + ParsersConstants.comment ] const map = {} types.forEach(type => { map[type] = TreeNode }) - map[GrammarConstantsConstantTypes.boolean] = GrammarParserConstantBoolean - map[GrammarConstantsConstantTypes.int] = GrammarParserConstantInt - map[GrammarConstantsConstantTypes.string] = GrammarParserConstantString - map[GrammarConstantsConstantTypes.float] = GrammarParserConstantFloat - map[GrammarConstants.compilerParser] = GrammarCompilerParser - map[GrammarConstants.example] = GrammarExampleParser - return new TreeNode.ParserCombinator(undefined, map, [{ regex: HandGrammarProgram.parserFullRegex, parser: parserDefinitionParser }]) + map[ParsersConstantsConstantTypes.boolean] = ParsersParserConstantBoolean + map[ParsersConstantsConstantTypes.int] = ParsersParserConstantInt + map[ParsersConstantsConstantTypes.string] = ParsersParserConstantString + map[ParsersConstantsConstantTypes.float] = ParsersParserConstantFloat + map[ParsersConstants.compilerParser] = ParsersCompilerParser + map[ParsersConstants.example] = ParsersExampleParser + return new TreeNode.ParserCombinator(undefined, map, [{ regex: HandParsersProgram.parserFullRegex, parser: parserDefinitionParser }]) } get sortSpec() { const sortSections = new Map() const sortIndices = new Map() - const sortTemplate = this.get(GrammarConstants.sortTemplate) + const sortTemplate = this.get(ParsersConstants.sortTemplate) if (!sortTemplate) return { sortSections, sortIndices } sortTemplate.split(" ").forEach((section, sectionIndex) => section.split(" ").forEach(word => sortSections.set(word, sectionIndex))) sortTemplate.split(" ").forEach((word, index) => sortIndices.set(word, index)) @@ -1488,7 +1488,7 @@ ${properties.join("\n")} return this.getWord(0) } get idWithoutSuffix() { - return this.id.replace(HandGrammarProgram.parserSuffixRegex, "") + return this.id.replace(HandParsersProgram.parserSuffixRegex, "") } get constantsObject() { const obj = this._getUniqueConstantNodes() @@ -1503,7 +1503,7 @@ ${properties.join("\n")} return obj } get examples() { - return this._getChildrenByParserInExtended(GrammarExampleParser) + return this._getChildrenByParserInExtended(ParsersExampleParser) } get parserIdFromDefinition() { return this.getWord(0) @@ -1516,13 +1516,13 @@ ${properties.join("\n")} return !!this.generatedClassName } _isAbstract() { - return this.id.startsWith(GrammarConstants.abstractParserPrefix) + return this.id.startsWith(ParsersConstants.abstractParserPrefix) } get cruxIfAny() { - return this.get(GrammarConstants.crux) || (this._hasFromExtended(GrammarConstants.cruxFromId) ? this.idWithoutSuffix : undefined) + return this.get(ParsersConstants.crux) || (this._hasFromExtended(ParsersConstants.cruxFromId) ? this.idWithoutSuffix : undefined) } get regexMatch() { - return this.get(GrammarConstants.pattern) + return this.get(ParsersConstants.pattern) } get firstCellEnumOptions() { const firstCellDef = this._getMyCellTypeDefs()[0] @@ -1532,8 +1532,8 @@ ${properties.join("\n")} return this.root } get customJavascriptMethods() { - const hasJsCode = this.has(GrammarConstants.javascript) - return hasJsCode ? this.getNode(GrammarConstants.javascript).childrenToString() : "" + const hasJsCode = this.has(ParsersConstants.javascript) + return hasJsCode ? this.getNode(ParsersConstants.javascript).childrenToString() : "" } get firstWordMapWithDefinitions() { if (!this._cache_firstWordToNodeDefMap) this._cache_firstWordToNodeDefMap = this._createParserInfo(this._getInScopeParserIds()).firstWordMap @@ -1544,11 +1544,11 @@ ${properties.join("\n")} return this._getParser().getFirstWordOptions() } _getMyCellTypeDefs() { - const requiredCells = this.get(GrammarConstants.cells) + const requiredCells = this.get(ParsersConstants.cells) if (!requiredCells) return [] - const grammarProgram = this.languageDefinitionProgram + const parsersProgram = this.languageDefinitionProgram return requiredCells.split(" ").map(cellTypeId => { - const cellTypeDef = grammarProgram.getCellTypeDefinitionById(cellTypeId) + const cellTypeDef = parsersProgram.getCellTypeDefinitionById(cellTypeId) if (!cellTypeDef) throw new Error(`No cellType "${cellTypeId}" found`) return cellTypeDef }) @@ -1556,10 +1556,10 @@ ${properties.join("\n")} // todo: what happens when you have a cell getter and constant with same name? get cellGettersAndParserConstants() { // todo: add cellType parsings - const grammarProgram = this.languageDefinitionProgram + const parsersProgram = this.languageDefinitionProgram const getters = this._getMyCellTypeDefs().map((cellTypeDef, index) => cellTypeDef.getGetter(index)) - const catchAllCellTypeId = this.get(GrammarConstants.catchAllCellType) - if (catchAllCellTypeId) getters.push(grammarProgram.getCellTypeDefinitionById(catchAllCellTypeId).getCatchAllGetter(getters.length)) + const catchAllCellTypeId = this.get(ParsersConstants.catchAllCellType) + if (catchAllCellTypeId) getters.push(parsersProgram.getCellTypeDefinitionById(catchAllCellTypeId).getCatchAllGetter(getters.length)) // Constants Object.values(this._getUniqueConstantNodes(false)).forEach(node => getters.push(node.getGetter())) return getters.join("\n") @@ -1596,7 +1596,7 @@ ${properties.join("\n")} return arr } _getMyInScopeParserIds(target = this) { - const parsersNode = target.getNode(GrammarConstants.inScope) + const parsersNode = target.getNode(ParsersConstants.inScope) const scopedDefinitionIds = target.myScopedParserDefinitions.map(def => def.id) return parsersNode ? parsersNode.getWordsFrom(1).concat(scopedDefinitionIds) : scopedDefinitionIds } @@ -1607,15 +1607,15 @@ ${properties.join("\n")} return parentDef ? ids.concat(parentDef._getInScopeParserIds()) : ids } get isSingle() { - const hit = this._getNodeFromExtended(GrammarConstants.single) - return hit && hit.get(GrammarConstants.single) !== "false" + const hit = this._getNodeFromExtended(ParsersConstants.single) + return hit && hit.get(ParsersConstants.single) !== "false" } get isUniqueLine() { - const hit = this._getNodeFromExtended(GrammarConstants.uniqueLine) - return hit && hit.get(GrammarConstants.uniqueLine) !== "false" + const hit = this._getNodeFromExtended(ParsersConstants.uniqueLine) + return hit && hit.get(ParsersConstants.uniqueLine) !== "false" } isRequired() { - return this._hasFromExtended(GrammarConstants.required) + return this._hasFromExtended(ParsersConstants.required) } getParserDefinitionByParserId(parserId) { // todo: return catch all? @@ -1640,11 +1640,11 @@ ${properties.join("\n")} return this.root.rootParserDefinition } _isErrorParser() { - return this.get(GrammarConstants.baseParser) === GrammarConstants.errorParser + return this.get(ParsersConstants.baseParser) === ParsersConstants.errorParser } _isBlobParser() { // Do not check extended classes. Only do once. - return this._getFromExtended(GrammarConstants.baseParser) === GrammarConstants.blobParser + return this._getFromExtended(ParsersConstants.baseParser) === ParsersConstants.blobParser } get errorMethodToJavascript() { if (this._isBlobParser()) return "getErrors() { return [] }" // Skips parsing child nodes for perf gains. @@ -1685,7 +1685,7 @@ ${properties.join("\n")} } get catchAllParserToJavascript() { if (this._isBlobParser()) return "this._getBlobParserCatchAllParser()" - const parserId = this.get(GrammarConstants.catchAllParser) + const parserId = this.get(ParsersConstants.catchAllParser) if (!parserId) return "" const nodeDef = this.getParserDefinitionByParserId(parserId) return nodeDef.generatedClassName @@ -1694,9 +1694,9 @@ ${properties.join("\n")} const components = [this.parserAsJavascript, this.errorMethodToJavascript, this.cellGettersAndParserConstants, this.customJavascriptMethods].filter(identity => identity) const thisClassName = this.generatedClassName if (this._amIRoot()) { - components.push(`static cachedHandGrammarProgramRoot = new HandGrammarProgram(\`${Utils.escapeBackTicks(this.parent.toString().replace(/\\/g, "\\\\"))}\`) - get handGrammarProgram() { - return this.constructor.cachedHandGrammarProgramRoot + components.push(`static cachedHandParsersProgramRoot = new HandParsersProgram(\`${Utils.escapeBackTicks(this.parent.toString().replace(/\\/g, "\\\\"))}\`) + get handParsersProgram() { + return this.constructor.cachedHandParsersProgramRoot }`) components.push(`static rootParser = ${thisClassName}`) } @@ -1706,14 +1706,14 @@ ${properties.join("\n")} } _getExtendsClassName() { // todo: this is hopefully a temporary line in place for now for the case where you want your base class to extend something other than another treeclass - const hardCodedExtend = this.get(GrammarConstants._extendsJsClass) + const hardCodedExtend = this.get(ParsersConstants._extendsJsClass) if (hardCodedExtend) return hardCodedExtend const extendedDef = this._getExtendedParent() - return extendedDef ? extendedDef.generatedClassName : "GrammarBackedNode" + return extendedDef ? extendedDef.generatedClassName : "ParserBackedNode" } _getCompilerObject() { let obj = {} - const items = this._getChildrenByParserInExtended(GrammarCompilerParser) + const items = this._getChildrenByParserInExtended(ParsersCompilerParser) items.reverse() // Last definition wins. items.forEach(node => { obj = Object.assign(obj, node.toObject()) // todo: what about multiline strings? @@ -1729,7 +1729,7 @@ ${properties.join("\n")} return firstWordsInScope.some(firstWord => chain.has(firstWord)) } isTerminalParser() { - return !this._getFromExtended(GrammarConstants.inScope) && !this._getFromExtended(GrammarConstants.catchAllParser) + return !this._getFromExtended(ParsersConstants.inScope) && !this._getFromExtended(ParsersConstants.catchAllParser) } get sublimeMatchLine() { const regexMatch = this.regexMatch @@ -1756,7 +1756,7 @@ ${properties.join("\n")} const captures = requiredCellTypeIds .map((cellTypeId, index) => { const cellTypeDefinition = program.getCellTypeDefinitionById(cellTypeId) // todo: cleanup - if (!cellTypeDefinition) throw new Error(`No ${GrammarConstants.cellType} ${cellTypeId} found`) // todo: standardize error/capture error at grammar time + if (!cellTypeDefinition) throw new Error(`No ${ParsersConstants.cellType} ${cellTypeId} found`) // todo: standardize error/capture error at parsers time return ` ${index + 1}: ${(cellTypeDefinition.highlightScope || defaultHighlightScope) + "." + cellTypeDefinition.cellTypeId}` }) .join("\n") @@ -1794,10 +1794,10 @@ ${captures} return cache } get description() { - return this._getFromExtended(GrammarConstants.description) || "" + return this._getFromExtended(ParsersConstants.description) || "" } get frequency() { - const val = this._getFromExtended(GrammarConstants.frequency) + const val = this._getFromExtended(ParsersConstants.frequency) return val ? parseFloat(val) : 0 } _getExtendedParserId() { @@ -1833,8 +1833,8 @@ ${cells.toString(1)}` _shouldSynthesize(def, parserChain) { if (def._isErrorParser() || def._isAbstract()) return false if (parserChain.includes(def.id)) return false - const tags = def.get(GrammarConstants.tags) - if (tags && tags.includes(GrammarConstantsMisc.doNotSynthesize)) return false + const tags = def.get(ParsersConstants.tags) + if (tags && tags.includes(ParsersConstantsMisc.doNotSynthesize)) return false return true } // Get all definitions in this current scope down, even ones that are scoped inside other definitions. @@ -1879,7 +1879,7 @@ ${cells.toString(1)}` // todo: refactor synthesizeNode(nodeCount = 1, indentCount = -1, parsersAlreadySynthesized = [], seed = Date.now()) { let inScopeParserIds = this._getInScopeParserIds() - const catchAllParserId = this._getFromExtended(GrammarConstants.catchAllParser) + const catchAllParserId = this._getFromExtended(ParsersConstants.catchAllParser) if (catchAllParserId) inScopeParserIds.push(catchAllParserId) const thisId = this.id if (!parsersAlreadySynthesized.includes(thisId)) parsersAlreadySynthesized.push(thisId) @@ -1900,9 +1900,9 @@ ${cells.toString(1)}` } get cellParser() { if (!this._cellParser) { - const cellParsingStrategy = this._getFromExtended(GrammarConstants.cellParser) - if (cellParsingStrategy === GrammarCellParser.postfix) this._cellParser = new PostfixCellParser(this) - else if (cellParsingStrategy === GrammarCellParser.omnifix) this._cellParser = new OmnifixCellParser(this) + const cellParsingStrategy = this._getFromExtended(ParsersConstants.cellParser) + if (cellParsingStrategy === ParsersCellParser.postfix) this._cellParser = new PostfixCellParser(this) + else if (cellParsingStrategy === ParsersCellParser.omnifix) this._cellParser = new OmnifixCellParser(this) else this._cellParser = new PrefixCellParser(this) } return this._cellParser @@ -1910,16 +1910,16 @@ ${cells.toString(1)}` } // todo: remove? class parserDefinitionParser extends AbstractParserDefinitionParser {} -// HandGrammarProgram is a constructor that takes a grammar file, and builds a new +// HandParsersProgram is a constructor that takes a parsers file, and builds a new // constructor for new language that takes files in that language to execute, compile, etc. -class HandGrammarProgram extends AbstractParserDefinitionParser { +class HandParsersProgram extends AbstractParserDefinitionParser { createParserCombinator() { const map = {} - map[GrammarConstants.comment] = TreeNode + map[ParsersConstants.comment] = TreeNode return new TreeNode.ParserCombinator(UnknownParserNode, map, [ - { regex: HandGrammarProgram.blankLineRegex, parser: TreeNode }, - { regex: HandGrammarProgram.parserFullRegex, parser: parserDefinitionParser }, - { regex: HandGrammarProgram.cellTypeFullRegex, parser: cellTypeDefinitionParser } + { regex: HandParsersProgram.blankLineRegex, parser: TreeNode }, + { regex: HandParsersProgram.parserFullRegex, parser: parserDefinitionParser }, + { regex: HandParsersProgram.cellTypeFullRegex, parser: cellTypeDefinitionParser } ]) } // rootParser @@ -2024,7 +2024,7 @@ class HandGrammarProgram extends AbstractParserDefinitionParser { return vm.runInThisContext(code) } catch (err) { // todo: figure out best error pattern here for debugging - console.log(`Error in compiled grammar code for language "${this.grammarName}"`) + console.log(`Error in compiled parsers code for language "${this.parsersName}"`) // console.log(new TreeNode(code).toStringWithLineNumbers()) console.log(err) throw err @@ -2105,7 +2105,7 @@ paragraph This readme was auto-generated using the const languageName = this.extensionName const example = rootNodeDef.examples[0] const sampleCode = example ? example.childrenToString() : "" - files[GrammarBundleFiles.package] = JSON.stringify( + files[ParsersBundleFiles.package] = JSON.stringify( { name: languageName, private: true, @@ -2116,7 +2116,7 @@ paragraph This readme was auto-generated using the null, 2 ) - files[GrammarBundleFiles.readme] = this.toReadMe() + files[ParsersBundleFiles.readme] = this.toReadMe() const testCode = `const program = new ${languageName}(sampleCode) const errors = program.getAllErrors() console.log("Sample program compiled with " + errors.length + " errors.") @@ -2124,12 +2124,12 @@ if (errors.length) console.log(errors.map(error => error.message))` const nodePath = `${languageName}.node.js` files[nodePath] = this.toNodeJsJavascript() - files[GrammarBundleFiles.indexJs] = `module.exports = require("./${nodePath}")` + files[ParsersBundleFiles.indexJs] = `module.exports = require("./${nodePath}")` const browserPath = `${languageName}.browser.js` files[browserPath] = this.toBrowserJavascript() - files[GrammarBundleFiles.indexHtml] = ` + files[ParsersBundleFiles.indexHtml] = ` - + ` const samplePath = "sample." + this.extensionName files[samplePath] = sampleCode.toString() - files[GrammarBundleFiles.testJs] = `const ${languageName} = require("./index.js") + files[ParsersBundleFiles.testJs] = `const ${languageName} = require("./index.js") /*keep-line*/ const sampleCode = require("fs").readFileSync("${samplePath}", "utf8") ${testCode}` return files } get targetExtension() { - return this.rootParserDefinition.get(GrammarConstants.compilesTo) + return this.rootParserDefinition.get(ParsersConstants.compilesTo) } get cellTypeDefinitions() { if (this._cache_cellTypes) return this._cache_cellTypes @@ -2169,7 +2169,7 @@ ${testCode}` return this.getChildrenByParser(parserDefinitionParser).filter(node => node._hasValidParserId()) } get lastRootParserDefinitionNode() { - return this.findLast(def => def instanceof AbstractParserDefinitionParser && def.has(GrammarConstants.root) && def._hasValidParserId()) + return this.findLast(def => def instanceof AbstractParserDefinitionParser && def.has(ParsersConstants.root) && def._hasValidParserId()) } _initRootParserDefinitionNode() { if (this._cache_rootParserNode) return @@ -2177,9 +2177,9 @@ ${testCode}` // By default, have a very permissive basic root node. // todo: whats the best design pattern to use for this sort of thing? if (!this._cache_rootParserNode) { - this._cache_rootParserNode = this.concat(`${GrammarConstants.DefaultRootParser} - ${GrammarConstants.root} - ${GrammarConstants.catchAllParser} ${GrammarConstants.BlobParser}`)[0] + this._cache_rootParserNode = this.concat(`${ParsersConstants.DefaultRootParser} + ${ParsersConstants.root} + ${ParsersConstants.catchAllParser} ${ParsersConstants.BlobParser}`)[0] this._addDefaultCatchAllBlobParser() } } @@ -2191,11 +2191,11 @@ ${testCode}` if (this._addedCatchAll) return this._addedCatchAll = true delete this._cache_parserDefinitionParsers - this.concat(`${GrammarConstants.BlobParser} - ${GrammarConstants.baseParser} ${GrammarConstants.blobParser}`) + this.concat(`${ParsersConstants.BlobParser} + ${ParsersConstants.baseParser} ${ParsersConstants.blobParser}`) } get extensionName() { - return this.grammarName + return this.parsersName } get id() { return this.rootParserId @@ -2203,14 +2203,14 @@ ${testCode}` get rootParserId() { return this.rootParserDefinition.parserIdFromDefinition } - get grammarName() { - return this.rootParserId.replace(HandGrammarProgram.parserSuffixRegex, "") + get parsersName() { + return this.rootParserId.replace(HandParsersProgram.parserSuffixRegex, "") } _getMyInScopeParserIds() { return super._getMyInScopeParserIds(this.rootParserDefinition) } _getInScopeParserIds() { - const parsersNode = this.rootParserDefinition.getNode(GrammarConstants.inScope) + const parsersNode = this.rootParserDefinition.getNode(ParsersConstants.inScope) return parsersNode ? parsersNode.getWordsFrom(1) : [] } makeProgramParserDefinitionCache() { @@ -2226,7 +2226,7 @@ ${testCode}` return this._cached_rootParser } get fileExtensions() { - return this.rootParserDefinition.get(GrammarConstants.extensions) ? this.rootParserDefinition.get(GrammarConstants.extensions).split(" ").join(",") : this.extensionName + return this.rootParserDefinition.get(ParsersConstants.extensions) ? this.rootParserDefinition.get(ParsersConstants.extensions).split(" ").join(",") : this.extensionName } toNodeJsJavascript(scrollsdkProductsPath = "scrollsdk/products") { return this._rootNodeDefToJavascriptClass(scrollsdkProductsPath, true).trim() @@ -2239,7 +2239,7 @@ ${testCode}` // todo: throw if there is no root node defined const parserClasses = defs.map(def => def.asJavascriptClass).join("\n\n") const rootDef = this.rootParserDefinition - const rootNodeJsHeader = forNodeJs && rootDef._getConcatBlockStringFromExtended(GrammarConstants._rootNodeJsHeader) + const rootNodeJsHeader = forNodeJs && rootDef._getConcatBlockStringFromExtended(ParsersConstants._rootNodeJsHeader) const rootName = rootDef.generatedClassName if (!rootName) throw new Error(`Root Node Type Has No Name`) let exportScript = "" @@ -2257,7 +2257,7 @@ ${rootName}` }) .join("\n") } - // todo: we can expose the previous "constants" export, if needed, via the grammar, which we preserve. + // todo: we can expose the previous "constants" export, if needed, via the parsers, which we preserve. return `{ ${nodeJsImports} ${rootNodeJsHeader ? rootNodeJsHeader : ""} @@ -2291,35 +2291,35 @@ ${includes} ${parserContexts}` } } -HandGrammarProgram.makeParserId = str => Utils._replaceNonAlphaNumericCharactersWithCharCodes(str).replace(HandGrammarProgram.parserSuffixRegex, "") + GrammarConstants.parserSuffix -HandGrammarProgram.makeCellTypeId = str => Utils._replaceNonAlphaNumericCharactersWithCharCodes(str).replace(HandGrammarProgram.cellTypeSuffixRegex, "") + GrammarConstants.cellTypeSuffix -HandGrammarProgram.parserSuffixRegex = new RegExp(GrammarConstants.parserSuffix + "$") -HandGrammarProgram.parserFullRegex = new RegExp("^[a-zA-Z0-9_]+" + GrammarConstants.parserSuffix + "$") -HandGrammarProgram.blankLineRegex = new RegExp("^$") -HandGrammarProgram.cellTypeSuffixRegex = new RegExp(GrammarConstants.cellTypeSuffix + "$") -HandGrammarProgram.cellTypeFullRegex = new RegExp("^[a-zA-Z0-9_]+" + GrammarConstants.cellTypeSuffix + "$") -HandGrammarProgram._languages = {} -HandGrammarProgram._parsers = {} +HandParsersProgram.makeParserId = str => Utils._replaceNonAlphaNumericCharactersWithCharCodes(str).replace(HandParsersProgram.parserSuffixRegex, "") + ParsersConstants.parserSuffix +HandParsersProgram.makeCellTypeId = str => Utils._replaceNonAlphaNumericCharactersWithCharCodes(str).replace(HandParsersProgram.cellTypeSuffixRegex, "") + ParsersConstants.cellTypeSuffix +HandParsersProgram.parserSuffixRegex = new RegExp(ParsersConstants.parserSuffix + "$") +HandParsersProgram.parserFullRegex = new RegExp("^[a-zA-Z0-9_]+" + ParsersConstants.parserSuffix + "$") +HandParsersProgram.blankLineRegex = new RegExp("^$") +HandParsersProgram.cellTypeSuffixRegex = new RegExp(ParsersConstants.cellTypeSuffix + "$") +HandParsersProgram.cellTypeFullRegex = new RegExp("^[a-zA-Z0-9_]+" + ParsersConstants.cellTypeSuffix + "$") +HandParsersProgram._languages = {} +HandParsersProgram._parsers = {} const PreludeKinds = {} -PreludeKinds[PreludeCellTypeIds.anyCell] = GrammarAnyCell -PreludeKinds[PreludeCellTypeIds.keywordCell] = GrammarKeywordCell -PreludeKinds[PreludeCellTypeIds.floatCell] = GrammarFloatCell -PreludeKinds[PreludeCellTypeIds.numberCell] = GrammarFloatCell -PreludeKinds[PreludeCellTypeIds.bitCell] = GrammarBitCell -PreludeKinds[PreludeCellTypeIds.boolCell] = GrammarBoolCell -PreludeKinds[PreludeCellTypeIds.intCell] = GrammarIntCell -class UnknownGrammarProgram extends TreeNode { - _inferRootNodeForAPrefixLanguage(grammarName) { - grammarName = HandGrammarProgram.makeParserId(grammarName) - const rootNode = new TreeNode(`${grammarName} - ${GrammarConstants.root}`) - // note: right now we assume 1 global cellTypeMap and parserMap per grammar. But we may have scopes in the future? +PreludeKinds[PreludeCellTypeIds.anyCell] = ParsersAnyCell +PreludeKinds[PreludeCellTypeIds.keywordCell] = ParsersKeywordCell +PreludeKinds[PreludeCellTypeIds.floatCell] = ParsersFloatCell +PreludeKinds[PreludeCellTypeIds.numberCell] = ParsersFloatCell +PreludeKinds[PreludeCellTypeIds.bitCell] = ParsersBitCell +PreludeKinds[PreludeCellTypeIds.boolCell] = ParsersBoolCell +PreludeKinds[PreludeCellTypeIds.intCell] = ParsersIntCell +class UnknownParsersProgram extends TreeNode { + _inferRootNodeForAPrefixLanguage(parsersName) { + parsersName = HandParsersProgram.makeParserId(parsersName) + const rootNode = new TreeNode(`${parsersName} + ${ParsersConstants.root}`) + // note: right now we assume 1 global cellTypeMap and parserMap per parsers. But we may have scopes in the future? const rootNodeNames = this.getFirstWords() .filter(identity => identity) - .map(word => HandGrammarProgram.makeParserId(word)) + .map(word => HandParsersProgram.makeParserId(word)) rootNode .nodeAt(0) - .touchNode(GrammarConstants.inScope) + .touchNode(ParsersConstants.inScope) .setWordsFrom(1, Array.from(new Set(rootNodeNames))) return rootNode } @@ -2328,7 +2328,7 @@ class UnknownGrammarProgram extends TreeNode { for (let node of clone.getTopDownArrayIterator()) { const firstWordIsAnInteger = !!node.firstWord.match(/^\d+$/) const parentFirstWord = node.parent.firstWord - if (firstWordIsAnInteger && parentFirstWord) node.setFirstWord(HandGrammarProgram.makeParserId(parentFirstWord + UnknownGrammarProgram._childSuffix)) + if (firstWordIsAnInteger && parentFirstWord) node.setFirstWord(HandParsersProgram.makeParserId(parentFirstWord + UnknownParsersProgram._childSuffix)) } } _getKeywordMaps(clone) { @@ -2345,10 +2345,10 @@ class UnknownGrammarProgram extends TreeNode { } _inferParserDef(firstWord, globalCellTypeMap, childFirstWords, instances) { const edgeSymbol = this.edgeSymbol - const parserId = HandGrammarProgram.makeParserId(firstWord) + const parserId = HandParsersProgram.makeParserId(firstWord) const nodeDefNode = new TreeNode(parserId).nodeAt(0) - const childParserIds = childFirstWords.map(word => HandGrammarProgram.makeParserId(word)) - if (childParserIds.length) nodeDefNode.touchNode(GrammarConstants.inScope).setWordsFrom(1, childParserIds) + const childParserIds = childFirstWords.map(word => HandParsersProgram.makeParserId(word)) + if (childParserIds.length) nodeDefNode.touchNode(ParsersConstants.inScope).setWordsFrom(1, childParserIds) const cellsForAllInstances = instances .map(line => line.content) .filter(identity => identity) @@ -2375,29 +2375,29 @@ class UnknownGrammarProgram extends TreeNode { cellTypeIds.pop() } } - const needsCruxProperty = !firstWord.endsWith(UnknownGrammarProgram._childSuffix + GrammarConstants.parserSuffix) // todo: cleanup - if (needsCruxProperty) nodeDefNode.set(GrammarConstants.crux, firstWord) - if (catchAllCellType) nodeDefNode.set(GrammarConstants.catchAllCellType, catchAllCellType) + const needsCruxProperty = !firstWord.endsWith(UnknownParsersProgram._childSuffix + ParsersConstants.parserSuffix) // todo: cleanup + if (needsCruxProperty) nodeDefNode.set(ParsersConstants.crux, firstWord) + if (catchAllCellType) nodeDefNode.set(ParsersConstants.catchAllCellType, catchAllCellType) const cellLine = cellTypeIds.slice() cellLine.unshift(PreludeCellTypeIds.keywordCell) - if (cellLine.length > 0) nodeDefNode.set(GrammarConstants.cells, cellLine.join(edgeSymbol)) - //if (!catchAllCellType && cellTypeIds.length === 1) nodeDefNode.set(GrammarConstants.cells, cellTypeIds[0]) + if (cellLine.length > 0) nodeDefNode.set(ParsersConstants.cells, cellLine.join(edgeSymbol)) + //if (!catchAllCellType && cellTypeIds.length === 1) nodeDefNode.set(ParsersConstants.cells, cellTypeIds[0]) // Todo: add conditional frequencies return nodeDefNode.parent.toString() } - // inferGrammarFileForAnSSVLanguage(grammarName: string): string { - // grammarName = HandGrammarProgram.makeParserId(grammarName) - // const rootNode = new TreeNode(`${grammarName} - // ${GrammarConstants.root}`) - // // note: right now we assume 1 global cellTypeMap and parserMap per grammar. But we may have scopes in the future? - // const rootNodeNames = this.getFirstWords().map(word => HandGrammarProgram.makeParserId(word)) + // inferParsersFileForAnSSVLanguage(parsersName: string): string { + // parsersName = HandParsersProgram.makeParserId(parsersName) + // const rootNode = new TreeNode(`${parsersName} + // ${ParsersConstants.root}`) + // // note: right now we assume 1 global cellTypeMap and parserMap per parsers. But we may have scopes in the future? + // const rootNodeNames = this.getFirstWords().map(word => HandParsersProgram.makeParserId(word)) // rootNode // .nodeAt(0) - // .touchNode(GrammarConstants.inScope) + // .touchNode(ParsersConstants.inScope) // .setWordsFrom(1, Array.from(new Set(rootNodeNames))) // return rootNode // } - inferGrammarFileForAKeywordLanguage(grammarName) { + inferParsersFileForAKeywordLanguage(parsersName) { const clone = this.clone() this._renameIntegerKeywords(clone) const { keywordsToChildKeywords, keywordsToNodeInstances } = this._getKeywordMaps(clone) @@ -2409,13 +2409,13 @@ class UnknownGrammarProgram extends TreeNode { const cellTypeDefs = [] globalCellTypeMap.forEach((def, id) => cellTypeDefs.push(def ? def : id)) const nodeBreakSymbol = this.nodeBreakSymbol - return this._formatCode([this._inferRootNodeForAPrefixLanguage(grammarName).toString(), cellTypeDefs.join(nodeBreakSymbol), parserDefs.join(nodeBreakSymbol)].filter(identity => identity).join("\n")) + return this._formatCode([this._inferRootNodeForAPrefixLanguage(parsersName).toString(), cellTypeDefs.join(nodeBreakSymbol), parserDefs.join(nodeBreakSymbol)].filter(identity => identity).join("\n")) } _formatCode(code) { // todo: make this run in browser too if (!this.isNodeJs()) return code - const grammarProgram = new HandGrammarProgram(TreeNode.fromDisk(__dirname + "/../langs/grammar/grammar.grammar")) - const rootParser = grammarProgram.compileAndReturnRootParser() + const parsersProgram = new HandParsersProgram(TreeNode.fromDisk(__dirname + "/../langs/parsers/parsers.parsers")) + const rootParser = parsersProgram.compileAndReturnRootParser() const program = new rootParser(code) return program.format().toString() } @@ -2446,17 +2446,17 @@ class UnknownGrammarProgram extends TreeNode { const enumLimit = 30 if (instanceCount > 1 && maxCellsOnLine === 1 && allValues.length > asSet.size && asSet.size < enumLimit) return { - cellTypeId: HandGrammarProgram.makeCellTypeId(firstWord), - cellTypeDefinition: `${HandGrammarProgram.makeCellTypeId(firstWord)} + cellTypeId: HandParsersProgram.makeCellTypeId(firstWord), + cellTypeDefinition: `${HandParsersProgram.makeCellTypeId(firstWord)} enum ${values.join(edgeSymbol)}` } return { cellTypeId: PreludeCellTypeIds.anyCell } } } -UnknownGrammarProgram._childSuffix = "Child" -window.GrammarConstants = GrammarConstants +UnknownParsersProgram._childSuffix = "Child" +window.ParsersConstants = ParsersConstants window.PreludeCellTypeIds = PreludeCellTypeIds -window.HandGrammarProgram = HandGrammarProgram -window.GrammarBackedNode = GrammarBackedNode +window.HandParsersProgram = HandParsersProgram +window.ParserBackedNode = ParserBackedNode window.UnknownParserError = UnknownParserError -window.UnknownGrammarProgram = UnknownGrammarProgram +window.UnknownParsersProgram = UnknownParsersProgram diff --git a/products/GrammarCodeMirrorMode.browser.js b/products/ParsersCodeMirrorMode.browser.js similarity index 98% rename from products/GrammarCodeMirrorMode.browser.js rename to products/ParsersCodeMirrorMode.browser.js index 2aba23e88..8e2cc3813 100644 --- a/products/GrammarCodeMirrorMode.browser.js +++ b/products/ParsersCodeMirrorMode.browser.js @@ -179,7 +179,7 @@ const textMateScopeToCodeMirrorStyle = (scopeSegments, styleTree = tmToCm) => { const matchingBranch = styleTree[scopeSegments.shift()] return matchingBranch ? textMateScopeToCodeMirrorStyle(scopeSegments, matchingBranch) || matchingBranch.$ || null : null } -class GrammarCodeMirrorMode { +class ParsersCodeMirrorMode { constructor(name, getRootParserFn, getProgramCodeFn, codeMirrorLib = undefined) { this._name = name this._getRootParserFn = getRootParserFn @@ -322,7 +322,7 @@ class GrammarCodeMirrorMode { if (!program.getCellHighlightScopeAtPosition) console.log(program) const highlightScope = program.getCellHighlightScopeAtPosition(lineIndex, cellIndex) const style = highlightScope ? textMateScopeToCodeMirrorStyle(highlightScope.split(".")) : undefined - return style || "noHighlightScopeDefinedInGrammar" + return style || "noHighlightScopeDefinedInParsers" } // todo: remove. startState() { @@ -334,4 +334,4 @@ class GrammarCodeMirrorMode { state.cellIndex = 0 } } -window.GrammarCodeMirrorMode = GrammarCodeMirrorMode +window.ParsersCodeMirrorMode = ParsersCodeMirrorMode diff --git a/products/GrammarCodeMirrorMode.js b/products/ParsersCodeMirrorMode.js similarity index 98% rename from products/GrammarCodeMirrorMode.js rename to products/ParsersCodeMirrorMode.js index 93115e7d8..d048bf97c 100644 --- a/products/GrammarCodeMirrorMode.js +++ b/products/ParsersCodeMirrorMode.js @@ -180,7 +180,7 @@ const textMateScopeToCodeMirrorStyle = (scopeSegments, styleTree = tmToCm) => { const matchingBranch = styleTree[scopeSegments.shift()] return matchingBranch ? textMateScopeToCodeMirrorStyle(scopeSegments, matchingBranch) || matchingBranch.$ || null : null } -class GrammarCodeMirrorMode { +class ParsersCodeMirrorMode { constructor(name, getRootParserFn, getProgramCodeFn, codeMirrorLib = undefined) { this._name = name this._getRootParserFn = getRootParserFn @@ -323,7 +323,7 @@ class GrammarCodeMirrorMode { if (!program.getCellHighlightScopeAtPosition) console.log(program) const highlightScope = program.getCellHighlightScopeAtPosition(lineIndex, cellIndex) const style = highlightScope ? textMateScopeToCodeMirrorStyle(highlightScope.split(".")) : undefined - return style || "noHighlightScopeDefinedInGrammar" + return style || "noHighlightScopeDefinedInParsers" } // todo: remove. startState() { @@ -336,4 +336,4 @@ class GrammarCodeMirrorMode { } } -module.exports = { GrammarCodeMirrorMode } +module.exports = { ParsersCodeMirrorMode } diff --git a/products/GrammarCompiler.js b/products/ParsersCompiler.js similarity index 54% rename from products/GrammarCompiler.js rename to products/ParsersCompiler.js index c420d4926..7d3e5988a 100644 --- a/products/GrammarCompiler.js +++ b/products/ParsersCompiler.js @@ -3,21 +3,21 @@ const fs = require("fs") const path = require("path") const { Utils } = require("../products/Utils.js") const { TreeNode } = require("../products/TreeNode.js") -const { HandGrammarProgram } = require("./GrammarLanguage.js") +const { HandParsersProgram } = require("./Parsers.js") var CompileTarget ;(function (CompileTarget) { CompileTarget["nodejs"] = "nodejs" CompileTarget["browser"] = "browser" })(CompileTarget || (CompileTarget = {})) -class GrammarCompiler { - static compileGrammarForNodeJs(pathToGrammar, outputFolder, usePrettier = true, scrollsdkProductsPath = __dirname) { - return this._compileGrammar(pathToGrammar, outputFolder, CompileTarget.nodejs, usePrettier, scrollsdkProductsPath) +class ParsersCompiler { + static compileParsersForNodeJs(pathToParsers, outputFolder, usePrettier = true, scrollsdkProductsPath = __dirname) { + return this._compileParsers(pathToParsers, outputFolder, CompileTarget.nodejs, usePrettier, scrollsdkProductsPath) } - static _compileGrammar(pathToGrammar, outputFolder, target, usePrettier, scrollsdkProductsPath) { + static _compileParsers(pathToParsers, outputFolder, target, usePrettier, scrollsdkProductsPath) { const isNodeJs = CompileTarget.nodejs === target - const grammarCode = TreeNode.fromDisk(pathToGrammar) - const program = new HandGrammarProgram(grammarCode.toString()) - const outputFilePath = path.join(outputFolder, `${program.grammarName}.${target}.js`) + const parsersCode = TreeNode.fromDisk(pathToParsers) + const program = new HandParsersProgram(parsersCode.toString()) + const outputFilePath = path.join(outputFolder, `${program.parsersName}.${target}.js`) let result = isNodeJs ? program.toNodeJsJavascript(scrollsdkProductsPath) : program.toBrowserJavascript() if (isNodeJs) result = @@ -34,42 +34,42 @@ if (!module.parent) new ${program.rootParserId}(TreeNode.fromDisk(process.argv[2 if (isNodeJs) fs.chmodSync(outputFilePath, 0o755) return outputFilePath } - static compileGrammarForBrowser(pathToGrammar, outputFolder, usePrettier = true) { - return this._compileGrammar(pathToGrammar, outputFolder, CompileTarget.browser, usePrettier) + static compileParsersForBrowser(pathToParsers, outputFolder, usePrettier = true) { + return this._compileParsers(pathToParsers, outputFolder, CompileTarget.browser, usePrettier) } } -_a = GrammarCompiler -GrammarCompiler.compileGrammarAndCreateProgram = (programPath, grammarPath) => { +_a = ParsersCompiler +ParsersCompiler.compileParsersAndCreateProgram = (programPath, parsersPath) => { // tod: remove? - const rootParser = _a.compileGrammarFileAtPathAndReturnRootParser(grammarPath) + const rootParser = _a.compileParsersFileAtPathAndReturnRootParser(parsersPath) return new rootParser(fs.readFileSync(programPath, "utf8")) } -GrammarCompiler.formatCode = (programCode, grammarPath) => { +ParsersCompiler.formatCode = (programCode, parsersPath) => { // tod: remove? - const rootParser = _a.compileGrammarFileAtPathAndReturnRootParser(grammarPath) + const rootParser = _a.compileParsersFileAtPathAndReturnRootParser(parsersPath) const program = new rootParser(programCode) return program.format().toString() } -GrammarCompiler.formatFileInPlace = (programPath, grammarPath) => { +ParsersCompiler.formatFileInPlace = (programPath, parsersPath) => { // tod: remove? const original = TreeNode.fromDisk(programPath) - const formatted = _a.formatCode(original.toString(), grammarPath) + const formatted = _a.formatCode(original.toString(), parsersPath) if (original === formatted) return false new TreeNode(formatted).toDisk(programPath) return true } -GrammarCompiler.compileGrammarFileAtPathAndReturnRootParser = grammarPath => { +ParsersCompiler.compileParsersFileAtPathAndReturnRootParser = parsersPath => { // todo: remove - if (!fs.existsSync(grammarPath)) throw new Error(`Grammar file does not exist: ${grammarPath}`) - const grammarCode = fs.readFileSync(grammarPath, "utf8") - const grammarProgram = new HandGrammarProgram(grammarCode) - return grammarProgram.compileAndReturnRootParser() + if (!fs.existsSync(parsersPath)) throw new Error(`Parsers file does not exist: ${parsersPath}`) + const parsersCode = fs.readFileSync(parsersPath, "utf8") + const parsersProgram = new HandParsersProgram(parsersCode) + return parsersProgram.compileAndReturnRootParser() } -GrammarCompiler.combineFiles = globPatterns => { +ParsersCompiler.combineFiles = globPatterns => { const glob = require("glob") const files = Utils.flatten(globPatterns.map(pattern => glob.sync(pattern))) const content = files.map(path => fs.readFileSync(path, "utf8")).join("\n") return new TreeNode(content) } -module.exports = { GrammarCompiler } +module.exports = { ParsersCompiler } diff --git a/products/ParsersLanguage.browser.js b/products/ParsersLanguage.browser.js new file mode 100644 index 000000000..91ea36b9b --- /dev/null +++ b/products/ParsersLanguage.browser.js @@ -0,0 +1,2462 @@ +// Compiled language parsers will include these files: +const GlobalNamespaceAdditions = { + Utils: "Utils.js", + TreeNode: "TreeNode.js", + HandParsersProgram: "Parsers.js", + ParserBackedNode: "Parsers.js" +} +var ParsersConstantsCompiler +;(function (ParsersConstantsCompiler) { + ParsersConstantsCompiler["stringTemplate"] = "stringTemplate" + ParsersConstantsCompiler["indentCharacter"] = "indentCharacter" + ParsersConstantsCompiler["catchAllCellDelimiter"] = "catchAllCellDelimiter" + ParsersConstantsCompiler["openChildren"] = "openChildren" + ParsersConstantsCompiler["joinChildrenWith"] = "joinChildrenWith" + ParsersConstantsCompiler["closeChildren"] = "closeChildren" +})(ParsersConstantsCompiler || (ParsersConstantsCompiler = {})) +var ParsersConstantsMisc +;(function (ParsersConstantsMisc) { + ParsersConstantsMisc["doNotSynthesize"] = "doNotSynthesize" +})(ParsersConstantsMisc || (ParsersConstantsMisc = {})) +var PreludeCellTypeIds +;(function (PreludeCellTypeIds) { + PreludeCellTypeIds["anyCell"] = "anyCell" + PreludeCellTypeIds["keywordCell"] = "keywordCell" + PreludeCellTypeIds["extraWordCell"] = "extraWordCell" + PreludeCellTypeIds["floatCell"] = "floatCell" + PreludeCellTypeIds["numberCell"] = "numberCell" + PreludeCellTypeIds["bitCell"] = "bitCell" + PreludeCellTypeIds["boolCell"] = "boolCell" + PreludeCellTypeIds["intCell"] = "intCell" +})(PreludeCellTypeIds || (PreludeCellTypeIds = {})) +var ParsersConstantsConstantTypes +;(function (ParsersConstantsConstantTypes) { + ParsersConstantsConstantTypes["boolean"] = "boolean" + ParsersConstantsConstantTypes["string"] = "string" + ParsersConstantsConstantTypes["int"] = "int" + ParsersConstantsConstantTypes["float"] = "float" +})(ParsersConstantsConstantTypes || (ParsersConstantsConstantTypes = {})) +var ParsersBundleFiles +;(function (ParsersBundleFiles) { + ParsersBundleFiles["package"] = "package.json" + ParsersBundleFiles["readme"] = "readme.md" + ParsersBundleFiles["indexHtml"] = "index.html" + ParsersBundleFiles["indexJs"] = "index.js" + ParsersBundleFiles["testJs"] = "test.js" +})(ParsersBundleFiles || (ParsersBundleFiles = {})) +var ParsersCellParser +;(function (ParsersCellParser) { + ParsersCellParser["prefix"] = "prefix" + ParsersCellParser["postfix"] = "postfix" + ParsersCellParser["omnifix"] = "omnifix" +})(ParsersCellParser || (ParsersCellParser = {})) +var ParsersConstants +;(function (ParsersConstants) { + // node types + ParsersConstants["extensions"] = "extensions" + ParsersConstants["comment"] = "//" + ParsersConstants["version"] = "version" + ParsersConstants["parser"] = "parser" + ParsersConstants["cellType"] = "cellType" + ParsersConstants["parsersFileExtension"] = "parsers" + ParsersConstants["abstractParserPrefix"] = "abstract" + ParsersConstants["parserSuffix"] = "Parser" + ParsersConstants["cellTypeSuffix"] = "Cell" + // error check time + ParsersConstants["regex"] = "regex" + ParsersConstants["reservedWords"] = "reservedWords" + ParsersConstants["enumFromCellTypes"] = "enumFromCellTypes" + ParsersConstants["enum"] = "enum" + ParsersConstants["examples"] = "examples" + ParsersConstants["min"] = "min" + ParsersConstants["max"] = "max" + // baseParsers + ParsersConstants["baseParser"] = "baseParser" + ParsersConstants["blobParser"] = "blobParser" + ParsersConstants["errorParser"] = "errorParser" + // parse time + ParsersConstants["extends"] = "extends" + ParsersConstants["root"] = "root" + ParsersConstants["crux"] = "crux" + ParsersConstants["cruxFromId"] = "cruxFromId" + ParsersConstants["pattern"] = "pattern" + ParsersConstants["inScope"] = "inScope" + ParsersConstants["cells"] = "cells" + ParsersConstants["listDelimiter"] = "listDelimiter" + ParsersConstants["contentKey"] = "contentKey" + ParsersConstants["childrenKey"] = "childrenKey" + ParsersConstants["uniqueFirstWord"] = "uniqueFirstWord" + ParsersConstants["catchAllCellType"] = "catchAllCellType" + ParsersConstants["cellParser"] = "cellParser" + ParsersConstants["catchAllParser"] = "catchAllParser" + ParsersConstants["constants"] = "constants" + ParsersConstants["required"] = "required" + ParsersConstants["single"] = "single" + ParsersConstants["uniqueLine"] = "uniqueLine" + ParsersConstants["tags"] = "tags" + ParsersConstants["_extendsJsClass"] = "_extendsJsClass" + ParsersConstants["_rootNodeJsHeader"] = "_rootNodeJsHeader" + // default catchAll parser + ParsersConstants["BlobParser"] = "BlobParser" + ParsersConstants["DefaultRootParser"] = "DefaultRootParser" + // code + ParsersConstants["javascript"] = "javascript" + // compile time + ParsersConstants["compilerParser"] = "compiler" + ParsersConstants["compilesTo"] = "compilesTo" + // develop time + ParsersConstants["description"] = "description" + ParsersConstants["example"] = "example" + ParsersConstants["sortTemplate"] = "sortTemplate" + ParsersConstants["frequency"] = "frequency" + ParsersConstants["highlightScope"] = "highlightScope" +})(ParsersConstants || (ParsersConstants = {})) +class TypedWord extends TreeWord { + constructor(node, cellIndex, type) { + super(node, cellIndex) + this._type = type + } + get type() { + return this._type + } + toString() { + return this.word + ":" + this.type + } +} +// todo: can we merge these methods into base TreeNode and ditch this class? +class ParserBackedNode extends TreeNode { + get definition() { + if (this._definition) return this._definition + this._definition = this.isRoot() ? this.handParsersProgram : this.parent.definition.getParserDefinitionByParserId(this.constructor.name) + return this._definition + } + get rootParsersTree() { + return this.definition.root + } + getAutocompleteResults(partialWord, cellIndex) { + return cellIndex === 0 ? this._getAutocompleteResultsForFirstWord(partialWord) : this._getAutocompleteResultsForCell(partialWord, cellIndex) + } + get nodeIndex() { + // StringMap {firstWord: index} + // When there are multiple tails with the same firstWord, _index stores the last content. + // todo: change the above behavior: when a collision occurs, create an array. + return this._nodeIndex || this._makeNodeIndex() + } + _clearIndex() { + delete this._nodeIndex + return super._clearIndex() + } + _makeIndex(startAt = 0) { + if (this._nodeIndex) this._makeNodeIndex(startAt) + return super._makeIndex(startAt) + } + _makeNodeIndex(startAt = 0) { + if (!this._nodeIndex || !startAt) this._nodeIndex = {} + const nodes = this._getChildrenArray() + const newIndex = this._nodeIndex + const length = nodes.length + for (let index = startAt; index < length; index++) { + const node = nodes[index] + const ancestors = Array.from(node.definition._getAncestorSet()).forEach(id => { + if (!newIndex[id]) newIndex[id] = [] + newIndex[id].push(node) + }) + } + return newIndex + } + getChildInstancesOfParserId(parserId) { + return this.nodeIndex[parserId] || [] + } + doesExtend(parserId) { + return this.definition._doesExtend(parserId) + } + _getErrorParserErrors() { + return [this.firstWord ? new UnknownParserError(this) : new BlankLineError(this)] + } + _getBlobParserCatchAllParser() { + return BlobParser + } + _getAutocompleteResultsForFirstWord(partialWord) { + const keywordMap = this.definition.firstWordMapWithDefinitions + let keywords = Object.keys(keywordMap) + if (partialWord) keywords = keywords.filter(keyword => keyword.includes(partialWord)) + return keywords + .map(keyword => { + const def = keywordMap[keyword] + if (def.suggestInAutocomplete === false) return false + const description = def.description + return { + text: keyword, + displayText: keyword + (description ? " " + description : "") + } + }) + .filter(i => i) + } + _getAutocompleteResultsForCell(partialWord, cellIndex) { + // todo: root should be [] correct? + const cell = this.parsedCells[cellIndex] + return cell ? cell.getAutoCompleteWords(partialWord) : [] + } + // note: this is overwritten by the root node of a runtime parsers program. + // some of the magic that makes this all work. but maybe there's a better way. + get handParsersProgram() { + if (this.isRoot()) throw new Error(`Root node without getHandParsersProgram defined.`) + return this.root.handParsersProgram + } + getRunTimeEnumOptions(cell) { + return undefined + } + _sortNodesByInScopeOrder() { + const parserOrder = this.definition._getMyInScopeParserIds() + if (!parserOrder.length) return this + const orderMap = {} + parserOrder.forEach((word, index) => (orderMap[word] = index)) + this.sort(Utils.makeSortByFn(runtimeNode => orderMap[runtimeNode.definition.parserIdFromDefinition])) + return this + } + get requiredNodeErrors() { + const errors = [] + Object.values(this.definition.firstWordMapWithDefinitions).forEach(def => { + if (def.isRequired() && !this.nodeIndex[def.id]) errors.push(new MissingRequiredParserError(this, def.id)) + }) + return errors + } + get programAsCells() { + // todo: what is this? + return this.topDownArray.map(node => { + const cells = node.parsedCells + let indents = node.getIndentLevel() - 1 + while (indents) { + cells.unshift(undefined) + indents-- + } + return cells + }) + } + get programWidth() { + return Math.max(...this.programAsCells.map(line => line.length)) + } + get allTypedWords() { + const words = [] + this.topDownArray.forEach(node => node.wordTypes.forEach((cell, index) => words.push(new TypedWord(node, index, cell.cellTypeId)))) + return words + } + findAllWordsWithCellType(cellTypeId) { + return this.allTypedWords.filter(typedWord => typedWord.type === cellTypeId) + } + findAllNodesWithParser(parserId) { + return this.topDownArray.filter(node => node.definition.parserIdFromDefinition === parserId) + } + toCellTypeTree() { + return this.topDownArray.map(child => child.indentation + child.lineCellTypes).join("\n") + } + getParseTable(maxColumnWidth = 40) { + const tree = new TreeNode(this.toCellTypeTree()) + return new TreeNode( + tree.topDownArray.map((node, lineNumber) => { + const sourceNode = this.nodeAtLine(lineNumber) + const errs = sourceNode.getErrors() + const errorCount = errs.length + const obj = { + lineNumber: lineNumber, + source: sourceNode.indentation + sourceNode.getLine(), + parser: sourceNode.constructor.name, + cellTypes: node.content, + errorCount: errorCount + } + if (errorCount) obj.errorMessages = errs.map(err => err.message).join(";") + return obj + }) + ).toFormattedTable(maxColumnWidth) + } + // Helper method for selecting potential parsers needed to update parsers file. + get invalidParsers() { + return Array.from( + new Set( + this.getAllErrors() + .filter(err => err instanceof UnknownParserError) + .map(err => err.getNode().firstWord) + ) + ) + } + _getAllAutoCompleteWords() { + return this.getAllWordBoundaryCoordinates().map(coordinate => { + const results = this.getAutocompleteResultsAt(coordinate.lineIndex, coordinate.charIndex) + return { + lineIndex: coordinate.lineIndex, + charIndex: coordinate.charIndex, + wordIndex: coordinate.wordIndex, + word: results.word, + suggestions: results.matches + } + }) + } + toAutoCompleteCube(fillChar = "") { + const trees = [this.clone()] + const filled = this.clone().fill(fillChar) + this._getAllAutoCompleteWords().forEach(hole => { + hole.suggestions.forEach((suggestion, index) => { + if (!trees[index + 1]) trees[index + 1] = filled.clone() + trees[index + 1].nodeAtLine(hole.lineIndex).setWord(hole.wordIndex, suggestion.text) + }) + }) + return new TreeNode(trees) + } + toAutoCompleteTable() { + return new TreeNode( + this._getAllAutoCompleteWords().map(result => { + result.suggestions = result.suggestions.map(node => node.text).join(" ") + return result + }) + ).asTable + } + getAutocompleteResultsAt(lineIndex, charIndex) { + const lineNode = this.nodeAtLine(lineIndex) || this + const nodeInScope = lineNode.getNodeInScopeAtCharIndex(charIndex) + // todo: add more tests + // todo: second param this.childrenToString() + // todo: change to getAutocomplete definitions + const wordIndex = lineNode.getWordIndexAtCharacterIndex(charIndex) + const wordProperties = lineNode.getWordProperties(wordIndex) + return { + startCharIndex: wordProperties.startCharIndex, + endCharIndex: wordProperties.endCharIndex, + word: wordProperties.word, + matches: nodeInScope.getAutocompleteResults(wordProperties.word, wordIndex) + } + } + _sortWithParentParsersUpTop() { + const familyTree = new HandParsersProgram(this.toString()).parserFamilyTree + const rank = {} + familyTree.topDownArray.forEach((node, index) => { + rank[node.getWord(0)] = index + }) + const nodeAFirst = -1 + const nodeBFirst = 1 + this.sort((nodeA, nodeB) => { + const nodeARank = rank[nodeA.getWord(0)] + const nodeBRank = rank[nodeB.getWord(0)] + return nodeARank < nodeBRank ? nodeAFirst : nodeBFirst + }) + return this + } + format() { + if (this.isRoot()) { + this._sortNodesByInScopeOrder() + try { + this._sortWithParentParsersUpTop() + } catch (err) { + console.log(`Warning: ${err}`) + } + } + this.topDownArray.forEach(child => { + child.format() + }) + return this + } + sortFromSortTemplate() { + if (!this.length) return this + // Recurse + this.forEach(node => node.sortFromSortTemplate()) + const def = this.isRoot() ? this.definition.rootParserDefinition : this.definition + const { sortIndices, sortSections } = def.sortSpec + // Sort and insert section breaks + if (sortIndices.size) { + // Sort keywords + this.sort((nodeA, nodeB) => { + var _a, _b + const aIndex = (_a = sortIndices.get(nodeA.firstWord)) !== null && _a !== void 0 ? _a : sortIndices.get(nodeA.sortKey) + const bIndex = (_b = sortIndices.get(nodeB.firstWord)) !== null && _b !== void 0 ? _b : sortIndices.get(nodeB.sortKey) + if (aIndex === undefined) console.error(`sortTemplate is missing "${nodeA.firstWord}"`) + const a = aIndex !== null && aIndex !== void 0 ? aIndex : 1000 + const b = bIndex !== null && bIndex !== void 0 ? bIndex : 1000 + return a > b ? 1 : a < b ? -1 : nodeA.getLine() > nodeB.getLine() + }) + // pad sections + let currentSection = 0 + this.forEach(node => { + var _a + const nodeSection = (_a = sortSections.get(node.firstWord)) !== null && _a !== void 0 ? _a : sortSections.get(node.sortKey) + const sectionHasAdvanced = nodeSection > currentSection + if (sectionHasAdvanced) { + currentSection = nodeSection + node.prependSibling("") // Put a blank line before this section + } + }) + } + return this + } + getParserUsage(filepath = "") { + // returns a report on what parsers from its language the program uses + const usage = new TreeNode() + const handParsersProgram = this.handParsersProgram + handParsersProgram.validConcreteAndAbstractParserDefinitions.forEach(def => { + const requiredCellTypeIds = def.cellParser.getRequiredCellTypeIds() + usage.appendLine([def.parserIdFromDefinition, "line-id", "parser", requiredCellTypeIds.join(" ")].join(" ")) + }) + this.topDownArray.forEach((node, lineNumber) => { + const stats = usage.getNode(node.parserId) + stats.appendLine([filepath + "-" + lineNumber, node.words.join(" ")].join(" ")) + }) + return usage + } + toHighlightScopeTree() { + return this.topDownArray.map(child => child.indentation + child.getLineHighlightScopes()).join("\n") + } + toDefinitionLineNumberTree() { + return this.topDownArray.map(child => child.definition.lineNumber + " " + child.indentation + child.cellDefinitionLineNumbers.join(" ")).join("\n") + } + get asCellTypeTreeWithParserIds() { + return this.topDownArray.map(child => child.constructor.name + this.wordBreakSymbol + child.indentation + child.lineCellTypes).join("\n") + } + toPreludeCellTypeTreeWithParserIds() { + return this.topDownArray.map(child => child.constructor.name + this.wordBreakSymbol + child.indentation + child.getLineCellPreludeTypes()).join("\n") + } + get asTreeWithParsers() { + return this.topDownArray.map(child => child.constructor.name + this.wordBreakSymbol + child.indentation + child.getLine()).join("\n") + } + getCellHighlightScopeAtPosition(lineIndex, wordIndex) { + this._initCellTypeCache() + const typeNode = this._cache_highlightScopeTree.topDownArray[lineIndex - 1] + return typeNode ? typeNode.getWord(wordIndex - 1) : undefined + } + _initCellTypeCache() { + const treeMTime = this.getLineOrChildrenModifiedTime() + if (this._cache_programCellTypeStringMTime === treeMTime) return undefined + this._cache_typeTree = new TreeNode(this.toCellTypeTree()) + this._cache_highlightScopeTree = new TreeNode(this.toHighlightScopeTree()) + this._cache_programCellTypeStringMTime = treeMTime + } + createParserCombinator() { + return this.isRoot() ? new TreeNode.ParserCombinator(BlobParser) : new TreeNode.ParserCombinator(this.parent._getParser()._getCatchAllParser(this.parent), {}) + } + get parserId() { + return this.definition.parserIdFromDefinition + } + get wordTypes() { + return this.parsedCells.filter(cell => cell.getWord() !== undefined) + } + get cellErrors() { + return this.parsedCells.map(check => check.getErrorIfAny()).filter(identity => identity) + } + get singleParserUsedTwiceErrors() { + const errors = [] + const parent = this.parent + const hits = parent.getChildInstancesOfParserId(this.definition.id) + if (hits.length > 1) + hits.forEach((node, index) => { + if (node === this) errors.push(new ParserUsedMultipleTimesError(node)) + }) + return errors + } + get uniqueLineAppearsTwiceErrors() { + const errors = [] + const parent = this.parent + const hits = parent.getChildInstancesOfParserId(this.definition.id) + if (hits.length > 1) { + const set = new Set() + hits.forEach((node, index) => { + const line = node.getLine() + if (set.has(line)) errors.push(new ParserUsedMultipleTimesError(node)) + set.add(line) + }) + } + return errors + } + get scopeErrors() { + let errors = [] + const def = this.definition + if (def.isSingle) errors = errors.concat(this.singleParserUsedTwiceErrors) + if (def.isUniqueLine) errors = errors.concat(this.uniqueLineAppearsTwiceErrors) + const { requiredNodeErrors } = this + if (requiredNodeErrors.length) errors = errors.concat(requiredNodeErrors) + return errors + } + getErrors() { + return this.cellErrors.concat(this.scopeErrors) + } + get parsedCells() { + return this.definition.cellParser.getCellArray(this) + } + // todo: just make a fn that computes proper spacing and then is given a node to print + get lineCellTypes() { + return this.parsedCells.map(slot => slot.cellTypeId).join(" ") + } + getLineCellPreludeTypes() { + return this.parsedCells + .map(slot => { + const def = slot.cellTypeDefinition + //todo: cleanup + return def ? def.preludeKindId : PreludeCellTypeIds.anyCell + }) + .join(" ") + } + getLineHighlightScopes(defaultScope = "source") { + return this.parsedCells.map(slot => slot.highlightScope || defaultScope).join(" ") + } + get cellDefinitionLineNumbers() { + return this.parsedCells.map(cell => cell.definitionLineNumber) + } + _getCompiledIndentation() { + const indentCharacter = this.definition._getCompilerObject()[ParsersConstantsCompiler.indentCharacter] + const indent = this.indentation + return indentCharacter !== undefined ? indentCharacter.repeat(indent.length) : indent + } + _getFields() { + // fields are like cells + const fields = {} + this.forEach(node => { + const def = node.definition + if (def.isRequired() || def.isSingle) fields[node.getWord(0)] = node.content + }) + return fields + } + _getCompiledLine() { + const compiler = this.definition._getCompilerObject() + const catchAllCellDelimiter = compiler[ParsersConstantsCompiler.catchAllCellDelimiter] + const str = compiler[ParsersConstantsCompiler.stringTemplate] + return str !== undefined ? Utils.formatStr(str, catchAllCellDelimiter, Object.assign(this._getFields(), this.cells)) : this.getLine() + } + get listDelimiter() { + return this.definition._getFromExtended(ParsersConstants.listDelimiter) + } + get contentKey() { + return this.definition._getFromExtended(ParsersConstants.contentKey) + } + get childrenKey() { + return this.definition._getFromExtended(ParsersConstants.childrenKey) + } + get childrenAreTextBlob() { + return this.definition._isBlobParser() + } + get isArrayElement() { + return this.definition._hasFromExtended(ParsersConstants.uniqueFirstWord) ? false : !this.definition.isSingle + } + get list() { + return this.listDelimiter ? this.content.split(this.listDelimiter) : super.list + } + get typedContent() { + // todo: probably a better way to do this, perhaps by defining a cellDelimiter at the node level + // todo: this currently parse anything other than string types + if (this.listDelimiter) return this.content.split(this.listDelimiter) + const cells = this.parsedCells + if (cells.length === 2) return cells[1].parsed + return this.content + } + get typedTuple() { + const key = this.firstWord + if (this.childrenAreTextBlob) return [key, this.childrenToString()] + const { typedContent, contentKey, childrenKey } = this + if (contentKey || childrenKey) { + let obj = {} + if (childrenKey) obj[childrenKey] = this.childrenToString() + else obj = this.typedMap + if (contentKey) { + obj[contentKey] = typedContent + } + return [key, obj] + } + const hasChildren = this.length > 0 + const hasChildrenNoContent = typedContent === undefined && hasChildren + const shouldReturnValueAsObject = hasChildrenNoContent + if (shouldReturnValueAsObject) return [key, this.typedMap] + const hasChildrenAndContent = typedContent !== undefined && hasChildren + const shouldReturnValueAsContentPlusChildren = hasChildrenAndContent + // If the node has a content and a subtree return it as a string, as + // Javascript object values can't be both a leaf and a tree. + if (shouldReturnValueAsContentPlusChildren) return [key, this.contentWithChildren] + return [key, typedContent] + } + get _shouldSerialize() { + const should = this.shouldSerialize + return should === undefined ? true : should + } + get typedMap() { + const obj = {} + this.forEach(node => { + if (!node._shouldSerialize) return true + const tuple = node.typedTuple + if (!node.isArrayElement) obj[tuple[0]] = tuple[1] + else { + if (!obj[tuple[0]]) obj[tuple[0]] = [] + obj[tuple[0]].push(tuple[1]) + } + }) + return obj + } + fromTypedMap() {} + compile() { + if (this.isRoot()) return super.compile() + const def = this.definition + const indent = this._getCompiledIndentation() + const compiledLine = this._getCompiledLine() + if (def.isTerminalParser()) return indent + compiledLine + const compiler = def._getCompilerObject() + const openChildrenString = compiler[ParsersConstantsCompiler.openChildren] || "" + const closeChildrenString = compiler[ParsersConstantsCompiler.closeChildren] || "" + const childJoinCharacter = compiler[ParsersConstantsCompiler.joinChildrenWith] || "\n" + const compiledChildren = this.map(child => child.compile()).join(childJoinCharacter) + return `${indent + compiledLine}${openChildrenString} +${compiledChildren} +${indent}${closeChildrenString}` + } + // todo: remove + get cells() { + const cells = {} + this.parsedCells.forEach(cell => { + const cellTypeId = cell.cellTypeId + if (!cell.isCatchAll()) cells[cellTypeId] = cell.parsed + else { + if (!cells[cellTypeId]) cells[cellTypeId] = [] + cells[cellTypeId].push(cell.parsed) + } + }) + return cells + } +} +class BlobParser extends ParserBackedNode { + createParserCombinator() { + return new TreeNode.ParserCombinator(BlobParser, {}) + } + getErrors() { + return [] + } +} +// todo: can we remove this? hard to extend. +class UnknownParserNode extends ParserBackedNode { + createParserCombinator() { + return new TreeNode.ParserCombinator(UnknownParserNode, {}) + } + getErrors() { + return [new UnknownParserError(this)] + } +} +/* +A cell contains a word but also the type information for that word. +*/ +class AbstractParsersBackedCell { + constructor(node, index, typeDef, cellTypeId, isCatchAll, parserDefinitionParser) { + this._typeDef = typeDef + this._node = node + this._isCatchAll = isCatchAll + this._index = index + this._cellTypeId = cellTypeId + this._parserDefinitionParser = parserDefinitionParser + } + getWord() { + return this._node.getWord(this._index) + } + get definitionLineNumber() { + return this._typeDef.lineNumber + } + get cellTypeId() { + return this._cellTypeId + } + getNode() { + return this._node + } + get cellIndex() { + return this._index + } + isCatchAll() { + return this._isCatchAll + } + get min() { + return this.cellTypeDefinition.get(ParsersConstants.min) || "0" + } + get max() { + return this.cellTypeDefinition.get(ParsersConstants.max) || "100" + } + get placeholder() { + return this.cellTypeDefinition.get(ParsersConstants.examples) || "" + } + get highlightScope() { + const definition = this.cellTypeDefinition + if (definition) return definition.highlightScope // todo: why the undefined? + } + getAutoCompleteWords(partialWord = "") { + const cellDef = this.cellTypeDefinition + let words = cellDef ? cellDef._getAutocompleteWordOptions(this.getNode().root) : [] + const runTimeOptions = this.getNode().getRunTimeEnumOptions(this) + if (runTimeOptions) words = runTimeOptions.concat(words) + if (partialWord) words = words.filter(word => word.includes(partialWord)) + return words.map(word => { + return { + text: word, + displayText: word + } + }) + } + synthesizeCell(seed = Date.now()) { + // todo: cleanup + const cellDef = this.cellTypeDefinition + const enumOptions = cellDef._getFromExtended(ParsersConstants.enum) + if (enumOptions) return Utils.getRandomString(1, enumOptions.split(" ")) + return this._synthesizeCell(seed) + } + _getStumpEnumInput(crux) { + const cellDef = this.cellTypeDefinition + const enumOptions = cellDef._getFromExtended(ParsersConstants.enum) + if (!enumOptions) return undefined + const options = new TreeNode( + enumOptions + .split(" ") + .map(option => `option ${option}`) + .join("\n") + ) + return `select + name ${crux} +${options.toString(1)}` + } + _toStumpInput(crux) { + // todo: remove + const enumInput = this._getStumpEnumInput(crux) + if (enumInput) return enumInput + // todo: cleanup. We shouldn't have these dual cellType classes. + return `input + name ${crux} + placeholder ${this.placeholder}` + } + get cellTypeDefinition() { + return this._typeDef + } + _getErrorContext() { + return this.getNode().getLine().split(" ")[0] // todo: WordBreakSymbol + } + isValid() { + const runTimeOptions = this.getNode().getRunTimeEnumOptions(this) + const word = this.getWord() + if (runTimeOptions) return runTimeOptions.includes(word) + return this.cellTypeDefinition.isValid(word, this.getNode().root) && this._isValid() + } + getErrorIfAny() { + const word = this.getWord() + if (word !== undefined && this.isValid()) return undefined + // todo: refactor invalidwordError. We want better error messages. + return word === undefined || word === "" ? new MissingWordError(this) : new InvalidWordError(this) + } +} +AbstractParsersBackedCell.parserFunctionName = "" +class ParsersBitCell extends AbstractParsersBackedCell { + _isValid() { + const word = this.getWord() + return word === "0" || word === "1" + } + _synthesizeCell() { + return Utils.getRandomString(1, "01".split("")) + } + get regexString() { + return "[01]" + } + get parsed() { + const word = this.getWord() + return !!parseInt(word) + } +} +ParsersBitCell.defaultHighlightScope = "constant.numeric" +class ParsersNumericCell extends AbstractParsersBackedCell { + _toStumpInput(crux) { + return `input + name ${crux} + type number + placeholder ${this.placeholder} + min ${this.min} + max ${this.max}` + } +} +class ParsersIntCell extends ParsersNumericCell { + _isValid() { + const word = this.getWord() + const num = parseInt(word) + if (isNaN(num)) return false + return num.toString() === word + } + _synthesizeCell(seed) { + return Utils.randomUniformInt(parseInt(this.min), parseInt(this.max), seed).toString() + } + get regexString() { + return "-?[0-9]+" + } + get parsed() { + const word = this.getWord() + return parseInt(word) + } +} +ParsersIntCell.defaultHighlightScope = "constant.numeric.integer" +ParsersIntCell.parserFunctionName = "parseInt" +class ParsersFloatCell extends ParsersNumericCell { + _isValid() { + const word = this.getWord() + const num = parseFloat(word) + return !isNaN(num) && /^-?\d*(\.\d+)?$/.test(word) + } + _synthesizeCell(seed) { + return Utils.randomUniformFloat(parseFloat(this.min), parseFloat(this.max), seed).toString() + } + get regexString() { + return "-?d*(.d+)?" + } + get parsed() { + const word = this.getWord() + return parseFloat(word) + } +} +ParsersFloatCell.defaultHighlightScope = "constant.numeric.float" +ParsersFloatCell.parserFunctionName = "parseFloat" +// ErrorCellType => parsers asks for a '' cell type here but the parsers does not specify a '' cell type. (todo: bring in didyoumean?) +class ParsersBoolCell extends AbstractParsersBackedCell { + constructor() { + super(...arguments) + this._trues = new Set(["1", "true", "t", "yes"]) + this._falses = new Set(["0", "false", "f", "no"]) + } + _isValid() { + const word = this.getWord() + const str = word.toLowerCase() + return this._trues.has(str) || this._falses.has(str) + } + _synthesizeCell() { + return Utils.getRandomString(1, ["1", "true", "t", "yes", "0", "false", "f", "no"]) + } + _getOptions() { + return Array.from(this._trues).concat(Array.from(this._falses)) + } + get regexString() { + return "(?:" + this._getOptions().join("|") + ")" + } + get parsed() { + const word = this.getWord() + return this._trues.has(word.toLowerCase()) + } +} +ParsersBoolCell.defaultHighlightScope = "constant.numeric" +class ParsersAnyCell extends AbstractParsersBackedCell { + _isValid() { + return true + } + _synthesizeCell() { + const examples = this.cellTypeDefinition._getFromExtended(ParsersConstants.examples) + if (examples) return Utils.getRandomString(1, examples.split(" ")) + return this._parserDefinitionParser.parserIdFromDefinition + "-" + this.constructor.name + } + get regexString() { + return "[^ ]+" + } + get parsed() { + return this.getWord() + } +} +class ParsersKeywordCell extends ParsersAnyCell { + _synthesizeCell() { + return this._parserDefinitionParser.cruxIfAny + } +} +ParsersKeywordCell.defaultHighlightScope = "keyword" +class ParsersExtraWordCellTypeCell extends AbstractParsersBackedCell { + _isValid() { + return false + } + synthesizeCell() { + throw new Error(`Trying to synthesize a ParsersExtraWordCellTypeCell`) + return this._synthesizeCell() + } + _synthesizeCell() { + return "extraWord" // should never occur? + } + get parsed() { + return this.getWord() + } + getErrorIfAny() { + return new ExtraWordError(this) + } +} +class ParsersUnknownCellTypeCell extends AbstractParsersBackedCell { + _isValid() { + return false + } + synthesizeCell() { + throw new Error(`Trying to synthesize an ParsersUnknownCellTypeCell`) + return this._synthesizeCell() + } + _synthesizeCell() { + return "extraWord" // should never occur? + } + get parsed() { + return this.getWord() + } + getErrorIfAny() { + return new UnknownCellTypeError(this) + } +} +class AbstractTreeError { + constructor(node) { + this._node = node + } + getLineIndex() { + return this.lineNumber - 1 + } + get lineNumber() { + return this.getNode()._getLineNumber() // todo: handle sourcemaps + } + isCursorOnWord(lineIndex, characterIndex) { + return lineIndex === this.getLineIndex() && this._doesCharacterIndexFallOnWord(characterIndex) + } + _doesCharacterIndexFallOnWord(characterIndex) { + return this.cellIndex === this.getNode().getWordIndexAtCharacterIndex(characterIndex) + } + // convenience method. may be removed. + isBlankLineError() { + return false + } + // convenience method. may be removed. + isMissingWordError() { + return false + } + getIndent() { + return this.getNode().indentation + } + getCodeMirrorLineWidgetElement(onApplySuggestionCallBack = () => {}) { + const suggestion = this.suggestionMessage + if (this.isMissingWordError()) return this._getCodeMirrorLineWidgetElementCellTypeHints() + if (suggestion) return this._getCodeMirrorLineWidgetElementWithSuggestion(onApplySuggestionCallBack, suggestion) + return this._getCodeMirrorLineWidgetElementWithoutSuggestion() + } + get parserId() { + return this.getNode().definition.parserIdFromDefinition + } + _getCodeMirrorLineWidgetElementCellTypeHints() { + const el = document.createElement("div") + el.appendChild(document.createTextNode(this.getIndent() + this.getNode().definition.lineHints)) + el.className = "LintCellTypeHints" + return el + } + _getCodeMirrorLineWidgetElementWithoutSuggestion() { + const el = document.createElement("div") + el.appendChild(document.createTextNode(this.getIndent() + this.message)) + el.className = "LintError" + return el + } + _getCodeMirrorLineWidgetElementWithSuggestion(onApplySuggestionCallBack, suggestion) { + const el = document.createElement("div") + el.appendChild(document.createTextNode(this.getIndent() + `${this.errorTypeName}. Suggestion: ${suggestion}`)) + el.className = "LintErrorWithSuggestion" + el.onclick = () => { + this.applySuggestion() + onApplySuggestionCallBack() + } + return el + } + getLine() { + return this.getNode().getLine() + } + getExtension() { + return this.getNode().handParsersProgram.extensionName + } + getNode() { + return this._node + } + get errorTypeName() { + return this.constructor.name.replace("Error", "") + } + get cellIndex() { + return 0 + } + toObject() { + return { + type: this.errorTypeName, + line: this.lineNumber, + cell: this.cellIndex, + suggestion: this.suggestionMessage, + path: this.getNode().getFirstWordPath(), + message: this.message + } + } + hasSuggestion() { + return this.suggestionMessage !== "" + } + get suggestionMessage() { + return "" + } + toString() { + return this.message + } + applySuggestion() {} + get message() { + return `${this.errorTypeName} at line ${this.lineNumber} cell ${this.cellIndex}.` + } +} +class AbstractCellError extends AbstractTreeError { + constructor(cell) { + super(cell.getNode()) + this._cell = cell + } + get cell() { + return this._cell + } + get cellIndex() { + return this._cell.cellIndex + } + get wordSuggestion() { + return Utils.didYouMean( + this.cell.getWord(), + this.cell.getAutoCompleteWords().map(option => option.text) + ) + } +} +class UnknownParserError extends AbstractTreeError { + get message() { + const node = this.getNode() + const parentNode = node.parent + const options = parentNode._getParser().getFirstWordOptions() + return super.message + ` Invalid parser "${node.firstWord}". Valid parsers are: ${Utils._listToEnglishText(options, 7)}.` + } + get wordSuggestion() { + const node = this.getNode() + const parentNode = node.parent + return Utils.didYouMean( + node.firstWord, + parentNode.getAutocompleteResults("", 0).map(option => option.text) + ) + } + get suggestionMessage() { + const suggestion = this.wordSuggestion + const node = this.getNode() + if (suggestion) return `Change "${node.firstWord}" to "${suggestion}"` + return "" + } + applySuggestion() { + const suggestion = this.wordSuggestion + if (suggestion) this.getNode().setWord(this.cellIndex, suggestion) + return this + } +} +class BlankLineError extends UnknownParserError { + get message() { + return super.message + ` Line: "${this.getNode().getLine()}". Blank lines are errors.` + } + // convenience method + isBlankLineError() { + return true + } + get suggestionMessage() { + return `Delete line ${this.lineNumber}` + } + applySuggestion() { + this.getNode().destroy() + return this + } +} +class MissingRequiredParserError extends AbstractTreeError { + constructor(node, missingParserId) { + super(node) + this._missingParserId = missingParserId + } + get message() { + return super.message + ` A "${this._missingParserId}" is required.` + } +} +class ParserUsedMultipleTimesError extends AbstractTreeError { + get message() { + return super.message + ` Multiple "${this.getNode().firstWord}" found.` + } + get suggestionMessage() { + return `Delete line ${this.lineNumber}` + } + applySuggestion() { + return this.getNode().destroy() + } +} +class LineAppearsMultipleTimesError extends AbstractTreeError { + get message() { + return super.message + ` "${this.getNode().getLine()}" appears multiple times.` + } + get suggestionMessage() { + return `Delete line ${this.lineNumber}` + } + applySuggestion() { + return this.getNode().destroy() + } +} +class UnknownCellTypeError extends AbstractCellError { + get message() { + return super.message + ` No cellType "${this.cell.cellTypeId}" found. Language parsers for "${this.getExtension()}" may need to be fixed.` + } +} +class InvalidWordError extends AbstractCellError { + get message() { + return super.message + ` "${this.cell.getWord()}" does not fit in cellType "${this.cell.cellTypeId}".` + } + get suggestionMessage() { + const suggestion = this.wordSuggestion + if (suggestion) return `Change "${this.cell.getWord()}" to "${suggestion}"` + return "" + } + applySuggestion() { + const suggestion = this.wordSuggestion + if (suggestion) this.getNode().setWord(this.cellIndex, suggestion) + return this + } +} +class ExtraWordError extends AbstractCellError { + get message() { + return super.message + ` Extra word "${this.cell.getWord()}" in ${this.parserId}.` + } + get suggestionMessage() { + return `Delete word "${this.cell.getWord()}" at cell ${this.cellIndex}` + } + applySuggestion() { + return this.getNode().deleteWordAt(this.cellIndex) + } +} +class MissingWordError extends AbstractCellError { + // todo: autocomplete suggestion + get message() { + return super.message + ` Missing word for cell "${this.cell.cellTypeId}".` + } + isMissingWordError() { + return true + } +} +// todo: add standard types, enum types, from disk types +class AbstractParsersWordTestParser extends TreeNode {} +class ParsersRegexTestParser extends AbstractParsersWordTestParser { + isValid(str) { + if (!this._regex) this._regex = new RegExp("^" + this.content + "$") + return !!str.match(this._regex) + } +} +class ParsersReservedWordsTestParser extends AbstractParsersWordTestParser { + isValid(str) { + if (!this._set) this._set = new Set(this.content.split(" ")) + return !this._set.has(str) + } +} +// todo: remove in favor of custom word type constructors +class EnumFromCellTypesTestParser extends AbstractParsersWordTestParser { + _getEnumFromCellTypes(programRootNode) { + const cellTypeIds = this.getWordsFrom(1) + const enumGroup = cellTypeIds.join(" ") + // note: hack where we store it on the program. otherwise has global effects. + if (!programRootNode._enumMaps) programRootNode._enumMaps = {} + if (programRootNode._enumMaps[enumGroup]) return programRootNode._enumMaps[enumGroup] + const wordIndex = 1 + const map = {} + const cellTypeMap = {} + cellTypeIds.forEach(typeId => (cellTypeMap[typeId] = true)) + programRootNode.allTypedWords + .filter(typedWord => cellTypeMap[typedWord.type]) + .forEach(typedWord => { + map[typedWord.word] = true + }) + programRootNode._enumMaps[enumGroup] = map + return map + } + // todo: remove + isValid(str, programRootNode) { + return this._getEnumFromCellTypes(programRootNode)[str] === true + } +} +class ParsersEnumTestNode extends AbstractParsersWordTestParser { + isValid(str) { + // enum c c++ java + return !!this.getOptions()[str] + } + getOptions() { + if (!this._map) this._map = Utils.arrayToMap(this.getWordsFrom(1)) + return this._map + } +} +class cellTypeDefinitionParser extends AbstractExtendibleTreeNode { + createParserCombinator() { + const types = {} + types[ParsersConstants.regex] = ParsersRegexTestParser + types[ParsersConstants.reservedWords] = ParsersReservedWordsTestParser + types[ParsersConstants.enumFromCellTypes] = EnumFromCellTypesTestParser + types[ParsersConstants.enum] = ParsersEnumTestNode + types[ParsersConstants.highlightScope] = TreeNode + types[ParsersConstants.comment] = TreeNode + types[ParsersConstants.examples] = TreeNode + types[ParsersConstants.min] = TreeNode + types[ParsersConstants.max] = TreeNode + types[ParsersConstants.description] = TreeNode + types[ParsersConstants.extends] = TreeNode + return new TreeNode.ParserCombinator(undefined, types) + } + get id() { + return this.getWord(0) + } + get idToNodeMap() { + return this.parent.cellTypeDefinitions + } + getGetter(wordIndex) { + const wordToNativeJavascriptTypeParser = this.getCellConstructor().parserFunctionName + return `get ${this.cellTypeId}() { + return ${wordToNativeJavascriptTypeParser ? wordToNativeJavascriptTypeParser + `(this.getWord(${wordIndex}))` : `this.getWord(${wordIndex})`} + }` + } + getCatchAllGetter(wordIndex) { + const wordToNativeJavascriptTypeParser = this.getCellConstructor().parserFunctionName + return `get ${this.cellTypeId}() { + return ${wordToNativeJavascriptTypeParser ? `this.getWordsFrom(${wordIndex}).map(val => ${wordToNativeJavascriptTypeParser}(val))` : `this.getWordsFrom(${wordIndex})`} + }` + } + // `this.getWordsFrom(${requireds.length + 1})` + // todo: cleanup typings. todo: remove this hidden logic. have a "baseType" property? + getCellConstructor() { + return this.preludeKind || ParsersAnyCell + } + get preludeKind() { + return PreludeKinds[this.getWord(0)] || PreludeKinds[this._getExtendedCellTypeId()] + } + get preludeKindId() { + if (PreludeKinds[this.getWord(0)]) return this.getWord(0) + else if (PreludeKinds[this._getExtendedCellTypeId()]) return this._getExtendedCellTypeId() + return PreludeCellTypeIds.anyCell + } + _getExtendedCellTypeId() { + const arr = this._getAncestorsArray() + return arr[arr.length - 1].id + } + get highlightScope() { + const hs = this._getFromExtended(ParsersConstants.highlightScope) + if (hs) return hs + const preludeKind = this.preludeKind + if (preludeKind) return preludeKind.defaultHighlightScope + } + _getEnumOptions() { + const enumNode = this._getNodeFromExtended(ParsersConstants.enum) + if (!enumNode) return undefined + // we sort by longest first to capture longest match first. todo: add test + const options = Object.keys(enumNode.getNode(ParsersConstants.enum).getOptions()) + options.sort((a, b) => b.length - a.length) + return options + } + _getEnumFromCellTypeOptions(program) { + const node = this._getNodeFromExtended(ParsersConstants.enumFromCellTypes) + return node ? Object.keys(node.getNode(ParsersConstants.enumFromCellTypes)._getEnumFromCellTypes(program)) : undefined + } + _getAutocompleteWordOptions(program) { + return this._getEnumOptions() || this._getEnumFromCellTypeOptions(program) || [] + } + get regexString() { + // todo: enum + const enumOptions = this._getEnumOptions() + return this._getFromExtended(ParsersConstants.regex) || (enumOptions ? "(?:" + enumOptions.join("|") + ")" : "[^ ]*") + } + _getAllTests() { + return this._getChildrenByParserInExtended(AbstractParsersWordTestParser) + } + isValid(str, programRootNode) { + return this._getAllTests().every(node => node.isValid(str, programRootNode)) + } + get cellTypeId() { + return this.getWord(0) + } +} +class AbstractCellParser { + constructor(definition) { + this._definition = definition + } + get catchAllCellTypeId() { + return this._definition._getFromExtended(ParsersConstants.catchAllCellType) + } + // todo: improve layout (use bold?) + get lineHints() { + const catchAllCellTypeId = this.catchAllCellTypeId + const parserId = this._definition.cruxIfAny || this._definition.id // todo: cleanup + return `${parserId}: ${this.getRequiredCellTypeIds().join(" ")}${catchAllCellTypeId ? ` ${catchAllCellTypeId}...` : ""}` + } + getRequiredCellTypeIds() { + if (!this._requiredCellTypeIds) { + const parameters = this._definition._getFromExtended(ParsersConstants.cells) + this._requiredCellTypeIds = parameters ? parameters.split(" ") : [] + } + return this._requiredCellTypeIds + } + _getCellTypeId(cellIndex, requiredCellTypeIds, totalWordCount) { + return requiredCellTypeIds[cellIndex] + } + _isCatchAllCell(cellIndex, numberOfRequiredCells, totalWordCount) { + return cellIndex >= numberOfRequiredCells + } + getCellArray(node = undefined) { + const wordCount = node ? node.words.length : 0 + const def = this._definition + const parsersProgram = def.languageDefinitionProgram + const requiredCellTypeIds = this.getRequiredCellTypeIds() + const numberOfRequiredCells = requiredCellTypeIds.length + const actualWordCountOrRequiredCellCount = Math.max(wordCount, numberOfRequiredCells) + const cells = [] + // A for loop instead of map because "numberOfCellsToFill" can be longer than words.length + for (let cellIndex = 0; cellIndex < actualWordCountOrRequiredCellCount; cellIndex++) { + const isCatchAll = this._isCatchAllCell(cellIndex, numberOfRequiredCells, wordCount) + let cellTypeId = isCatchAll ? this.catchAllCellTypeId : this._getCellTypeId(cellIndex, requiredCellTypeIds, wordCount) + let cellTypeDefinition = parsersProgram.getCellTypeDefinitionById(cellTypeId) + let cellConstructor + if (cellTypeDefinition) cellConstructor = cellTypeDefinition.getCellConstructor() + else if (cellTypeId) cellConstructor = ParsersUnknownCellTypeCell + else { + cellConstructor = ParsersExtraWordCellTypeCell + cellTypeId = PreludeCellTypeIds.extraWordCell + cellTypeDefinition = parsersProgram.getCellTypeDefinitionById(cellTypeId) + } + const anyCellConstructor = cellConstructor + cells[cellIndex] = new anyCellConstructor(node, cellIndex, cellTypeDefinition, cellTypeId, isCatchAll, def) + } + return cells + } +} +class PrefixCellParser extends AbstractCellParser {} +class PostfixCellParser extends AbstractCellParser { + _isCatchAllCell(cellIndex, numberOfRequiredCells, totalWordCount) { + return cellIndex < totalWordCount - numberOfRequiredCells + } + _getCellTypeId(cellIndex, requiredCellTypeIds, totalWordCount) { + const catchAllWordCount = Math.max(totalWordCount - requiredCellTypeIds.length, 0) + return requiredCellTypeIds[cellIndex - catchAllWordCount] + } +} +class OmnifixCellParser extends AbstractCellParser { + getCellArray(node = undefined) { + const cells = [] + const def = this._definition + const program = node ? node.root : undefined + const parsersProgram = def.languageDefinitionProgram + const words = node ? node.words : [] + const requiredCellTypeDefs = this.getRequiredCellTypeIds().map(cellTypeId => parsersProgram.getCellTypeDefinitionById(cellTypeId)) + const catchAllCellTypeId = this.catchAllCellTypeId + const catchAllCellTypeDef = catchAllCellTypeId && parsersProgram.getCellTypeDefinitionById(catchAllCellTypeId) + words.forEach((word, wordIndex) => { + let cellConstructor + for (let index = 0; index < requiredCellTypeDefs.length; index++) { + const cellTypeDefinition = requiredCellTypeDefs[index] + if (cellTypeDefinition.isValid(word, program)) { + // todo: cleanup cellIndex/wordIndex stuff + cellConstructor = cellTypeDefinition.getCellConstructor() + cells.push(new cellConstructor(node, wordIndex, cellTypeDefinition, cellTypeDefinition.id, false, def)) + requiredCellTypeDefs.splice(index, 1) + return true + } + } + if (catchAllCellTypeDef && catchAllCellTypeDef.isValid(word, program)) { + cellConstructor = catchAllCellTypeDef.getCellConstructor() + cells.push(new cellConstructor(node, wordIndex, catchAllCellTypeDef, catchAllCellTypeId, true, def)) + return true + } + cells.push(new ParsersUnknownCellTypeCell(node, wordIndex, undefined, undefined, false, def)) + }) + const wordCount = words.length + requiredCellTypeDefs.forEach((cellTypeDef, index) => { + let cellConstructor = cellTypeDef.getCellConstructor() + cells.push(new cellConstructor(node, wordCount + index, cellTypeDef, cellTypeDef.id, false, def)) + }) + return cells + } +} +class ParsersExampleParser extends TreeNode {} +class ParsersCompilerParser extends TreeNode { + createParserCombinator() { + const types = [ + ParsersConstantsCompiler.stringTemplate, + ParsersConstantsCompiler.indentCharacter, + ParsersConstantsCompiler.catchAllCellDelimiter, + ParsersConstantsCompiler.joinChildrenWith, + ParsersConstantsCompiler.openChildren, + ParsersConstantsCompiler.closeChildren + ] + const map = {} + types.forEach(type => { + map[type] = TreeNode + }) + return new TreeNode.ParserCombinator(undefined, map) + } +} +class AbstractParserConstantParser extends TreeNode { + constructor(children, line, parent) { + super(children, line, parent) + parent[this.identifier] = this.constantValue + } + getGetter() { + return `get ${this.identifier}() { return ${this.constantValueAsJsText} }` + } + get identifier() { + return this.getWord(1) + } + get constantValueAsJsText() { + const words = this.getWordsFrom(2) + return words.length > 1 ? `[${words.join(",")}]` : words[0] + } + get constantValue() { + return JSON.parse(this.constantValueAsJsText) + } +} +class ParsersParserConstantInt extends AbstractParserConstantParser {} +class ParsersParserConstantString extends AbstractParserConstantParser { + get constantValueAsJsText() { + return "`" + Utils.escapeBackTicks(this.constantValue) + "`" + } + get constantValue() { + return this.length ? this.childrenToString() : this.getWordsFrom(2).join(" ") + } +} +class ParsersParserConstantFloat extends AbstractParserConstantParser {} +class ParsersParserConstantBoolean extends AbstractParserConstantParser {} +class AbstractParserDefinitionParser extends AbstractExtendibleTreeNode { + createParserCombinator() { + // todo: some of these should just be on nonRootNodes + const types = [ + ParsersConstants.frequency, + ParsersConstants.inScope, + ParsersConstants.cells, + ParsersConstants.extends, + ParsersConstants.description, + ParsersConstants.catchAllParser, + ParsersConstants.catchAllCellType, + ParsersConstants.cellParser, + ParsersConstants.extensions, + ParsersConstants.version, + ParsersConstants.sortTemplate, + ParsersConstants.tags, + ParsersConstants.crux, + ParsersConstants.cruxFromId, + ParsersConstants.listDelimiter, + ParsersConstants.contentKey, + ParsersConstants.childrenKey, + ParsersConstants.uniqueFirstWord, + ParsersConstants.uniqueLine, + ParsersConstants.pattern, + ParsersConstants.baseParser, + ParsersConstants.required, + ParsersConstants.root, + ParsersConstants._extendsJsClass, + ParsersConstants._rootNodeJsHeader, + ParsersConstants.javascript, + ParsersConstants.compilesTo, + ParsersConstants.javascript, + ParsersConstants.single, + ParsersConstants.comment + ] + const map = {} + types.forEach(type => { + map[type] = TreeNode + }) + map[ParsersConstantsConstantTypes.boolean] = ParsersParserConstantBoolean + map[ParsersConstantsConstantTypes.int] = ParsersParserConstantInt + map[ParsersConstantsConstantTypes.string] = ParsersParserConstantString + map[ParsersConstantsConstantTypes.float] = ParsersParserConstantFloat + map[ParsersConstants.compilerParser] = ParsersCompilerParser + map[ParsersConstants.example] = ParsersExampleParser + return new TreeNode.ParserCombinator(undefined, map, [{ regex: HandParsersProgram.parserFullRegex, parser: parserDefinitionParser }]) + } + get sortSpec() { + const sortSections = new Map() + const sortIndices = new Map() + const sortTemplate = this.get(ParsersConstants.sortTemplate) + if (!sortTemplate) return { sortSections, sortIndices } + sortTemplate.split(" ").forEach((section, sectionIndex) => section.split(" ").forEach(word => sortSections.set(word, sectionIndex))) + sortTemplate.split(" ").forEach((word, index) => sortIndices.set(word, index)) + return { sortSections, sortIndices } + } + toTypeScriptInterface(used = new Set()) { + let childrenInterfaces = [] + let properties = [] + const inScope = this.firstWordMapWithDefinitions + const thisId = this.id + used.add(thisId) + Object.keys(inScope).forEach(key => { + const def = inScope[key] + const map = def.firstWordMapWithDefinitions + const id = def.id + const optionalTag = def.isRequired() ? "" : "?" + const escapedKey = key.match(/\?/) ? `"${key}"` : key + const description = def.description + if (Object.keys(map).length && !used.has(id)) { + childrenInterfaces.push(def.toTypeScriptInterface(used)) + properties.push(` ${escapedKey}${optionalTag}: ${id}`) + } else properties.push(` ${escapedKey}${optionalTag}: any${description ? " // " + description : ""}`) + }) + properties.sort() + const description = this.description + const myInterface = "" + return `${childrenInterfaces.join("\n")} +${description ? "// " + description : ""} +interface ${thisId} { +${properties.join("\n")} +}`.trim() + } + get id() { + return this.getWord(0) + } + get idWithoutSuffix() { + return this.id.replace(HandParsersProgram.parserSuffixRegex, "") + } + get constantsObject() { + const obj = this._getUniqueConstantNodes() + Object.keys(obj).forEach(key => (obj[key] = obj[key].constantValue)) + return obj + } + _getUniqueConstantNodes(extended = true) { + const obj = {} + const items = extended ? this._getChildrenByParserInExtended(AbstractParserConstantParser) : this.getChildrenByParser(AbstractParserConstantParser) + items.reverse() // Last definition wins. + items.forEach(node => (obj[node.identifier] = node)) + return obj + } + get examples() { + return this._getChildrenByParserInExtended(ParsersExampleParser) + } + get parserIdFromDefinition() { + return this.getWord(0) + } + // todo: remove? just reused parserId + get generatedClassName() { + return this.parserIdFromDefinition + } + _hasValidParserId() { + return !!this.generatedClassName + } + _isAbstract() { + return this.id.startsWith(ParsersConstants.abstractParserPrefix) + } + get cruxIfAny() { + return this.get(ParsersConstants.crux) || (this._hasFromExtended(ParsersConstants.cruxFromId) ? this.idWithoutSuffix : undefined) + } + get regexMatch() { + return this.get(ParsersConstants.pattern) + } + get firstCellEnumOptions() { + const firstCellDef = this._getMyCellTypeDefs()[0] + return firstCellDef ? firstCellDef._getEnumOptions() : undefined + } + get languageDefinitionProgram() { + return this.root + } + get customJavascriptMethods() { + const hasJsCode = this.has(ParsersConstants.javascript) + return hasJsCode ? this.getNode(ParsersConstants.javascript).childrenToString() : "" + } + get firstWordMapWithDefinitions() { + if (!this._cache_firstWordToNodeDefMap) this._cache_firstWordToNodeDefMap = this._createParserInfo(this._getInScopeParserIds()).firstWordMap + return this._cache_firstWordToNodeDefMap + } + // todo: remove + get runTimeFirstWordsInScope() { + return this._getParser().getFirstWordOptions() + } + _getMyCellTypeDefs() { + const requiredCells = this.get(ParsersConstants.cells) + if (!requiredCells) return [] + const parsersProgram = this.languageDefinitionProgram + return requiredCells.split(" ").map(cellTypeId => { + const cellTypeDef = parsersProgram.getCellTypeDefinitionById(cellTypeId) + if (!cellTypeDef) throw new Error(`No cellType "${cellTypeId}" found`) + return cellTypeDef + }) + } + // todo: what happens when you have a cell getter and constant with same name? + get cellGettersAndParserConstants() { + // todo: add cellType parsings + const parsersProgram = this.languageDefinitionProgram + const getters = this._getMyCellTypeDefs().map((cellTypeDef, index) => cellTypeDef.getGetter(index)) + const catchAllCellTypeId = this.get(ParsersConstants.catchAllCellType) + if (catchAllCellTypeId) getters.push(parsersProgram.getCellTypeDefinitionById(catchAllCellTypeId).getCatchAllGetter(getters.length)) + // Constants + Object.values(this._getUniqueConstantNodes(false)).forEach(node => getters.push(node.getGetter())) + return getters.join("\n") + } + _createParserInfo(parserIdsInScope) { + const result = { + firstWordMap: {}, + regexTests: [] + } + if (!parserIdsInScope.length) return result + const allProgramParserDefinitionsMap = this.programParserDefinitionCache + Object.keys(allProgramParserDefinitionsMap) + .filter(parserId => { + const def = allProgramParserDefinitionsMap[parserId] + return def.isOrExtendsAParserInScope(parserIdsInScope) && !def._isAbstract() + }) + .forEach(parserId => { + const def = allProgramParserDefinitionsMap[parserId] + const regex = def.regexMatch + const crux = def.cruxIfAny + const enumOptions = def.firstCellEnumOptions + if (regex) result.regexTests.push({ regex: regex, parser: def.parserIdFromDefinition }) + else if (crux) result.firstWordMap[crux] = def + else if (enumOptions) { + enumOptions.forEach(option => (result.firstWordMap[option] = def)) + } + }) + return result + } + get topParserDefinitions() { + const arr = Object.values(this.firstWordMapWithDefinitions) + arr.sort(Utils.makeSortByFn(definition => definition.frequency)) + arr.reverse() + return arr + } + _getMyInScopeParserIds(target = this) { + const parsersNode = target.getNode(ParsersConstants.inScope) + const scopedDefinitionIds = target.myScopedParserDefinitions.map(def => def.id) + return parsersNode ? parsersNode.getWordsFrom(1).concat(scopedDefinitionIds) : scopedDefinitionIds + } + _getInScopeParserIds() { + // todo: allow multiple of these if we allow mixins? + const ids = this._getMyInScopeParserIds() + const parentDef = this._getExtendedParent() + return parentDef ? ids.concat(parentDef._getInScopeParserIds()) : ids + } + get isSingle() { + const hit = this._getNodeFromExtended(ParsersConstants.single) + return hit && hit.get(ParsersConstants.single) !== "false" + } + get isUniqueLine() { + const hit = this._getNodeFromExtended(ParsersConstants.uniqueLine) + return hit && hit.get(ParsersConstants.uniqueLine) !== "false" + } + isRequired() { + return this._hasFromExtended(ParsersConstants.required) + } + getParserDefinitionByParserId(parserId) { + // todo: return catch all? + const def = this.programParserDefinitionCache[parserId] + if (def) return def + this.languageDefinitionProgram._addDefaultCatchAllBlobParser() // todo: cleanup. Why did I do this? Needs to be removed or documented. + const nodeDef = this.languageDefinitionProgram.programParserDefinitionCache[parserId] + if (!nodeDef) throw new Error(`No definition found for parser id "${parserId}". Node: \n---\n${this.asString}\n---`) + return nodeDef + } + isDefined(parserId) { + return !!this.programParserDefinitionCache[parserId] + } + get idToNodeMap() { + return this.programParserDefinitionCache + } + _amIRoot() { + if (this._cache_isRoot === undefined) this._cache_isRoot = this._languageRootNode === this + return this._cache_isRoot + } + get _languageRootNode() { + return this.root.rootParserDefinition + } + _isErrorParser() { + return this.get(ParsersConstants.baseParser) === ParsersConstants.errorParser + } + _isBlobParser() { + // Do not check extended classes. Only do once. + return this._getFromExtended(ParsersConstants.baseParser) === ParsersConstants.blobParser + } + get errorMethodToJavascript() { + if (this._isBlobParser()) return "getErrors() { return [] }" // Skips parsing child nodes for perf gains. + if (this._isErrorParser()) return "getErrors() { return this._getErrorParserErrors() }" + return "" + } + get parserAsJavascript() { + if (this._isBlobParser()) + // todo: do we need this? + return "createParserCombinator() { return new TreeNode.ParserCombinator(this._getBlobParserCatchAllParser())}" + const parserInfo = this._createParserInfo(this._getMyInScopeParserIds()) + const myFirstWordMap = parserInfo.firstWordMap + const regexRules = parserInfo.regexTests + // todo: use constants in first word maps? + // todo: cache the super extending? + const firstWords = Object.keys(myFirstWordMap) + const hasFirstWords = firstWords.length + const catchAllParser = this.catchAllParserToJavascript + if (!hasFirstWords && !catchAllParser && !regexRules.length) return "" + const firstWordsStr = hasFirstWords + ? `Object.assign(Object.assign({}, super.createParserCombinator()._getFirstWordMapAsObject()), {` + firstWords.map(firstWord => `"${firstWord}" : ${myFirstWordMap[firstWord].parserIdFromDefinition}`).join(",\n") + "})" + : "undefined" + const regexStr = regexRules.length + ? `[${regexRules + .map(rule => { + return `{regex: /${rule.regex}/, parser: ${rule.parser}}` + }) + .join(",")}]` + : "undefined" + const catchAllStr = catchAllParser ? catchAllParser : this._amIRoot() ? `this._getBlobParserCatchAllParser()` : "undefined" + const scopedParserJavascript = this.myScopedParserDefinitions.map(def => def.asJavascriptClass).join("\n\n") + return `createParserCombinator() {${scopedParserJavascript} + return new TreeNode.ParserCombinator(${catchAllStr}, ${firstWordsStr}, ${regexStr}) + }` + } + get myScopedParserDefinitions() { + return this.getChildrenByParser(parserDefinitionParser) + } + get catchAllParserToJavascript() { + if (this._isBlobParser()) return "this._getBlobParserCatchAllParser()" + const parserId = this.get(ParsersConstants.catchAllParser) + if (!parserId) return "" + const nodeDef = this.getParserDefinitionByParserId(parserId) + return nodeDef.generatedClassName + } + get asJavascriptClass() { + const components = [this.parserAsJavascript, this.errorMethodToJavascript, this.cellGettersAndParserConstants, this.customJavascriptMethods].filter(identity => identity) + const thisClassName = this.generatedClassName + if (this._amIRoot()) { + components.push(`static cachedHandParsersProgramRoot = new HandParsersProgram(\`${Utils.escapeBackTicks(this.parent.toString().replace(/\\/g, "\\\\"))}\`) + get handParsersProgram() { + return this.constructor.cachedHandParsersProgramRoot + }`) + components.push(`static rootParser = ${thisClassName}`) + } + return `class ${thisClassName} extends ${this._getExtendsClassName()} { + ${components.join("\n")} + }` + } + _getExtendsClassName() { + // todo: this is hopefully a temporary line in place for now for the case where you want your base class to extend something other than another treeclass + const hardCodedExtend = this.get(ParsersConstants._extendsJsClass) + if (hardCodedExtend) return hardCodedExtend + const extendedDef = this._getExtendedParent() + return extendedDef ? extendedDef.generatedClassName : "ParserBackedNode" + } + _getCompilerObject() { + let obj = {} + const items = this._getChildrenByParserInExtended(ParsersCompilerParser) + items.reverse() // Last definition wins. + items.forEach(node => { + obj = Object.assign(obj, node.toObject()) // todo: what about multiline strings? + }) + return obj + } + // todo: improve layout (use bold?) + get lineHints() { + return this.cellParser.lineHints + } + isOrExtendsAParserInScope(firstWordsInScope) { + const chain = this._getParserInheritanceSet() + return firstWordsInScope.some(firstWord => chain.has(firstWord)) + } + isTerminalParser() { + return !this._getFromExtended(ParsersConstants.inScope) && !this._getFromExtended(ParsersConstants.catchAllParser) + } + get sublimeMatchLine() { + const regexMatch = this.regexMatch + if (regexMatch) return `'${regexMatch}'` + const cruxMatch = this.cruxIfAny + if (cruxMatch) return `'^ *${Utils.escapeRegExp(cruxMatch)}(?: |$)'` + const enumOptions = this.firstCellEnumOptions + if (enumOptions) return `'^ *(${Utils.escapeRegExp(enumOptions.join("|"))})(?: |$)'` + } + // todo: refactor. move some parts to cellParser? + _toSublimeMatchBlock() { + const defaultHighlightScope = "source" + const program = this.languageDefinitionProgram + const cellParser = this.cellParser + const requiredCellTypeIds = cellParser.getRequiredCellTypeIds() + const catchAllCellTypeId = cellParser.catchAllCellTypeId + const firstCellTypeDef = program.getCellTypeDefinitionById(requiredCellTypeIds[0]) + const firstWordHighlightScope = (firstCellTypeDef ? firstCellTypeDef.highlightScope : defaultHighlightScope) + "." + this.parserIdFromDefinition + const topHalf = ` '${this.parserIdFromDefinition}': + - match: ${this.sublimeMatchLine} + scope: ${firstWordHighlightScope}` + if (catchAllCellTypeId) requiredCellTypeIds.push(catchAllCellTypeId) + if (!requiredCellTypeIds.length) return topHalf + const captures = requiredCellTypeIds + .map((cellTypeId, index) => { + const cellTypeDefinition = program.getCellTypeDefinitionById(cellTypeId) // todo: cleanup + if (!cellTypeDefinition) throw new Error(`No ${ParsersConstants.cellType} ${cellTypeId} found`) // todo: standardize error/capture error at parsers time + return ` ${index + 1}: ${(cellTypeDefinition.highlightScope || defaultHighlightScope) + "." + cellTypeDefinition.cellTypeId}` + }) + .join("\n") + const cellTypesToRegex = cellTypeIds => cellTypeIds.map(cellTypeId => `({{${cellTypeId}}})?`).join(" ?") + return `${topHalf} + push: + - match: ${cellTypesToRegex(requiredCellTypeIds)} + captures: +${captures} + - match: $ + pop: true` + } + _getParserInheritanceSet() { + if (!this._cache_parserInheritanceSet) this._cache_parserInheritanceSet = new Set(this.ancestorParserIdsArray) + return this._cache_parserInheritanceSet + } + get ancestorParserIdsArray() { + if (!this._cache_ancestorParserIdsArray) { + this._cache_ancestorParserIdsArray = this._getAncestorsArray().map(def => def.parserIdFromDefinition) + this._cache_ancestorParserIdsArray.reverse() + } + return this._cache_ancestorParserIdsArray + } + get programParserDefinitionCache() { + if (!this._cache_parserDefinitionParsers) this._cache_parserDefinitionParsers = this.isRoot || this.hasParserDefinitions ? this.makeProgramParserDefinitionCache() : this.parent.programParserDefinitionCache + return this._cache_parserDefinitionParsers + } + get hasParserDefinitions() { + return !!this.getChildrenByParser(parserDefinitionParser).length + } + makeProgramParserDefinitionCache() { + const scopedParsers = this.getChildrenByParser(parserDefinitionParser) + const cache = Object.assign({}, this.parent.programParserDefinitionCache) // todo. We don't really need this. we should just lookup the parent if no local hits. + scopedParsers.forEach(parserDefinitionParser => (cache[parserDefinitionParser.parserIdFromDefinition] = parserDefinitionParser)) + return cache + } + get description() { + return this._getFromExtended(ParsersConstants.description) || "" + } + get frequency() { + const val = this._getFromExtended(ParsersConstants.frequency) + return val ? parseFloat(val) : 0 + } + _getExtendedParserId() { + const ancestorIds = this.ancestorParserIdsArray + if (ancestorIds.length > 1) return ancestorIds[ancestorIds.length - 2] + } + _toStumpString() { + const crux = this.cruxIfAny + const cellArray = this.cellParser.getCellArray().filter((item, index) => index) // for now this only works for keyword langs + if (!cellArray.length) + // todo: remove this! just doing it for now until we refactor getCellArray to handle catchAlls better. + return "" + const cells = new TreeNode(cellArray.map((cell, index) => cell._toStumpInput(crux)).join("\n")) + return `div + label ${crux} +${cells.toString(1)}` + } + toStumpString() { + const nodeBreakSymbol = "\n" + return this._getConcreteNonErrorInScopeNodeDefinitions(this._getInScopeParserIds()) + .map(def => def._toStumpString()) + .filter(identity => identity) + .join(nodeBreakSymbol) + } + _generateSimulatedLine(seed) { + // todo: generate simulated data from catch all + const crux = this.cruxIfAny + return this.cellParser + .getCellArray() + .map((cell, index) => (!index && crux ? crux : cell.synthesizeCell(seed))) + .join(" ") + } + _shouldSynthesize(def, parserChain) { + if (def._isErrorParser() || def._isAbstract()) return false + if (parserChain.includes(def.id)) return false + const tags = def.get(ParsersConstants.tags) + if (tags && tags.includes(ParsersConstantsMisc.doNotSynthesize)) return false + return true + } + // Get all definitions in this current scope down, even ones that are scoped inside other definitions. + get inScopeAndDescendantDefinitions() { + return this.languageDefinitionProgram._collectAllDefinitions(Object.values(this.programParserDefinitionCache), []) + } + _collectAllDefinitions(defs, collection = []) { + defs.forEach(def => { + collection.push(def) + def._collectAllDefinitions(def.getChildrenByParser(parserDefinitionParser), collection) + }) + return collection + } + get cruxPath() { + const parentPath = this.parent.cruxPath + return (parentPath ? parentPath + " " : "") + this.cruxIfAny + } + get cruxPathAsColumnName() { + return this.cruxPath.replace(/ /g, "_") + } + // Get every definition that extends from this one, even ones that are scoped inside other definitions. + get concreteDescendantDefinitions() { + const { inScopeAndDescendantDefinitions, id } = this + return Object.values(inScopeAndDescendantDefinitions).filter(def => def._doesExtend(id) && !def._isAbstract()) + } + get concreteInScopeDescendantDefinitions() { + // Note: non-recursive. + const defs = this.programParserDefinitionCache + const id = this.id + return Object.values(defs).filter(def => def._doesExtend(id) && !def._isAbstract()) + } + _getConcreteNonErrorInScopeNodeDefinitions(parserIds) { + const defs = [] + parserIds.forEach(parserId => { + const def = this.getParserDefinitionByParserId(parserId) + if (def._isErrorParser()) return + else if (def._isAbstract()) def.concreteInScopeDescendantDefinitions.forEach(def => defs.push(def)) + else defs.push(def) + }) + return defs + } + // todo: refactor + synthesizeNode(nodeCount = 1, indentCount = -1, parsersAlreadySynthesized = [], seed = Date.now()) { + let inScopeParserIds = this._getInScopeParserIds() + const catchAllParserId = this._getFromExtended(ParsersConstants.catchAllParser) + if (catchAllParserId) inScopeParserIds.push(catchAllParserId) + const thisId = this.id + if (!parsersAlreadySynthesized.includes(thisId)) parsersAlreadySynthesized.push(thisId) + const lines = [] + while (nodeCount) { + const line = this._generateSimulatedLine(seed) + if (line) lines.push(" ".repeat(indentCount >= 0 ? indentCount : 0) + line) + this._getConcreteNonErrorInScopeNodeDefinitions(inScopeParserIds.filter(parserId => !parsersAlreadySynthesized.includes(parserId))) + .filter(def => this._shouldSynthesize(def, parsersAlreadySynthesized)) + .forEach(def => { + const chain = parsersAlreadySynthesized // .slice(0) + chain.push(def.id) + def.synthesizeNode(1, indentCount + 1, chain, seed).forEach(line => lines.push(line)) + }) + nodeCount-- + } + return lines + } + get cellParser() { + if (!this._cellParser) { + const cellParsingStrategy = this._getFromExtended(ParsersConstants.cellParser) + if (cellParsingStrategy === ParsersCellParser.postfix) this._cellParser = new PostfixCellParser(this) + else if (cellParsingStrategy === ParsersCellParser.omnifix) this._cellParser = new OmnifixCellParser(this) + else this._cellParser = new PrefixCellParser(this) + } + return this._cellParser + } +} +// todo: remove? +class parserDefinitionParser extends AbstractParserDefinitionParser {} +// HandParsersProgram is a constructor that takes a parsers file, and builds a new +// constructor for new language that takes files in that language to execute, compile, etc. +class HandParsersProgram extends AbstractParserDefinitionParser { + createParserCombinator() { + const map = {} + map[ParsersConstants.comment] = TreeNode + return new TreeNode.ParserCombinator(UnknownParserNode, map, [ + { regex: HandParsersProgram.blankLineRegex, parser: TreeNode }, + { regex: HandParsersProgram.parserFullRegex, parser: parserDefinitionParser }, + { regex: HandParsersProgram.cellTypeFullRegex, parser: cellTypeDefinitionParser } + ]) + } + // rootParser + // Note: this is some so far unavoidable tricky code. We need to eval the transpiled JS, in a NodeJS or browser environment. + _compileAndReturnRootParser() { + if (this._cache_rootParser) return this._cache_rootParser + if (!this.isNodeJs()) { + this._cache_rootParser = Utils.appendCodeAndReturnValueOnWindow(this.toBrowserJavascript(), this.rootParserId).rootParser + return this._cache_rootParser + } + const path = require("path") + const code = this.toNodeJsJavascript(__dirname) + try { + const rootNode = this._requireInVmNodeJsRootParser(code) + this._cache_rootParser = rootNode.rootParser + if (!this._cache_rootParser) throw new Error(`Failed to rootParser`) + } catch (err) { + // todo: figure out best error pattern here for debugging + console.log(err) + // console.log(`Error in code: `) + // console.log(new TreeNode(code).toStringWithLineNumbers()) + } + return this._cache_rootParser + } + get cruxPath() { + return "" + } + trainModel(programs, rootParser = this.compileAndReturnRootParser()) { + const nodeDefs = this.validConcreteAndAbstractParserDefinitions + const nodeDefCountIncludingRoot = nodeDefs.length + 1 + const matrix = Utils.makeMatrix(nodeDefCountIncludingRoot, nodeDefCountIncludingRoot, 0) + const idToIndex = {} + const indexToId = {} + nodeDefs.forEach((def, index) => { + const id = def.id + idToIndex[id] = index + 1 + indexToId[index + 1] = id + }) + programs.forEach(code => { + const exampleProgram = new rootParser(code) + exampleProgram.topDownArray.forEach(node => { + const nodeIndex = idToIndex[node.definition.id] + const parentNode = node.parent + if (!nodeIndex) return undefined + if (parentNode.isRoot()) matrix[0][nodeIndex]++ + else { + const parentIndex = idToIndex[parentNode.definition.id] + if (!parentIndex) return undefined + matrix[parentIndex][nodeIndex]++ + } + }) + }) + return { + idToIndex, + indexToId, + matrix + } + } + _mapPredictions(predictionsVector, model) { + const total = Utils.sum(predictionsVector) + const predictions = predictionsVector.slice(1).map((count, index) => { + const id = model.indexToId[index + 1] + return { + id, + def: this.getParserDefinitionByParserId(id), + count, + prob: count / total + } + }) + predictions.sort(Utils.makeSortByFn(prediction => prediction.count)).reverse() + return predictions + } + predictChildren(model, node) { + return this._mapPredictions(this._predictChildren(model, node), model) + } + predictParents(model, node) { + return this._mapPredictions(this._predictParents(model, node), model) + } + _predictChildren(model, node) { + return model.matrix[node.isRoot() ? 0 : model.idToIndex[node.definition.id]] + } + _predictParents(model, node) { + if (node.isRoot()) return [] + const nodeIndex = model.idToIndex[node.definition.id] + return model.matrix.map(row => row[nodeIndex]) + } + _setDirName(name) { + this._dirName = name + return this + } + _requireInVmNodeJsRootParser(code) { + const vm = require("vm") + const path = require("path") + // todo: cleanup up + try { + Object.keys(GlobalNamespaceAdditions).forEach(key => { + global[key] = require("./" + GlobalNamespaceAdditions[key]) + }) + global.require = require + global.__dirname = this._dirName + global.module = {} + return vm.runInThisContext(code) + } catch (err) { + // todo: figure out best error pattern here for debugging + console.log(`Error in compiled parsers code for language "${this.parsersName}"`) + // console.log(new TreeNode(code).toStringWithLineNumbers()) + console.log(err) + throw err + } + } + examplesToTestBlocks(rootParser = this.compileAndReturnRootParser(), expectedErrorMessage = "") { + const testBlocks = {} + this.validConcreteAndAbstractParserDefinitions.forEach(def => + def.examples.forEach(example => { + const id = def.id + example.content + testBlocks[id] = equal => { + const exampleProgram = new rootParser(example.childrenToString()) + const errors = exampleProgram.getAllErrors(example._getLineNumber() + 1) + equal(errors.join("\n"), expectedErrorMessage, `Expected no errors in ${id}`) + } + }) + ) + return testBlocks + } + toReadMe() { + const languageName = this.extensionName + const rootNodeDef = this.rootParserDefinition + const cellTypes = this.cellTypeDefinitions + const parserFamilyTree = this.parserFamilyTree + const exampleNode = rootNodeDef.examples[0] + return `title ${languageName} Readme + +paragraph ${rootNodeDef.description} + +subtitle Quick Example + +code +${exampleNode ? exampleNode.childrenToString(1) : ""} + +subtitle Quick facts about ${languageName} + +list + - ${languageName} has ${parserFamilyTree.topDownArray.length} node types. + - ${languageName} has ${Object.keys(cellTypes).length} cell types + - The source code for ${languageName} is ${this.topDownArray.length} lines long. + +subtitle Installing + +code + npm install . + +subtitle Testing + +code + node test.js + +subtitle Node Types + +code +${parserFamilyTree.toString(1)} + +subtitle Cell Types + +code +${new TreeNode(Object.keys(cellTypes).join("\n")).toString(1)} + +subtitle Road Map + +paragraph Here are the "todos" present in the source code for ${languageName}: + +list +${this.topDownArray + .filter(node => node.getWord(0) === "todo") + .map(node => ` - ${node.getLine()}`) + .join("\n")} + +paragraph This readme was auto-generated using the + link https://github.com/breck7/scrollsdk ScrollSDK.` + } + toBundle() { + const files = {} + const rootNodeDef = this.rootParserDefinition + const languageName = this.extensionName + const example = rootNodeDef.examples[0] + const sampleCode = example ? example.childrenToString() : "" + files[ParsersBundleFiles.package] = JSON.stringify( + { + name: languageName, + private: true, + dependencies: { + scrollsdk: TreeNode.getVersion() + } + }, + null, + 2 + ) + files[ParsersBundleFiles.readme] = this.toReadMe() + const testCode = `const program = new ${languageName}(sampleCode) +const errors = program.getAllErrors() +console.log("Sample program compiled with " + errors.length + " errors.") +if (errors.length) + console.log(errors.map(error => error.message))` + const nodePath = `${languageName}.node.js` + files[nodePath] = this.toNodeJsJavascript() + files[ParsersBundleFiles.indexJs] = `module.exports = require("./${nodePath}")` + const browserPath = `${languageName}.browser.js` + files[browserPath] = this.toBrowserJavascript() + files[ParsersBundleFiles.indexHtml] = ` + + + +` + const samplePath = "sample." + this.extensionName + files[samplePath] = sampleCode.toString() + files[ParsersBundleFiles.testJs] = `const ${languageName} = require("./index.js") +/*keep-line*/ const sampleCode = require("fs").readFileSync("${samplePath}", "utf8") +${testCode}` + return files + } + get targetExtension() { + return this.rootParserDefinition.get(ParsersConstants.compilesTo) + } + get cellTypeDefinitions() { + if (this._cache_cellTypes) return this._cache_cellTypes + const types = {} + // todo: add built in word types? + this.getChildrenByParser(cellTypeDefinitionParser).forEach(type => (types[type.cellTypeId] = type)) + this._cache_cellTypes = types + return types + } + getCellTypeDefinitionById(cellTypeId) { + // todo: return unknownCellTypeDefinition? or is that handled somewhere else? + return this.cellTypeDefinitions[cellTypeId] + } + get parserFamilyTree() { + const tree = new TreeNode() + Object.values(this.validConcreteAndAbstractParserDefinitions).forEach(node => tree.touchNode(node.ancestorParserIdsArray.join(" "))) + return tree + } + get languageDefinitionProgram() { + return this + } + get validConcreteAndAbstractParserDefinitions() { + return this.getChildrenByParser(parserDefinitionParser).filter(node => node._hasValidParserId()) + } + get lastRootParserDefinitionNode() { + return this.findLast(def => def instanceof AbstractParserDefinitionParser && def.has(ParsersConstants.root) && def._hasValidParserId()) + } + _initRootParserDefinitionNode() { + if (this._cache_rootParserNode) return + if (!this._cache_rootParserNode) this._cache_rootParserNode = this.lastRootParserDefinitionNode + // By default, have a very permissive basic root node. + // todo: whats the best design pattern to use for this sort of thing? + if (!this._cache_rootParserNode) { + this._cache_rootParserNode = this.concat(`${ParsersConstants.DefaultRootParser} + ${ParsersConstants.root} + ${ParsersConstants.catchAllParser} ${ParsersConstants.BlobParser}`)[0] + this._addDefaultCatchAllBlobParser() + } + } + get rootParserDefinition() { + this._initRootParserDefinitionNode() + return this._cache_rootParserNode + } + _addDefaultCatchAllBlobParser() { + if (this._addedCatchAll) return + this._addedCatchAll = true + delete this._cache_parserDefinitionParsers + this.concat(`${ParsersConstants.BlobParser} + ${ParsersConstants.baseParser} ${ParsersConstants.blobParser}`) + } + get extensionName() { + return this.parsersName + } + get id() { + return this.rootParserId + } + get rootParserId() { + return this.rootParserDefinition.parserIdFromDefinition + } + get parsersName() { + return this.rootParserId.replace(HandParsersProgram.parserSuffixRegex, "") + } + _getMyInScopeParserIds() { + return super._getMyInScopeParserIds(this.rootParserDefinition) + } + _getInScopeParserIds() { + const parsersNode = this.rootParserDefinition.getNode(ParsersConstants.inScope) + return parsersNode ? parsersNode.getWordsFrom(1) : [] + } + makeProgramParserDefinitionCache() { + const cache = {} + this.getChildrenByParser(parserDefinitionParser).forEach(parserDefinitionParser => (cache[parserDefinitionParser.parserIdFromDefinition] = parserDefinitionParser)) + return cache + } + compileAndReturnRootParser() { + if (!this._cached_rootParser) { + const rootDef = this.rootParserDefinition + this._cached_rootParser = rootDef.languageDefinitionProgram._compileAndReturnRootParser() + } + return this._cached_rootParser + } + get fileExtensions() { + return this.rootParserDefinition.get(ParsersConstants.extensions) ? this.rootParserDefinition.get(ParsersConstants.extensions).split(" ").join(",") : this.extensionName + } + toNodeJsJavascript(scrollsdkProductsPath = "scrollsdk/products") { + return this._rootNodeDefToJavascriptClass(scrollsdkProductsPath, true).trim() + } + toBrowserJavascript() { + return this._rootNodeDefToJavascriptClass("", false).trim() + } + _rootNodeDefToJavascriptClass(scrollsdkProductsPath, forNodeJs = true) { + const defs = this.validConcreteAndAbstractParserDefinitions + // todo: throw if there is no root node defined + const parserClasses = defs.map(def => def.asJavascriptClass).join("\n\n") + const rootDef = this.rootParserDefinition + const rootNodeJsHeader = forNodeJs && rootDef._getConcatBlockStringFromExtended(ParsersConstants._rootNodeJsHeader) + const rootName = rootDef.generatedClassName + if (!rootName) throw new Error(`Root Node Type Has No Name`) + let exportScript = "" + if (forNodeJs) + exportScript = `module.exports = ${rootName}; +${rootName}` + else exportScript = `window.${rootName} = ${rootName}` + let nodeJsImports = `` + if (forNodeJs) { + const path = require("path") + nodeJsImports = Object.keys(GlobalNamespaceAdditions) + .map(key => { + const thePath = scrollsdkProductsPath + "/" + GlobalNamespaceAdditions[key] + return `const { ${key} } = require("${thePath.replace(/\\/g, "\\\\")}")` // escape windows backslashes + }) + .join("\n") + } + // todo: we can expose the previous "constants" export, if needed, via the parsers, which we preserve. + return `{ +${nodeJsImports} +${rootNodeJsHeader ? rootNodeJsHeader : ""} +${parserClasses} + +${exportScript} +} +` + } + toSublimeSyntaxFile() { + const cellTypeDefs = this.cellTypeDefinitions + const variables = Object.keys(cellTypeDefs) + .map(name => ` ${name}: '${cellTypeDefs[name].regexString}'`) + .join("\n") + const defs = this.validConcreteAndAbstractParserDefinitions.filter(kw => !kw._isAbstract()) + const parserContexts = defs.map(def => def._toSublimeMatchBlock()).join("\n\n") + const includes = defs.map(parserDef => ` - include: '${parserDef.parserIdFromDefinition}'`).join("\n") + return `%YAML 1.2 +--- +name: ${this.extensionName} +file_extensions: [${this.fileExtensions}] +scope: source.${this.extensionName} + +variables: +${variables} + +contexts: + main: +${includes} + +${parserContexts}` + } +} +HandParsersProgram.makeParserId = str => Utils._replaceNonAlphaNumericCharactersWithCharCodes(str).replace(HandParsersProgram.parserSuffixRegex, "") + ParsersConstants.parserSuffix +HandParsersProgram.makeCellTypeId = str => Utils._replaceNonAlphaNumericCharactersWithCharCodes(str).replace(HandParsersProgram.cellTypeSuffixRegex, "") + ParsersConstants.cellTypeSuffix +HandParsersProgram.parserSuffixRegex = new RegExp(ParsersConstants.parserSuffix + "$") +HandParsersProgram.parserFullRegex = new RegExp("^[a-zA-Z0-9_]+" + ParsersConstants.parserSuffix + "$") +HandParsersProgram.blankLineRegex = new RegExp("^$") +HandParsersProgram.cellTypeSuffixRegex = new RegExp(ParsersConstants.cellTypeSuffix + "$") +HandParsersProgram.cellTypeFullRegex = new RegExp("^[a-zA-Z0-9_]+" + ParsersConstants.cellTypeSuffix + "$") +HandParsersProgram._languages = {} +HandParsersProgram._parsers = {} +const PreludeKinds = {} +PreludeKinds[PreludeCellTypeIds.anyCell] = ParsersAnyCell +PreludeKinds[PreludeCellTypeIds.keywordCell] = ParsersKeywordCell +PreludeKinds[PreludeCellTypeIds.floatCell] = ParsersFloatCell +PreludeKinds[PreludeCellTypeIds.numberCell] = ParsersFloatCell +PreludeKinds[PreludeCellTypeIds.bitCell] = ParsersBitCell +PreludeKinds[PreludeCellTypeIds.boolCell] = ParsersBoolCell +PreludeKinds[PreludeCellTypeIds.intCell] = ParsersIntCell +class UnknownParsersProgram extends TreeNode { + _inferRootNodeForAPrefixLanguage(parsersName) { + parsersName = HandParsersProgram.makeParserId(parsersName) + const rootNode = new TreeNode(`${parsersName} + ${ParsersConstants.root}`) + // note: right now we assume 1 global cellTypeMap and parserMap per parsers. But we may have scopes in the future? + const rootNodeNames = this.getFirstWords() + .filter(identity => identity) + .map(word => HandParsersProgram.makeParserId(word)) + rootNode + .nodeAt(0) + .touchNode(ParsersConstants.inScope) + .setWordsFrom(1, Array.from(new Set(rootNodeNames))) + return rootNode + } + _renameIntegerKeywords(clone) { + // todo: why are we doing this? + for (let node of clone.getTopDownArrayIterator()) { + const firstWordIsAnInteger = !!node.firstWord.match(/^\d+$/) + const parentFirstWord = node.parent.firstWord + if (firstWordIsAnInteger && parentFirstWord) node.setFirstWord(HandParsersProgram.makeParserId(parentFirstWord + UnknownParsersProgram._childSuffix)) + } + } + _getKeywordMaps(clone) { + const keywordsToChildKeywords = {} + const keywordsToNodeInstances = {} + for (let node of clone.getTopDownArrayIterator()) { + const firstWord = node.firstWord + if (!keywordsToChildKeywords[firstWord]) keywordsToChildKeywords[firstWord] = {} + if (!keywordsToNodeInstances[firstWord]) keywordsToNodeInstances[firstWord] = [] + keywordsToNodeInstances[firstWord].push(node) + node.forEach(child => (keywordsToChildKeywords[firstWord][child.firstWord] = true)) + } + return { keywordsToChildKeywords: keywordsToChildKeywords, keywordsToNodeInstances: keywordsToNodeInstances } + } + _inferParserDef(firstWord, globalCellTypeMap, childFirstWords, instances) { + const edgeSymbol = this.edgeSymbol + const parserId = HandParsersProgram.makeParserId(firstWord) + const nodeDefNode = new TreeNode(parserId).nodeAt(0) + const childParserIds = childFirstWords.map(word => HandParsersProgram.makeParserId(word)) + if (childParserIds.length) nodeDefNode.touchNode(ParsersConstants.inScope).setWordsFrom(1, childParserIds) + const cellsForAllInstances = instances + .map(line => line.content) + .filter(identity => identity) + .map(line => line.split(edgeSymbol)) + const instanceCellCounts = new Set(cellsForAllInstances.map(cells => cells.length)) + const maxCellsOnLine = Math.max(...Array.from(instanceCellCounts)) + const minCellsOnLine = Math.min(...Array.from(instanceCellCounts)) + let catchAllCellType + let cellTypeIds = [] + for (let cellIndex = 0; cellIndex < maxCellsOnLine; cellIndex++) { + const cellType = this._getBestCellType( + firstWord, + instances.length, + maxCellsOnLine, + cellsForAllInstances.map(cells => cells[cellIndex]) + ) + if (!globalCellTypeMap.has(cellType.cellTypeId)) globalCellTypeMap.set(cellType.cellTypeId, cellType.cellTypeDefinition) + cellTypeIds.push(cellType.cellTypeId) + } + if (maxCellsOnLine > minCellsOnLine) { + //columns = columns.slice(0, min) + catchAllCellType = cellTypeIds.pop() + while (cellTypeIds[cellTypeIds.length - 1] === catchAllCellType) { + cellTypeIds.pop() + } + } + const needsCruxProperty = !firstWord.endsWith(UnknownParsersProgram._childSuffix + ParsersConstants.parserSuffix) // todo: cleanup + if (needsCruxProperty) nodeDefNode.set(ParsersConstants.crux, firstWord) + if (catchAllCellType) nodeDefNode.set(ParsersConstants.catchAllCellType, catchAllCellType) + const cellLine = cellTypeIds.slice() + cellLine.unshift(PreludeCellTypeIds.keywordCell) + if (cellLine.length > 0) nodeDefNode.set(ParsersConstants.cells, cellLine.join(edgeSymbol)) + //if (!catchAllCellType && cellTypeIds.length === 1) nodeDefNode.set(ParsersConstants.cells, cellTypeIds[0]) + // Todo: add conditional frequencies + return nodeDefNode.parent.toString() + } + // inferParsersFileForAnSSVLanguage(parsersName: string): string { + // parsersName = HandParsersProgram.makeParserId(parsersName) + // const rootNode = new TreeNode(`${parsersName} + // ${ParsersConstants.root}`) + // // note: right now we assume 1 global cellTypeMap and parserMap per parsers. But we may have scopes in the future? + // const rootNodeNames = this.getFirstWords().map(word => HandParsersProgram.makeParserId(word)) + // rootNode + // .nodeAt(0) + // .touchNode(ParsersConstants.inScope) + // .setWordsFrom(1, Array.from(new Set(rootNodeNames))) + // return rootNode + // } + inferParsersFileForAKeywordLanguage(parsersName) { + const clone = this.clone() + this._renameIntegerKeywords(clone) + const { keywordsToChildKeywords, keywordsToNodeInstances } = this._getKeywordMaps(clone) + const globalCellTypeMap = new Map() + globalCellTypeMap.set(PreludeCellTypeIds.keywordCell, undefined) + const parserDefs = Object.keys(keywordsToChildKeywords) + .filter(identity => identity) + .map(firstWord => this._inferParserDef(firstWord, globalCellTypeMap, Object.keys(keywordsToChildKeywords[firstWord]), keywordsToNodeInstances[firstWord])) + const cellTypeDefs = [] + globalCellTypeMap.forEach((def, id) => cellTypeDefs.push(def ? def : id)) + const nodeBreakSymbol = this.nodeBreakSymbol + return this._formatCode([this._inferRootNodeForAPrefixLanguage(parsersName).toString(), cellTypeDefs.join(nodeBreakSymbol), parserDefs.join(nodeBreakSymbol)].filter(identity => identity).join("\n")) + } + _formatCode(code) { + // todo: make this run in browser too + if (!this.isNodeJs()) return code + const parsersProgram = new HandParsersProgram(TreeNode.fromDisk(__dirname + "/../langs/parsers/parsers.parsers")) + const rootParser = parsersProgram.compileAndReturnRootParser() + const program = new rootParser(code) + return program.format().toString() + } + _getBestCellType(firstWord, instanceCount, maxCellsOnLine, allValues) { + const asSet = new Set(allValues) + const edgeSymbol = this.edgeSymbol + const values = Array.from(asSet).filter(identity => identity) + const every = fn => { + for (let index = 0; index < values.length; index++) { + if (!fn(values[index])) return false + } + return true + } + if (every(str => str === "0" || str === "1")) return { cellTypeId: PreludeCellTypeIds.bitCell } + if ( + every(str => { + const num = parseInt(str) + if (isNaN(num)) return false + return num.toString() === str + }) + ) { + return { cellTypeId: PreludeCellTypeIds.intCell } + } + if (every(str => str.match(/^-?\d*.?\d+$/))) return { cellTypeId: PreludeCellTypeIds.floatCell } + const bools = new Set(["1", "0", "true", "false", "t", "f", "yes", "no"]) + if (every(str => bools.has(str.toLowerCase()))) return { cellTypeId: PreludeCellTypeIds.boolCell } + // todo: cleanup + const enumLimit = 30 + if (instanceCount > 1 && maxCellsOnLine === 1 && allValues.length > asSet.size && asSet.size < enumLimit) + return { + cellTypeId: HandParsersProgram.makeCellTypeId(firstWord), + cellTypeDefinition: `${HandParsersProgram.makeCellTypeId(firstWord)} + enum ${values.join(edgeSymbol)}` + } + return { cellTypeId: PreludeCellTypeIds.anyCell } + } +} +UnknownParsersProgram._childSuffix = "Child" +window.ParsersConstants = ParsersConstants +window.PreludeCellTypeIds = PreludeCellTypeIds +window.HandParsersProgram = HandParsersProgram +window.ParserBackedNode = ParserBackedNode +window.UnknownParserError = UnknownParserError +window.UnknownParsersProgram = UnknownParsersProgram diff --git a/products/SandboxApp.browser.js b/products/SandboxApp.browser.js index 8849e60dd..49e201be2 100644 --- a/products/SandboxApp.browser.js +++ b/products/SandboxApp.browser.js @@ -15,7 +15,7 @@ class SandboxApp extends AbstractTreeComponentParser { "toJsonSubset", `{ "name": "scrollsdk", - "description": "Scroll Notation parser, compiler-compiler, and virtual machine for Tree Languages", + "description": "Scroll Notation parser, compiler-compiler, and virtual machine for Languages", "keywords": "scrollsdk" }` ) @@ -164,7 +164,7 @@ class headerComponent extends AbstractTreeComponentParser { title TreeNotation.org span Scroll Notation Sandbox p - a Scroll Designer + a Parser Designer href /designer/ span | a Unit Tests @@ -270,7 +270,7 @@ class tableComponent extends AbstractTreeComponentParser { tr td div asHtmlCube - title Experimental. This is a very specific kind of Tree Language. + title Experimental. This is a very specific kind of Language. div id htmlCubeConsole style position:relative;` diff --git a/products/TreeComponentFramework.browser.js b/products/TreeComponentFramework.browser.js index 21d93bda9..166c42e53 100644 --- a/products/TreeComponentFramework.browser.js +++ b/products/TreeComponentFramework.browser.js @@ -899,7 +899,7 @@ class AbstractTheme { } } class DefaultTheme extends AbstractTheme {} -class AbstractTreeComponentParser extends GrammarBackedNode { +class AbstractTreeComponentParser extends ParserBackedNode { async startWhenReady() { if (this.isNodeJs()) return this.start() document.addEventListener( diff --git a/products/TreeComponentFramework.node.js b/products/TreeComponentFramework.node.js index 2711fcd7d..8b9c5e22d 100644 --- a/products/TreeComponentFramework.node.js +++ b/products/TreeComponentFramework.node.js @@ -1,7 +1,7 @@ //onsave scrollsdk build produce TreeComponentFramework.browser.js const { TreeNode } = require("../products/TreeNode.js") const { Utils } = require("../products/Utils.js") -const { GrammarBackedNode } = require("../products/GrammarLanguage.js") +const { ParserBackedNode } = require("../products/Parsers.js") const stumpParser = require("../products/stump.nodejs.js") const hakonParser = require("../products/hakon.nodejs.js") const superagent = require("superagent") @@ -905,7 +905,7 @@ class AbstractTheme { } } class DefaultTheme extends AbstractTheme {} -class AbstractTreeComponentParser extends GrammarBackedNode { +class AbstractTreeComponentParser extends ParserBackedNode { async startWhenReady() { if (this.isNodeJs()) return this.start() document.addEventListener( diff --git a/products/TreeFileSystem.browser.js b/products/TreeFileSystem.browser.js index 33f7774b4..7e3751710 100644 --- a/products/TreeFileSystem.browser.js +++ b/products/TreeFileSystem.browser.js @@ -1,4 +1,4 @@ -const GRAMMAR_EXTENSION = ".grammar" +const PARSERS_EXTENSION = ".parsers" const parserRegex = /^[a-zA-Z0-9_]+Parser/gm // A regex to check if a multiline string has a line that starts with "import ". const importRegex = /^import /gm @@ -61,7 +61,7 @@ class TreeFileSystem { this._treeCache = {} this._parserCache = {} this._expandedImportCache = {} - this._grammarExpandersCache = {} + this._parsersExpandersCache = {} if (inMemoryFiles) this._storage = new MemoryWriter(inMemoryFiles) else this._storage = new DiskWriter() } @@ -95,15 +95,17 @@ class TreeFileSystem { if (_expandedImportCache[absoluteFilePath]) return _expandedImportCache[absoluteFilePath] let code = this.read(absoluteFilePath) const isImportOnly = importOnlyRegex.test(code) - // Strip any parsers - const stripIt = code.includes("// parsersOnly") // temporary perf hack - if (stripIt) + // Perf hack + // If its a parsers file, it will have no content, just parsers (and maybe imports). + // The parsers will already have been processed. We can skip them + const stripParsers = absoluteFilePath.endsWith(PARSERS_EXTENSION) + if (stripParsers) code = code .split("\n") .filter(line => line.startsWith("import ")) .join("\n") const filepathsWithParserDefinitions = [] - if (this._doesFileHaveGrammarDefinitions(absoluteFilePath)) filepathsWithParserDefinitions.push(absoluteFilePath) + if (this._doesFileHaveParsersDefinitions(absoluteFilePath)) filepathsWithParserDefinitions.push(absoluteFilePath) if (!importRegex.test(code)) return { afterImportPass: code, @@ -134,37 +136,38 @@ class TreeFileSystem { importFilePaths, isImportOnly, afterImportPass: combinedLines, - filepathsWithParserDefinitions: importFilePaths.filter(filename => this._doesFileHaveGrammarDefinitions(filename)).concat(filepathsWithParserDefinitions) + filepathsWithParserDefinitions: importFilePaths.filter(filename => this._doesFileHaveParsersDefinitions(filename)).concat(filepathsWithParserDefinitions) } return _expandedImportCache[absoluteFilePath] } - _doesFileHaveGrammarDefinitions(absoluteFilePath) { + _doesFileHaveParsersDefinitions(absoluteFilePath) { if (!absoluteFilePath) return false - const { _grammarExpandersCache } = this - if (_grammarExpandersCache[absoluteFilePath] === undefined) _grammarExpandersCache[absoluteFilePath] = !!this._storage.read(absoluteFilePath).match(parserRegex) - return _grammarExpandersCache[absoluteFilePath] + const { _parsersExpandersCache } = this + if (_parsersExpandersCache[absoluteFilePath] === undefined) _parsersExpandersCache[absoluteFilePath] = !!this._storage.read(absoluteFilePath).match(parserRegex) + return _parsersExpandersCache[absoluteFilePath] } - _getOneGrammarParserFromFiles(filePaths, baseGrammarCode) { + _getOneParsersParserFromFiles(filePaths, baseParsersCode) { const parserDefinitionRegex = /^[a-zA-Z0-9_]+Parser/ + const cellDefinitionRegex = /^[a-zA-Z0-9_]+Cell/ const asOneFile = filePaths .map(filePath => { const content = this._storage.read(filePath) - if (filePath.endsWith(GRAMMAR_EXTENSION)) return content + if (filePath.endsWith(PARSERS_EXTENSION)) return content // Strip scroll content return new TreeNode(content) - .filter(node => node.getLine().match(parserDefinitionRegex)) + .filter(node => node.getLine().match(parserDefinitionRegex) || node.getLine().match(cellDefinitionRegex)) .map(node => node.asString) .join("\n") }) .join("\n") .trim() - // todo: clean up scrollsdk so we are using supported methods (perhaps add a formatOptions that allows you to tell Grammar not to run prettier on js nodes) - return new grammarParser(baseGrammarCode + "\n" + asOneFile)._sortNodesByInScopeOrder()._sortWithParentParsersUpTop() + // todo: clean up scrollsdk so we are using supported methods (perhaps add a formatOptions that allows you to tell Parsers not to run prettier on js nodes) + return new parsersParser(baseParsersCode + "\n" + asOneFile)._sortNodesByInScopeOrder()._sortWithParentParsersUpTop() } get parsers() { - return Object.values(this._parserCache).map(parser => parser.grammarParser) + return Object.values(this._parserCache).map(parser => parser.parsersParser) } - getParser(filePaths, baseGrammarCode = "") { + getParser(filePaths, baseParsersCode = "") { const { _parserCache } = this const key = filePaths .filter(fp => fp) @@ -172,19 +175,19 @@ class TreeFileSystem { .join("\n") const hit = _parserCache[key] if (hit) return hit - const grammarParser = this._getOneGrammarParserFromFiles(filePaths, baseGrammarCode) - const grammarCode = grammarParser.asString + const parsersParser = this._getOneParsersParserFromFiles(filePaths, baseParsersCode) + const parsersCode = parsersParser.asString _parserCache[key] = { - grammarParser, - grammarCode, - parser: new HandGrammarProgram(grammarCode).compileAndReturnRootParser() + parsersParser, + parsersCode, + parser: new HandParsersProgram(parsersCode).compileAndReturnRootParser() } return _parserCache[key] } assembleFile(absoluteFilePath, defaultParserCode) { const assembledFile = this._assembleFile(absoluteFilePath) if (!defaultParserCode) return assembledFile - // BUILD CUSTOM COMPILER, IF THERE ARE CUSTOM GRAMMAR NODES DEFINED + // BUILD CUSTOM COMPILER, IF THERE ARE CUSTOM PARSERS NODES DEFINED if (assembledFile.filepathsWithParserDefinitions.length) assembledFile.parser = this.getParser(assembledFile.filepathsWithParserDefinitions, defaultParserCode).parser return assembledFile } diff --git a/products/TreeFileSystem.js b/products/TreeFileSystem.js index 3056e8df5..7f51511ad 100644 --- a/products/TreeFileSystem.js +++ b/products/TreeFileSystem.js @@ -3,10 +3,10 @@ const path = require("path") const { Disk } = require("../products/Disk.node.js") const { Utils } = require("../products/Utils.js") const { TreeNode } = require("../products/TreeNode.js") -const { HandGrammarProgram } = require("../products/GrammarLanguage.js") -const grammarParser = require("../products/grammar.nodejs.js") +const { HandParsersProgram } = require("../products/Parsers.js") +const parsersParser = require("../products/parsers.nodejs.js") const { posix } = require("../products/Path.js") -const GRAMMAR_EXTENSION = ".grammar" +const PARSERS_EXTENSION = ".parsers" const parserRegex = /^[a-zA-Z0-9_]+Parser/gm // A regex to check if a multiline string has a line that starts with "import ". const importRegex = /^import /gm @@ -69,7 +69,7 @@ class TreeFileSystem { this._treeCache = {} this._parserCache = {} this._expandedImportCache = {} - this._grammarExpandersCache = {} + this._parsersExpandersCache = {} if (inMemoryFiles) this._storage = new MemoryWriter(inMemoryFiles) else this._storage = new DiskWriter() } @@ -103,15 +103,17 @@ class TreeFileSystem { if (_expandedImportCache[absoluteFilePath]) return _expandedImportCache[absoluteFilePath] let code = this.read(absoluteFilePath) const isImportOnly = importOnlyRegex.test(code) - // Strip any parsers - const stripIt = code.includes("// parsersOnly") // temporary perf hack - if (stripIt) + // Perf hack + // If its a parsers file, it will have no content, just parsers (and maybe imports). + // The parsers will already have been processed. We can skip them + const stripParsers = absoluteFilePath.endsWith(PARSERS_EXTENSION) + if (stripParsers) code = code .split("\n") .filter(line => line.startsWith("import ")) .join("\n") const filepathsWithParserDefinitions = [] - if (this._doesFileHaveGrammarDefinitions(absoluteFilePath)) filepathsWithParserDefinitions.push(absoluteFilePath) + if (this._doesFileHaveParsersDefinitions(absoluteFilePath)) filepathsWithParserDefinitions.push(absoluteFilePath) if (!importRegex.test(code)) return { afterImportPass: code, @@ -142,37 +144,38 @@ class TreeFileSystem { importFilePaths, isImportOnly, afterImportPass: combinedLines, - filepathsWithParserDefinitions: importFilePaths.filter(filename => this._doesFileHaveGrammarDefinitions(filename)).concat(filepathsWithParserDefinitions) + filepathsWithParserDefinitions: importFilePaths.filter(filename => this._doesFileHaveParsersDefinitions(filename)).concat(filepathsWithParserDefinitions) } return _expandedImportCache[absoluteFilePath] } - _doesFileHaveGrammarDefinitions(absoluteFilePath) { + _doesFileHaveParsersDefinitions(absoluteFilePath) { if (!absoluteFilePath) return false - const { _grammarExpandersCache } = this - if (_grammarExpandersCache[absoluteFilePath] === undefined) _grammarExpandersCache[absoluteFilePath] = !!this._storage.read(absoluteFilePath).match(parserRegex) - return _grammarExpandersCache[absoluteFilePath] + const { _parsersExpandersCache } = this + if (_parsersExpandersCache[absoluteFilePath] === undefined) _parsersExpandersCache[absoluteFilePath] = !!this._storage.read(absoluteFilePath).match(parserRegex) + return _parsersExpandersCache[absoluteFilePath] } - _getOneGrammarParserFromFiles(filePaths, baseGrammarCode) { + _getOneParsersParserFromFiles(filePaths, baseParsersCode) { const parserDefinitionRegex = /^[a-zA-Z0-9_]+Parser/ + const cellDefinitionRegex = /^[a-zA-Z0-9_]+Cell/ const asOneFile = filePaths .map(filePath => { const content = this._storage.read(filePath) - if (filePath.endsWith(GRAMMAR_EXTENSION)) return content + if (filePath.endsWith(PARSERS_EXTENSION)) return content // Strip scroll content return new TreeNode(content) - .filter(node => node.getLine().match(parserDefinitionRegex)) + .filter(node => node.getLine().match(parserDefinitionRegex) || node.getLine().match(cellDefinitionRegex)) .map(node => node.asString) .join("\n") }) .join("\n") .trim() - // todo: clean up scrollsdk so we are using supported methods (perhaps add a formatOptions that allows you to tell Grammar not to run prettier on js nodes) - return new grammarParser(baseGrammarCode + "\n" + asOneFile)._sortNodesByInScopeOrder()._sortWithParentParsersUpTop() + // todo: clean up scrollsdk so we are using supported methods (perhaps add a formatOptions that allows you to tell Parsers not to run prettier on js nodes) + return new parsersParser(baseParsersCode + "\n" + asOneFile)._sortNodesByInScopeOrder()._sortWithParentParsersUpTop() } get parsers() { - return Object.values(this._parserCache).map(parser => parser.grammarParser) + return Object.values(this._parserCache).map(parser => parser.parsersParser) } - getParser(filePaths, baseGrammarCode = "") { + getParser(filePaths, baseParsersCode = "") { const { _parserCache } = this const key = filePaths .filter(fp => fp) @@ -180,19 +183,19 @@ class TreeFileSystem { .join("\n") const hit = _parserCache[key] if (hit) return hit - const grammarParser = this._getOneGrammarParserFromFiles(filePaths, baseGrammarCode) - const grammarCode = grammarParser.asString + const parsersParser = this._getOneParsersParserFromFiles(filePaths, baseParsersCode) + const parsersCode = parsersParser.asString _parserCache[key] = { - grammarParser, - grammarCode, - parser: new HandGrammarProgram(grammarCode).compileAndReturnRootParser() + parsersParser, + parsersCode, + parser: new HandParsersProgram(parsersCode).compileAndReturnRootParser() } return _parserCache[key] } assembleFile(absoluteFilePath, defaultParserCode) { const assembledFile = this._assembleFile(absoluteFilePath) if (!defaultParserCode) return assembledFile - // BUILD CUSTOM COMPILER, IF THERE ARE CUSTOM GRAMMAR NODES DEFINED + // BUILD CUSTOM COMPILER, IF THERE ARE CUSTOM PARSERS NODES DEFINED if (assembledFile.filepathsWithParserDefinitions.length) assembledFile.parser = this.getParser(assembledFile.filepathsWithParserDefinitions, defaultParserCode).parser return assembledFile } diff --git a/products/TreeNode.browser.js b/products/TreeNode.browser.js index 71e9d1c2c..1ee8a0d93 100644 --- a/products/TreeNode.browser.js +++ b/products/TreeNode.browser.js @@ -1658,7 +1658,7 @@ class TreeNode extends AbstractNode { } // todo: add more testing. // todo: solve issue with where extend should overwrite or append - // todo: should take a grammar? to decide whether to overwrite or append. + // todo: should take a parsers? to decide whether to overwrite or append. // todo: this is slow. extend(nodeOrStr) { const node = nodeOrStr instanceof TreeNode ? nodeOrStr : new TreeNode(nodeOrStr) @@ -2555,7 +2555,7 @@ TreeNode.iris = `sepal_length,sepal_width,petal_length,petal_width,species 4.9,2.5,4.5,1.7,virginica 5.1,3.5,1.4,0.2,setosa 5,3.4,1.5,0.2,setosa` -TreeNode.getVersion = () => "77.1.1" +TreeNode.getVersion = () => "80.0.0" class AbstractExtendibleTreeNode extends TreeNode { _getFromExtended(firstWordPath) { const hit = this._getNodeFromExtended(firstWordPath) diff --git a/products/TreeNode.js b/products/TreeNode.js index a9c5d9fe7..8371dd468 100644 --- a/products/TreeNode.js +++ b/products/TreeNode.js @@ -1648,7 +1648,7 @@ class TreeNode extends AbstractNode { } // todo: add more testing. // todo: solve issue with where extend should overwrite or append - // todo: should take a grammar? to decide whether to overwrite or append. + // todo: should take a parsers? to decide whether to overwrite or append. // todo: this is slow. extend(nodeOrStr) { const node = nodeOrStr instanceof TreeNode ? nodeOrStr : new TreeNode(nodeOrStr) @@ -2545,7 +2545,7 @@ TreeNode.iris = `sepal_length,sepal_width,petal_length,petal_width,species 4.9,2.5,4.5,1.7,virginica 5.1,3.5,1.4,0.2,setosa 5,3.4,1.5,0.2,setosa` -TreeNode.getVersion = () => "77.1.1" +TreeNode.getVersion = () => "80.0.0" class AbstractExtendibleTreeNode extends TreeNode { _getFromExtended(firstWordPath) { const hit = this._getNodeFromExtended(firstWordPath) diff --git a/products/arrow.browser.js b/products/arrow.browser.js index 96cc42c72..2051026a5 100644 --- a/products/arrow.browser.js +++ b/products/arrow.browser.js @@ -1,5 +1,5 @@ { - class commentParser extends GrammarBackedNode { + class commentParser extends ParserBackedNode { get commentCell() { return this.getWord(0) } @@ -11,14 +11,14 @@ } } - class arrowParser extends GrammarBackedNode { + class arrowParser extends ParserBackedNode { createParserCombinator() { return new TreeNode.ParserCombinator(errorParser, Object.assign(Object.assign({}, super.createParserCombinator()._getFirstWordMapAsObject()), { Comment: commentParser, charge: chargeParser }), undefined) } compile() { return this.asJsonSubset } - static cachedHandGrammarProgramRoot = new HandGrammarProgram(`// Cell parsers + static cachedHandParsersProgramRoot = new HandParsersProgram(`// Cell parsers keywordCell enum charge cardNumber amount currency description token floatCell @@ -56,7 +56,7 @@ commentParser crux Comment boolean suggestInAutocomplete false arrowParser - description A demonstration prefix Tree Language showing how in the future Scroll Notation will be used for simpler and more intelligent APIs. + description A demonstration prefix Language showing how in the future Scroll Notation will be used for simpler and more intelligent APIs. root inScope chargeParser commentParser catchAllParser errorParser @@ -99,19 +99,19 @@ descriptionParser tokenParser cruxFromId cells keywordCell tokenCell`) - get handGrammarProgram() { - return this.constructor.cachedHandGrammarProgramRoot + get handParsersProgram() { + return this.constructor.cachedHandParsersProgramRoot } static rootParser = arrowParser } - class errorParser extends GrammarBackedNode { + class errorParser extends ParserBackedNode { getErrors() { return this._getErrorParserErrors() } } - class chargeParser extends GrammarBackedNode { + class chargeParser extends ParserBackedNode { createParserCombinator() { return new TreeNode.ParserCombinator( undefined, @@ -128,7 +128,7 @@ tokenParser } } - class abstractChargeAttributeParser extends GrammarBackedNode {} + class abstractChargeAttributeParser extends ParserBackedNode {} class cardNumberParser extends abstractChargeAttributeParser { get keywordCell() { @@ -169,7 +169,7 @@ tokenParser } } - class tokenParser extends GrammarBackedNode { + class tokenParser extends ParserBackedNode { get keywordCell() { return this.getWord(0) } diff --git a/products/arrow.nodejs.js b/products/arrow.nodejs.js index 57e8b0bc3..ca19d3d58 100755 --- a/products/arrow.nodejs.js +++ b/products/arrow.nodejs.js @@ -2,10 +2,10 @@ { const { Utils } = require("./Utils.js") const { TreeNode } = require("./TreeNode.js") - const { HandGrammarProgram } = require("./GrammarLanguage.js") - const { GrammarBackedNode } = require("./GrammarLanguage.js") + const { HandParsersProgram } = require("./Parsers.js") + const { ParserBackedNode } = require("./Parsers.js") - class commentParser extends GrammarBackedNode { + class commentParser extends ParserBackedNode { get commentCell() { return this.getWord(0) } @@ -17,14 +17,14 @@ } } - class arrowParser extends GrammarBackedNode { + class arrowParser extends ParserBackedNode { createParserCombinator() { return new TreeNode.ParserCombinator(errorParser, Object.assign(Object.assign({}, super.createParserCombinator()._getFirstWordMapAsObject()), { Comment: commentParser, charge: chargeParser }), undefined) } compile() { return this.asJsonSubset } - static cachedHandGrammarProgramRoot = new HandGrammarProgram(`// Cell parsers + static cachedHandParsersProgramRoot = new HandParsersProgram(`// Cell parsers keywordCell enum charge cardNumber amount currency description token floatCell @@ -62,7 +62,7 @@ commentParser crux Comment boolean suggestInAutocomplete false arrowParser - description A demonstration prefix Tree Language showing how in the future Scroll Notation will be used for simpler and more intelligent APIs. + description A demonstration prefix Language showing how in the future Scroll Notation will be used for simpler and more intelligent APIs. root inScope chargeParser commentParser catchAllParser errorParser @@ -105,19 +105,19 @@ descriptionParser tokenParser cruxFromId cells keywordCell tokenCell`) - get handGrammarProgram() { - return this.constructor.cachedHandGrammarProgramRoot + get handParsersProgram() { + return this.constructor.cachedHandParsersProgramRoot } static rootParser = arrowParser } - class errorParser extends GrammarBackedNode { + class errorParser extends ParserBackedNode { getErrors() { return this._getErrorParserErrors() } } - class chargeParser extends GrammarBackedNode { + class chargeParser extends ParserBackedNode { createParserCombinator() { return new TreeNode.ParserCombinator( undefined, @@ -134,7 +134,7 @@ tokenParser } } - class abstractChargeAttributeParser extends GrammarBackedNode {} + class abstractChargeAttributeParser extends ParserBackedNode {} class cardNumberParser extends abstractChargeAttributeParser { get keywordCell() { @@ -175,7 +175,7 @@ tokenParser } } - class tokenParser extends GrammarBackedNode { + class tokenParser extends ParserBackedNode { get keywordCell() { return this.getWord(0) } diff --git a/products/chuck.browser.js b/products/chuck.browser.js index a688906d9..7e383c1c3 100644 --- a/products/chuck.browser.js +++ b/products/chuck.browser.js @@ -1,5 +1,5 @@ { - class chuckParser extends GrammarBackedNode { + class chuckParser extends ParserBackedNode { createParserCombinator() { return new TreeNode.ParserCombinator(this._getBlobParserCatchAllParser(), undefined, [ { regex: /\+/, parser: addParser }, @@ -8,7 +8,7 @@ { regex: /^[\d\. ]+$/, parser: onlyNumbersParser } ]) } - static cachedHandGrammarProgramRoot = new HandGrammarProgram(`// todo Make this compile and execute + static cachedHandParsersProgramRoot = new HandParsersProgram(`// todo Make this compile and execute // Cell Parsers operatorCell @@ -18,7 +18,7 @@ floatCell // Line Parsers chuckParser - description A useless demo Tree Language inspired by Forth that tests postfix notation. + description A useless demo Language inspired by Forth that tests postfix notation. root inScope abstractOperatorParser onlyNumbersParser abstractOperatorParser @@ -37,13 +37,13 @@ printParser onlyNumbersParser catchAllCellType floatCell pattern ^[\\d\\. ]+$`) - get handGrammarProgram() { - return this.constructor.cachedHandGrammarProgramRoot + get handParsersProgram() { + return this.constructor.cachedHandParsersProgramRoot } static rootParser = chuckParser } - class abstractOperatorParser extends GrammarBackedNode { + class abstractOperatorParser extends ParserBackedNode { get operatorCell() { return this.getWord(0) } @@ -58,7 +58,7 @@ onlyNumbersParser class printParser extends abstractOperatorParser {} - class onlyNumbersParser extends GrammarBackedNode { + class onlyNumbersParser extends ParserBackedNode { get floatCell() { return this.getWordsFrom(0).map(val => parseFloat(val)) } diff --git a/products/chuck.nodejs.js b/products/chuck.nodejs.js index e4465e580..78a17abc0 100755 --- a/products/chuck.nodejs.js +++ b/products/chuck.nodejs.js @@ -2,10 +2,10 @@ { const { Utils } = require("./Utils.js") const { TreeNode } = require("./TreeNode.js") - const { HandGrammarProgram } = require("./GrammarLanguage.js") - const { GrammarBackedNode } = require("./GrammarLanguage.js") + const { HandParsersProgram } = require("./Parsers.js") + const { ParserBackedNode } = require("./Parsers.js") - class chuckParser extends GrammarBackedNode { + class chuckParser extends ParserBackedNode { createParserCombinator() { return new TreeNode.ParserCombinator(this._getBlobParserCatchAllParser(), undefined, [ { regex: /\+/, parser: addParser }, @@ -14,7 +14,7 @@ { regex: /^[\d\. ]+$/, parser: onlyNumbersParser } ]) } - static cachedHandGrammarProgramRoot = new HandGrammarProgram(`// todo Make this compile and execute + static cachedHandParsersProgramRoot = new HandParsersProgram(`// todo Make this compile and execute // Cell Parsers operatorCell @@ -24,7 +24,7 @@ floatCell // Line Parsers chuckParser - description A useless demo Tree Language inspired by Forth that tests postfix notation. + description A useless demo Language inspired by Forth that tests postfix notation. root inScope abstractOperatorParser onlyNumbersParser abstractOperatorParser @@ -43,13 +43,13 @@ printParser onlyNumbersParser catchAllCellType floatCell pattern ^[\\d\\. ]+$`) - get handGrammarProgram() { - return this.constructor.cachedHandGrammarProgramRoot + get handParsersProgram() { + return this.constructor.cachedHandParsersProgramRoot } static rootParser = chuckParser } - class abstractOperatorParser extends GrammarBackedNode { + class abstractOperatorParser extends ParserBackedNode { get operatorCell() { return this.getWord(0) } @@ -64,7 +64,7 @@ onlyNumbersParser class printParser extends abstractOperatorParser {} - class onlyNumbersParser extends GrammarBackedNode { + class onlyNumbersParser extends ParserBackedNode { get floatCell() { return this.getWordsFrom(0).map(val => parseFloat(val)) } diff --git a/products/dug.browser.js b/products/dug.browser.js index ec227cd51..430f91c24 100644 --- a/products/dug.browser.js +++ b/products/dug.browser.js @@ -1,5 +1,5 @@ { - class dugParser extends GrammarBackedNode { + class dugParser extends ParserBackedNode { createParserCombinator() { return new TreeNode.ParserCombinator( errorParser, @@ -11,7 +11,7 @@ const res = super.compile() return JSON.stringify(JSON.parse(res), null, 2) } - static cachedHandGrammarProgramRoot = new HandGrammarProgram(`// todo Add swarm tests for top scenarios, including the scalar at root level scenario. + static cachedHandParsersProgramRoot = new HandParsersProgram(`// todo Add swarm tests for top scenarios, including the scalar at root level scenario. // todo Create a new language, similar to this, except using pattern matching instead of prefix notation. // Cell Parsers @@ -29,7 +29,7 @@ numberCell // Line Parsers dugParser root - description A demonstration prefix Tree Language that compiles to JSON. + description A demonstration prefix Language that compiles to JSON. inScope abstractValueParser catchAllParser errorParser javascript @@ -82,13 +82,13 @@ memberParser cells stringCell errorParser baseParser errorParser`) - get handGrammarProgram() { - return this.constructor.cachedHandGrammarProgramRoot + get handParsersProgram() { + return this.constructor.cachedHandParsersProgramRoot } static rootParser = dugParser } - class abstractValueParser extends GrammarBackedNode { + class abstractValueParser extends ParserBackedNode { get keywordCell() { return this.getWord(0) } @@ -136,7 +136,7 @@ errorParser } } - class memberParser extends GrammarBackedNode { + class memberParser extends ParserBackedNode { createParserCombinator() { return new TreeNode.ParserCombinator( undefined, @@ -149,7 +149,7 @@ errorParser } } - class errorParser extends GrammarBackedNode { + class errorParser extends ParserBackedNode { getErrors() { return this._getErrorParserErrors() } diff --git a/products/dug.nodejs.js b/products/dug.nodejs.js index f10ea1b70..4e121b0e6 100755 --- a/products/dug.nodejs.js +++ b/products/dug.nodejs.js @@ -2,10 +2,10 @@ { const { Utils } = require("./Utils.js") const { TreeNode } = require("./TreeNode.js") - const { HandGrammarProgram } = require("./GrammarLanguage.js") - const { GrammarBackedNode } = require("./GrammarLanguage.js") + const { HandParsersProgram } = require("./Parsers.js") + const { ParserBackedNode } = require("./Parsers.js") - class dugParser extends GrammarBackedNode { + class dugParser extends ParserBackedNode { createParserCombinator() { return new TreeNode.ParserCombinator( errorParser, @@ -17,7 +17,7 @@ const res = super.compile() return JSON.stringify(JSON.parse(res), null, 2) } - static cachedHandGrammarProgramRoot = new HandGrammarProgram(`// todo Add swarm tests for top scenarios, including the scalar at root level scenario. + static cachedHandParsersProgramRoot = new HandParsersProgram(`// todo Add swarm tests for top scenarios, including the scalar at root level scenario. // todo Create a new language, similar to this, except using pattern matching instead of prefix notation. // Cell Parsers @@ -35,7 +35,7 @@ numberCell // Line Parsers dugParser root - description A demonstration prefix Tree Language that compiles to JSON. + description A demonstration prefix Language that compiles to JSON. inScope abstractValueParser catchAllParser errorParser javascript @@ -88,13 +88,13 @@ memberParser cells stringCell errorParser baseParser errorParser`) - get handGrammarProgram() { - return this.constructor.cachedHandGrammarProgramRoot + get handParsersProgram() { + return this.constructor.cachedHandParsersProgramRoot } static rootParser = dugParser } - class abstractValueParser extends GrammarBackedNode { + class abstractValueParser extends ParserBackedNode { get keywordCell() { return this.getWord(0) } @@ -142,7 +142,7 @@ errorParser } } - class memberParser extends GrammarBackedNode { + class memberParser extends ParserBackedNode { createParserCombinator() { return new TreeNode.ParserCombinator( undefined, @@ -155,7 +155,7 @@ errorParser } } - class errorParser extends GrammarBackedNode { + class errorParser extends ParserBackedNode { getErrors() { return this._getErrorParserErrors() } diff --git a/products/dumbdown.browser.js b/products/dumbdown.browser.js index d03abdf5d..5dbd6f62f 100644 --- a/products/dumbdown.browser.js +++ b/products/dumbdown.browser.js @@ -1,11 +1,11 @@ { - class errorParser extends GrammarBackedNode { + class errorParser extends ParserBackedNode { getErrors() { return this._getErrorParserErrors() } } - class dumbdownParser extends GrammarBackedNode { + class dumbdownParser extends ParserBackedNode { createParserCombinator() { return new TreeNode.ParserCombinator( quickParagraphParser, @@ -24,7 +24,7 @@ [{ regex: /^$/, parser: blankLineParser }] ) } - static cachedHandGrammarProgramRoot = new HandGrammarProgram(`// Cell Parsers + static cachedHandParsersProgramRoot = new HandParsersProgram(`// Cell Parsers anyCell blankCell dashCell @@ -43,7 +43,7 @@ errorParser baseParser errorParser dumbdownParser extensions dd dumbdown - description A Tree Language that compiles to HTML. An alternative to Markdown. + description A Language that compiles to HTML. An alternative to Markdown. root inScope abstractTopLevelParser blankLineParser catchAllParser quickParagraphParser @@ -54,7 +54,7 @@ dumbdownParser paragraph It compiles to HTML. Blank lines get turned into brs. - link https://notation.scroll.pub Dumbdown is a Tree Language. + link https://notation.scroll.pub Dumbdown is a Language. list - It has lists - Too! @@ -158,13 +158,13 @@ quickParagraphParser catchAllCellType textCell compiler stringTemplate

{textCell}

`) - get handGrammarProgram() { - return this.constructor.cachedHandGrammarProgramRoot + get handParsersProgram() { + return this.constructor.cachedHandParsersProgramRoot } static rootParser = dumbdownParser } - class abstractTopLevelParser extends GrammarBackedNode { + class abstractTopLevelParser extends ParserBackedNode { get keywordCell() { return this.getWord(0) } @@ -188,7 +188,7 @@ quickParagraphParser } } - class paragraphContentParser extends GrammarBackedNode { + class paragraphContentParser extends ParserBackedNode { get textCell() { return this.getWordsFrom(0) } @@ -209,13 +209,13 @@ quickParagraphParser } } - class blankLineParser extends GrammarBackedNode { + class blankLineParser extends ParserBackedNode { get blankCell() { return this.getWord(0) } } - class lineOfCodeParser extends GrammarBackedNode { + class lineOfCodeParser extends ParserBackedNode { createParserCombinator() { return new TreeNode.ParserCombinator(lineOfCodeParser, undefined, undefined) } @@ -224,7 +224,7 @@ quickParagraphParser } } - class dashParser extends GrammarBackedNode { + class dashParser extends ParserBackedNode { get dashCell() { return this.getWord(0) } @@ -258,7 +258,7 @@ quickParagraphParser class title6Parser extends title2Parser {} - class quickParagraphParser extends GrammarBackedNode { + class quickParagraphParser extends ParserBackedNode { get textCell() { return this.getWordsFrom(0) } diff --git a/products/dumbdown.nodejs.js b/products/dumbdown.nodejs.js index e68813eca..16880bbcb 100755 --- a/products/dumbdown.nodejs.js +++ b/products/dumbdown.nodejs.js @@ -2,16 +2,16 @@ { const { Utils } = require("./Utils.js") const { TreeNode } = require("./TreeNode.js") - const { HandGrammarProgram } = require("./GrammarLanguage.js") - const { GrammarBackedNode } = require("./GrammarLanguage.js") + const { HandParsersProgram } = require("./Parsers.js") + const { ParserBackedNode } = require("./Parsers.js") - class errorParser extends GrammarBackedNode { + class errorParser extends ParserBackedNode { getErrors() { return this._getErrorParserErrors() } } - class dumbdownParser extends GrammarBackedNode { + class dumbdownParser extends ParserBackedNode { createParserCombinator() { return new TreeNode.ParserCombinator( quickParagraphParser, @@ -30,7 +30,7 @@ [{ regex: /^$/, parser: blankLineParser }] ) } - static cachedHandGrammarProgramRoot = new HandGrammarProgram(`// Cell Parsers + static cachedHandParsersProgramRoot = new HandParsersProgram(`// Cell Parsers anyCell blankCell dashCell @@ -49,7 +49,7 @@ errorParser baseParser errorParser dumbdownParser extensions dd dumbdown - description A Tree Language that compiles to HTML. An alternative to Markdown. + description A Language that compiles to HTML. An alternative to Markdown. root inScope abstractTopLevelParser blankLineParser catchAllParser quickParagraphParser @@ -60,7 +60,7 @@ dumbdownParser paragraph It compiles to HTML. Blank lines get turned into brs. - link https://notation.scroll.pub Dumbdown is a Tree Language. + link https://notation.scroll.pub Dumbdown is a Language. list - It has lists - Too! @@ -164,13 +164,13 @@ quickParagraphParser catchAllCellType textCell compiler stringTemplate

{textCell}

`) - get handGrammarProgram() { - return this.constructor.cachedHandGrammarProgramRoot + get handParsersProgram() { + return this.constructor.cachedHandParsersProgramRoot } static rootParser = dumbdownParser } - class abstractTopLevelParser extends GrammarBackedNode { + class abstractTopLevelParser extends ParserBackedNode { get keywordCell() { return this.getWord(0) } @@ -194,7 +194,7 @@ quickParagraphParser } } - class paragraphContentParser extends GrammarBackedNode { + class paragraphContentParser extends ParserBackedNode { get textCell() { return this.getWordsFrom(0) } @@ -215,13 +215,13 @@ quickParagraphParser } } - class blankLineParser extends GrammarBackedNode { + class blankLineParser extends ParserBackedNode { get blankCell() { return this.getWord(0) } } - class lineOfCodeParser extends GrammarBackedNode { + class lineOfCodeParser extends ParserBackedNode { createParserCombinator() { return new TreeNode.ParserCombinator(lineOfCodeParser, undefined, undefined) } @@ -230,7 +230,7 @@ quickParagraphParser } } - class dashParser extends GrammarBackedNode { + class dashParser extends ParserBackedNode { get dashCell() { return this.getWord(0) } @@ -264,7 +264,7 @@ quickParagraphParser class title6Parser extends title2Parser {} - class quickParagraphParser extends GrammarBackedNode { + class quickParagraphParser extends ParserBackedNode { get textCell() { return this.getWordsFrom(0) } diff --git a/products/fire.browser.js b/products/fire.browser.js index 428bd3fa6..dc87d682a 100644 --- a/products/fire.browser.js +++ b/products/fire.browser.js @@ -1,5 +1,5 @@ { - class fireParser extends GrammarBackedNode { + class fireParser extends ParserBackedNode { createParserCombinator() { return new TreeNode.ParserCombinator( errorParser, @@ -51,7 +51,7 @@ console.log(outputLines.join("\n")) return outputLines } - static cachedHandGrammarProgramRoot = new HandGrammarProgram(`// todo Explore best ways to add polymorphism + static cachedHandParsersProgramRoot = new HandParsersProgram(`// todo Explore best ways to add polymorphism // Cell Parsers anyCell @@ -99,7 +99,7 @@ leftAnyCell // Line Parsers fireParser root - description A useless prefix Tree Language that compiles to Javascript for testing Scroll Notation features. + description A useless prefix Language that compiles to Javascript for testing Scroll Notation features. compilesTo js inScope hashbangParser abstractTerminalParser abstractNonTerminalParser catchAllParser errorParser @@ -397,13 +397,13 @@ errorParser baseParser errorParser compiler stringTemplate // error`) - get handGrammarProgram() { - return this.constructor.cachedHandGrammarProgramRoot + get handParsersProgram() { + return this.constructor.cachedHandParsersProgramRoot } static rootParser = fireParser } - class abstractNonTerminalParser extends GrammarBackedNode { + class abstractNonTerminalParser extends ParserBackedNode { createParserCombinator() { return new TreeNode.ParserCombinator( undefined, @@ -482,7 +482,7 @@ errorParser } } - class abstractTerminalParser extends GrammarBackedNode { + class abstractTerminalParser extends ParserBackedNode { get keywordCell() { return this.getWord(0) } @@ -769,7 +769,7 @@ errorParser } } - class hashbangParser extends GrammarBackedNode { + class hashbangParser extends ParserBackedNode { get hashBangKeywordCell() { return this.getWord(0) } @@ -778,7 +778,7 @@ errorParser } } - class errorParser extends GrammarBackedNode { + class errorParser extends ParserBackedNode { getErrors() { return this._getErrorParserErrors() } diff --git a/products/fire.nodejs.js b/products/fire.nodejs.js index d75c54b0a..9c02ae620 100755 --- a/products/fire.nodejs.js +++ b/products/fire.nodejs.js @@ -2,10 +2,10 @@ { const { Utils } = require("./Utils.js") const { TreeNode } = require("./TreeNode.js") - const { HandGrammarProgram } = require("./GrammarLanguage.js") - const { GrammarBackedNode } = require("./GrammarLanguage.js") + const { HandParsersProgram } = require("./Parsers.js") + const { ParserBackedNode } = require("./Parsers.js") - class fireParser extends GrammarBackedNode { + class fireParser extends ParserBackedNode { createParserCombinator() { return new TreeNode.ParserCombinator( errorParser, @@ -57,7 +57,7 @@ console.log(outputLines.join("\n")) return outputLines } - static cachedHandGrammarProgramRoot = new HandGrammarProgram(`// todo Explore best ways to add polymorphism + static cachedHandParsersProgramRoot = new HandParsersProgram(`// todo Explore best ways to add polymorphism // Cell Parsers anyCell @@ -105,7 +105,7 @@ leftAnyCell // Line Parsers fireParser root - description A useless prefix Tree Language that compiles to Javascript for testing Scroll Notation features. + description A useless prefix Language that compiles to Javascript for testing Scroll Notation features. compilesTo js inScope hashbangParser abstractTerminalParser abstractNonTerminalParser catchAllParser errorParser @@ -403,13 +403,13 @@ errorParser baseParser errorParser compiler stringTemplate // error`) - get handGrammarProgram() { - return this.constructor.cachedHandGrammarProgramRoot + get handParsersProgram() { + return this.constructor.cachedHandParsersProgramRoot } static rootParser = fireParser } - class abstractNonTerminalParser extends GrammarBackedNode { + class abstractNonTerminalParser extends ParserBackedNode { createParserCombinator() { return new TreeNode.ParserCombinator( undefined, @@ -488,7 +488,7 @@ errorParser } } - class abstractTerminalParser extends GrammarBackedNode { + class abstractTerminalParser extends ParserBackedNode { get keywordCell() { return this.getWord(0) } @@ -775,7 +775,7 @@ errorParser } } - class hashbangParser extends GrammarBackedNode { + class hashbangParser extends ParserBackedNode { get hashBangKeywordCell() { return this.getWord(0) } @@ -784,7 +784,7 @@ errorParser } } - class errorParser extends GrammarBackedNode { + class errorParser extends ParserBackedNode { getErrors() { return this._getErrorParserErrors() } diff --git a/products/fruit.browser.js b/products/fruit.browser.js index 936e26ba9..c6596c85c 100644 --- a/products/fruit.browser.js +++ b/products/fruit.browser.js @@ -1,9 +1,9 @@ { - class fruitParser extends GrammarBackedNode { + class fruitParser extends ParserBackedNode { createParserCombinator() { return new TreeNode.ParserCombinator(errorParser, Object.assign(Object.assign({}, super.createParserCombinator()._getFirstWordMapAsObject()), { apple: appleParser }), undefined) } - static cachedHandGrammarProgramRoot = new HandGrammarProgram(`fruitNameCell + static cachedHandParsersProgramRoot = new HandParsersProgram(`fruitNameCell highlightScope keyword fruitParser description A useless language to test scoped parsers. @@ -23,13 +23,13 @@ appleParser extends abstractFruitParser errorParser baseParser errorParser`) - get handGrammarProgram() { - return this.constructor.cachedHandGrammarProgramRoot + get handParsersProgram() { + return this.constructor.cachedHandParsersProgramRoot } static rootParser = fruitParser } - class abstractFruitParser extends GrammarBackedNode { + class abstractFruitParser extends ParserBackedNode { get fruitNameCell() { return this.getWord(0) } @@ -42,7 +42,7 @@ errorParser } } - class errorParser extends GrammarBackedNode { + class errorParser extends ParserBackedNode { getErrors() { return this._getErrorParserErrors() } diff --git a/products/fruit.nodejs.js b/products/fruit.nodejs.js index dc1402c9f..fbeb43e8c 100755 --- a/products/fruit.nodejs.js +++ b/products/fruit.nodejs.js @@ -2,14 +2,14 @@ { const { Utils } = require("./Utils.js") const { TreeNode } = require("./TreeNode.js") - const { HandGrammarProgram } = require("./GrammarLanguage.js") - const { GrammarBackedNode } = require("./GrammarLanguage.js") + const { HandParsersProgram } = require("./Parsers.js") + const { ParserBackedNode } = require("./Parsers.js") - class fruitParser extends GrammarBackedNode { + class fruitParser extends ParserBackedNode { createParserCombinator() { return new TreeNode.ParserCombinator(errorParser, Object.assign(Object.assign({}, super.createParserCombinator()._getFirstWordMapAsObject()), { apple: appleParser }), undefined) } - static cachedHandGrammarProgramRoot = new HandGrammarProgram(`fruitNameCell + static cachedHandParsersProgramRoot = new HandParsersProgram(`fruitNameCell highlightScope keyword fruitParser description A useless language to test scoped parsers. @@ -29,13 +29,13 @@ appleParser extends abstractFruitParser errorParser baseParser errorParser`) - get handGrammarProgram() { - return this.constructor.cachedHandGrammarProgramRoot + get handParsersProgram() { + return this.constructor.cachedHandParsersProgramRoot } static rootParser = fruitParser } - class abstractFruitParser extends GrammarBackedNode { + class abstractFruitParser extends ParserBackedNode { get fruitNameCell() { return this.getWord(0) } @@ -48,7 +48,7 @@ errorParser } } - class errorParser extends GrammarBackedNode { + class errorParser extends ParserBackedNode { getErrors() { return this._getErrorParserErrors() } diff --git a/products/hakon.browser.js b/products/hakon.browser.js index 1b98e1a44..e754714f9 100644 --- a/products/hakon.browser.js +++ b/products/hakon.browser.js @@ -1,5 +1,5 @@ { - class hakonParser extends GrammarBackedNode { + class hakonParser extends ParserBackedNode { createParserCombinator() { return new TreeNode.ParserCombinator(selectorParser, Object.assign(Object.assign({}, super.createParserCombinator()._getFirstWordMapAsObject()), { comment: commentParser }), undefined) } @@ -12,7 +12,7 @@ .map(child => child.compile()) .join("") } - static cachedHandGrammarProgramRoot = new HandGrammarProgram(`// Cell Parsers + static cachedHandParsersProgramRoot = new HandParsersProgram(`// Cell Parsers anyCell keywordCell commentKeywordCell @@ -45,7 +45,7 @@ commentCell hakonParser root // todo Add variables? - description A prefix Tree Language that compiles to CSS + description A prefix Language that compiles to CSS compilesTo css inScope commentParser catchAllParser selectorParser @@ -115,13 +115,13 @@ selectorParser }\\n\` } cells selectorCell`) - get handGrammarProgram() { - return this.constructor.cachedHandGrammarProgramRoot + get handParsersProgram() { + return this.constructor.cachedHandParsersProgramRoot } static rootParser = hakonParser } - class propertyParser extends GrammarBackedNode { + class propertyParser extends ParserBackedNode { createParserCombinator() { return new TreeNode.ParserCombinator(errorParser, undefined, undefined) } @@ -144,7 +144,7 @@ selectorParser } } - class errorParser extends GrammarBackedNode { + class errorParser extends ParserBackedNode { createParserCombinator() { return new TreeNode.ParserCombinator(errorParser, undefined, undefined) } @@ -156,7 +156,7 @@ selectorParser } } - class commentParser extends GrammarBackedNode { + class commentParser extends ParserBackedNode { createParserCombinator() { return new TreeNode.ParserCombinator(commentParser, undefined, undefined) } @@ -168,7 +168,7 @@ selectorParser } } - class selectorParser extends GrammarBackedNode { + class selectorParser extends ParserBackedNode { createParserCombinator() { return new TreeNode.ParserCombinator( selectorParser, diff --git a/products/hakon.nodejs.js b/products/hakon.nodejs.js index c5fb3425d..17ddc50d0 100755 --- a/products/hakon.nodejs.js +++ b/products/hakon.nodejs.js @@ -2,10 +2,10 @@ { const { Utils } = require("./Utils.js") const { TreeNode } = require("./TreeNode.js") - const { HandGrammarProgram } = require("./GrammarLanguage.js") - const { GrammarBackedNode } = require("./GrammarLanguage.js") + const { HandParsersProgram } = require("./Parsers.js") + const { ParserBackedNode } = require("./Parsers.js") - class hakonParser extends GrammarBackedNode { + class hakonParser extends ParserBackedNode { createParserCombinator() { return new TreeNode.ParserCombinator(selectorParser, Object.assign(Object.assign({}, super.createParserCombinator()._getFirstWordMapAsObject()), { comment: commentParser }), undefined) } @@ -18,7 +18,7 @@ .map(child => child.compile()) .join("") } - static cachedHandGrammarProgramRoot = new HandGrammarProgram(`// Cell Parsers + static cachedHandParsersProgramRoot = new HandParsersProgram(`// Cell Parsers anyCell keywordCell commentKeywordCell @@ -51,7 +51,7 @@ commentCell hakonParser root // todo Add variables? - description A prefix Tree Language that compiles to CSS + description A prefix Language that compiles to CSS compilesTo css inScope commentParser catchAllParser selectorParser @@ -121,13 +121,13 @@ selectorParser }\\n\` } cells selectorCell`) - get handGrammarProgram() { - return this.constructor.cachedHandGrammarProgramRoot + get handParsersProgram() { + return this.constructor.cachedHandParsersProgramRoot } static rootParser = hakonParser } - class propertyParser extends GrammarBackedNode { + class propertyParser extends ParserBackedNode { createParserCombinator() { return new TreeNode.ParserCombinator(errorParser, undefined, undefined) } @@ -150,7 +150,7 @@ selectorParser } } - class errorParser extends GrammarBackedNode { + class errorParser extends ParserBackedNode { createParserCombinator() { return new TreeNode.ParserCombinator(errorParser, undefined, undefined) } @@ -162,7 +162,7 @@ selectorParser } } - class commentParser extends GrammarBackedNode { + class commentParser extends ParserBackedNode { createParserCombinator() { return new TreeNode.ParserCombinator(commentParser, undefined, undefined) } @@ -174,7 +174,7 @@ selectorParser } } - class selectorParser extends GrammarBackedNode { + class selectorParser extends ParserBackedNode { createParserCombinator() { return new TreeNode.ParserCombinator( selectorParser, diff --git a/products/jibberish.browser.js b/products/jibberish.browser.js index cd4e3b4a6..3daa3358f 100644 --- a/products/jibberish.browser.js +++ b/products/jibberish.browser.js @@ -1,5 +1,5 @@ { - class jibberishParser extends GrammarBackedNode { + class jibberishParser extends ParserBackedNode { createParserCombinator() { return new TreeNode.ParserCombinator( errorParser, @@ -30,7 +30,7 @@ execute() { return 42 } - static cachedHandGrammarProgramRoot = new HandGrammarProgram(`// Cell Parsers + static cachedHandParsersProgramRoot = new HandParsersProgram(`// Cell Parsers anyCell columnNameEnumCell columnNameCell @@ -49,7 +49,7 @@ opSymbolCell // Line Parsers jibberishParser root - description A useless Tree Language built for testing Scroll Notation code. + description A useless Language built for testing Scroll Notation code. javascript execute() { return 42 @@ -170,13 +170,13 @@ scoresParser catchAllCellType intCell cells topLevelPropertyCell crux scores`) - get handGrammarProgram() { - return this.constructor.cachedHandGrammarProgramRoot + get handParsersProgram() { + return this.constructor.cachedHandParsersProgramRoot } static rootParser = jibberishParser } - class abstractBaseClassParser extends GrammarBackedNode {} + class abstractBaseClassParser extends ParserBackedNode {} class extendsAbstractParser extends abstractBaseClassParser { get topLevelPropertyCell() { @@ -187,7 +187,7 @@ scoresParser } } - class abstractTopLevelParser extends GrammarBackedNode { + class abstractTopLevelParser extends ParserBackedNode { get topLevelPropertyCell() { return this.getWord(0) } @@ -344,7 +344,7 @@ world` } } - class contentParser extends GrammarBackedNode { + class contentParser extends ParserBackedNode { createParserCombinator() { return new TreeNode.ParserCombinator(this._getBlobParserCatchAllParser()) } @@ -353,7 +353,7 @@ world` } } - class errorParser extends GrammarBackedNode { + class errorParser extends ParserBackedNode { getErrors() { return this._getErrorParserErrors() } @@ -365,13 +365,13 @@ world` } } - class lineOfCodeParser extends GrammarBackedNode { + class lineOfCodeParser extends ParserBackedNode { get wordCell() { return this.getWordsFrom(0) } } - class textParser extends GrammarBackedNode { + class textParser extends ParserBackedNode { createParserCombinator() { return new TreeNode.ParserCombinator(this._getBlobParserCatchAllParser()) } @@ -380,7 +380,7 @@ world` } } - class scoresParser extends GrammarBackedNode { + class scoresParser extends ParserBackedNode { get topLevelPropertyCell() { return this.getWord(0) } diff --git a/products/jibberish.nodejs.js b/products/jibberish.nodejs.js index c9b3df22e..5bc3f06c8 100755 --- a/products/jibberish.nodejs.js +++ b/products/jibberish.nodejs.js @@ -2,10 +2,10 @@ { const { Utils } = require("./Utils.js") const { TreeNode } = require("./TreeNode.js") - const { HandGrammarProgram } = require("./GrammarLanguage.js") - const { GrammarBackedNode } = require("./GrammarLanguage.js") + const { HandParsersProgram } = require("./Parsers.js") + const { ParserBackedNode } = require("./Parsers.js") - class jibberishParser extends GrammarBackedNode { + class jibberishParser extends ParserBackedNode { createParserCombinator() { return new TreeNode.ParserCombinator( errorParser, @@ -36,7 +36,7 @@ execute() { return 42 } - static cachedHandGrammarProgramRoot = new HandGrammarProgram(`// Cell Parsers + static cachedHandParsersProgramRoot = new HandParsersProgram(`// Cell Parsers anyCell columnNameEnumCell columnNameCell @@ -55,7 +55,7 @@ opSymbolCell // Line Parsers jibberishParser root - description A useless Tree Language built for testing Scroll Notation code. + description A useless Language built for testing Scroll Notation code. javascript execute() { return 42 @@ -176,13 +176,13 @@ scoresParser catchAllCellType intCell cells topLevelPropertyCell crux scores`) - get handGrammarProgram() { - return this.constructor.cachedHandGrammarProgramRoot + get handParsersProgram() { + return this.constructor.cachedHandParsersProgramRoot } static rootParser = jibberishParser } - class abstractBaseClassParser extends GrammarBackedNode {} + class abstractBaseClassParser extends ParserBackedNode {} class extendsAbstractParser extends abstractBaseClassParser { get topLevelPropertyCell() { @@ -193,7 +193,7 @@ scoresParser } } - class abstractTopLevelParser extends GrammarBackedNode { + class abstractTopLevelParser extends ParserBackedNode { get topLevelPropertyCell() { return this.getWord(0) } @@ -350,7 +350,7 @@ world` } } - class contentParser extends GrammarBackedNode { + class contentParser extends ParserBackedNode { createParserCombinator() { return new TreeNode.ParserCombinator(this._getBlobParserCatchAllParser()) } @@ -359,7 +359,7 @@ world` } } - class errorParser extends GrammarBackedNode { + class errorParser extends ParserBackedNode { getErrors() { return this._getErrorParserErrors() } @@ -371,13 +371,13 @@ world` } } - class lineOfCodeParser extends GrammarBackedNode { + class lineOfCodeParser extends ParserBackedNode { get wordCell() { return this.getWordsFrom(0) } } - class textParser extends GrammarBackedNode { + class textParser extends ParserBackedNode { createParserCombinator() { return new TreeNode.ParserCombinator(this._getBlobParserCatchAllParser()) } @@ -386,7 +386,7 @@ world` } } - class scoresParser extends GrammarBackedNode { + class scoresParser extends ParserBackedNode { get topLevelPropertyCell() { return this.getWord(0) } diff --git a/products/jibjab.browser.js b/products/jibjab.browser.js index f930cc270..bf4471241 100644 --- a/products/jibjab.browser.js +++ b/products/jibjab.browser.js @@ -1,5 +1,5 @@ { - class jibberishParser extends GrammarBackedNode { + class jibberishParser extends ParserBackedNode { createParserCombinator() { return new TreeNode.ParserCombinator( errorParser, @@ -34,7 +34,7 @@ } class jibjabParser extends jibberishParser { - static cachedHandGrammarProgramRoot = new HandGrammarProgram(`// Cell Parsers + static cachedHandParsersProgramRoot = new HandParsersProgram(`// Cell Parsers anyCell columnNameEnumCell columnNameCell @@ -55,7 +55,7 @@ commentCell // Line Parsers jibberishParser root - description A useless Tree Language built for testing Scroll Notation code. + description A useless Language built for testing Scroll Notation code. javascript execute() { return 42 @@ -185,13 +185,13 @@ scoresParser catchAllCellType intCell cells topLevelPropertyCell crux scores`) - get handGrammarProgram() { - return this.constructor.cachedHandGrammarProgramRoot + get handParsersProgram() { + return this.constructor.cachedHandParsersProgramRoot } static rootParser = jibjabParser } - class abstractBaseClassParser extends GrammarBackedNode {} + class abstractBaseClassParser extends ParserBackedNode {} class extendsAbstractParser extends abstractBaseClassParser { get topLevelPropertyCell() { @@ -202,7 +202,7 @@ scoresParser } } - class abstractTopLevelParser extends GrammarBackedNode { + class abstractTopLevelParser extends ParserBackedNode { get topLevelPropertyCell() { return this.getWord(0) } @@ -369,7 +369,7 @@ world` } } - class contentParser extends GrammarBackedNode { + class contentParser extends ParserBackedNode { createParserCombinator() { return new TreeNode.ParserCombinator(this._getBlobParserCatchAllParser()) } @@ -378,7 +378,7 @@ world` } } - class errorParser extends GrammarBackedNode { + class errorParser extends ParserBackedNode { getErrors() { return this._getErrorParserErrors() } @@ -390,13 +390,13 @@ world` } } - class lineOfCodeParser extends GrammarBackedNode { + class lineOfCodeParser extends ParserBackedNode { get wordCell() { return this.getWordsFrom(0) } } - class textParser extends GrammarBackedNode { + class textParser extends ParserBackedNode { createParserCombinator() { return new TreeNode.ParserCombinator(this._getBlobParserCatchAllParser()) } @@ -405,7 +405,7 @@ world` } } - class scoresParser extends GrammarBackedNode { + class scoresParser extends ParserBackedNode { get topLevelPropertyCell() { return this.getWord(0) } diff --git a/products/jibjab.nodejs.js b/products/jibjab.nodejs.js index d65e55fac..227eae73e 100755 --- a/products/jibjab.nodejs.js +++ b/products/jibjab.nodejs.js @@ -2,10 +2,10 @@ { const { Utils } = require("./Utils.js") const { TreeNode } = require("./TreeNode.js") - const { HandGrammarProgram } = require("./GrammarLanguage.js") - const { GrammarBackedNode } = require("./GrammarLanguage.js") + const { HandParsersProgram } = require("./Parsers.js") + const { ParserBackedNode } = require("./Parsers.js") - class jibberishParser extends GrammarBackedNode { + class jibberishParser extends ParserBackedNode { createParserCombinator() { return new TreeNode.ParserCombinator( errorParser, @@ -40,7 +40,7 @@ } class jibjabParser extends jibberishParser { - static cachedHandGrammarProgramRoot = new HandGrammarProgram(`// Cell Parsers + static cachedHandParsersProgramRoot = new HandParsersProgram(`// Cell Parsers anyCell columnNameEnumCell columnNameCell @@ -61,7 +61,7 @@ commentCell // Line Parsers jibberishParser root - description A useless Tree Language built for testing Scroll Notation code. + description A useless Language built for testing Scroll Notation code. javascript execute() { return 42 @@ -191,13 +191,13 @@ scoresParser catchAllCellType intCell cells topLevelPropertyCell crux scores`) - get handGrammarProgram() { - return this.constructor.cachedHandGrammarProgramRoot + get handParsersProgram() { + return this.constructor.cachedHandParsersProgramRoot } static rootParser = jibjabParser } - class abstractBaseClassParser extends GrammarBackedNode {} + class abstractBaseClassParser extends ParserBackedNode {} class extendsAbstractParser extends abstractBaseClassParser { get topLevelPropertyCell() { @@ -208,7 +208,7 @@ scoresParser } } - class abstractTopLevelParser extends GrammarBackedNode { + class abstractTopLevelParser extends ParserBackedNode { get topLevelPropertyCell() { return this.getWord(0) } @@ -375,7 +375,7 @@ world` } } - class contentParser extends GrammarBackedNode { + class contentParser extends ParserBackedNode { createParserCombinator() { return new TreeNode.ParserCombinator(this._getBlobParserCatchAllParser()) } @@ -384,7 +384,7 @@ world` } } - class errorParser extends GrammarBackedNode { + class errorParser extends ParserBackedNode { getErrors() { return this._getErrorParserErrors() } @@ -396,13 +396,13 @@ world` } } - class lineOfCodeParser extends GrammarBackedNode { + class lineOfCodeParser extends ParserBackedNode { get wordCell() { return this.getWordsFrom(0) } } - class textParser extends GrammarBackedNode { + class textParser extends ParserBackedNode { createParserCombinator() { return new TreeNode.ParserCombinator(this._getBlobParserCatchAllParser()) } @@ -411,7 +411,7 @@ world` } } - class scoresParser extends GrammarBackedNode { + class scoresParser extends ParserBackedNode { get topLevelPropertyCell() { return this.getWord(0) } diff --git a/products/numbers.browser.js b/products/numbers.browser.js index 3d812efb1..ff2aa0be5 100644 --- a/products/numbers.browser.js +++ b/products/numbers.browser.js @@ -1,5 +1,5 @@ { - class numbersParser extends GrammarBackedNode { + class numbersParser extends ParserBackedNode { createParserCombinator() { return new TreeNode.ParserCombinator( errorParser, @@ -18,7 +18,7 @@ execute() { return this.map(child => child.execute()) } - static cachedHandGrammarProgramRoot = new HandGrammarProgram(`// Cell Parsers + static cachedHandParsersProgramRoot = new HandParsersProgram(`// Cell Parsers floatCell commentCell highlightScope comment @@ -43,7 +43,7 @@ operatorCell // Line Parsers numbersParser root - description A useless Tree Language for testing Scroll Notation features. + description A useless Language for testing Scroll Notation features. inScope abstractArithmeticReducerParser commentParser hashBangParser catchAllParser errorParser javascript @@ -95,13 +95,13 @@ errorParser catchAllCellType errorCell baseParser errorParser cells errorCell`) - get handGrammarProgram() { - return this.constructor.cachedHandGrammarProgramRoot + get handParsersProgram() { + return this.constructor.cachedHandParsersProgramRoot } static rootParser = numbersParser } - class abstractArithmeticReducerParser extends GrammarBackedNode { + class abstractArithmeticReducerParser extends ParserBackedNode { createParserCombinator() { return new TreeNode.ParserCombinator( undefined, @@ -150,7 +150,7 @@ errorParser } } - class commentParser extends GrammarBackedNode { + class commentParser extends ParserBackedNode { createParserCombinator() { return new TreeNode.ParserCombinator(commentContentParser, undefined, undefined) } @@ -162,7 +162,7 @@ errorParser } } - class commentContentParser extends GrammarBackedNode { + class commentContentParser extends ParserBackedNode { createParserCombinator() { return new TreeNode.ParserCombinator(commentContentParser, undefined, undefined) } @@ -171,7 +171,7 @@ errorParser } } - class hashBangParser extends GrammarBackedNode { + class hashBangParser extends ParserBackedNode { get hashBangKeywordCell() { return this.getWord(0) } @@ -180,7 +180,7 @@ errorParser } } - class errorParser extends GrammarBackedNode { + class errorParser extends ParserBackedNode { getErrors() { return this._getErrorParserErrors() } diff --git a/products/numbers.nodejs.js b/products/numbers.nodejs.js index 0fed40f6e..f5efa1322 100755 --- a/products/numbers.nodejs.js +++ b/products/numbers.nodejs.js @@ -2,10 +2,10 @@ { const { Utils } = require("./Utils.js") const { TreeNode } = require("./TreeNode.js") - const { HandGrammarProgram } = require("./GrammarLanguage.js") - const { GrammarBackedNode } = require("./GrammarLanguage.js") + const { HandParsersProgram } = require("./Parsers.js") + const { ParserBackedNode } = require("./Parsers.js") - class numbersParser extends GrammarBackedNode { + class numbersParser extends ParserBackedNode { createParserCombinator() { return new TreeNode.ParserCombinator( errorParser, @@ -24,7 +24,7 @@ execute() { return this.map(child => child.execute()) } - static cachedHandGrammarProgramRoot = new HandGrammarProgram(`// Cell Parsers + static cachedHandParsersProgramRoot = new HandParsersProgram(`// Cell Parsers floatCell commentCell highlightScope comment @@ -49,7 +49,7 @@ operatorCell // Line Parsers numbersParser root - description A useless Tree Language for testing Scroll Notation features. + description A useless Language for testing Scroll Notation features. inScope abstractArithmeticReducerParser commentParser hashBangParser catchAllParser errorParser javascript @@ -101,13 +101,13 @@ errorParser catchAllCellType errorCell baseParser errorParser cells errorCell`) - get handGrammarProgram() { - return this.constructor.cachedHandGrammarProgramRoot + get handParsersProgram() { + return this.constructor.cachedHandParsersProgramRoot } static rootParser = numbersParser } - class abstractArithmeticReducerParser extends GrammarBackedNode { + class abstractArithmeticReducerParser extends ParserBackedNode { createParserCombinator() { return new TreeNode.ParserCombinator( undefined, @@ -156,7 +156,7 @@ errorParser } } - class commentParser extends GrammarBackedNode { + class commentParser extends ParserBackedNode { createParserCombinator() { return new TreeNode.ParserCombinator(commentContentParser, undefined, undefined) } @@ -168,7 +168,7 @@ errorParser } } - class commentContentParser extends GrammarBackedNode { + class commentContentParser extends ParserBackedNode { createParserCombinator() { return new TreeNode.ParserCombinator(commentContentParser, undefined, undefined) } @@ -177,7 +177,7 @@ errorParser } } - class hashBangParser extends GrammarBackedNode { + class hashBangParser extends ParserBackedNode { get hashBangKeywordCell() { return this.getWord(0) } @@ -186,7 +186,7 @@ errorParser } } - class errorParser extends GrammarBackedNode { + class errorParser extends ParserBackedNode { getErrors() { return this._getErrorParserErrors() } diff --git a/products/grammar.browser.js b/products/parsers.browser.js similarity index 93% rename from products/grammar.browser.js rename to products/parsers.browser.js index 0e5629287..60b27ba34 100644 --- a/products/grammar.browser.js +++ b/products/parsers.browser.js @@ -1,5 +1,5 @@ { - class grammarParser extends GrammarBackedNode { + class parsersParser extends ParserBackedNode { createParserCombinator() { return new TreeNode.ParserCombinator(catchAllErrorParser, Object.assign(Object.assign({}, super.createParserCombinator()._getFirstWordMapAsObject()), { "//": slashCommentParser }), [ { regex: /^$/, parser: blankLineParser }, @@ -7,8 +7,8 @@ { regex: /^[a-zA-Z0-9_]+Parser$/, parser: parserDefinitionParser } ]) } - static cachedHandGrammarProgramRoot = - new HandGrammarProgram(`// todo Add imports parsers, along with source maps, so we can correctly support grammars split across multiple files, and better enable grammars from compositions of reusable bits? + static cachedHandParsersProgramRoot = + new HandParsersProgram(`// todo Add imports parsers, along with source maps, so we can correctly support parsers split across multiple files, and better enable parsers from compositions of reusable bits? // todo Do error checking for if you have a firstwordCellType, cells, and/or catchAllCellType with same name. // todo Add enumOption root level type? // todo compile cells. add javascript property. move getRunTimeEnumOptions to cells. @@ -108,12 +108,12 @@ commentCell highlightScope comment // Line Parsers -grammarParser +parsersParser root - description Grammar is a Tree Language for creating new Tree Languages. By creating a grammar file you get a parser, a type checker, syntax highlighting, autocomplete, a compiler, and virtual machine for executing your new language. Grammar uses both postfix and prefix language features. + description Parsers is a language for creating new languages on top of Scroll Notation. By creating a parsers file you get a parser, a type checker, syntax highlighting, autocomplete, a compiler, and virtual machine for executing your new language. Parsers uses both postfix and prefix language features. catchAllParser catchAllErrorParser - extensions grammar gram - example A grammar that parses anything: + extensions parsers gram + example A parsers that parses anything: latinParser root catchAllParser anyParser @@ -122,7 +122,7 @@ grammarParser version 5.0.0 inScope slashCommentParser blankLineParser cellTypeDefinitionParser parserDefinitionParser blankLineParser - description Blank lines are OK in Grammar. + description Blank lines are OK in Parsers. cells blankCell pattern ^$ tags doNotSynthesize @@ -425,19 +425,19 @@ extendsCellTypeParser // todo Add mixin support in addition to/in place of extends? cells propertyKeywordCell cellTypeIdCell single`) - get handGrammarProgram() { - return this.constructor.cachedHandGrammarProgramRoot + get handParsersProgram() { + return this.constructor.cachedHandParsersProgramRoot } - static rootParser = grammarParser + static rootParser = parsersParser } - class blankLineParser extends GrammarBackedNode { + class blankLineParser extends ParserBackedNode { get blankCell() { return this.getWord(0) } } - class abstractCompilerRuleParser extends GrammarBackedNode { + class abstractCompilerRuleParser extends ParserBackedNode { get propertyKeywordCell() { return this.getWord(0) } @@ -458,7 +458,7 @@ extendsCellTypeParser class joinChildrenWithParser extends abstractCompilerRuleParser {} - class abstractConstantParser extends GrammarBackedNode { + class abstractConstantParser extends ParserBackedNode { get propertyKeywordCell() { return this.getWord(0) } @@ -515,7 +515,7 @@ extendsCellTypeParser } } - class abstractParserRuleParser extends GrammarBackedNode { + class abstractParserRuleParser extends ParserBackedNode { get propertyKeywordCell() { return this.getWord(0) } @@ -732,13 +732,13 @@ extendsCellTypeParser } } - class catchAllErrorParser extends GrammarBackedNode { + class catchAllErrorParser extends ParserBackedNode { getErrors() { return this._getErrorParserErrors() } } - class catchAllExampleLineParser extends GrammarBackedNode { + class catchAllExampleLineParser extends ParserBackedNode { createParserCombinator() { return new TreeNode.ParserCombinator(catchAllExampleLineParser, undefined, undefined) } @@ -750,7 +750,7 @@ extendsCellTypeParser } } - class catchAllJavascriptCodeLineParser extends GrammarBackedNode { + class catchAllJavascriptCodeLineParser extends ParserBackedNode { createParserCombinator() { return new TreeNode.ParserCombinator(catchAllJavascriptCodeLineParser, undefined, undefined) } @@ -759,7 +759,7 @@ extendsCellTypeParser } } - class catchAllMultilineStringConstantParser extends GrammarBackedNode { + class catchAllMultilineStringConstantParser extends ParserBackedNode { createParserCombinator() { return new TreeNode.ParserCombinator(catchAllMultilineStringConstantParser, undefined, undefined) } @@ -771,7 +771,7 @@ extendsCellTypeParser } } - class cellTypeDefinitionParser extends GrammarBackedNode { + class cellTypeDefinitionParser extends ParserBackedNode { createParserCombinator() { return new TreeNode.ParserCombinator( undefined, @@ -796,7 +796,7 @@ extendsCellTypeParser } } - class enumFromCellTypesParser extends GrammarBackedNode { + class enumFromCellTypesParser extends ParserBackedNode { get cellPropertyNameCell() { return this.getWord(0) } @@ -805,7 +805,7 @@ extendsCellTypeParser } } - class enumParser extends GrammarBackedNode { + class enumParser extends ParserBackedNode { get cellPropertyNameCell() { return this.getWord(0) } @@ -814,7 +814,7 @@ extendsCellTypeParser } } - class examplesParser extends GrammarBackedNode { + class examplesParser extends ParserBackedNode { get cellPropertyNameCell() { return this.getWord(0) } @@ -823,7 +823,7 @@ extendsCellTypeParser } } - class cellMinParser extends GrammarBackedNode { + class cellMinParser extends ParserBackedNode { get cellPropertyNameCell() { return this.getWord(0) } @@ -832,7 +832,7 @@ extendsCellTypeParser } } - class cellMaxParser extends GrammarBackedNode { + class cellMaxParser extends ParserBackedNode { get cellPropertyNameCell() { return this.getWord(0) } @@ -841,7 +841,7 @@ extendsCellTypeParser } } - class highlightScopeParser extends GrammarBackedNode { + class highlightScopeParser extends ParserBackedNode { get propertyKeywordCell() { return this.getWord(0) } @@ -850,13 +850,13 @@ extendsCellTypeParser } } - class rootFlagParser extends GrammarBackedNode { + class rootFlagParser extends ParserBackedNode { get propertyKeywordCell() { return this.getWord(0) } } - class parserDefinitionParser extends GrammarBackedNode { + class parserDefinitionParser extends ParserBackedNode { createParserCombinator() { return new TreeNode.ParserCombinator( catchAllErrorParser, @@ -920,7 +920,7 @@ extendsCellTypeParser } } - class regexParser extends GrammarBackedNode { + class regexParser extends ParserBackedNode { get cellPropertyNameCell() { return this.getWord(0) } @@ -929,7 +929,7 @@ extendsCellTypeParser } } - class reservedWordsParser extends GrammarBackedNode { + class reservedWordsParser extends ParserBackedNode { get cellPropertyNameCell() { return this.getWord(0) } @@ -938,13 +938,13 @@ extendsCellTypeParser } } - class commentLineParser extends GrammarBackedNode { + class commentLineParser extends ParserBackedNode { get commentCell() { return this.getWordsFrom(0) } } - class slashCommentParser extends GrammarBackedNode { + class slashCommentParser extends ParserBackedNode { createParserCombinator() { return new TreeNode.ParserCombinator(commentLineParser, undefined, undefined) } @@ -953,7 +953,7 @@ extendsCellTypeParser } } - class extendsCellTypeParser extends GrammarBackedNode { + class extendsCellTypeParser extends ParserBackedNode { get propertyKeywordCell() { return this.getWord(0) } @@ -962,5 +962,5 @@ extendsCellTypeParser } } - window.grammarParser = grammarParser + window.parsersParser = parsersParser } diff --git a/products/grammar.nodejs.js b/products/parsers.nodejs.js similarity index 93% rename from products/grammar.nodejs.js rename to products/parsers.nodejs.js index c67c37d41..4711effdb 100755 --- a/products/grammar.nodejs.js +++ b/products/parsers.nodejs.js @@ -2,10 +2,10 @@ { const { Utils } = require("./Utils.js") const { TreeNode } = require("./TreeNode.js") - const { HandGrammarProgram } = require("./GrammarLanguage.js") - const { GrammarBackedNode } = require("./GrammarLanguage.js") + const { HandParsersProgram } = require("./Parsers.js") + const { ParserBackedNode } = require("./Parsers.js") - class grammarParser extends GrammarBackedNode { + class parsersParser extends ParserBackedNode { createParserCombinator() { return new TreeNode.ParserCombinator(catchAllErrorParser, Object.assign(Object.assign({}, super.createParserCombinator()._getFirstWordMapAsObject()), { "//": slashCommentParser }), [ { regex: /^$/, parser: blankLineParser }, @@ -13,8 +13,8 @@ { regex: /^[a-zA-Z0-9_]+Parser$/, parser: parserDefinitionParser } ]) } - static cachedHandGrammarProgramRoot = - new HandGrammarProgram(`// todo Add imports parsers, along with source maps, so we can correctly support grammars split across multiple files, and better enable grammars from compositions of reusable bits? + static cachedHandParsersProgramRoot = + new HandParsersProgram(`// todo Add imports parsers, along with source maps, so we can correctly support parsers split across multiple files, and better enable parsers from compositions of reusable bits? // todo Do error checking for if you have a firstwordCellType, cells, and/or catchAllCellType with same name. // todo Add enumOption root level type? // todo compile cells. add javascript property. move getRunTimeEnumOptions to cells. @@ -114,12 +114,12 @@ commentCell highlightScope comment // Line Parsers -grammarParser +parsersParser root - description Grammar is a Tree Language for creating new Tree Languages. By creating a grammar file you get a parser, a type checker, syntax highlighting, autocomplete, a compiler, and virtual machine for executing your new language. Grammar uses both postfix and prefix language features. + description Parsers is a language for creating new languages on top of Scroll Notation. By creating a parsers file you get a parser, a type checker, syntax highlighting, autocomplete, a compiler, and virtual machine for executing your new language. Parsers uses both postfix and prefix language features. catchAllParser catchAllErrorParser - extensions grammar gram - example A grammar that parses anything: + extensions parsers gram + example A parsers that parses anything: latinParser root catchAllParser anyParser @@ -128,7 +128,7 @@ grammarParser version 5.0.0 inScope slashCommentParser blankLineParser cellTypeDefinitionParser parserDefinitionParser blankLineParser - description Blank lines are OK in Grammar. + description Blank lines are OK in Parsers. cells blankCell pattern ^$ tags doNotSynthesize @@ -431,19 +431,19 @@ extendsCellTypeParser // todo Add mixin support in addition to/in place of extends? cells propertyKeywordCell cellTypeIdCell single`) - get handGrammarProgram() { - return this.constructor.cachedHandGrammarProgramRoot + get handParsersProgram() { + return this.constructor.cachedHandParsersProgramRoot } - static rootParser = grammarParser + static rootParser = parsersParser } - class blankLineParser extends GrammarBackedNode { + class blankLineParser extends ParserBackedNode { get blankCell() { return this.getWord(0) } } - class abstractCompilerRuleParser extends GrammarBackedNode { + class abstractCompilerRuleParser extends ParserBackedNode { get propertyKeywordCell() { return this.getWord(0) } @@ -464,7 +464,7 @@ extendsCellTypeParser class joinChildrenWithParser extends abstractCompilerRuleParser {} - class abstractConstantParser extends GrammarBackedNode { + class abstractConstantParser extends ParserBackedNode { get propertyKeywordCell() { return this.getWord(0) } @@ -521,7 +521,7 @@ extendsCellTypeParser } } - class abstractParserRuleParser extends GrammarBackedNode { + class abstractParserRuleParser extends ParserBackedNode { get propertyKeywordCell() { return this.getWord(0) } @@ -738,13 +738,13 @@ extendsCellTypeParser } } - class catchAllErrorParser extends GrammarBackedNode { + class catchAllErrorParser extends ParserBackedNode { getErrors() { return this._getErrorParserErrors() } } - class catchAllExampleLineParser extends GrammarBackedNode { + class catchAllExampleLineParser extends ParserBackedNode { createParserCombinator() { return new TreeNode.ParserCombinator(catchAllExampleLineParser, undefined, undefined) } @@ -756,7 +756,7 @@ extendsCellTypeParser } } - class catchAllJavascriptCodeLineParser extends GrammarBackedNode { + class catchAllJavascriptCodeLineParser extends ParserBackedNode { createParserCombinator() { return new TreeNode.ParserCombinator(catchAllJavascriptCodeLineParser, undefined, undefined) } @@ -765,7 +765,7 @@ extendsCellTypeParser } } - class catchAllMultilineStringConstantParser extends GrammarBackedNode { + class catchAllMultilineStringConstantParser extends ParserBackedNode { createParserCombinator() { return new TreeNode.ParserCombinator(catchAllMultilineStringConstantParser, undefined, undefined) } @@ -777,7 +777,7 @@ extendsCellTypeParser } } - class cellTypeDefinitionParser extends GrammarBackedNode { + class cellTypeDefinitionParser extends ParserBackedNode { createParserCombinator() { return new TreeNode.ParserCombinator( undefined, @@ -802,7 +802,7 @@ extendsCellTypeParser } } - class enumFromCellTypesParser extends GrammarBackedNode { + class enumFromCellTypesParser extends ParserBackedNode { get cellPropertyNameCell() { return this.getWord(0) } @@ -811,7 +811,7 @@ extendsCellTypeParser } } - class enumParser extends GrammarBackedNode { + class enumParser extends ParserBackedNode { get cellPropertyNameCell() { return this.getWord(0) } @@ -820,7 +820,7 @@ extendsCellTypeParser } } - class examplesParser extends GrammarBackedNode { + class examplesParser extends ParserBackedNode { get cellPropertyNameCell() { return this.getWord(0) } @@ -829,7 +829,7 @@ extendsCellTypeParser } } - class cellMinParser extends GrammarBackedNode { + class cellMinParser extends ParserBackedNode { get cellPropertyNameCell() { return this.getWord(0) } @@ -838,7 +838,7 @@ extendsCellTypeParser } } - class cellMaxParser extends GrammarBackedNode { + class cellMaxParser extends ParserBackedNode { get cellPropertyNameCell() { return this.getWord(0) } @@ -847,7 +847,7 @@ extendsCellTypeParser } } - class highlightScopeParser extends GrammarBackedNode { + class highlightScopeParser extends ParserBackedNode { get propertyKeywordCell() { return this.getWord(0) } @@ -856,13 +856,13 @@ extendsCellTypeParser } } - class rootFlagParser extends GrammarBackedNode { + class rootFlagParser extends ParserBackedNode { get propertyKeywordCell() { return this.getWord(0) } } - class parserDefinitionParser extends GrammarBackedNode { + class parserDefinitionParser extends ParserBackedNode { createParserCombinator() { return new TreeNode.ParserCombinator( catchAllErrorParser, @@ -926,7 +926,7 @@ extendsCellTypeParser } } - class regexParser extends GrammarBackedNode { + class regexParser extends ParserBackedNode { get cellPropertyNameCell() { return this.getWord(0) } @@ -935,7 +935,7 @@ extendsCellTypeParser } } - class reservedWordsParser extends GrammarBackedNode { + class reservedWordsParser extends ParserBackedNode { get cellPropertyNameCell() { return this.getWord(0) } @@ -944,13 +944,13 @@ extendsCellTypeParser } } - class commentLineParser extends GrammarBackedNode { + class commentLineParser extends ParserBackedNode { get commentCell() { return this.getWordsFrom(0) } } - class slashCommentParser extends GrammarBackedNode { + class slashCommentParser extends ParserBackedNode { createParserCombinator() { return new TreeNode.ParserCombinator(commentLineParser, undefined, undefined) } @@ -959,7 +959,7 @@ extendsCellTypeParser } } - class extendsCellTypeParser extends GrammarBackedNode { + class extendsCellTypeParser extends ParserBackedNode { get propertyKeywordCell() { return this.getWord(0) } @@ -968,8 +968,8 @@ extendsCellTypeParser } } - module.exports = grammarParser - grammarParser + module.exports = parsersParser + parsersParser - if (!module.parent) new grammarParser(TreeNode.fromDisk(process.argv[2]).toString()).execute() + if (!module.parent) new parsersParser(TreeNode.fromDisk(process.argv[2]).toString()).execute() } diff --git a/products/poop.browser.js b/products/poop.browser.js index 6357e7ec3..0e1bba70d 100644 --- a/products/poop.browser.js +++ b/products/poop.browser.js @@ -1,5 +1,5 @@ { - class poopParser extends GrammarBackedNode { + class poopParser extends ParserBackedNode { createParserCombinator() { return new TreeNode.ParserCombinator(this._getBlobParserCatchAllParser(), Object.assign(Object.assign({}, super.createParserCombinator()._getFirstWordMapAsObject()), { "๐ŸŒ„": dayParser }), [ { regex: /๐Ÿ’ฉ/, parser: bowelParser }, @@ -25,7 +25,7 @@ .filter(identity => identity) return `date,time,event,notes\n` + rows.join("\n") } - static cachedHandGrammarProgramRoot = new HandGrammarProgram(`// Cell parsers + static cachedHandParsersProgramRoot = new HandParsersProgram(`// Cell parsers dateIntCell highlightScope constant.numeric.integer monthIntCell @@ -48,9 +48,9 @@ eventTypeCell // Line parsers poopParser - description POOP is the Programming Option for Overtired Parents. It is a Tree Language for sleep deprived parents to log their child's bathroom, feeding, and sleep events and compile them to CSV. You can use POOP with computers or pen and paper. Each line records an event, a time, and optionally notes. POOP is an anyfix language. You can put the time first or the event type first. You can write the actual symbols, or, if it is 3am, you can just use some of the natural medium to record the event type. + description POOP is the Programming Option for Overtired Parents. It is a Language for sleep deprived parents to log their child's bathroom, feeding, and sleep events and compile them to CSV. You can use POOP with computers or pen and paper. Each line records an event, a time, and optionally notes. POOP is an anyfix language. You can put the time first or the event type first. You can write the actual symbols, or, if it is 3am, you can just use some of the natural medium to record the event type. root - tags nonPrefixGrammar + tags nonPrefixParsers compilesTo csv javascript compile() { @@ -141,13 +141,13 @@ dayParser .trim() .replace(/ /g, "/") }`) - get handGrammarProgram() { - return this.constructor.cachedHandGrammarProgramRoot + get handParsersProgram() { + return this.constructor.cachedHandParsersProgramRoot } static rootParser = poopParser } - class abstractEventParser extends GrammarBackedNode { + class abstractEventParser extends ParserBackedNode { get eventTypeCell() { return this.getWord(0) } @@ -211,7 +211,7 @@ dayParser } } - class dayParser extends GrammarBackedNode { + class dayParser extends ParserBackedNode { get symbolCell() { return this.getWord(0) } diff --git a/products/poop.nodejs.js b/products/poop.nodejs.js index e10f43f91..f03b40869 100755 --- a/products/poop.nodejs.js +++ b/products/poop.nodejs.js @@ -2,10 +2,10 @@ { const { Utils } = require("./Utils.js") const { TreeNode } = require("./TreeNode.js") - const { HandGrammarProgram } = require("./GrammarLanguage.js") - const { GrammarBackedNode } = require("./GrammarLanguage.js") + const { HandParsersProgram } = require("./Parsers.js") + const { ParserBackedNode } = require("./Parsers.js") - class poopParser extends GrammarBackedNode { + class poopParser extends ParserBackedNode { createParserCombinator() { return new TreeNode.ParserCombinator(this._getBlobParserCatchAllParser(), Object.assign(Object.assign({}, super.createParserCombinator()._getFirstWordMapAsObject()), { "๐ŸŒ„": dayParser }), [ { regex: /๐Ÿ’ฉ/, parser: bowelParser }, @@ -31,7 +31,7 @@ .filter(identity => identity) return `date,time,event,notes\n` + rows.join("\n") } - static cachedHandGrammarProgramRoot = new HandGrammarProgram(`// Cell parsers + static cachedHandParsersProgramRoot = new HandParsersProgram(`// Cell parsers dateIntCell highlightScope constant.numeric.integer monthIntCell @@ -54,9 +54,9 @@ eventTypeCell // Line parsers poopParser - description POOP is the Programming Option for Overtired Parents. It is a Tree Language for sleep deprived parents to log their child's bathroom, feeding, and sleep events and compile them to CSV. You can use POOP with computers or pen and paper. Each line records an event, a time, and optionally notes. POOP is an anyfix language. You can put the time first or the event type first. You can write the actual symbols, or, if it is 3am, you can just use some of the natural medium to record the event type. + description POOP is the Programming Option for Overtired Parents. It is a Language for sleep deprived parents to log their child's bathroom, feeding, and sleep events and compile them to CSV. You can use POOP with computers or pen and paper. Each line records an event, a time, and optionally notes. POOP is an anyfix language. You can put the time first or the event type first. You can write the actual symbols, or, if it is 3am, you can just use some of the natural medium to record the event type. root - tags nonPrefixGrammar + tags nonPrefixParsers compilesTo csv javascript compile() { @@ -147,13 +147,13 @@ dayParser .trim() .replace(/ /g, "/") }`) - get handGrammarProgram() { - return this.constructor.cachedHandGrammarProgramRoot + get handParsersProgram() { + return this.constructor.cachedHandParsersProgramRoot } static rootParser = poopParser } - class abstractEventParser extends GrammarBackedNode { + class abstractEventParser extends ParserBackedNode { get eventTypeCell() { return this.getWord(0) } @@ -217,7 +217,7 @@ dayParser } } - class dayParser extends GrammarBackedNode { + class dayParser extends ParserBackedNode { get symbolCell() { return this.getWord(0) } diff --git a/products/project.browser.js b/products/project.browser.js index 9f908f0e2..e4681fdef 100644 --- a/products/project.browser.js +++ b/products/project.browser.js @@ -1,5 +1,5 @@ { - class projectParser extends GrammarBackedNode { + class projectParser extends ParserBackedNode { createParserCombinator() { return new TreeNode.ParserCombinator(errorParser, Object.assign(Object.assign({}, super.createParserCombinator()._getFirstWordMapAsObject()), { file: fileParser }), undefined) } @@ -68,7 +68,7 @@ ${missing.join("\n")} }) return requiredFileList.toString() } - static cachedHandGrammarProgramRoot = new HandGrammarProgram(`// Cell Parsers + static cachedHandParsersProgramRoot = new HandParsersProgram(`// Cell Parsers anyCell filepathCell highlightScope string @@ -81,7 +81,7 @@ fileConstantCell projectParser root version 2.0.0 - description A prefix Tree Language for project dependency management in Javascript and Typescript. + description A prefix Language for project dependency management in Javascript and Typescript. javascript getScriptPathsInCorrectDependencyOrder() { const cloned = this.clone() @@ -190,13 +190,13 @@ fileParser } cells fileConstantCell crux file`) - get handGrammarProgram() { - return this.constructor.cachedHandGrammarProgramRoot + get handParsersProgram() { + return this.constructor.cachedHandParsersProgramRoot } static rootParser = projectParser } - class abstractTermParser extends GrammarBackedNode { + class abstractTermParser extends ParserBackedNode { get termCell() { return this.getWord(0) } @@ -211,13 +211,13 @@ fileParser class relativeParser extends abstractTermParser {} - class errorParser extends GrammarBackedNode { + class errorParser extends ParserBackedNode { getErrors() { return this._getErrorParserErrors() } } - class fileParser extends GrammarBackedNode { + class fileParser extends ParserBackedNode { createParserCombinator() { return new TreeNode.ParserCombinator(undefined, Object.assign(Object.assign({}, super.createParserCombinator()._getFirstWordMapAsObject()), { absolute: absoluteParser, external: externalParser, relative: relativeParser }), undefined) } diff --git a/products/project.nodejs.js b/products/project.nodejs.js index 4a5c26def..b347caef1 100755 --- a/products/project.nodejs.js +++ b/products/project.nodejs.js @@ -2,10 +2,10 @@ { const { Utils } = require("./Utils.js") const { TreeNode } = require("./TreeNode.js") - const { HandGrammarProgram } = require("./GrammarLanguage.js") - const { GrammarBackedNode } = require("./GrammarLanguage.js") + const { HandParsersProgram } = require("./Parsers.js") + const { ParserBackedNode } = require("./Parsers.js") - class projectParser extends GrammarBackedNode { + class projectParser extends ParserBackedNode { createParserCombinator() { return new TreeNode.ParserCombinator(errorParser, Object.assign(Object.assign({}, super.createParserCombinator()._getFirstWordMapAsObject()), { file: fileParser }), undefined) } @@ -74,7 +74,7 @@ ${missing.join("\n")} }) return requiredFileList.toString() } - static cachedHandGrammarProgramRoot = new HandGrammarProgram(`// Cell Parsers + static cachedHandParsersProgramRoot = new HandParsersProgram(`// Cell Parsers anyCell filepathCell highlightScope string @@ -87,7 +87,7 @@ fileConstantCell projectParser root version 2.0.0 - description A prefix Tree Language for project dependency management in Javascript and Typescript. + description A prefix Language for project dependency management in Javascript and Typescript. javascript getScriptPathsInCorrectDependencyOrder() { const cloned = this.clone() @@ -196,13 +196,13 @@ fileParser } cells fileConstantCell crux file`) - get handGrammarProgram() { - return this.constructor.cachedHandGrammarProgramRoot + get handParsersProgram() { + return this.constructor.cachedHandParsersProgramRoot } static rootParser = projectParser } - class abstractTermParser extends GrammarBackedNode { + class abstractTermParser extends ParserBackedNode { get termCell() { return this.getWord(0) } @@ -217,13 +217,13 @@ fileParser class relativeParser extends abstractTermParser {} - class errorParser extends GrammarBackedNode { + class errorParser extends ParserBackedNode { getErrors() { return this._getErrorParserErrors() } } - class fileParser extends GrammarBackedNode { + class fileParser extends ParserBackedNode { createParserCombinator() { return new TreeNode.ParserCombinator(undefined, Object.assign(Object.assign({}, super.createParserCombinator()._getFirstWordMapAsObject()), { absolute: absoluteParser, external: externalParser, relative: relativeParser }), undefined) } diff --git a/products/scrollNotationTypes.ts b/products/scrollNotationTypes.ts index b9106a527..aa77b119c 100644 --- a/products/scrollNotationTypes.ts +++ b/products/scrollNotationTypes.ts @@ -76,9 +76,9 @@ namespace scrollNotationTypes { export declare type url = string export declare type typeScriptFilePath = filepath export declare type treeProgramFilePath = filepath - export declare type grammarFilePath = filepath + export declare type parsersFilePath = filepath export declare type fileName = string - export declare type grammarName = string + export declare type parsersName = string export declare type globPattern = string export declare type highlightScope = string export declare type fileExtension = string diff --git a/products/stamp.browser.js b/products/stamp.browser.js index e25395a03..4d6b531b5 100644 --- a/products/stamp.browser.js +++ b/products/stamp.browser.js @@ -1,5 +1,5 @@ { - class stampParser extends GrammarBackedNode { + class stampParser extends ParserBackedNode { createParserCombinator() { return new TreeNode.ParserCombinator(errorParser, Object.assign(Object.assign({}, super.createParserCombinator()._getFirstWordMapAsObject()), { "#!": hashbangParser, file: fileParser, folder: folderParser }), undefined) } @@ -74,7 +74,7 @@ const pathStartIndex = rootFolderPath.length + 1 return files.map(file => fileFn(file, file.substr(pathStartIndex))).join("\n") } - static cachedHandGrammarProgramRoot = new HandGrammarProgram(`// todo File permissions + static cachedHandParsersProgramRoot = new HandParsersProgram(`// todo File permissions // Cell parsers anyCell @@ -97,7 +97,7 @@ keywordCell // Line parsers stampParser root - description A prefix Tree Language for creating distributable text template files that expand to folders and files. + description A prefix Language for creating distributable text template files that expand to folders and files. catchAllParser errorParser javascript async executeSeries(parentDir) { @@ -229,13 +229,13 @@ folderParser fs.mkdirSync(path, {recursive: true}) } crux folder`) - get handGrammarProgram() { - return this.constructor.cachedHandGrammarProgramRoot + get handParsersProgram() { + return this.constructor.cachedHandParsersProgramRoot } static rootParser = stampParser } - class hashbangParser extends GrammarBackedNode { + class hashbangParser extends ParserBackedNode { get commentCell() { return this.getWord(0) } @@ -244,7 +244,7 @@ folderParser } } - class catchAllAnyLineParser extends GrammarBackedNode { + class catchAllAnyLineParser extends ParserBackedNode { createParserCombinator() { return new TreeNode.ParserCombinator(catchAllAnyLineParser, undefined, undefined) } @@ -256,7 +256,7 @@ folderParser } } - class dataParser extends GrammarBackedNode { + class dataParser extends ParserBackedNode { createParserCombinator() { return new TreeNode.ParserCombinator(catchAllAnyLineParser, undefined, undefined) } @@ -265,19 +265,19 @@ folderParser } } - class errorParser extends GrammarBackedNode { + class errorParser extends ParserBackedNode { getErrors() { return this._getErrorParserErrors() } } - class executableParser extends GrammarBackedNode { + class executableParser extends ParserBackedNode { get keywordCell() { return this.getWord(0) } } - class fileParser extends GrammarBackedNode { + class fileParser extends ParserBackedNode { createParserCombinator() { return new TreeNode.ParserCombinator(undefined, Object.assign(Object.assign({}, super.createParserCombinator()._getFirstWordMapAsObject()), { data: dataParser, executable: executableParser }), undefined) } @@ -307,7 +307,7 @@ folderParser } } - class folderParser extends GrammarBackedNode { + class folderParser extends ParserBackedNode { get keywordCell() { return this.getWord(0) } diff --git a/products/stamp.nodejs.js b/products/stamp.nodejs.js index 05ee3567e..02bd59fca 100755 --- a/products/stamp.nodejs.js +++ b/products/stamp.nodejs.js @@ -2,10 +2,10 @@ { const { Utils } = require("./Utils.js") const { TreeNode } = require("./TreeNode.js") - const { HandGrammarProgram } = require("./GrammarLanguage.js") - const { GrammarBackedNode } = require("./GrammarLanguage.js") + const { HandParsersProgram } = require("./Parsers.js") + const { ParserBackedNode } = require("./Parsers.js") - class stampParser extends GrammarBackedNode { + class stampParser extends ParserBackedNode { createParserCombinator() { return new TreeNode.ParserCombinator(errorParser, Object.assign(Object.assign({}, super.createParserCombinator()._getFirstWordMapAsObject()), { "#!": hashbangParser, file: fileParser, folder: folderParser }), undefined) } @@ -80,7 +80,7 @@ const pathStartIndex = rootFolderPath.length + 1 return files.map(file => fileFn(file, file.substr(pathStartIndex))).join("\n") } - static cachedHandGrammarProgramRoot = new HandGrammarProgram(`// todo File permissions + static cachedHandParsersProgramRoot = new HandParsersProgram(`// todo File permissions // Cell parsers anyCell @@ -103,7 +103,7 @@ keywordCell // Line parsers stampParser root - description A prefix Tree Language for creating distributable text template files that expand to folders and files. + description A prefix Language for creating distributable text template files that expand to folders and files. catchAllParser errorParser javascript async executeSeries(parentDir) { @@ -235,13 +235,13 @@ folderParser fs.mkdirSync(path, {recursive: true}) } crux folder`) - get handGrammarProgram() { - return this.constructor.cachedHandGrammarProgramRoot + get handParsersProgram() { + return this.constructor.cachedHandParsersProgramRoot } static rootParser = stampParser } - class hashbangParser extends GrammarBackedNode { + class hashbangParser extends ParserBackedNode { get commentCell() { return this.getWord(0) } @@ -250,7 +250,7 @@ folderParser } } - class catchAllAnyLineParser extends GrammarBackedNode { + class catchAllAnyLineParser extends ParserBackedNode { createParserCombinator() { return new TreeNode.ParserCombinator(catchAllAnyLineParser, undefined, undefined) } @@ -262,7 +262,7 @@ folderParser } } - class dataParser extends GrammarBackedNode { + class dataParser extends ParserBackedNode { createParserCombinator() { return new TreeNode.ParserCombinator(catchAllAnyLineParser, undefined, undefined) } @@ -271,19 +271,19 @@ folderParser } } - class errorParser extends GrammarBackedNode { + class errorParser extends ParserBackedNode { getErrors() { return this._getErrorParserErrors() } } - class executableParser extends GrammarBackedNode { + class executableParser extends ParserBackedNode { get keywordCell() { return this.getWord(0) } } - class fileParser extends GrammarBackedNode { + class fileParser extends ParserBackedNode { createParserCombinator() { return new TreeNode.ParserCombinator(undefined, Object.assign(Object.assign({}, super.createParserCombinator()._getFirstWordMapAsObject()), { data: dataParser, executable: executableParser }), undefined) } @@ -313,7 +313,7 @@ folderParser } } - class folderParser extends GrammarBackedNode { + class folderParser extends ParserBackedNode { get keywordCell() { return this.getWord(0) } diff --git a/products/stump.browser.js b/products/stump.browser.js index b0b986d56..dfa49b658 100644 --- a/products/stump.browser.js +++ b/products/stump.browser.js @@ -1,5 +1,5 @@ { - class stumpParser extends GrammarBackedNode { + class stumpParser extends ParserBackedNode { createParserCombinator() { return new TreeNode.ParserCombinator( errorParser, @@ -127,7 +127,7 @@ _getHtmlJoinByCharacter() { return "" } - static cachedHandGrammarProgramRoot = new HandGrammarProgram(`// Cell parsers + static cachedHandParsersProgramRoot = new HandParsersProgram(`// Cell parsers anyCell keywordCell emptyCell @@ -155,7 +155,7 @@ bernKeywordCell // Line parsers stumpParser root - description A prefix Tree Language that compiles to HTML. + description A prefix Language that compiles to HTML. catchAllParser errorParser inScope htmlTagParser blankLineParser example @@ -396,13 +396,13 @@ bernParser } getTextContent() {return ""} cells bernKeywordCell`) - get handGrammarProgram() { - return this.constructor.cachedHandGrammarProgramRoot + get handParsersProgram() { + return this.constructor.cachedHandParsersProgramRoot } static rootParser = stumpParser } - class blankLineParser extends GrammarBackedNode { + class blankLineParser extends ParserBackedNode { get emptyCell() { return this.getWord(0) } @@ -414,7 +414,7 @@ bernParser } } - class htmlTagParser extends GrammarBackedNode { + class htmlTagParser extends ParserBackedNode { createParserCombinator() { return new TreeNode.ParserCombinator( undefined, @@ -873,7 +873,7 @@ bernParser } } - class errorParser extends GrammarBackedNode { + class errorParser extends ParserBackedNode { getErrors() { return this._getErrorParserErrors() } @@ -888,7 +888,7 @@ bernParser } } - class htmlAttributeParser extends GrammarBackedNode { + class htmlAttributeParser extends ParserBackedNode { createParserCombinator() { return new TreeNode.ParserCombinator(errorParser, undefined, undefined) } @@ -921,7 +921,7 @@ bernParser } } - class lineOfHtmlContentParser extends GrammarBackedNode { + class lineOfHtmlContentParser extends ParserBackedNode { createParserCombinator() { return new TreeNode.ParserCombinator(lineOfHtmlContentParser, undefined, undefined) } @@ -936,7 +936,7 @@ bernParser } } - class bernParser extends GrammarBackedNode { + class bernParser extends ParserBackedNode { createParserCombinator() { return new TreeNode.ParserCombinator(lineOfHtmlContentParser, undefined, undefined) } diff --git a/products/stump.nodejs.js b/products/stump.nodejs.js index 9c59257b2..24d61f7be 100755 --- a/products/stump.nodejs.js +++ b/products/stump.nodejs.js @@ -2,10 +2,10 @@ { const { Utils } = require("./Utils.js") const { TreeNode } = require("./TreeNode.js") - const { HandGrammarProgram } = require("./GrammarLanguage.js") - const { GrammarBackedNode } = require("./GrammarLanguage.js") + const { HandParsersProgram } = require("./Parsers.js") + const { ParserBackedNode } = require("./Parsers.js") - class stumpParser extends GrammarBackedNode { + class stumpParser extends ParserBackedNode { createParserCombinator() { return new TreeNode.ParserCombinator( errorParser, @@ -133,7 +133,7 @@ _getHtmlJoinByCharacter() { return "" } - static cachedHandGrammarProgramRoot = new HandGrammarProgram(`// Cell parsers + static cachedHandParsersProgramRoot = new HandParsersProgram(`// Cell parsers anyCell keywordCell emptyCell @@ -161,7 +161,7 @@ bernKeywordCell // Line parsers stumpParser root - description A prefix Tree Language that compiles to HTML. + description A prefix Language that compiles to HTML. catchAllParser errorParser inScope htmlTagParser blankLineParser example @@ -402,13 +402,13 @@ bernParser } getTextContent() {return ""} cells bernKeywordCell`) - get handGrammarProgram() { - return this.constructor.cachedHandGrammarProgramRoot + get handParsersProgram() { + return this.constructor.cachedHandParsersProgramRoot } static rootParser = stumpParser } - class blankLineParser extends GrammarBackedNode { + class blankLineParser extends ParserBackedNode { get emptyCell() { return this.getWord(0) } @@ -420,7 +420,7 @@ bernParser } } - class htmlTagParser extends GrammarBackedNode { + class htmlTagParser extends ParserBackedNode { createParserCombinator() { return new TreeNode.ParserCombinator( undefined, @@ -879,7 +879,7 @@ bernParser } } - class errorParser extends GrammarBackedNode { + class errorParser extends ParserBackedNode { getErrors() { return this._getErrorParserErrors() } @@ -894,7 +894,7 @@ bernParser } } - class htmlAttributeParser extends GrammarBackedNode { + class htmlAttributeParser extends ParserBackedNode { createParserCombinator() { return new TreeNode.ParserCombinator(errorParser, undefined, undefined) } @@ -927,7 +927,7 @@ bernParser } } - class lineOfHtmlContentParser extends GrammarBackedNode { + class lineOfHtmlContentParser extends ParserBackedNode { createParserCombinator() { return new TreeNode.ParserCombinator(lineOfHtmlContentParser, undefined, undefined) } @@ -942,7 +942,7 @@ bernParser } } - class bernParser extends GrammarBackedNode { + class bernParser extends ParserBackedNode { createParserCombinator() { return new TreeNode.ParserCombinator(lineOfHtmlContentParser, undefined, undefined) } diff --git a/products/swarm.browser.js b/products/swarm.browser.js index 1743f5462..66f161e94 100644 --- a/products/swarm.browser.js +++ b/products/swarm.browser.js @@ -1,5 +1,5 @@ { - class swarmParser extends GrammarBackedNode { + class swarmParser extends ParserBackedNode { createParserCombinator() { return new TreeNode.ParserCombinator( errorParser, @@ -25,7 +25,7 @@ files[filepath] = testBlocks return files } - static cachedHandGrammarProgramRoot = new HandGrammarProgram(`// todo Add comments? + static cachedHandParsersProgramRoot = new HandParsersProgram(`// todo Add comments? // todo Make run in browser // todo Add print or tracer type of intermediate element. debugger? @@ -71,7 +71,7 @@ typeOfOptionCell // Line parsers swarmParser root - description A prefix Tree Language for unit testing of classes. + description A prefix Language for unit testing of classes. inScope hashbangParser arrangeParser abstractTestBlockParser catchAllParser errorParser javascript @@ -354,13 +354,13 @@ todoParser catchAllParser todoParser crux todo cells todoKeywordCell`) - get handGrammarProgram() { - return this.constructor.cachedHandGrammarProgramRoot + get handParsersProgram() { + return this.constructor.cachedHandParsersProgramRoot } static rootParser = swarmParser } - class abstractAssertionParser extends GrammarBackedNode { + class abstractAssertionParser extends ParserBackedNode { get assertionKeywordCell() { return this.getWord(0) } @@ -470,7 +470,7 @@ todoParser } } - class abstractArrangeFlagParser extends GrammarBackedNode { + class abstractArrangeFlagParser extends ParserBackedNode { get keywordCell() { return this.getWord(0) } @@ -478,7 +478,7 @@ todoParser class arrangeAsyncParser extends abstractArrangeFlagParser {} - class arrangeRequireParser extends GrammarBackedNode { + class arrangeRequireParser extends ParserBackedNode { get keywordCell() { return this.getWord(0) } @@ -492,7 +492,7 @@ todoParser class arrangeStaticParser extends abstractArrangeFlagParser {} - class abstractTestBlockParser extends GrammarBackedNode { + class abstractTestBlockParser extends ParserBackedNode { createParserCombinator() { return new TreeNode.ParserCombinator(actParser, Object.assign(Object.assign({}, super.createParserCombinator()._getFirstWordMapAsObject()), { arrange: arrangeParser }), undefined) } @@ -544,7 +544,7 @@ todoParser } } - class hashbangParser extends GrammarBackedNode { + class hashbangParser extends ParserBackedNode { get hashBangKeywordCell() { return this.getWord(0) } @@ -556,7 +556,7 @@ todoParser } } - class arrangeParser extends GrammarBackedNode { + class arrangeParser extends ParserBackedNode { createParserCombinator() { return new TreeNode.ParserCombinator( undefined, @@ -599,7 +599,7 @@ todoParser executeSync() {} } - class withParagraphParser extends GrammarBackedNode { + class withParagraphParser extends ParserBackedNode { createParserCombinator() { return new TreeNode.ParserCombinator(paragraphLineParser, undefined, undefined) } @@ -609,7 +609,7 @@ todoParser executeSync() {} } - class actParser extends GrammarBackedNode { + class actParser extends ParserBackedNode { createParserCombinator() { return new TreeNode.ParserCombinator( actParser, @@ -659,7 +659,7 @@ todoParser } } - class constructWithParagraphParser extends GrammarBackedNode { + class constructWithParagraphParser extends ParserBackedNode { createParserCombinator() { return new TreeNode.ParserCombinator(paragraphLineParser, undefined, undefined) } @@ -669,13 +669,13 @@ todoParser executeSync() {} } - class errorParser extends GrammarBackedNode { + class errorParser extends ParserBackedNode { getErrors() { return this._getErrorParserErrors() } } - class paragraphLineParser extends GrammarBackedNode { + class paragraphLineParser extends ParserBackedNode { createParserCombinator() { return new TreeNode.ParserCombinator(paragraphLineParser, undefined, undefined) } @@ -687,7 +687,7 @@ todoParser } } - class todoParser extends GrammarBackedNode { + class todoParser extends ParserBackedNode { createParserCombinator() { return new TreeNode.ParserCombinator(todoParser, undefined, undefined) } diff --git a/products/swarm.nodejs.js b/products/swarm.nodejs.js index 3e71cd615..56585946e 100755 --- a/products/swarm.nodejs.js +++ b/products/swarm.nodejs.js @@ -2,10 +2,10 @@ { const { Utils } = require("./Utils.js") const { TreeNode } = require("./TreeNode.js") - const { HandGrammarProgram } = require("./GrammarLanguage.js") - const { GrammarBackedNode } = require("./GrammarLanguage.js") + const { HandParsersProgram } = require("./Parsers.js") + const { ParserBackedNode } = require("./Parsers.js") - class swarmParser extends GrammarBackedNode { + class swarmParser extends ParserBackedNode { createParserCombinator() { return new TreeNode.ParserCombinator( errorParser, @@ -31,7 +31,7 @@ files[filepath] = testBlocks return files } - static cachedHandGrammarProgramRoot = new HandGrammarProgram(`// todo Add comments? + static cachedHandParsersProgramRoot = new HandParsersProgram(`// todo Add comments? // todo Make run in browser // todo Add print or tracer type of intermediate element. debugger? @@ -77,7 +77,7 @@ typeOfOptionCell // Line parsers swarmParser root - description A prefix Tree Language for unit testing of classes. + description A prefix Language for unit testing of classes. inScope hashbangParser arrangeParser abstractTestBlockParser catchAllParser errorParser javascript @@ -360,13 +360,13 @@ todoParser catchAllParser todoParser crux todo cells todoKeywordCell`) - get handGrammarProgram() { - return this.constructor.cachedHandGrammarProgramRoot + get handParsersProgram() { + return this.constructor.cachedHandParsersProgramRoot } static rootParser = swarmParser } - class abstractAssertionParser extends GrammarBackedNode { + class abstractAssertionParser extends ParserBackedNode { get assertionKeywordCell() { return this.getWord(0) } @@ -476,7 +476,7 @@ todoParser } } - class abstractArrangeFlagParser extends GrammarBackedNode { + class abstractArrangeFlagParser extends ParserBackedNode { get keywordCell() { return this.getWord(0) } @@ -484,7 +484,7 @@ todoParser class arrangeAsyncParser extends abstractArrangeFlagParser {} - class arrangeRequireParser extends GrammarBackedNode { + class arrangeRequireParser extends ParserBackedNode { get keywordCell() { return this.getWord(0) } @@ -498,7 +498,7 @@ todoParser class arrangeStaticParser extends abstractArrangeFlagParser {} - class abstractTestBlockParser extends GrammarBackedNode { + class abstractTestBlockParser extends ParserBackedNode { createParserCombinator() { return new TreeNode.ParserCombinator(actParser, Object.assign(Object.assign({}, super.createParserCombinator()._getFirstWordMapAsObject()), { arrange: arrangeParser }), undefined) } @@ -550,7 +550,7 @@ todoParser } } - class hashbangParser extends GrammarBackedNode { + class hashbangParser extends ParserBackedNode { get hashBangKeywordCell() { return this.getWord(0) } @@ -562,7 +562,7 @@ todoParser } } - class arrangeParser extends GrammarBackedNode { + class arrangeParser extends ParserBackedNode { createParserCombinator() { return new TreeNode.ParserCombinator( undefined, @@ -605,7 +605,7 @@ todoParser executeSync() {} } - class withParagraphParser extends GrammarBackedNode { + class withParagraphParser extends ParserBackedNode { createParserCombinator() { return new TreeNode.ParserCombinator(paragraphLineParser, undefined, undefined) } @@ -615,7 +615,7 @@ todoParser executeSync() {} } - class actParser extends GrammarBackedNode { + class actParser extends ParserBackedNode { createParserCombinator() { return new TreeNode.ParserCombinator( actParser, @@ -665,7 +665,7 @@ todoParser } } - class constructWithParagraphParser extends GrammarBackedNode { + class constructWithParagraphParser extends ParserBackedNode { createParserCombinator() { return new TreeNode.ParserCombinator(paragraphLineParser, undefined, undefined) } @@ -675,13 +675,13 @@ todoParser executeSync() {} } - class errorParser extends GrammarBackedNode { + class errorParser extends ParserBackedNode { getErrors() { return this._getErrorParserErrors() } } - class paragraphLineParser extends GrammarBackedNode { + class paragraphLineParser extends ParserBackedNode { createParserCombinator() { return new TreeNode.ParserCombinator(paragraphLineParser, undefined, undefined) } @@ -693,7 +693,7 @@ todoParser } } - class todoParser extends GrammarBackedNode { + class todoParser extends ParserBackedNode { createParserCombinator() { return new TreeNode.ParserCombinator(todoParser, undefined, undefined) } diff --git a/readme.scroll b/readme.scroll index a006ae4fa..f0915b47a 100644 --- a/readme.scroll +++ b/readme.scroll @@ -9,7 +9,7 @@ Scroll Homepage https://scroll.pub Scroll Notation Sandbox https://sdk.scroll.pub/sandbox -Scroll Designer +Parser Designer https://sdk.scroll.pub/designer ScrollSDK https://github.com/breck7/scrollsdk @@ -20,7 +20,7 @@ Scroll Notation FAQ SDK Release Notes https://sdk.scroll.pub/releaseNotes.html Scroll Subreddit - https://reddit.com/r/treenotation + https://www.reddit.com/r/ScrollLang Ohayo - A data science studio powered by Scroll Notation https://github.com/breck7/ohayo ScrollSDK UnitTests @@ -32,12 +32,12 @@ ScrollSDK PerfTests The ScrollSDK is for people who want to build on top of Scroll. ? How do I build Scroll Parsers? -You can try the Grammar tutorial. - link grammarTutorial.html Grammar tutorial +You can try the Parsers tutorial. + link parsersTutorial.html Parsers tutorial # Writing Scroll Parsers -The ScrollSDK contains a language for building Scroll Parsers temporarily called "Grammar". You can write new Grammar files to extend your version of Scroll. By creating ScrollParsers with Grammar file you get a parser, a type checker, syntax highlighting, autocomplete, a compiler, and virtual machine for executing your version of Scroll. The ScrollSDK also includes a simple web IDE for writing Scroll Parsers called Scroll Designer. - https://sdk.scroll.pub/designer Scroll Designer +The ScrollSDK contains a language for building Scroll Parsers. You can write new Parsers to extend your version of Scroll. By creating Parsers with the SDK you get a parser, a type checker, syntax highlighting, autocomplete, a compiler, and virtual machine for executing your version of Scroll. The ScrollSDK also includes a simple web IDE for writing Scroll Parsers called Parser Designer. + https://sdk.scroll.pub/designer Parser Designer At this point in time, to make your Scroll Parsers do very useful things, you also need to use another language that you know. The ScrollSDK lets you create new languages using just Scroll or Scroll + Javascript. Scroll Parsers can include code from any programming language, not just Javascript. Though at the moment only Scroll + Javascript is supported by Breck's Lab. https://breckyunits.com/lab.html Breck's Lab @@ -61,11 +61,11 @@ code const tree = new TreeNode("hello world") console.log(tree.asString) -# Basic Scroll Notation Library + Grammar for the browser: +# Basic Scroll Notation Library + Parsers for the browser: code - + ## Scroll Notation Sandbox web app for exploring base Scroll Notation code @@ -73,7 +73,7 @@ code npm run local open http://localhost:3333/ -## Scroll Designer web app for building new Scroll Parsers +## Parser Designer web app for building new Scroll Parsers code npm install . npm run local @@ -103,14 +103,14 @@ All breaking changes are mentioned in the releaseNotes. We follow semantic versi If you build a Scroll Notation library/SDK in another language, let us know and we'll add a link. If you are working on a Scroll Notation library in a new host language, feel free to post an issue or ask for help in the Scroll subreddit. - https://reddit.com/r/scroll-lang subreddit + https://reddit.com/r/ScrollLang subreddit ## How to bump versions code npm run updateVersion NEW_NUMBER # Former Name -Scroll Notation was originally called Tree Notation. Scroll is the name of combined languages which were previously called Grammar and Scrolldown. +Scroll Notation was originally called Tree Notation. Scroll Parsers was originally called Grammar. # Alternatives Considered This is the first Scroll library in existence, so there were no alternative implementations. Note and Space were predecessors to Scroll Notation. If a better alternative low level notation to Scroll Notation is possible, it has yet to be discovered. diff --git a/releaseNotes.scroll b/releaseNotes.scroll index 84755f4ca..ca2de738b 100644 --- a/releaseNotes.scroll +++ b/releaseNotes.scroll @@ -4,6 +4,14 @@ startColumns 4 Here's a list of the notable changes in the Scroll SDK. +# 80.0.0 2024-6-19 +- โš ๏ธ BREAKING: the `Grammar` language is now called `Parsers`. This is a massive change but a simple Grammar/Parsers and grammar/parsers find/replace should update any affected code. + +# 79.0.0 2024-6-18 +- ๐ŸŽ‰ TreeFileSystem now supports cell parsers +- โš ๏ธ BREAKING: TreeFileSystem now expects parsers to use the `.parsers` file extension instead of `.grammar` +- โš ๏ธ BREAKING: (no one should be affected) to use the previous "// parsersOnly" perf boost, end file in `.parsers` + # 78.0.0 2024-5-30 - ๐ŸŽ‰ jtree is now called the Scroll SDK - โš ๏ธ BREAKING: jtree => scrollsdk @@ -67,7 +75,7 @@ This is purely a maintenance release. Unused code and npm packages were removed. - ๐Ÿฅ fix regression in Designer app # 73.0.0 2023-4-2 -This is a major release with significant name breaks. All logic is the same but methods have been renamed to better express the core idea of Tree Languages as small simple parsers combined. +This is a major release with significant name breaks. All logic is the same but methods have been renamed to better express the core idea of Languages as small simple parsers combined. - โš ๏ธ BREAKING: - Tree Langauges: - grammarNode, hakonNode, etc. > grammarParser, hakonParser @@ -77,9 +85,9 @@ This is a major release with significant name breaks. All logic is the same but - TreeNode.Parser > TreeNode.ParserCombinator - getChildInstancesOfNodeTypeId > getChildInstancesOfParserId - findAllNodesWithNodeType > findAllNodesWithParser - - GrammarCompiler: - - compileGrammarFileAtPathAndReturnRootConstructor > compileGrammarFileAtPathAndReturnRootParser - - GrammarLanguage.ts: + - ParsersCompiler: + - compileParsersFileAtPathAndReturnRootConstructor > compileParsersFileAtPathAndReturnRootParser + - Parsers.ts: - rootNodeTypeDefinitionNode > rootParserDefinition - invalidNodeTypes > invalidParsers - getNodeTypeUsage > getParserUsage @@ -266,7 +274,7 @@ This releases introduced a new language called Tree Query Language (TQL) for que This is a major release that makes the code more modular and eliminates a lot of technical debt. In the past to simplify NodeJs+Browser isomorphism I created the `jtree` namespace and bundled everything together. This was a mistake. This release fixes that, and makes each subproject more independent. This should speed up future development. - โš ๏ธ BREAKING: Replace all `jtree.getVersion()` with `TreeNode.getVersion()` -- โš ๏ธ BREAKING: `products/TreeNotationCodeMirrorMode.js` is now `products/GrammarCodeMirrorMode.js` +- โš ๏ธ BREAKING: `products/TreeNotationCodeMirrorMode.js` is now `products/ParsersCodeMirrorMode.js` - โš ๏ธ BREAKING: The bundled file `jtree.browser.js` is now deprecated. That file will be kept for now (for external links) but will no longer be updated and will be removed in a future version. Include exactly what you need. Before: code @@ -275,8 +283,8 @@ After: (to get everything that was previously in the bundle) code - - + + - โš ๏ธ BREAKING: The `jtree` namespace is no more. Include exactly what you need: @@ -294,7 +302,7 @@ code - ๐ŸŽ‰ removed jtree.node.js and added instructions for only importing the specific product needed directly. # 62.1.0 2023-1-12 -- ๐ŸŽ‰ new Node products to import directly from: GrammarLanguage.js, TreeNode.js, TestRacer.js, GrammarCompiler.js +- ๐ŸŽ‰ new Node products to import directly from: Parsers.js, TreeNode.js, TestRacer.js, ParsersCompiler.js # 62.0.0 2023-1-11 - โš ๏ธ Removed Upgrader. In practice better handled by an external package which can have multiple versions of jtree as dependencies. @@ -534,9 +542,9 @@ This is an unstable release. Please wait a few days for bug fix releases before - ๐ŸŽ‰ examplesToTestBlocks method on grammar programs - ๐ŸŽ‰ command line app uses compiled grammar files more - โš ๏ธ getRootConstructor is now compileAndReturnRootConstructor -- โš ๏ธ jtree.getProgramConstructor is now compileGrammarFileAtPathAndReturnRootConstructor -- โš ๏ธ jtree.GrammarProgram is now jtree.HandGrammarProgram -- โš ๏ธ getGrammarProgram is now getHandGrammarProgram +- โš ๏ธ jtree.getProgramConstructor is now compileParsersFileAtPathAndReturnRootConstructor +- โš ๏ธ jtree.ParsersProgram is now jtree.HandParsersProgram +- โš ๏ธ getParsersProgram is now getHandParsersProgram - โš ๏ธ _getRootNodeTypeDefinitionNode is now getRootNodeTypeDefinitionNode - โš ๏ธ removed commandLineApp "create" command. Was broken. Use the Designer app instead. - โš ๏ธ removed jtree.executeFiles @@ -545,7 +553,7 @@ This is an unstable release. Please wait a few days for bug fix releases before - โš ๏ธ removed jtree.executeFileSync and executeFile methods - โš ๏ธ removed executeSync method on Core. - โš ๏ธ removed default execute implementation on Core. Up to grammar to specify. -- โš ๏ธ jtree.makeProgram is now jtree.compileGrammarAndCreateProgram +- โš ๏ธ jtree.makeProgram is now jtree.compileParsersAndCreateProgram - โš ๏ธ jtree.formatFile is now jtree.formatFileInPlace and jtree.formatProgram is now jtree.formatCode - โš ๏ธ removed getErrorsInGrammarExamples. Use examplesToTestBlocks @@ -705,7 +713,7 @@ This is an unstable release. Please wait a few days for bug fix releases before - ๐Ÿฅ added GitHub link and show keyboard shortcuts by default in SweeperCraft # 40.0.0 2019-09-03 -- โš ๏ธ removed "firstCellType" property. Now you must specifically add a cell for the firstCellType for keyword Tree Languages. langs/grammar/GrammarUpgrader.ts should be able to automatically upgrade most grammars without manual intervention. +- โš ๏ธ removed "firstCellType" property. Now you must specifically add a cell for the firstCellType for keyword Languages. langs/grammar/GrammarUpgrader.ts should be able to automatically upgrade most grammars without manual intervention. - ๐ŸŽ‰ default highlightScopes for basic cellTypes - ๐Ÿฅ fixes from reducing complexity of ExtendibleTreeNode and firstCellType @@ -758,21 +766,21 @@ This is an unstable release. Please wait a few days for bug fix releases before - ๐Ÿฅ sample code fix in bundle files # 38.0.0 2019-08-17 -- ๐ŸŽ‰ toReadMe method on GrammarProgram -- ๐ŸŽ‰ toBundle method on GrammarProgram +- ๐ŸŽ‰ toReadMe method on ParsersProgram +- ๐ŸŽ‰ toBundle method on ParsersProgram - โš ๏ธ removed "anyFirstCell". Now just use "anyCell" - ๐Ÿฅ anyCell now always added to inferred grammar - ๐Ÿฅ various fixes to make inferring prefix grammars more robust -- ๐Ÿงน now run UnknownGrammarProgram against all sample grammars +- ๐Ÿงน now run UnknownParsersProgram against all sample grammars - ๐Ÿงน builder is now compiled into a product # 37.1.0 2019-08-10 - ๐ŸŽ‰ support for inference of prefix languages with unicode characters (emojis) -- โš ๏ธ UnknownGrammarProgram "getPredictedGrammarFile" is now "inferGrammarFileForAPrefixLanguage" to be more precise about what the method does +- โš ๏ธ UnknownParsersProgram "getPredictedGrammarFile" is now "inferGrammarFileForAPrefixLanguage" to be more precise about what the method does # 37.0.0 2019-08-08 - โš ๏ธ No more "dist" folder. Use files in "/products/" folder instead. -- ๐Ÿฅ Grammar inference (UnknownGrammarProgram) now predicts base cell types +- ๐Ÿฅ Grammar inference (UnknownParsersProgram) now predicts base cell types - ๐Ÿงน switched to TypeScript for all JS src files and test files. - ๐Ÿงน new folders for each product - ๐Ÿงน "products" folder. Currently checking in compiled versions as this makes distribution simpler. In the future maybe move products to separate repo. @@ -783,7 +791,7 @@ This is an unstable release. Please wait a few days for bug fix releases before # 36.1.0 2019-07-31 - ๐Ÿงน jBuild - ๐Ÿงน improved error messaging for invalid nodeType. -- โš ๏ธ some method names changed in Project Tree Language. See that readme for details. +- โš ๏ธ some method names changed in Project Language. See that readme for details. # 36.0.2 2019-07-30 - ๐Ÿฅ TrueBase Disk path fix @@ -816,7 +824,7 @@ This is an unstable release. Please wait a few days for bug fix releases before - ๐ŸŽ‰ in Grammar Language instead of `nodeType person` now do `personNode` and instead of `cellType int` do `intCell` - ๐ŸŽ‰ findAllWordsWithCellType and findAllNodesWithNodeType methods in Grammar Programs which are like our versions of "findAllReferences" - ๐ŸŽ‰ getAllTypedWords method in Grammar Programs -- ๐Ÿฅ removed all "grammarPath" 2nd params to new jtree.GrammarProgram(grammarCode, gammarPath), since it is no longer used. +- ๐Ÿฅ removed all "parsersPath" 2nd params to new jtree.ParsersProgram(grammarCode, gammarPath), since it is no longer used. - โš ๏ธ Javascript code and compiler nodes that previously referred to cellTypes that have been renamed, must be updated manually - โš ๏ธ Javascript code that previously referred to nodeTypeIds that have been renamed, must be updated manually (check uses of getChildInstancesOfNodeTypeId and doesExtend) - โš ๏ธ lineHints string is different @@ -872,7 +880,7 @@ This is an unstable release. Please wait a few days for bug fix releases before - โš ๏ธ removed getDoc - โš ๏ธ no longer export BlobNode or ErrorNode - โš ๏ธ toFormattedTable now adds ellipsis ("...") when columns overrun limit -- โš ๏ธ removed toNodeJsJavascriptPrettier and toBrowserJavascriptPrettier. Use compileGrammarForNodeJs and compileGrammarForBrowser w/prettier param instead. +- โš ๏ธ removed toNodeJsJavascriptPrettier and toBrowserJavascriptPrettier. Use compileParsersForNodeJs and compileParsersForBrowser w/prettier param instead. - ๐Ÿงน fixed 2.5x test speed regression and got them back down to 2s # 31.0.0 2019-07-05 @@ -886,9 +894,9 @@ This is an unstable release. Please wait a few days for bug fix releases before # 30.0.0 2019-07-03 - ๐ŸŽ‰ much easier way to do Grammar Composition => simple concatenate strings & define a new nodeType as root! -- โš ๏ธ removed newFromCondensed method, which became a noOp. Use new GrammarProgram(grammarCode, grammarPath) instead -- โš ๏ธ removed "grammar" root node type in GrammarLanguage. Add a "root" property to a nodeType for the new root node. -- โš ๏ธ instead of "{grammarName}ProgramRoot" as the root class, the root class is now just "grammarName" +- โš ๏ธ removed newFromCondensed method, which became a noOp. Use new ParsersProgram(grammarCode, parsersPath) instead +- โš ๏ธ removed "grammar" root node type in Parsers. Add a "root" property to a nodeType for the new root node. +- โš ๏ธ instead of "{parsersName}ProgramRoot" as the root class, the root class is now just "parsersName" - โš ๏ธ paths to shipped language program constructors are now like "fire.js" instead of "FireProgram.js" # 29.0.0 2019-07-02 @@ -901,7 +909,7 @@ This is an unstable release. Please wait a few days for bug fix releases before - ๐ŸŽ‰ "match" keyword in Grammar Language to use if you have a non-alphanumeric keyword as the first word match - ๐ŸŽ‰ "reservedWords" attribute on cellTypes in Grammar Language - โš ๏ธ removed "abstract" nodeType in Grammar Language. now its a property of nodeType -- โš ๏ธ compileGrammar method is now compileGrammarForNodeJs and compileGrammarForBrowser +- โš ๏ธ compileParsers method is now compileParsersForNodeJs and compileParsersForBrowser - โš ๏ธ nodeTypeId's now can only be alphanumeric - โš ๏ธ nodeTypeId's are now identical to the generated Javascript class names. Some nodeTypeIds are now reserved and those now require using a "match" node - โš ๏ธ cellTypeId's now can only be alphanumeric @@ -910,7 +918,7 @@ This is an unstable release. Please wait a few days for bug fix releases before - โš ๏ธ "constructors" now no longer take a class name. The class name must be identical to nodeTypeId. # 27.2.0 2019-06-26 -- ๐ŸŽ‰ /sandbox/build/ => refactored Tree Language IDE +- ๐ŸŽ‰ /sandbox/build/ => refactored Language IDE - ๐ŸŽ‰ added "New" simple grammar language template - ๐ŸŽ‰ added deep linking to /sandbox/build/ - โš ๏ธ removed undocumented BackupConstructor feature as IDE should no longer need it @@ -922,7 +930,7 @@ This is an unstable release. Please wait a few days for bug fix releases before # 27.0.0 2019-06-23 - ๐ŸŽ‰ simplified compile method to take 0 params - ๐ŸŽ‰ refactored Fire language -- ๐ŸŽ‰ compilesTo property on grammar node in GrammarLanguage +- ๐ŸŽ‰ compilesTo property on grammar node in Parsers - ๐ŸŽ‰ perf fix for compiled languages - ๐Ÿฅ fire grammar fixes - ๐Ÿฅ compilation open and close children fixes @@ -967,7 +975,7 @@ This is an unstable release. Please wait a few days for bug fix releases before - Warning: this was a major refactor that may have introduced new bugs, so if using please be ready to ping me with bug reports - ๐ŸŽ‰ ability to compile grammar files to Javascript - ๐ŸŽ‰ grammar sandbox now has "download bundle" -- ๐ŸŽ‰ Upgrader class for making Tree Language upgrades easier +- ๐ŸŽ‰ Upgrader class for making Language upgrades easier - ๐ŸŽ‰ added support for "tooling" directives in Grammar language - ๐ŸŽ‰ getFirstNode method - ๐ŸŽ‰ getNodeTypeId on NonRootRunTime nodes @@ -990,23 +998,23 @@ This is an unstable release. Please wait a few days for bug fix releases before - โš ๏ธ removed getProgramErrorMessages. Use getAllErrors - โš ๏ธ getFirstCellType is now getFirstCellTypeId - โš ๏ธ getProgram() is now get getRootProgramNode and getProgram on grammar programs is getLanguageDefinitionProgram -- โš ๏ธ getGrammarProgram is now getGrammarProgramRoot +- โš ๏ธ getParsersProgram is now getParsersProgramRoot - โš ๏ธ getParsedWords removed - โš ๏ธ getCellTypeName is now getCellTypeId - โš ๏ธ getCellTypeDefinition is now getCellTypeDefinitionById - โš ๏ธ getNodeTypeDefinitionByName is now getNodeTypeDefinitionByNodeTypeId - โš ๏ธ getProgramErrors is now getAllErrors, getProgramErrorsIterator is now getAllErrorsIterator - โš ๏ธ getCompiledIndentation, getCompiledLine, getCompilerNode are now protected -- โš ๏ธ removed "nodeType constructors javascript" in GrammarLanguage. Use "nodeType javascript" directly. +- โš ๏ธ removed "nodeType constructors javascript" in Parsers. Use "nodeType javascript" directly. - โš ๏ธ no more getConstantsObject. No more "constants". Instead use "nodeType > boolean|int|string|float id value...". Adds getters to generated nodeType classes. -- โš ๏ธ in GrammarLanguage, use "stringCell" instead of "string", "intCell" instead of "int", "floatCell" instead of "float" +- โš ๏ธ in Parsers, use "stringCell" instead of "string", "intCell" instead of "int", "floatCell" instead of "float" - โš ๏ธ no more "ErrorNode", "BlobNode", "Terminal/NonTerminal" built in constructors. BlobNode is no longer exported. Now use "baseNodeType" to specify a base node type. - โš ๏ธ the nodeType name for each nodeType is now based on the nodeTypeId. It is no longer TerminalNode, NonTerminalNode, etc. A regex for finding breaks in untyped code: regexCode - \b(defaults|getExpectedLineCellTypes|nodeTypes|isLeafColumn|_getDuplicateLinesMap|_getFirstWordByIndex|toFlatTree|fromJson|toJson|getExpanded|getCompiledProgramName|getAncestorNodeTypeNamesArray|getCatchAllCellTypeName|getRequiredCellTypeNames|getRunTimeNodeTypeNames|getProgramErrorMessages|getFirstCellType|getProgram|getGrammarProgram|getParsedWords|getCellTypeName|getCellTypeDefinition|getNodeTypeDefinitionByName|getProgramErrors|getCompiledIndentation|getCompiledLine|getCompilerNode|getProgramErrorsIterator)\b + \b(defaults|getExpectedLineCellTypes|nodeTypes|isLeafColumn|_getDuplicateLinesMap|_getFirstWordByIndex|toFlatTree|fromJson|toJson|getExpanded|getCompiledProgramName|getAncestorNodeTypeNamesArray|getCatchAllCellTypeName|getRequiredCellTypeNames|getRunTimeNodeTypeNames|getProgramErrorMessages|getFirstCellType|getProgram|getParsersProgram|getParsedWords|getCellTypeName|getCellTypeDefinition|getNodeTypeDefinitionByName|getProgramErrors|getCompiledIndentation|getCompiledLine|getCompilerNode|getProgramErrorsIterator)\b # 25.2.0 2019-05-30 - ๐Ÿฅ Node.js fix for _getNow and renamed to _getProcessTimeInMilliseconds @@ -1034,7 +1042,7 @@ regexCode # 24.1.0 2019-05-27 - ๐ŸŽ‰ getAncestorNodeTypeNamesArray method on definition nodes -- ๐ŸŽ‰ getNodeTypeFamilyTree method on grammarPrograms +- ๐ŸŽ‰ getNodeTypeFamilyTree method on parsersPrograms - ๐ŸŽ‰ setWords, setWordsFrom and appendWord methods on base tree # 24.0.0 2019-05-21 @@ -1069,7 +1077,7 @@ code # 23.1.0 2019-05-21 - ๐ŸŽ‰ executeFiles method -- ๐ŸŽ‰ 50% speed improvement in getExpanded and extend and GrammarProgram.newFromCondensed +- ๐ŸŽ‰ 50% speed improvement in getExpanded and extend and ParsersProgram.newFromCondensed - โš ๏ธ getGraphByKey is now getAncestorNodesByInheritanceViaExtendsKeyword - โš ๏ธ getGraph is now getAncestorNodesByInheritanceViaColumnIndices @@ -1113,7 +1121,7 @@ code - โš ๏ธ getChildrenByNodeType is now getChildrenByNodeConstructor - โš ๏ธ extend now throws if attempting to extend with a non-map. Better solution to come. - โš ๏ธ removed combine.js script -- โš ๏ธ GrammarProgram.predictGrammarFile is now new UnknownGrammarProgram(input).getPredictedGrammarFile() +- โš ๏ธ ParsersProgram.predictGrammarFile is now new UnknownParsersProgram(input).getPredictedGrammarFile() - โš ๏ธ instead of title or style tags in Stump use "titleTag" or "styleTag" to overcome the inherent attribute/tag html name conflict. - โš ๏ธ no more @ prefix in Stump - โš ๏ธ for Stump collapseNode, just have it, don't set it to "true" @@ -1128,7 +1136,7 @@ code - โš ๏ธ in grammar language: wordType to cellType, columns to cells, catchAllColumn to catchAllCellType - โš ๏ธ removed ability in grammar files to have a wordType and keyword share the same name - โš ๏ธ getGraph now requires a uniqueId column. Throws if you attempt to extend a non-unique id -- โš ๏ธ instead of "grammar grammarName" oneliner now use the grammar name keyword +- โš ๏ธ instead of "grammar parsersName" oneliner now use the grammar name keyword - โš ๏ธ removed parseWith cellType property - โš ๏ธ removed jtree.getLanguage. Instead do require('.../langs/...'). - โš ๏ธ in grammar keywordTable now enumFromGrammar @@ -1156,7 +1164,7 @@ code # 19.5.0 2019-04-25 - ๐ŸŽ‰ @example keyword in grammar -- ๐ŸŽ‰ getErrorsInGrammarExamples method on GrammarProgram +- ๐ŸŽ‰ getErrorsInGrammarExamples method on ParsersProgram # 19.4.0 2019-04-24 - ๐ŸŽ‰ getKeywordInheritanceSet method @@ -1191,7 +1199,7 @@ code # 19.0.0 2019-04-19 - ๐ŸŽ‰ CodeMirror support -- ๐ŸŽ‰ Tree Language Sandbox webpage using CodeMirror +- ๐ŸŽ‰ Language Sandbox webpage using CodeMirror - ๐ŸŽ‰ in Grammar files we now have support for different constructors for node and browser environments - โš ๏ธ in grammar files @constructor is now @constructors. Browser and nodejs constructors must be specified separately. @@ -1285,7 +1293,7 @@ code # 15.2.0 2019-02-10 - ๐ŸŽ‰ added `getNumberOfLines` method -- ๐ŸŽ‰ GrammarProgram speedup 20%+ +- ๐ŸŽ‰ ParsersProgram speedup 20%+ - ๐ŸŽ‰ getProgramErrors speedup 10x+ - ๐ŸŽ‰ toString speedup 5%+ @@ -1398,7 +1406,7 @@ code - โš ๏ธ use getGraphByKey to getGraphByKey # 11.4.1 2017-11-08 -- ๐ŸŽ‰ export GrammarProgram +- ๐ŸŽ‰ export ParsersProgram # 11.4.0 2017-11-08 - โš ๏ธ getGrammarUsage is now getKeywordUsage @@ -1467,7 +1475,7 @@ code - ๐Ÿงน renamed slot types to columnTypes and better error messaging for when graph expansion fails # 8.6.0 2017-10-30 -- โš ๏ธ renamed @parameters to @columns in Grammar Tree Language +- โš ๏ธ renamed @parameters to @columns in Grammar Language # 8.5.0 2017-10-30 - ๐ŸŽ‰ New usage command line tool @@ -1508,7 +1516,7 @@ code - ๐Ÿฅ fixed browser version # 8.0.0 2017-10-15 -- ๐ŸŽ‰ Create new Tree Languages using a tree grammar file +- ๐ŸŽ‰ Create new Languages using a tree grammar file - ๐ŸŽ‰ Tree Console app - โš ๏ธ ImmutableNode no longer exposed on TreeProgram diff --git a/sandbox/SandboxApp.ts b/sandbox/SandboxApp.ts index ca83eb2fc..5d6f453d6 100644 --- a/sandbox/SandboxApp.ts +++ b/sandbox/SandboxApp.ts @@ -21,7 +21,7 @@ class SandboxApp extends AbstractTreeComponentParser { "toJsonSubset", `{ "name": "scrollsdk", - "description": "Scroll Notation parser, compiler-compiler, and virtual machine for Tree Languages", + "description": "Scroll Notation parser, compiler-compiler, and virtual machine for Languages", "keywords": "scrollsdk" }` ) @@ -192,7 +192,7 @@ class headerComponent extends AbstractTreeComponentParser { title TreeNotation.org span Scroll Notation Sandbox p - a Scroll Designer + a Parser Designer href /designer/ span | a Unit Tests @@ -298,7 +298,7 @@ class tableComponent extends AbstractTreeComponentParser { tr td div asHtmlCube - title Experimental. This is a very specific kind of Tree Language. + title Experimental. This is a very specific kind of Language. div id htmlCubeConsole style position:relative;` diff --git a/sandbox/index.html b/sandbox/index.html index a403b80ba..9b49fff9b 100644 --- a/sandbox/index.html +++ b/sandbox/index.html @@ -5,7 +5,7 @@ - + diff --git a/sandbox/perfTests.html b/sandbox/perfTests.html index d81f45429..fcaf047e9 100644 --- a/sandbox/perfTests.html +++ b/sandbox/perfTests.html @@ -3,7 +3,7 @@ - + @@ -15,7 +15,7 @@ - + diff --git a/sandbox/perfTests.js b/sandbox/perfTests.js index 82a6f33e4..941c28083 100644 --- a/sandbox/perfTests.js +++ b/sandbox/perfTests.js @@ -24,9 +24,9 @@ to fillThis` return code } -const main = (grammarCode, code) => { +const main = (parsersCode, code) => { logFn("Building language...") - const rootParser = new HandGrammarProgram(grammarCode).compileAndReturnRootParser() + const rootParser = new HandParsersProgram(parsersCode).compileAndReturnRootParser() logFn("Loading program...") @@ -83,9 +83,9 @@ const toStringTest = () => { } const fetchAndRun = async () => { - const result = await fetch("/langs/jibberish/jibberish.grammar") - const grammarCode = await result.text() - main(grammarCode, getBigCode()) + const result = await fetch("/langs/jibberish/jibberish.parsers") + const parsersCode = await result.text() + main(parsersCode, getBigCode()) } fetchAndRun() diff --git a/scrollNotationGrammarZoo.tree b/scrollNotationGrammarZoo.tree deleted file mode 100644 index 41298bbfc..000000000 --- a/scrollNotationGrammarZoo.tree +++ /dev/null @@ -1,61 +0,0 @@ -keywordGrammar - description A grammar where each node type is determined by the presence of a keyword - prefixKeywordGrammar - keyword 1 2 3 foo - postfixKeywordGrammar - 1 2 keyword - omnifixKeywordGrammar - 1 keyword 2 -flatGrammar - description A grammar that has only 1 scope - example -singleScopeGrammar - description A grammar with multiple scopes - benefit Isomorphic to a single table - downsides -staticGrammar - description A grammar where the parser and cellTypes cannot be changed or defined at runtime - example - print hello world -dynamicGrammar - description A grammar where new parser and/or cellTypes can be defined at runtime - example - name score - string int - sandy 123 -identifierGrammar - description A grammar where identifiers can be created - example - score = 10 - increment score -anonymousGrammar - description A grammar without any identifiers or naming - example - 10 - increment -recursiveGrammar - description A grammarNode with a scope that eventually includes itself - example - sum - 2 3 - sum - 4 6 -dagGrammar - description A non recursive grammar - example - person - phone - cell 123-1234 -multiAnchorGrammars - description A grammar where root level nodes (for instance) can be parsed/compiled/executed completely independently -singleAnchorGrammars - description A grammar where parsing/compilation and/or execution must begin from the beginning of the sequence and process sequentially -orderIsImportantGrammars - example - add 10 - checkBalance() -orderIsNotImportantGrammars - description When order is not important and rearranging nodes does not affect meaning. - example - name ali - score 100 \ No newline at end of file diff --git a/scrollNotationParsersZoo.tree b/scrollNotationParsersZoo.tree new file mode 100644 index 000000000..7ad8c878f --- /dev/null +++ b/scrollNotationParsersZoo.tree @@ -0,0 +1,61 @@ +keywordParsers + description A parser where each node type is determined by the presence of a keyword + prefixKeywordParsers + keyword 1 2 3 foo + postfixKeywordParsers + 1 2 keyword + omnifixKeywordParsers + 1 keyword 2 +flatParsers + description A parser that has only 1 scope + example +singleScopeParsers + description A parser with multiple scopes + benefit Isomorphic to a single table + downsides +staticParsers + description A parser where the parser and cellTypes cannot be changed or defined at runtime + example + print hello world +dynamicParsers + description A parser where new parser and/or cellTypes can be defined at runtime + example + name score + string int + sandy 123 +identifierParsers + description A parser where identifiers can be created + example + score = 10 + increment score +anonymousParsers + description A parser without any identifiers or naming + example + 10 + increment +recursiveParsers + description A parserNode with a scope that eventually includes itself + example + sum + 2 3 + sum + 4 6 +dagParsers + description A non recursive parser + example + person + phone + cell 123-1234 +multiAnchorParserss + description A parser where root level nodes (for instance) can be parsed/compiled/executed completely independently +singleAnchorParserss + description A parser where parsing/compilation and/or execution must begin from the beginning of the sequence and process sequentially +orderIsImportantParserss + example + add 10 + checkBalance() +orderIsNotImportantParserss + description When order is not important and rearranging nodes does not affect meaning. + example + name ali + score 100 \ No newline at end of file diff --git a/treeComponentFramework/TreeComponentFramework.ts b/treeComponentFramework/TreeComponentFramework.ts index f121689b5..b91e59ed2 100644 --- a/treeComponentFramework/TreeComponentFramework.ts +++ b/treeComponentFramework/TreeComponentFramework.ts @@ -4,7 +4,7 @@ import { scrollNotationTypes } from "../products/scrollNotationTypes" const { TreeNode } = require("../products/TreeNode.js") const { Utils } = require("../products/Utils.js") -const { GrammarBackedNode } = require("../products/GrammarLanguage.js") +const { ParserBackedNode } = require("../products/Parsers.js") const stumpParser = require("../products/stump.nodejs.js") const hakonParser = require("../products/hakon.nodejs.js") @@ -1146,7 +1146,7 @@ interface childShouldUpdateResult { /** Declaration file generated by dts-gen */ // Todo: clean up declaration file generation -declare class abstractHtmlTag extends GrammarBackedNode { +declare class abstractHtmlTag extends ParserBackedNode { constructor(...args: any[]) addClassToStumpNode(...args: any[]): void findStumpNodeByChild(...args: any[]): void @@ -1176,7 +1176,7 @@ declare class abstractHtmlTag extends GrammarBackedNode { asHtmlWithSuids(...args: any[]): void } -abstract class AbstractTreeComponentParser extends GrammarBackedNode { +abstract class AbstractTreeComponentParser extends ParserBackedNode { private _commandsBuffer: scrollNotationTypes.treeNode[] private _messageBuffer: scrollNotationTypes.treeNode private _htmlStumpNode: abstractHtmlTag diff --git a/treeComponentFramework/readme.scroll b/treeComponentFramework/readme.scroll index d98b6d66e..13d51ea5f 100644 --- a/treeComponentFramework/readme.scroll +++ b/treeComponentFramework/readme.scroll @@ -6,9 +6,9 @@ TreeComponentFramework is a *research* web framework for building reactive web a TreeComponentFramework is a step toward a world where web app development and debugging is much simpler! Every app can be dumped to a string and you can see all the state in the app in that string. See for yourself in the SweeperCraft app--just press "d" to dump the app to a string. https://sdk.scroll.pub/treeComponentFramework/sweepercraft/ SweeperCraft app -With TreeComponentFramework, you build your components in Tree Languages: instead of CSS use Hakon; instead of HTML use Stump; and instead of TypeScript/Javascript use TreeScript (coming soon). You define your components in those and then you create a high level Tree Language specifically for your app to stitch those components together. +With TreeComponentFramework, you build your components in Languages: instead of CSS use Hakon; instead of HTML use Stump; and instead of TypeScript/Javascript use TreeScript (coming soon). You define your components in those and then you create a high level Language specifically for your app to stitch those components together. -In the future as Scroll Notation and Tree Language tooling improves you will be able to build enormously powerful and complex app webs using a single universal syntax from top to bottom. We think this will greatly simplify and improve the reliability of web apps. +In the future as Scroll Notation and Language tooling improves you will be able to build enormously powerful and complex app webs using a single universal syntax from top to bottom. We think this will greatly simplify and improve the reliability of web apps. Today, your TreeComponentFramework apps are compiled to Javascript and HTML and then run on Virtual Machines like v8/Chromium, which will further compile your code to assembly/machine code and then send that to microprocessors which then compile it to microcode before final execution on hardware. In the long run if people build Tree Machines your code could be run directly as is on those. @@ -23,10 +23,10 @@ This framework also powers: - Scroll Notation Sandbox https://github.com/breck7/scrollsdk/tree/main/sandbox -- Scroll Designer +- Parser Designer https://github.com/breck7/scrollsdk/tree/main/designer - Ohayo - https://github.com/treenotation/ohayo + https://github.com/breck7/ohayo - PauSynth https://pau.treenotation.org/synth/ diff --git a/treeComponentFramework/sweepercraft/index.html b/treeComponentFramework/sweepercraft/index.html index 2f0a3289d..be21592ff 100644 --- a/treeComponentFramework/sweepercraft/index.html +++ b/treeComponentFramework/sweepercraft/index.html @@ -6,7 +6,7 @@ - + diff --git a/treeComponentFramework/sweepercraft/sweepercraft.grammar b/treeComponentFramework/sweepercraft/sweepercraft.parsers similarity index 100% rename from treeComponentFramework/sweepercraft/sweepercraft.grammar rename to treeComponentFramework/sweepercraft/sweepercraft.parsers diff --git a/treeFileSystem/TreeFileSystem.ts b/treeFileSystem/TreeFileSystem.ts index e5272c04c..9ce55fd60 100644 --- a/treeFileSystem/TreeFileSystem.ts +++ b/treeFileSystem/TreeFileSystem.ts @@ -5,11 +5,11 @@ import { scrollNotationTypes } from "../products/scrollNotationTypes" const { Disk } = require("../products/Disk.node.js") const { Utils } = require("../products/Utils.js") const { TreeNode } = require("../products/TreeNode.js") -const { HandGrammarProgram } = require("../products/GrammarLanguage.js") -const grammarParser = require("../products/grammar.nodejs.js") +const { HandParsersProgram } = require("../products/Parsers.js") +const parsersParser = require("../products/parsers.nodejs.js") const { posix } = require("../products/Path.js") -const GRAMMAR_EXTENSION = ".grammar" +const PARSERS_EXTENSION = ".parsers" interface OpenedFile { absolutePath: scrollNotationTypes.filepath @@ -140,7 +140,7 @@ class TreeFileSystem implements Storage { private _treeCache: { [filepath: string]: typeof TreeNode } = {} private _parserCache: { [concatenatedFilepaths: string]: any } = {} private _expandedImportCache: { [filepath: string]: AssembledFile } = {} - private _grammarExpandersCache: { [filepath: string]: boolean } = {} + private _parsersExpandersCache: { [filepath: string]: boolean } = {} private _getFileAsTree(absoluteFilePath: string) { const { _treeCache } = this @@ -158,16 +158,18 @@ class TreeFileSystem implements Storage { const isImportOnly = importOnlyRegex.test(code) - // Strip any parsers - const stripIt = code.includes("// parsersOnly") // temporary perf hack - if (stripIt) + // Perf hack + // If its a parsers file, it will have no content, just parsers (and maybe imports). + // The parsers will already have been processed. We can skip them + const stripParsers = absoluteFilePath.endsWith(PARSERS_EXTENSION) + if (stripParsers) code = code .split("\n") .filter(line => line.startsWith("import ")) .join("\n") const filepathsWithParserDefinitions = [] - if (this._doesFileHaveGrammarDefinitions(absoluteFilePath)) filepathsWithParserDefinitions.push(absoluteFilePath) + if (this._doesFileHaveParsersDefinitions(absoluteFilePath)) filepathsWithParserDefinitions.push(absoluteFilePath) if (!importRegex.test(code)) return { @@ -204,44 +206,45 @@ class TreeFileSystem implements Storage { importFilePaths, isImportOnly, afterImportPass: combinedLines, - filepathsWithParserDefinitions: importFilePaths.filter((filename: string) => this._doesFileHaveGrammarDefinitions(filename)).concat(filepathsWithParserDefinitions) + filepathsWithParserDefinitions: importFilePaths.filter((filename: string) => this._doesFileHaveParsersDefinitions(filename)).concat(filepathsWithParserDefinitions) } return _expandedImportCache[absoluteFilePath] } - private _doesFileHaveGrammarDefinitions(absoluteFilePath: scrollNotationTypes.filepath) { + private _doesFileHaveParsersDefinitions(absoluteFilePath: scrollNotationTypes.filepath) { if (!absoluteFilePath) return false - const { _grammarExpandersCache } = this - if (_grammarExpandersCache[absoluteFilePath] === undefined) _grammarExpandersCache[absoluteFilePath] = !!this._storage.read(absoluteFilePath).match(parserRegex) + const { _parsersExpandersCache } = this + if (_parsersExpandersCache[absoluteFilePath] === undefined) _parsersExpandersCache[absoluteFilePath] = !!this._storage.read(absoluteFilePath).match(parserRegex) - return _grammarExpandersCache[absoluteFilePath] + return _parsersExpandersCache[absoluteFilePath] } - private _getOneGrammarParserFromFiles(filePaths: string[], baseGrammarCode: string) { + private _getOneParsersParserFromFiles(filePaths: string[], baseParsersCode: string) { const parserDefinitionRegex = /^[a-zA-Z0-9_]+Parser/ + const cellDefinitionRegex = /^[a-zA-Z0-9_]+Cell/ const asOneFile = filePaths .map(filePath => { const content = this._storage.read(filePath) - if (filePath.endsWith(GRAMMAR_EXTENSION)) return content + if (filePath.endsWith(PARSERS_EXTENSION)) return content // Strip scroll content return new TreeNode(content) - .filter((node: scrollNotationTypes.treeNode) => node.getLine().match(parserDefinitionRegex)) + .filter((node: scrollNotationTypes.treeNode) => node.getLine().match(parserDefinitionRegex) || node.getLine().match(cellDefinitionRegex)) .map((node: scrollNotationTypes.treeNode) => node.asString) .join("\n") }) .join("\n") .trim() - // todo: clean up scrollsdk so we are using supported methods (perhaps add a formatOptions that allows you to tell Grammar not to run prettier on js nodes) - return new grammarParser(baseGrammarCode + "\n" + asOneFile)._sortNodesByInScopeOrder()._sortWithParentParsersUpTop() + // todo: clean up scrollsdk so we are using supported methods (perhaps add a formatOptions that allows you to tell Parsers not to run prettier on js nodes) + return new parsersParser(baseParsersCode + "\n" + asOneFile)._sortNodesByInScopeOrder()._sortWithParentParsersUpTop() } get parsers() { - return Object.values(this._parserCache).map(parser => parser.grammarParser) + return Object.values(this._parserCache).map(parser => parser.parsersParser) } - getParser(filePaths: string[], baseGrammarCode = "") { + getParser(filePaths: string[], baseParsersCode = "") { const { _parserCache } = this const key = filePaths .filter(fp => fp) @@ -249,12 +252,12 @@ class TreeFileSystem implements Storage { .join("\n") const hit = _parserCache[key] if (hit) return hit - const grammarParser = this._getOneGrammarParserFromFiles(filePaths, baseGrammarCode) - const grammarCode = grammarParser.asString + const parsersParser = this._getOneParsersParserFromFiles(filePaths, baseParsersCode) + const parsersCode = parsersParser.asString _parserCache[key] = { - grammarParser, - grammarCode, - parser: new HandGrammarProgram(grammarCode).compileAndReturnRootParser() + parsersParser, + parsersCode, + parser: new HandParsersProgram(parsersCode).compileAndReturnRootParser() } return _parserCache[key] } @@ -264,7 +267,7 @@ class TreeFileSystem implements Storage { if (!defaultParserCode) return assembledFile - // BUILD CUSTOM COMPILER, IF THERE ARE CUSTOM GRAMMAR NODES DEFINED + // BUILD CUSTOM COMPILER, IF THERE ARE CUSTOM PARSERS NODES DEFINED if (assembledFile.filepathsWithParserDefinitions.length) assembledFile.parser = this.getParser(assembledFile.filepathsWithParserDefinitions, defaultParserCode).parser return assembledFile } diff --git a/treeFileSystem/readme.scroll b/treeFileSystem/readme.scroll index 271e6fa6f..f20aae81e 100644 --- a/treeFileSystem/readme.scroll +++ b/treeFileSystem/readme.scroll @@ -1,3 +1,3 @@ # TreeFileSystem -Code that implements Disk and Memory file systems for Tree Languages that have `imports`. +Code that implements Disk and Memory file systems for Languages that have `imports`. diff --git a/treeNode/TreeNode.ts b/treeNode/TreeNode.ts index 0f21f29a6..609b7267e 100644 --- a/treeNode/TreeNode.ts +++ b/treeNode/TreeNode.ts @@ -2008,7 +2008,7 @@ class TreeNode extends AbstractNode { // todo: add more testing. // todo: solve issue with where extend should overwrite or append - // todo: should take a grammar? to decide whether to overwrite or append. + // todo: should take a parsers? to decide whether to overwrite or append. // todo: this is slow. extend(nodeOrStr: TreeNode | string | Object) { const node = nodeOrStr instanceof TreeNode ? nodeOrStr : new TreeNode(nodeOrStr) @@ -3043,7 +3043,7 @@ class TreeNode extends AbstractNode { return str ? indent + str.replace(/\n/g, indent) : "" } - static getVersion = () => "77.1.1" + static getVersion = () => "80.0.0" static fromDisk(path: string): TreeNode { const format = this._getFileFormat(path)