diff --git a/Readme.md b/Readme.md
new file mode 100644
index 0000000..d2c6796
--- /dev/null
+++ b/Readme.md
@@ -0,0 +1,76 @@
+# Human2Regex
+
+## Purpose
+
+Generate regular expressions from natural language. Currently WIP, but should look something like this:
+
+Instead of a convoluted mess of symbols why not
+
+ using global matching
+ create a group called "capture_me"
+ match 0+ words or "." or "=" or "-"
+ match 1+ words
+
+Running the program should result in the following output:
+
+ Your regex = /\$([\w\.=\-]*[\w]+)/g
+ "capture_me" is group id 1
+
+Is the former not much easier to read and bug fix than the latter?
+
+Another example
+
+ // H2R supports // # and /**/ as comments
+ // A group is only captured if given a name.
+ // You can use "and", "or", "not" to specify `[]` regex
+ // You can use "then" to combine match statements, however I find using multiple "match" statements easier to read
+
+ // exact matching means use a ^ and $ to signify the start and end of the string
+
+ using global and exact matching
+ create an optional group called "protocol"
+ match "http"
+ optionally match "s"
+ match "://"
+ create a group called "subdomain"
+ repeat
+ match 1+ words
+ match "."
+ create a group called "domain"
+ match 1+ words or "_" or "-"
+ match "."
+ match a word
+ # port, but we don't care about it, so ignore it
+ optionally match ":" then 0+ digits
+ create an optional group called "path"
+ repeat
+ match "/"
+ match 0+ words or "_" or "-"
+ create an optional group
+ # we don't want to capture the '?', so don't name the group until afterwards
+ match "?"
+ create a group called "query"
+ repeat
+ match 1+ words or "_" or "-"
+ match "="
+ match 1+ words or "_" or "-"
+ create an optional group
+ # fragment, again, we don't care, so ignore everything afterwards
+ match "#"
+ match 0+ anything
+
+Running the program should result in the following output:
+
+ Your regex = /^(https?:\/\/)?((\w\.)*)(:\d+)?([\w_\-]\.\w)((/[\w_\-]))?(\?([\w_\-]=[\w_\-]))?(#.*)$/g
+ "protocol" is group id 1
+ "subdomain" is group id 2
+ "domain" is group id 4
+ "path" is group id 5
+ "query" is group id 5 or 6 if "path" exists
+
+## Usage
+Configure config.ts
+Run
+
+ npm run build
+
diff --git a/build.ts b/build.ts
index 726d594..8ff19ff 100644
--- a/build.ts
+++ b/build.ts
@@ -5,7 +5,7 @@ import { readFileSync, copyFileSync, writeFileSync, existsSync, mkdirSync } from
import { emptyDirSync } from 'fs-extra';
import { minify } from 'html-minifier';
import { basename } from 'path';
-import { minify as uglify } from 'uglify-js';
+import { minify as uglify } from 'uglify-es';
import clean_css from 'clean-css';
import { glob } from 'glob';
import { config } from './config';
@@ -73,7 +73,7 @@ function build() {
const error_files = glob.sync(join(config.src, 'error', '*.json'));
// get partials
- let partials = {
+ const partials = {
header: read_file(join(config.src, '/header.mustache')),
footer: read_file(join(config.src, '/footer.mustache'))
};
diff --git a/docs/400.html b/docs/400.html
index 9816360..db1e89f 100644
--- a/docs/400.html
+++ b/docs/400.html
@@ -1 +1 @@
-
Error 400 - Bad Request Skip to main content
\ No newline at end of file
+Error 400 - Bad Request Skip to main content
\ No newline at end of file
diff --git a/docs/401.html b/docs/401.html
index de1b1c1..98b4129 100644
--- a/docs/401.html
+++ b/docs/401.html
@@ -1 +1 @@
-Error 401 - Unauthorized Skip to main content
\ No newline at end of file
+Error 401 - Unauthorized Skip to main content
\ No newline at end of file
diff --git a/docs/404.html b/docs/404.html
index a433ca9..de773ba 100644
--- a/docs/404.html
+++ b/docs/404.html
@@ -1 +1 @@
-Error 404 - Not Found Skip to main content
\ No newline at end of file
+Error 404 - Not Found Skip to main content
\ No newline at end of file
diff --git a/docs/501.html b/docs/501.html
index 0f69fd9..de46433 100644
--- a/docs/501.html
+++ b/docs/501.html
@@ -1 +1 @@
-Error 501 - Not Implemented Skip to main content
\ No newline at end of file
+Error 501 - Not Implemented Skip to main content
\ No newline at end of file
diff --git a/docs/index.html b/docs/index.html
index 11b83be..a6d9659 100644
--- a/docs/index.html
+++ b/docs/index.html
@@ -1 +1 @@
-Human2Regex Skip to main content
\ No newline at end of file
+Human2Regex Skip to main content
\ No newline at end of file
diff --git a/docs/script.min.js b/docs/script.min.js
index efb3da0..59fdb0d 100644
--- a/docs/script.min.js
+++ b/docs/script.min.js
@@ -1,2 +1,2 @@
/*! Copyright (c) 2020 Patrick Demian; Licensed under MIT */
-"use strict";$(function(){});
\ No newline at end of file
+"use strict";const keywords=["optional","optionally","match","then","any","of","or","word","digit","unicode","character","multiple","one","two","three","four","five","six","seven","eight","nine","ten","anything","whitespace","as","number","if","starts","with","ends","otherwise","else","unless","while","more","using","global","and","multiline","exact","matching","not","between","tab","linefeed","carriage","return","group","by","exactly","inclusive","inclusively","exclusive","exclusively","including","from","to"];var TokenType;!function(e){e[e.END_OF_STATEMENT=0]="END_OF_STATEMENT",e[e.INDENT=1]="INDENT",e[e.BETWEEN=2]="BETWEEN",e[e.QUOTE=3]="QUOTE",e[e.KEYWORD_BETWEEN=4]="KEYWORD_BETWEEN",e[e.KEYWORD_OPTIONAL=5]="KEYWORD_OPTIONAL",e[e.KEYWORD_MATCH=6]="KEYWORD_MATCH",e[e.KEYWORD_THEN=7]="KEYWORD_THEN",e[e.KEYWORD_AND=8]="KEYWORD_AND",e[e.KEYWORD_OR=9]="KEYWORD_OR",e[e.KEYWORD_ANY=10]="KEYWORD_ANY",e[e.KEYWORD_OF=11]="KEYWORD_OF"}(TokenType||(TokenType={}));class Token{constructor(e,n){this.type=e,this.token_string=n}}class TokenizerOptions{constructor(){this.convert_spaces_to_tabs=!1}}function tokenize(e,n){let t=[];for(let s=0;sli.nav-item>a{font-size:12px;font-weight:800;letter-spacing:1px;text-transform:uppercase}@media only screen and (max-width:991px){#mainNav{position:fixed}}@media only screen and (min-width:992px){#mainNav .navbar-brand{padding:10px 20px;color:#fff}#mainNav .navbar-brand:focus,#mainNav .navbar-brand:hover{color:rgba(255,255,255,.8)}#mainNav .navbar-nav>li.nav-item>a{padding:10px 20px;color:#fff}#mainNav .navbar-nav>li.nav-item>a:focus,#mainNav .navbar-nav>li.nav-item>a:hover{color:rgba(255,255,255,.8)}}header.masthead{background:no-repeat center center;background-color:#868e96;background-attachment:scroll;position:relative;background-size:cover}header.masthead .overlay{position:absolute;top:0;left:0;height:100%;width:100%;background-color:#212529;opacity:.5}header.masthead .site-heading{padding:60px 0 20px;color:#fff}@media only screen and (min-width:768px){header.masthead .site-heading{padding:60px 0 20px}}header.masthead .site-heading{text-align:center}header.masthead .site-heading h1{font-size:50px;margin-top:0}header.masthead .site-heading .subheading{font-size:24px;font-weight:300;line-height:1.1;display:block;margin:10px 0 0;font-family:'Open Sans','Helvetica Neue',Helvetica,Arial,sans-serif}@media only screen and (min-width:768px){header.masthead .site-heading h1{font-size:60px}}.wrapper{display:flex;flex-direction:column;height:100vh}#maincontent{flex:1 0 auto}header{flex-shrink:0}footer{flex-shrink:0;width:100%;right:0;left:0;padding:20px 0 20px;background-color:#54595e;color:#fff}.copyright{font-size:14px;margin-bottom:0;text-align:center}.btn{font-family:"Open Sans","Helvetica Neue",Helvetica,Arial,sans-serif}.btn-primary{background-color:#00748c;border-color:#00748c}.btn-primary:active,.btn-primary:focus,.btn-primary:hover{color:#fff;background-color:#004b5c!important;border-color:#004b5c!important}.btn-lg{font-size:16px;padding:25px 35px}/*! Copyright (c) 2020 Patrick Demian; Licensed under MIT */.align_header{text-align:center;margin-bottom:20px}.skip-top{top:10px;margin:10px 40%!important}.skip{background:#335075!important;color:#fff!important;position:absolute!important;clip:rect(1px,1px,1px,1px);float:left;margin-left:20%}.skip:active,.skip:focus{font-weight:700;box-shadow:0 0 2px 2px rgba(0,0,0,.6);clip:auto!important;display:block;text-decoration:underline;padding:5px;text-align:center;top:auto;min-width:20%;text-align:center;z-index:10000}.mid-margin{margin-left:20px;margin-right:20px}a{color:#00497a}.navbar-light .navbar-nav .nav-link{color:rgba(0,0,0,.54)}
\ No newline at end of file
+ */body{font-size:20px;color:#212529}p{line-height:1.5}p a{text-decoration:underline}@media (max-width:575px){.form-inline .form-control{display:inline-block;width:auto;vertical-align:middle}.form-inline label{display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center;-ms-flex-pack:center;justify-content:center;margin-bottom:0}.form-inline .form-group{display:-ms-flexbox;display:flex;-ms-flex:0 0 auto;flex:0 0 auto;-ms-flex-flow:row wrap;flex-flow:row wrap;-ms-flex-align:center;align-items:center;margin-bottom:0}}h1,h2,h3,h4,h5,h6{font-weight:800;font-family:'Open Sans','Helvetica Neue',Helvetica,Arial,sans-serif}::-moz-selection{color:#fff;background:#0085a1;text-shadow:none}::selection{color:#fff;background:#0085a1;text-shadow:none}#mainNav{position:absolute;border-bottom:1px solid transparent;background-color:#232323;font-family:'Open Sans','Helvetica Neue',Helvetica,Arial,sans-serif}#mainNav .navbar-brand{font-weight:800;color:#fff}#mainNav .navbar-toggler{font-size:16px;font-weight:800;padding:13px;text-transform:uppercase;color:#343a40}#mainNav .navbar-nav>li.nav-item>a{font-size:12px;font-weight:800;letter-spacing:1px;text-transform:uppercase}@media only screen and (max-width:991px){#mainNav{position:fixed}}@media only screen and (min-width:992px){#mainNav .navbar-brand{padding:10px 20px;color:#fff}#mainNav .navbar-brand:focus,#mainNav .navbar-brand:hover{color:rgba(255,255,255,.8)}#mainNav .navbar-nav>li.nav-item>a{padding:10px 20px;color:#fff}#mainNav .navbar-nav>li.nav-item>a:focus,#mainNav .navbar-nav>li.nav-item>a:hover{color:rgba(255,255,255,.8)}}header.masthead{background:no-repeat center center;background-color:#868e96;background-attachment:scroll;position:relative;background-size:cover}header.masthead .overlay{position:absolute;top:0;left:0;height:100%;width:100%;background-color:#212529;opacity:.5}header.masthead .site-heading{padding:60px 0 20px;color:#fff}@media only screen and (min-width:768px){header.masthead .site-heading{padding:60px 0 20px}}header.masthead .site-heading{text-align:center}header.masthead .site-heading h1{font-size:50px;margin-top:0}header.masthead .site-heading .subheading{font-size:24px;font-weight:300;line-height:1.1;display:block;margin:10px 0 0;font-family:'Open Sans','Helvetica Neue',Helvetica,Arial,sans-serif}@media only screen and (min-width:768px){header.masthead .site-heading h1{font-size:60px}}.wrapper{display:flex;flex-direction:column;height:100vh}#maincontent{flex:1 0 auto}header{flex-shrink:0}footer{flex-shrink:0;width:100%;right:0;left:0;padding:20px 0 20px;background-color:#232323;color:#fff}.copyright{font-size:14px;margin-bottom:0;text-align:center}.btn{font-family:"Open Sans","Helvetica Neue",Helvetica,Arial,sans-serif}.btn-primary{background-color:#00748c;border-color:#00748c}.btn-primary:active,.btn-primary:focus,.btn-primary:hover{color:#fff;background-color:#004b5c!important;border-color:#004b5c!important}.btn-lg{font-size:16px;padding:25px 35px}/*! Copyright (c) 2020 Patrick Demian; Licensed under MIT */.align_header{text-align:center;margin-bottom:20px}.skip-top{top:10px;margin:10px 40%!important}.skip{background:#335075!important;color:#fff!important;position:absolute!important;clip:rect(1px,1px,1px,1px);float:left;margin-left:20%}.skip:active,.skip:focus{font-weight:700;box-shadow:0 0 2px 2px rgba(0,0,0,.6);clip:auto!important;display:block;text-decoration:underline;padding:5px;text-align:center;top:auto;min-width:20%;text-align:center;z-index:10000}.mid-margin{margin-left:20px;margin-right:20px}a{color:#00497a}.navbar-light .navbar-nav .nav-link{color:rgba(0,0,0,.54)}
\ No newline at end of file
diff --git a/package-lock.json b/package-lock.json
index e7d85e7..92b4c79 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -44,9 +44,10 @@
}
},
"@types/jquery": {
- "version": "3.5.1",
- "resolved": "https://registry.npmjs.org/@types/jquery/-/jquery-3.5.1.tgz",
- "integrity": "sha512-Tyctjh56U7eX2b9udu3wG853ASYP0uagChJcQJXLUXEU6C/JiW5qt5dl8ao01VRj1i5pgXPAf8f1mq4+FDLRQg==",
+ "version": "3.5.2",
+ "resolved": "https://registry.npmjs.org/@types/jquery/-/jquery-3.5.2.tgz",
+ "integrity": "sha512-+MFOdKF5Zr41t3y2wfzJvK1PrUK0KtPLAFwYownp/0nCoMIANDDu5aFSpWfb8S0ZajCSNeaBnMrBGxksXK5yeg==",
+ "dev": true,
"requires": {
"@types/sizzle": "*"
}
@@ -78,7 +79,17 @@
"@types/sizzle": {
"version": "2.3.2",
"resolved": "https://registry.npmjs.org/@types/sizzle/-/sizzle-2.3.2.tgz",
- "integrity": "sha512-7EJYyKTL7tFR8+gDbB6Wwz/arpGa0Mywk1TJbNzKzHtzbwVmY4HR9WqS5VV7dsBUKQmPNr192jHr/VpBluj/hg=="
+ "integrity": "sha512-7EJYyKTL7tFR8+gDbB6Wwz/arpGa0Mywk1TJbNzKzHtzbwVmY4HR9WqS5VV7dsBUKQmPNr192jHr/VpBluj/hg==",
+ "dev": true
+ },
+ "@types/uglify-es": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/@types/uglify-es/-/uglify-es-3.0.0.tgz",
+ "integrity": "sha512-Oc/c7pGIQL0MVhC6g+VftWiDQethKsT4c3fQKYm6nOprkvkx9s1MLrnJprDTKlZL3ZJulMpCF9Qn7s6u3uCNxQ==",
+ "dev": true,
+ "requires": {
+ "@types/uglify-js": "*"
+ }
},
"@types/uglify-js": {
"version": "3.11.0",
@@ -293,6 +304,24 @@
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
"dev": true
},
+ "uglify-es": {
+ "version": "3.3.9",
+ "resolved": "https://registry.npmjs.org/uglify-es/-/uglify-es-3.3.9.tgz",
+ "integrity": "sha512-r+MU0rfv4L/0eeW3xZrd16t4NZfK8Ld4SWVglYBb7ez5uXFWHuVRs6xCTrf1yirs9a4j4Y27nn7SRfO6v67XsQ==",
+ "dev": true,
+ "requires": {
+ "commander": "~2.13.0",
+ "source-map": "~0.6.1"
+ },
+ "dependencies": {
+ "commander": {
+ "version": "2.13.0",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-2.13.0.tgz",
+ "integrity": "sha512-MVuS359B+YzaWqjCL/c+22gfryv+mCBPHAv3zyVI2GN8EY6IRP8VwtasXn8jyyhvvq84R4ImN1OKRtcbIasjYA==",
+ "dev": true
+ }
+ }
+ },
"uglify-js": {
"version": "3.11.0",
"resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.11.0.tgz",
diff --git a/package.json b/package.json
index d417df5..5bd9222 100644
--- a/package.json
+++ b/package.json
@@ -8,12 +8,14 @@
"@types/fs-extra": "^9.0.1",
"@types/glob": "^7.1.3",
"@types/html-minifier": "^3.5.3",
+ "@types/jquery": "^3.5.2",
"@types/mustache": "^4.0.1",
- "@types/uglify-js": "^3.9.2",
+ "@types/uglify-es": "^3.0.0",
"fs-extra": "^9.0.0",
"glob": "^7.1.6",
"html-minifier": "^4.0.0",
- "mustache": "^4.0.1"
+ "mustache": "^4.0.1",
+ "uglify-es": "^3.3.9"
},
"scripts": {
"build": "tsc && node build.js && rm build.js && rm config.js",
@@ -24,9 +26,7 @@
],
"author": "Patrick Demian",
"license": "MIT",
- "dependencies": {
- "@types/jquery": "^3.5.1"
- },
+ "dependencies": {},
"repository": {
"type": "git",
"url": "git+https://github.com/pdemian/human2regex.git"
diff --git a/src/script.js b/src/script.js
index a5899b5..5e027ff 100644
--- a/src/script.js
+++ b/src/script.js
@@ -1,5 +1,134 @@
/*! Copyright (c) 2020 Patrick Demian; Licensed under MIT */
"use strict";
+const keywords = [
+ "optional", "optionally", "match", "then", "any", "of", "or", "word", "digit", "unicode", "character",
+ "multiple", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten", "anything",
+ "whitespace", "as", "number", "if", "starts", "with", "ends", "otherwise", "else", "unless", "while", "more",
+ "using", "global", "and", "multiline", "exact", "matching", "not", "between", "tab", "linefeed", "carriage", "return",
+ "group", "by", "exactly", "inclusive", "inclusively", "exclusive", "exclusively", "including", "from", "to"
+];
+var TokenType;
+(function (TokenType) {
+ TokenType[TokenType["END_OF_STATEMENT"] = 0] = "END_OF_STATEMENT";
+ TokenType[TokenType["INDENT"] = 1] = "INDENT";
+ TokenType[TokenType["BETWEEN"] = 2] = "BETWEEN";
+ TokenType[TokenType["QUOTE"] = 3] = "QUOTE";
+ TokenType[TokenType["KEYWORD_BETWEEN"] = 4] = "KEYWORD_BETWEEN";
+ TokenType[TokenType["KEYWORD_OPTIONAL"] = 5] = "KEYWORD_OPTIONAL";
+ TokenType[TokenType["KEYWORD_MATCH"] = 6] = "KEYWORD_MATCH";
+ TokenType[TokenType["KEYWORD_THEN"] = 7] = "KEYWORD_THEN";
+ TokenType[TokenType["KEYWORD_AND"] = 8] = "KEYWORD_AND";
+ TokenType[TokenType["KEYWORD_OR"] = 9] = "KEYWORD_OR";
+ TokenType[TokenType["KEYWORD_ANY"] = 10] = "KEYWORD_ANY";
+ TokenType[TokenType["KEYWORD_OF"] = 11] = "KEYWORD_OF";
+})(TokenType || (TokenType = {}));
+class Token {
+ constructor(type, token_string) {
+ this.type = type;
+ this.token_string = token_string;
+ }
+}
+class TokenizerOptions {
+ constructor() {
+ this.convert_spaces_to_tabs = false;
+ }
+}
+/* Basic Tokenizer: To be replaced with a unicode variant later */
+function tokenize(input, options) {
+ let tokens = [];
+ let errors = [];
+ for (let i = 0; i < input.length; i++) {
+ // 4 spaces = 1 tab. That is final. Debate over
+ if (options.convert_spaces_to_tabs && input.startsWith(" ", i)) {
+ tokens.push(new Token(TokenType.INDENT));
+ i += 3;
+ }
+ // between (ex: 0...3 or 0-3)
+ else if (input.startsWith("...", i)) {
+ tokens.push(new Token(TokenType.BETWEEN));
+ i += 2;
+ }
+ else if (input.startsWith("..", i)) {
+ tokens.push(new Token(TokenType.BETWEEN));
+ i += 1;
+ }
+ // comments
+ else if (input.startsWith("//", i)) {
+ i += 1;
+ while (i < input.length) {
+ if (input[i] == '\n') {
+ tokens.push(new Token(TokenType.END_OF_STATEMENT));
+ break;
+ }
+ i++;
+ }
+ }
+ else if (input.startsWith("\r\n", i)) {
+ tokens.push(new Token(TokenType.END_OF_STATEMENT));
+ i += 1;
+ }
+ else {
+ switch (input[i]) {
+ // comment
+ case '#':
+ i++;
+ while (i < input.length) {
+ if (input[i] == '\n') {
+ tokens.push(new Token(TokenType.END_OF_STATEMENT));
+ break;
+ }
+ i++;
+ }
+ break;
+ // quote
+ case '"':
+ case '\"':
+ // build up a word between quotes
+ const quote_char = input[i];
+ let found_ending = false;
+ let quote = "";
+ do {
+ i++;
+ if (input[i] == quote_char) {
+ found_ending = true;
+ break;
+ }
+ else if (input[i] == '\n') {
+ }
+ } while (i < input.length);
+ if (found_ending) {
+ tokens.push(new Token(TokenType.QUOTE, quote));
+ }
+ else {
+ // Skip until newline and throw an error
+ }
+ break;
+ // between (ex: 0...3 or 0-3)
+ case '-':
+ tokens.push(new Token(TokenType.BETWEEN));
+ break;
+ case '\n':
+ tokens.push(new Token(TokenType.END_OF_STATEMENT));
+ break;
+ case '\r':
+ // ignore
+ break;
+ case '\t':
+ tokens.push(new Token(TokenType.INDENT));
+ break;
+ case ' ':
+ break;
+ default:
+ // is digit? build up a number
+ // is char? build up a word
+ keywords.includes("word");
+ // build up a word
+ break;
+ }
+ }
+ }
+ return { tokens: tokens, errors: errors };
+}
/*
String.prototype.escape = function() {
var tagsToReplace = {
diff --git a/src/script.ts b/src/script.ts
index 5a02b5d..831c670 100644
--- a/src/script.ts
+++ b/src/script.ts
@@ -2,6 +2,146 @@
"use strict";
+const keywords = [
+ "optional", "optionally", "match", "then", "any", "of", "or", "word", "digit", "unicode", "character",
+ "multiple", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten", "anything",
+ "whitespace", "as", "number", "if", "starts", "with", "ends", "otherwise", "else", "unless", "while", "more",
+ "using", "global", "and", "multiline", "exact", "matching", "not", "between", "tab", "linefeed", "carriage", "return",
+ "group", "by", "exactly", "inclusive", "inclusively", "exclusive", "exclusively", "including", "from", "to"
+];
+
+enum TokenType {
+ END_OF_STATEMENT,
+ INDENT,
+ BETWEEN,
+ QUOTE,
+ KEYWORD_BETWEEN,
+ KEYWORD_OPTIONAL,
+ KEYWORD_MATCH,
+ KEYWORD_THEN,
+ KEYWORD_AND,
+ KEYWORD_OR,
+ KEYWORD_ANY,
+ KEYWORD_OF,
+}
+
+class Token {
+ constructor(public type: TokenType, public token_string?: string) {
+
+ }
+}
+
+class TokenizerOptions {
+ public convert_spaces_to_tabs: boolean = false;
+
+}
+
+/* Basic Tokenizer: To be replaced with a unicode variant later */
+
+function tokenize(input: string, options: TokenizerOptions) : { tokens: Token[], errors: Error[] } {
+ let tokens : Token[] = [];
+ let errors : Error[] = [];
+
+ for(let i = 0; i < input.length; i++) {
+
+ // 4 spaces = 1 tab. That is final. Debate over
+ if(options.convert_spaces_to_tabs && input.startsWith(" ", i)) {
+ tokens.push(new Token(TokenType.INDENT));
+ i += 3;
+ }
+ // between (ex: 0...3 or 0-3)
+ else if(input.startsWith("...", i)) {
+ tokens.push(new Token(TokenType.BETWEEN));
+ i += 2;
+ } else if(input.startsWith("..", i)) {
+ tokens.push(new Token(TokenType.BETWEEN));
+ i += 1;
+ }
+ // comments
+ else if(input.startsWith("//", i)) {
+ i += 1;
+ while(i < input.length) {
+ if(input[i] == '\n') {
+ tokens.push(new Token(TokenType.END_OF_STATEMENT));
+ break;
+ }
+ i++;
+ }
+ } else if (input.startsWith("\r\n", i)) {
+ tokens.push(new Token(TokenType.END_OF_STATEMENT));
+ i += 1;
+ } else {
+ switch(input[i]) {
+ // comment
+ case '#':
+ i++;
+ while(i < input.length) {
+ if(input[i] == '\n') {
+ tokens.push(new Token(TokenType.END_OF_STATEMENT));
+ break;
+ }
+ i++;
+ }
+ break;
+ // quote
+ case '"':
+ case '\"':
+ // build up a word between quotes
+ const quote_char = input[i];
+ let found_ending = false;
+
+ let quote = "";
+
+ do {
+ i++;
+ if(input[i] == quote_char) {
+ found_ending = true;
+ break;
+ }
+ else if(input[i] == '\n') {
+
+ }
+ } while(i < input.length);
+
+ if(found_ending) {
+ tokens.push(new Token(TokenType.QUOTE, quote));
+ }
+ else {
+ // Skip until newline and throw an error
+ }
+
+ break;
+
+ // between (ex: 0...3 or 0-3)
+ case '-':
+ tokens.push(new Token(TokenType.BETWEEN));
+ break;
+ case '\n':
+ tokens.push(new Token(TokenType.END_OF_STATEMENT));
+ break;
+ case '\r':
+ // ignore
+ break;
+ case '\t':
+ tokens.push(new Token(TokenType.INDENT));
+ break;
+ case ' ':
+ break;
+ default:
+ // is digit? build up a number
+
+ // is char? build up a word
+
+ keywords.includes("word");
+ // build up a word
+ break;
+ }
+ }
+ }
+
+ return { tokens: tokens, errors: errors };
+}
+
/*
String.prototype.escape = function() {
var tagsToReplace = {
diff --git a/src/style.css b/src/style.css
index 3f790fb..577c6b4 100644
--- a/src/style.css
+++ b/src/style.css
@@ -77,7 +77,7 @@ h6 {
#mainNav .navbar-brand {
font-weight: 800;
- color: #343a40;
+ color: #fff;
}
#mainNav .navbar-toggler {
@@ -191,7 +191,7 @@ footer {
right: 0;
left: 0;
padding: 20px 0 20px;
- background-color: #54595e;
+ background-color: #232323;
color: #fff;
}