1
0
mirror of https://github.com/pdemian/human2regex.git synced 2025-05-16 04:20:35 -07:00

Almost ready for a release

This commit is contained in:
Patrick Demian 2020-11-02 01:26:44 -05:00
parent 424cb59d6d
commit 851042ede6
9 changed files with 194 additions and 111 deletions

5
docs/bundle.min.css vendored

File diff suppressed because one or more lines are too long

18
docs/bundle.min.js vendored

File diff suppressed because one or more lines are too long

View File

@ -1,4 +1,4 @@
<!DOCTYPE html><html lang="en" dir="ltr"><head><meta name="viewport" content="width=device-width,initial-scale=1,shrink-to-fit=no"><meta name="description" content="Create regular expressions with natural, human language"><meta name="keywords" content="Human2Regex, Human, Regex, Natural, Language, Natural Language"><meta http-equiv="Content-Type" content="text/html; charset=utf-8"><title>Human2Regex</title><link href="bundle.min.css" rel="stylesheet" type="text/css"><meta name="theme-color" content="#212529"><meta name="apple-mobile-web-app-capable" content="yes"><meta name="apple-mobile-web-app-status-bar-style" content="default"><link rel="icon" type="image/x-icon" href="favicon.ico"></head><body><a class="skip skip-top" href="#maincontent">Skip to main content</a><div class="wrapper"><nav class="navbar navbar-expand-lg navbar-light fixed-top" id="mainNav"><div class="container"><a class="navbar-brand" href="index.html"><img src="favicon.png" width="30" height="30" class="d-inline-block align-top" alt="logo">&nbsp;Human2Regex</a></div></nav><div class="container" id="maincontent" role="main"><div class="row"><div class="col-lg-8 tenpx-margin-bottom"><div class="form-group row zero-margin-bottom"><label for="dialect" class="col-sm-4 col-form-label">Regex dialect:</label><div class="col-sm-8"><select class="form-control" id="dialect"><option value="js" selected="selected">Javascript</option><option value="dotnet">.NET</option><option value="java">Java</option><option value="perl">Perl</option></select></div></div><h4>Your Regular Expression:</h4><div class="row"><div class="col-xl-11"><input readonly="readonly" class="form-control" id="regex"></div><div class="col-xl-1"><button type="button" class="btn btn-secondary" id="clip">Copy</button></div></div><h4>Human Speak:</h4><textarea class="form-control" id="human" rows="25"> <!DOCTYPE html><html lang="en" dir="ltr"><head><meta name="viewport" content="width=device-width,initial-scale=1,shrink-to-fit=no"><meta name="description" content="Create regular expressions with natural, human language"><meta name="keywords" content="Human2Regex, Human, Regex, Natural, Language, Natural Language"><meta http-equiv="Content-Type" content="text/html; charset=utf-8"><title>Human2Regex</title><link href="bundle.min.css" rel="stylesheet" type="text/css"><meta name="theme-color" content="#212529"><meta name="apple-mobile-web-app-capable" content="yes"><meta name="apple-mobile-web-app-status-bar-style" content="default"><link rel="icon" type="image/x-icon" href="favicon.ico"></head><body><a class="skip skip-top" href="#maincontent">Skip to main content</a><div class="wrapper"><nav class="navbar navbar-expand-lg navbar-light fixed-top" id="mainNav"><div class="container"><a class="navbar-brand" href="index.html"><img src="favicon.png" width="30" height="30" class="d-inline-block align-top" alt="logo">&nbsp;Human2Regex</a></div></nav><div class="container" id="maincontent" role="main"><div class="row"><div class="col-lg-8 tenpx-margin-bottom"><div class="form-group row zero-margin-bottom"><label for="dialect" class="col-sm-4 col-form-label">Regex dialect:</label><div class="col-sm-8"><select class="form-control" id="dialect"><option value="js" selected="selected">Javascript</option><option value="dotnet">.NET</option><option value="java">Java</option><option value="pcre">PCRE</option></select></div></div><h4>Your Regular Expression:</h4><div class="row"><div class="col-xl-11 tenpx-margin-bottom"><input readonly="readonly" class="form-control" id="regex"></div><div class="col-xl-1"><button type="button" class="btn btn-secondary float-right" id="clip">Copy</button></div></div><h4>Human Speak:</h4><textarea class="form-control cm-s-idea" id="human" rows="25">
// H2R supports // # and /**/ as comments // H2R supports // # and /**/ as comments
// A group is only captured if given a name. // A group is only captured if given a name.
// You can use "and", "or", "not" to specify "[]" regex // You can use "and", "or", "not" to specify "[]" regex
@ -37,4 +37,4 @@ create an optional group
# fragment, again, we don't care, so ignore everything afterwards # fragment, again, we don't care, so ignore everything afterwards
match "#" match "#"
match 0+ any thing match 0+ any thing
</textarea><h4>Errors:</h4><textarea readonly="readonly" class="form-control" id="errors" rows="5"></textarea></div><br><div class="col-lg-4 tenpx-margin-bottom"><div class="cheatsheet"><h2>Cheat Sheet:</h2><p>Full documentation available <a href="tutorial.html">here</a></p><p class="font-weight-bold">Matching</p><p><code>match "hello world"</code> matches "hello world" exactly</p><p></p><p><code>match "hello" then optionally " world"</code> matches "hello" or "hello world"</p><p><code>match "hello" or "world"</code> matches "hello" or "world</p><p><code>match a word</code> matches any word</p><p class="font-weight-bold">Repetition</p><p><code>match 0+ "hello"</code> matches 0 or more "hello"s</p><p><code>match 3 "hello"</code> matches exactly "hellohellohello"</p><p><code>match 1 to 5 "hello"</code> matches between 1 to 5 "hello"s</p><p><code>repeat 0 or more</code> repeats the intended text 0 or more times (default)</p><p><code>optionally repeat between 3 to 5</code> optionally repeats the indented text 3 to 5 times</p><p class="font-weight-bold">Grouping</p><p><code>create a group called "mygroup"</code> creates a group called "mygroup"</p><p><code>create an optional group</code> creates an unnamed optional group</p></div></div></div></div><footer><div class="container"><div class="row"><div class="col-lg-8 col-md-10 mx-auto"><p class="copyright">Copyright &copy; 2020 Patrick Demian. This page's source code is available at <a rel="noopener noreferrer" href="https://github.com/pdemian/">github.com/pdemian/</a></p></div></div></div></footer></div><script defer="defer" src="bundle.min.js"></script></body></html> </textarea><h4>Errors:</h4><textarea readonly="readonly" class="form-control" id="errors" rows="5"></textarea></div><br><div class="col-lg-4 tenpx-margin-bottom"><div class="cheatsheet"><h2>Cheat Sheet:</h2><p>Full documentation available <a href="tutorial.html">here</a></p><p class="font-weight-bold">Matching</p><p><code class="cm-s-idea">match "hello world"</code> matches "hello world" exactly</p><p></p><p><code class="cm-s-idea">match "hello" then optionally " world"</code> matches "hello" or "hello world"</p><p><code class="cm-s-idea">match "hello" or "world"</code> matches "hello" or "world</p><p><code class="cm-s-idea">match a word</code> matches any word</p><p class="font-weight-bold">Repetition</p><p><code class="cm-s-idea">match 0+ "hello"</code> matches 0 or more "hello"s</p><p><code class="cm-s-idea">match 3 "hello"</code> matches exactly "hellohellohello"</p><p><code class="cm-s-idea">match 1 to 5 "hello"</code> matches between 1 to 5 "hello"s</p><p><code class="cm-s-idea">repeat 0 or more</code> repeats the intended text 0 or more times (default)</p><p><code class="cm-s-idea">optionally repeat between 3 to 5</code> optionally repeats the indented text 3 to 5 times</p><p class="font-weight-bold">Grouping</p><p><code class="cm-s-idea">create a group called "mygroup"</code> creates a group called "mygroup"</p><p><code class="cm-s-idea">create an optional group</code> creates an unnamed optional group</p></div></div></div></div><footer><div class="container"><div class="row"><div class="col-lg-8 col-md-10 mx-auto"><p class="copyright">Copyright &copy; 2020 Patrick Demian. This page's source code is available at <a rel="noopener noreferrer" href="https://github.com/pdemian/">github.com/pdemian/</a></p></div></div></div></footer></div><script defer="defer" src="bundle.min.js"></script></body></html>

View File

@ -1,6 +1,6 @@
{ {
"name": "human2regex", "name": "human2regex",
"version": "0.1.0", "version": "0.9.0",
"description": "Humanized Regular Expressions", "description": "Humanized Regular Expressions",
"main": "bundle.min.js", "main": "bundle.min.js",
"devDependencies": { "devDependencies": {

View File

@ -13,7 +13,7 @@ import { IToken } from "chevrotain";
*/ */
export enum RegexDialect { export enum RegexDialect {
JS, JS,
Perl, PCRE,
DotNet, DotNet,
Java Java
} }
@ -400,7 +400,7 @@ export class CountSubStatementCST extends H2RCST {
return this.opt === "+" ? "+" : "*"; return this.opt === "+" ? "+" : "*";
} }
else if (from === 0) { else if (from === 0) {
return this.opt === "+" ? "*" : ""; return this.opt === "+" ? "*" : "{0}";
} }
} }

View File

@ -7,88 +7,166 @@ import { RegexDialect } from "./generator";
import { CommonError, unusedParameter, usefulConditional } from "./utilities"; import { CommonError, unusedParameter, usefulConditional } from "./utilities";
import $ from "jquery"; import $ from "jquery";
import CodeMirror from "codemirror/lib/codemirror"; import CodeMirror from "codemirror/lib/codemirror";
import "codemirror/mode/javascript/javascript"; import "codemirror/addon/mode/simple";
import "codemirror/addon/runmode/runmode";
import "./webpage/bootstrap.css"; import "./webpage/bootstrap.css";
import "./webpage/cleanblog.css"; import "./webpage/cleanblog.css";
import "codemirror/lib/codemirror.css"; import "codemirror/lib/codemirror.css";
import "codemirror/theme/idea.css";
import "./webpage/style.css"; import "./webpage/style.css";
$(function() { $(function() {
const total_errors: CommonError[] = []; CodeMirror.defineSimpleMode("human2regex", {
start: [
{token: "number", regex: /zero/i},
{token: "number", regex: /one/i},
{token: "number", regex: /two/i},
{token: "number", regex: /three/i},
{token: "number", regex: /four/i},
{token: "number", regex: /five/i},
{token: "number", regex: /six/i},
{token: "number", regex: /seven/i},
{token: "number", regex: /eight/i},
{token: "number", regex: /nine/i},
{token: "number", regex: /ten/i},
{token: "qualifier", regex: /optional(ly)?/i},
{token: "builtin", regex: /matching/i},
{token: "keyword", regex: /match(es)?/i},
{token: "operator", regex: /then/i},
{token: "builtin", regex: /(any thing|any|anything)(s)?/i},
{token: "operator", regex: /or/i},
{token: "operator", regex: /and|,/i},
{token: "builtin", regex: /word(s)?/i},
{token: "builtin", regex: /digit(s)?/i},
{token: "builtin", regex: /character(s)?/i},
{token: "builtin", regex: /(white space|whitespace)(s)?/i},
{token: "builtin", regex: /number(s)?/i},
{token: "keyword", regex: /using/i},
{token: "builtin", regex: /global/i},
{token: "builtin", regex: /(multi line|multiline)/i},
{token: "builtin", regex: /exact/i},
{token: "operator", regex: /not/i},
{token: "operator", regex: /between/i},
{token: "builtin", regex: /tab/i},
{token: "builtin", regex: /(line feed|linefeed)/i},
{token: "keyword", regex: /group/i},
{token: "keyword", regex: /a(n)?/i},
{token: "keyword", regex: /times/i},
{token: "keyword", regex: /exact(ly)?/i},
{token: "keyword", regex: /inclusive(ly)?/i},
{token: "keyword", regex: /exclusive(ly)?/i},
{token: "keyword", regex: /from/i},
{token: "keyword", regex: /(to|through|thru|\-|\.\.|\.\.\.)/i},
{token: "keyword", regex: /create(s)?/i},
{token: "keyword", regex: /name(d)?|call(ed)?/i},
{token: "keyword", regex: /repeat(s|ing)?/i},
{token: "builtin", regex: /(new line|newline)/i},
{token: "builtin", regex: /carriage return/i},
{token: "builtin", regex: /case insensitive/i},
{token: "builtin", regex: /case sensitive/i},
{token: "operator", regex: /\+|or more/i},
{token: "variable", regex: /[a-z]\w*/i},
{token: "number", regex: /-?\d+/},
{token: "string", regex: /"(?:[^\\"]|\\(?:[bfnrtv"\\/]|u[0-9a-f]{4}|U[0-9a-f]{8}))*"/i},
{token: "comment", regex: /(#|\/\/).*/},
{token: "comment", regex: /\/\*/, next: "comment"}
],
comment: [
{regex: /.*?\*\//, token: "comment", next: "start"},
{regex: /.*/, token: "comment"}
],
meta: {
dontIndentStates: [ "comment" ],
lineComment: "//",
blockComment: [ "/*", "*/" ]
}
});
const $regex = $("#regex");
const $dialect = $("#dialect");
const $clip = $("#clip");
const $human = $("#human");
const $errors = $("#errors");
// We're not on index
if (!$regex.length || !$human.length) {
return;
}
const lexer = new Human2RegexLexer(new Human2RegexLexerOptions(true)); const lexer = new Human2RegexLexer(new Human2RegexLexerOptions(true));
const parser = new Human2RegexParser(new Human2RegexParserOptions(true)); const parser = new Human2RegexParser(new Human2RegexParserOptions(true));
const result = lexer.tokenize($("#human").text()); let regex_result: string = "";
let dialect = RegexDialect.JS;
result.errors.map(CommonError.fromLexError).forEach((x) => total_errors.push(x)); function mapDialect(value: string | string[] | number | undefined): RegexDialect {
switch (value) {
let regex_result = "";
if (total_errors.length === 0) {
parser.input = result.tokens;
const regex = parser.parse();
parser.errors.map(CommonError.fromParseError).forEach((x) => total_errors.push(x));
let lang: RegexDialect = RegexDialect.JS;
switch ($("#dialect option:selected").val()) {
case "dotnet": case "dotnet":
lang = RegexDialect.DotNet; return RegexDialect.DotNet;
break;
case "java": case "java":
lang = RegexDialect.Java; return RegexDialect.Java;
break; case "pcre":
case "perl": return RegexDialect.PCRE;
lang = RegexDialect.Perl;
break;
default: default:
lang = RegexDialect.JS; return RegexDialect.JS;
break;
}
const valid = regex.validate(lang);
valid.map(CommonError.fromSemanticError).forEach((x) => total_errors.push(x));
if (!usefulConditional(total_errors.length, "total_errors may have added an error")) {
regex_result = regex.toRegex(lang);
$("#regex").attr("value", regex_result);
} }
} }
$("#errors").empty();
for (const error of total_errors) { function runH2R(text: string): void {
$("#errors").append(`${error.toString()}\n`); $errors.empty();
$errors.append("Compiling...");
const total_errors: CommonError[] = [];
const result = lexer.tokenize(text);
result.errors.map(CommonError.fromLexError).forEach((x) => total_errors.push(x));
if (total_errors.length === 0) {
parser.input = result.tokens;
const regex = parser.parse();
parser.errors.map(CommonError.fromParseError).forEach((x) => total_errors.push(x));
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
if (total_errors.length === 0) {
const validate = regex.validate(dialect);
validate.map(CommonError.fromSemanticError).forEach((x) => total_errors.push(x));
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
if (total_errors.length === 0) {
regex_result = regex.toRegex(dialect);
$regex.attr("value", regex_result);
}
}
}
$errors.empty();
for (const error of total_errors) {
$errors.append(`${error.toString()}\n`);
}
} }
console.log("Errors = " + total_errors);
$("#dialect").on("selectionchanged", () => { $dialect.on("change", () => {
//do something dialect = mapDialect($("#dialect option:selected").val());
}); });
$("#human").on("input", () => { $clip.on("click", () => {
//do something // prefer to use writeText, but "emulate" selecting all, even though it isn't required
}); const text = $regex[0] as unknown as { select: () => void };
text.select();
$("#clip").on("click", () => {
if (window.isSecureContext && if (window.isSecureContext &&
usefulConditional(navigator.clipboard, "clipboard may be undefined") && usefulConditional(navigator.clipboard, "clipboard may be undefined") &&
usefulConditional(navigator.clipboard.writeText, "writeText may be undefined")) { usefulConditional(navigator.clipboard.writeText, "writeText may be undefined")) {
navigator.clipboard.writeText(regex_result); navigator.clipboard.writeText(regex_result);
} }
else { else {
const text = document.getElementById("regex") as any;
text.select();
text.setSelectionRange(0, 10*10*10*10);
document.execCommand("copy"); document.execCommand("copy");
} }
}); });
const editor = CodeMirror.fromTextArea(document.getElementById("human"), { const editor = CodeMirror.fromTextArea($human[0], {
mode: {name: "javascript"}, mode: {name: "human2regex"},
lineNumbers: false, lineNumbers: false,
indentUnit: 4, indentUnit: 4,
viewportMargin: Infinity viewportMargin: Infinity
@ -98,11 +176,13 @@ $(function() {
unusedParameter(instance, "Instance is not required, we have a reference already"); unusedParameter(instance, "Instance is not required, we have a reference already");
unusedParameter(change_obj, "Change is not required, we want the full value"); unusedParameter(change_obj, "Change is not required, we want the full value");
/* not empty */ runH2R(editor.getValue());
console.log(editor.getValue());
}); });
});
//run what's currently in the textarea to initialize
runH2R(editor.getValue());
for (const code of $("code")) {
CodeMirror.runMode(code.innerText, {name: "human2regex"}, code);
}
});

View File

@ -7,21 +7,21 @@
import { createToken, Lexer } from "chevrotain"; import { createToken, Lexer } from "chevrotain";
/** @internal */ export const Zero = createToken({name: "Zero", pattern: /zero/i }); /** @internal */ export const Zero = createToken({name: "Zero", pattern: /zero/i});
/** @internal */ export const One = createToken({name: "One", pattern: /one/i }); /** @internal */ export const One = createToken({name: "One", pattern: /one/i});
/** @internal */ export const Two = createToken({name: "Two", pattern: /two/i }); /** @internal */ export const Two = createToken({name: "Two", pattern: /two/i});
/** @internal */ export const Three = createToken({name: "Three", pattern: /three/i }); /** @internal */ export const Three = createToken({name: "Three", pattern: /three/i});
/** @internal */ export const Four = createToken({name: "Four", pattern: /four/i }); /** @internal */ export const Four = createToken({name: "Four", pattern: /four/i});
/** @internal */ export const Five = createToken({name: "Five", pattern: /five/i }); /** @internal */ export const Five = createToken({name: "Five", pattern: /five/i});
/** @internal */ export const Six = createToken({name: "Six", pattern: /six/i }); /** @internal */ export const Six = createToken({name: "Six", pattern: /six/i});
/** @internal */ export const Seven = createToken({name: "Seven", pattern: /seven/i }); /** @internal */ export const Seven = createToken({name: "Seven", pattern: /seven/i});
/** @internal */ export const Eight = createToken({name: "Eight", pattern: /eight/i }); /** @internal */ export const Eight = createToken({name: "Eight", pattern: /eight/i});
/** @internal */ export const Nine = createToken({name: "Nine", pattern: /nine/i }); /** @internal */ export const Nine = createToken({name: "Nine", pattern: /nine/i});
/** @internal */ export const Ten = createToken({name: "Ten", pattern: /ten/i }); /** @internal */ export const Ten = createToken({name: "Ten", pattern: /ten/i});
/** @internal */ export const Optional = createToken({name: "Optional", pattern: /optional(ly)?/i }); /** @internal */ export const Optional = createToken({name: "Optional", pattern: /optional(ly)?/i});
/** @internal */ export const Match = createToken({name: "Match", pattern: /match(es)?/i }); /** @internal */ export const Match = createToken({name: "Match", pattern: /match(es)?/i});
/** @internal */ export const Then = createToken({name: "Then", pattern: /then/i }); /** @internal */ export const Then = createToken({name: "Then", pattern: /then/i});
/** @internal */ export const Anything = createToken({name: "Anything", pattern: /(any thing|any|anything)(s)?/i}); /** @internal */ export const Anything = createToken({name: "Anything", pattern: /(any thing|any|anything)(s)?/i});
/** @internal */ export const Or = createToken({name: "Or", pattern: /or/i}); /** @internal */ export const Or = createToken({name: "Or", pattern: /or/i});
/** @internal */ export const And = createToken({name: "And", pattern: /and|,/i}); /** @internal */ export const And = createToken({name: "And", pattern: /and|,/i});
@ -35,13 +35,13 @@ import { createToken, Lexer } from "chevrotain";
/** @internal */ export const Multiline = createToken({name: "Multiline", pattern: /(multi line|multiline)/i}); /** @internal */ export const Multiline = createToken({name: "Multiline", pattern: /(multi line|multiline)/i});
/** @internal */ export const Exact = createToken({name: "Exact", pattern: /exact/i}); /** @internal */ export const Exact = createToken({name: "Exact", pattern: /exact/i});
/** @internal */ export const Matching = createToken({name: "Matching", pattern: /matching/i}); /** @internal */ export const Matching = createToken({name: "Matching", pattern: /matching/i});
/** @internal */ export const Not = createToken({name: "Not", pattern: /not/i }); //, longer_alt: Nothing}); /** @internal */ export const Not = createToken({name: "Not", pattern: /not/i}); //, longer_alt: Nothing});
/** @internal */ export const Between = createToken({name: "Between", pattern: /between/i}); /** @internal */ export const Between = createToken({name: "Between", pattern: /between/i});
/** @internal */ export const Tab = createToken({name: "Tab", pattern: /tab/i}); /** @internal */ export const Tab = createToken({name: "Tab", pattern: /tab/i});
/** @internal */ export const Linefeed = createToken({name: "Linefeed", pattern: /(line feed|linefeed)/i}); /** @internal */ export const Linefeed = createToken({name: "Linefeed", pattern: /(line feed|linefeed)/i});
/** @internal */ export const Group = createToken({name: "Group", pattern: /group/i}); /** @internal */ export const Group = createToken({name: "Group", pattern: /group/i});
/** @internal */ export const A = createToken({name: "A", pattern: /a(n)?/i }); //, longer_alt: Anything}); /** @internal */ export const A = createToken({name: "A", pattern: /a(n)?/i }); //, longer_alt: Anything});
/** @internal */ export const Times = createToken({name: "Times", pattern: /times/i }); /** @internal */ export const Times = createToken({name: "Times", pattern: /times/i});
/** @internal */ export const Exactly = createToken({name: "Exactly", pattern: /exact(ly)?/i}); /** @internal */ export const Exactly = createToken({name: "Exactly", pattern: /exact(ly)?/i});
/** @internal */ export const Inclusive = createToken({name: "Inclusive", pattern: /inclusive(ly)?/i}); /** @internal */ export const Inclusive = createToken({name: "Inclusive", pattern: /inclusive(ly)?/i});
/** @internal */ export const Exclusive = createToken({name: "Exclusive", pattern: /exclusive(ly)?/i}); /** @internal */ export const Exclusive = createToken({name: "Exclusive", pattern: /exclusive(ly)?/i});
@ -54,7 +54,7 @@ import { createToken, Lexer } from "chevrotain";
/** @internal */ export const CarriageReturn = createToken({name: "CarriageReturn", pattern: /carriage return/i}); /** @internal */ export const CarriageReturn = createToken({name: "CarriageReturn", pattern: /carriage return/i});
/** @internal */ export const CaseInsensitive = createToken({name: "CaseInsensitive", pattern: /case insensitive/i}); /** @internal */ export const CaseInsensitive = createToken({name: "CaseInsensitive", pattern: /case insensitive/i});
/** @internal */ export const CaseSensitive = createToken({name: "CaseSensitive", pattern: /case sensitive/i}); /** @internal */ export const CaseSensitive = createToken({name: "CaseSensitive", pattern: /case sensitive/i});
/** @internal */ export const OrMore = createToken({name: "OrMore", pattern: /\+|or more/i }); /** @internal */ export const OrMore = createToken({name: "OrMore", pattern: /\+|or more/i});
/* /*
//Not being used currently //Not being used currently
@ -77,14 +77,14 @@ export const By = createToken({name: "By", pattern: /by/i});
*/ */
/** @internal */ export const EndOfLine = createToken({name: "EOL", pattern: /\n/ }); /** @internal */ export const EndOfLine = createToken({name: "EOL", pattern: /\n/});
/** @internal */ export const WS = createToken({name: "Whitespace", pattern: /\s+/, group: Lexer.SKIPPED }); /** @internal */ export const WS = createToken({name: "Whitespace", pattern: /[^\S\n]+/, start_chars_hint: [ " ", "\r" ], group: Lexer.SKIPPED});
/** @internal */ export const SingleLineComment = createToken({name: "SingleLineComment", pattern: /(#|\/\/).*/, group: Lexer.SKIPPED }); /** @internal */ export const SingleLineComment = createToken({name: "SingleLineComment", pattern: /(#|\/\/).*/, group: Lexer.SKIPPED});
/** @internal */ export const MultilineComment = createToken({name: "MultiLineComment", pattern: /\/\*(.*)\*\//, line_breaks: true, group: Lexer.SKIPPED }); /** @internal */ export const MultilineComment = createToken({name: "MultiLineComment", pattern: /\/\*(.*)\*\//, line_breaks: true, group: Lexer.SKIPPED});
/** @internal */ export const Identifier = createToken({name: "Identifier", pattern: /[a-z]\w*/i }); /** @internal */ export const Identifier = createToken({name: "Identifier", pattern: /[a-z]\w*/i});
/** @internal */ export const NumberLiteral = createToken({name: "NumberLiteral", pattern: /-?\d+/ }); /** @internal */ export const NumberLiteral = createToken({name: "NumberLiteral", pattern: /-?\d+/});
/** @internal */ export const StringLiteral = createToken({name: "StringLiteral", pattern: /"(?:[^\\"]|\\(?:[bfnrtv"\\/]|u[0-9a-f]{4}|U[0-9a-f]{8}))*"/i }); /** @internal */ export const StringLiteral = createToken({name: "StringLiteral", pattern: /"(?:[^\\"]|\\(?:[bfnrtv"\\/]|u[0-9a-f]{4}|U[0-9a-f]{8}))*"/i});
/** @internal */ export const Indent = createToken({name: "Indent"}); /** @internal */ export const Indent = createToken({name: "Indent"});
/** @internal */ export const Outdent = createToken({name: "Outdent"}); /** @internal */ export const Outdent = createToken({name: "Outdent"});

View File

@ -10,22 +10,22 @@
<option value="js" selected>Javascript</option> <option value="js" selected>Javascript</option>
<option value="dotnet">.NET</option> <option value="dotnet">.NET</option>
<option value="java">Java</option> <option value="java">Java</option>
<option value="perl">Perl</option> <option value="pcre">PCRE</option>
</select> </select>
</div> </div>
</div> </div>
<h4>Your Regular Expression:</h4> <h4>Your Regular Expression:</h4>
<div class="row"> <div class="row">
<div class="col-xl-11"> <div class="col-xl-11 tenpx-margin-bottom">
<input readonly type="text" class="form-control" id="regex"></input> <input readonly type="text" class="form-control" id="regex"></input>
</div> </div>
<div class="col-xl-1"> <div class="col-xl-1">
<button type="button" class="btn btn-secondary" id="clip">Copy</button> <button type="button" class="btn btn-secondary float-right" id="clip">Copy</button>
</div> </div>
</div> </div>
<h4>Human Speak:</h4> <h4>Human Speak:</h4>
<textarea class="form-control" id="human" rows="25"> <textarea class="form-control cm-s-idea" id="human" rows="25">
// H2R supports // # and /**/ as comments // H2R supports // # and /**/ as comments
// A group is only captured if given a name. // A group is only captured if given a name.
// You can use "and", "or", "not" to specify "[]" regex // You can use "and", "or", "not" to specify "[]" regex
@ -74,19 +74,19 @@ create an optional group
<h2>Cheat Sheet:</h2> <h2>Cheat Sheet:</h2>
<p>Full documentation available <a href="tutorial.html">here</a></p> <p>Full documentation available <a href="tutorial.html">here</a></p>
<p class="font-weight-bold">Matching</p> <p class="font-weight-bold">Matching</p>
<p><code>match "hello world"</code> matches "hello world" exactly<p> <p><code class="cm-s-idea">match "hello world"</code> matches "hello world" exactly<p>
<p><code>match "hello" then optionally " world"</code> matches "hello" or "hello world"</p> <p><code class="cm-s-idea">match "hello" then optionally " world"</code> matches "hello" or "hello world"</p>
<p><code>match "hello" or "world"</code> matches "hello" or "world</p> <p><code class="cm-s-idea">match "hello" or "world"</code> matches "hello" or "world</p>
<p><code>match a word</code> matches any word <p><code class="cm-s-idea">match a word</code> matches any word
<p class="font-weight-bold">Repetition</p> <p class="font-weight-bold">Repetition</p>
<p><code>match 0+ "hello"</code> matches 0 or more "hello"s</p> <p><code class="cm-s-idea">match 0+ "hello"</code> matches 0 or more "hello"s</p>
<p><code>match 3 "hello"</code> matches exactly "hellohellohello"</p> <p><code class="cm-s-idea">match 3 "hello"</code> matches exactly "hellohellohello"</p>
<p><code>match 1 to 5 "hello"</code> matches between 1 to 5 "hello"s</p> <p><code class="cm-s-idea">match 1 to 5 "hello"</code> matches between 1 to 5 "hello"s</p>
<p><code>repeat 0 or more</code> repeats the intended text 0 or more times (default)</p> <p><code class="cm-s-idea">repeat 0 or more</code> repeats the intended text 0 or more times (default)</p>
<p><code>optionally repeat between 3 to 5</code> optionally repeats the indented text 3 to 5 times</p> <p><code class="cm-s-idea">optionally repeat between 3 to 5</code> optionally repeats the indented text 3 to 5 times</p>
<p class="font-weight-bold">Grouping</p> <p class="font-weight-bold">Grouping</p>
<p><code>create a group called "mygroup"</code> creates a group called "mygroup"</p> <p><code class="cm-s-idea">create a group called "mygroup"</code> creates a group called "mygroup"</p>
<p><code>create an optional group</code> creates an unnamed optional group</p> <p><code class="cm-s-idea">create an optional group</code> creates an unnamed optional group</p>
</div> </div>
</div> </div>
</div> </div>

View File

@ -122,4 +122,8 @@ a:hover {
outline: 0; outline: 0;
box-shadow: 0 0 0.2rem rgba(102, 175, 233, .6); box-shadow: 0 0 0.2rem rgba(102, 175, 233, .6);
transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s; transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;
}
code {
font-style: italic!important;
} }