mirror of
https://github.com/pdemian/human2regex.git
synced 2025-05-16 04:20:35 -07:00
Added lib path, reorganized, began working on tutorial proper
This commit is contained in:
parent
298aee7226
commit
7f516ec33b
13
.npmignore
Normal file
13
.npmignore
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
# Node build artifacts
|
||||||
|
node_modules/
|
||||||
|
coverage/
|
||||||
|
npm-debug.log
|
||||||
|
docs/
|
||||||
|
src/
|
||||||
|
tests/
|
||||||
|
jest.config.ts
|
||||||
|
webpack.config.js
|
||||||
|
tsconfig.json
|
||||||
|
.gitignore
|
||||||
|
.travis.yml
|
||||||
|
.eslintrc.json
|
14
.travis.yml
Normal file
14
.travis.yml
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
language: node_js
|
||||||
|
|
||||||
|
node_js:
|
||||||
|
- "node"
|
||||||
|
|
||||||
|
before_script:
|
||||||
|
- npm install
|
||||||
|
- npm run build
|
||||||
|
|
||||||
|
script:
|
||||||
|
- npm t
|
||||||
|
|
||||||
|
after_success:
|
||||||
|
- npm run extract
|
152
API.md
Normal file
152
API.md
Normal file
@ -0,0 +1,152 @@
|
|||||||
|
# Tutorial
|
||||||
|
|
||||||
|
## Preface
|
||||||
|
|
||||||
|
Human2Regex (H2R) comes with a simple API allowing you to embed the H2R language inside your application.
|
||||||
|
The steps to generate a regular expression go as follows
|
||||||
|
- Lex the input text (detects lexing errors)
|
||||||
|
- Parse the input text (detects parsing errors)
|
||||||
|
- Generate/interpret the input text (detects semantic errors)
|
||||||
|
|
||||||
|
## Lexing your text
|
||||||
|
|
||||||
|
H2R's lexer comes with a few options for stricter parsing and some performance optimizations
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
export declare class Human2RegexLexerOptions {
|
||||||
|
// If true, the lexer will skip validations (~25% faster)
|
||||||
|
skip_validations?: boolean = false;
|
||||||
|
// The type of indents the lexer will allow
|
||||||
|
type?: IndentType = IndentType.Both;
|
||||||
|
// Number of spaces per tab
|
||||||
|
spaces_per_tab?: number = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
export declare enum IndentType {
|
||||||
|
Tabs = 0,
|
||||||
|
Spaces = 1,
|
||||||
|
Both = 2
|
||||||
|
}
|
||||||
|
```
|
||||||
|
Once your options are determined, you can instanciate a lexer like so:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import { Human2RegexLexer, Human2RegexLexerOptions } from "./lexer";
|
||||||
|
const lexer = new Human2RegexLexer(new Human2RegexLexerOptions(true));
|
||||||
|
```
|
||||||
|
|
||||||
|
Due to a technical limitation as well as just for performance reasons, only 1 instance of `Human2RegexLexer` is allowed.
|
||||||
|
|
||||||
|
To use the lexer, call tokenize on your input text:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
const lex_result = lexer.tokenize("<your text here>");
|
||||||
|
```
|
||||||
|
|
||||||
|
This returns an ILexingResult which is passed on to the parser.
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
export interface ILexingResult {
|
||||||
|
// tokens parsed
|
||||||
|
tokens: IToken[];
|
||||||
|
// errors found
|
||||||
|
errors: ILexingError[];
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
To determine if the lex occured successfully, check to see if `lex_result.errors` contains any elements. If so you can extract the errors by converting them to `CommonError` and calling the `toString()` function
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import { CommonError } from "./utilities";
|
||||||
|
result.errors.map(CommonError.fromLexError).forEach((x) => console.log(x.toString()));
|
||||||
|
```
|
||||||
|
|
||||||
|
You may also use the `CommonError` itself if you wish to incorporate it into a text editor
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
export declare class CommonError {
|
||||||
|
// Type of error (Lexer, Parser, Semantic)
|
||||||
|
type: string;
|
||||||
|
|
||||||
|
// position of error
|
||||||
|
start_line: number;
|
||||||
|
start_column: number;
|
||||||
|
length: number;
|
||||||
|
|
||||||
|
//textual message
|
||||||
|
message: string;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
You can reuse the lexer by calling `tokenize()` again.
|
||||||
|
|
||||||
|
## Parsing the tokens
|
||||||
|
|
||||||
|
H2R's parser comes only with a performance optimization
|
||||||
|
```typescript
|
||||||
|
export declare class Human2RegexParserOptions {
|
||||||
|
// If true, the lexer will skip validations (~25% faster)
|
||||||
|
skip_validations?: boolean = true;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Once your options are determined, you can instanciate a lexer like so:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import { Human2RegexParser, Human2RegexParserOptions } from "./parser";
|
||||||
|
const parser = new Human2RegexParser(new Human2RegexParserOptions(true));
|
||||||
|
```
|
||||||
|
|
||||||
|
Due to a technical limitation as well as just for performance reasons, only 1 instance of `Human2RegexParser` is allowed.
|
||||||
|
|
||||||
|
To use it, call the parser with your tokens from the lexer:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
parser.input = lex_result.tokens;
|
||||||
|
const parse_result = parser.parse();
|
||||||
|
```
|
||||||
|
|
||||||
|
The parser's errors are found via `parser.errors` and again can be checked to see if the parse was successful by checking the length of this list. If it contains any errors, you can extract the errors by converting them to `CommonError` and calling the `toString()` function
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
parser.errors.map(CommonError.fromParseError).forEach((x) => console.log(x.toString()));
|
||||||
|
```
|
||||||
|
|
||||||
|
The parser contains state and so to re-use it, it must be reset by inputting (new) tokens to reset it
|
||||||
|
```typescript
|
||||||
|
parser.input = lex_result.tokens;
|
||||||
|
```
|
||||||
|
|
||||||
|
## Generating your regex
|
||||||
|
Assuming no errors were found, now it's time to generate the regular expression
|
||||||
|
|
||||||
|
H2R supports a few languages so far:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
export enum RegexDialect {
|
||||||
|
JS,
|
||||||
|
PCRE,
|
||||||
|
DotNet,
|
||||||
|
Java
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
After choosing one, you must validate the regular expression. This may be skipped if and only if the input has already been validated before as the generator is not guaranteed to work unless there are no errors.
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
const validation_errors = parse_result.validate();
|
||||||
|
```
|
||||||
|
|
||||||
|
The result is a list of errors which, again, may be converted to a `CommonError` to extract information from it.
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
validation_errors.map(CommonError.fromParseError).forEach((x) => console.log(x.toString()));
|
||||||
|
```
|
||||||
|
|
||||||
|
If there are no errors, you can call the `toRegex()` function to create a string representation of the regular expression. You can then convert that to a `RegExp` object for regex matching.
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
const my_regex = new RegExp(parse_result.toRegex());
|
||||||
|
```
|
||||||
|
|
||||||
|
This will contain your regular expression.
|
12
Readme.md
12
Readme.md
@ -1,5 +1,4 @@
|
|||||||
# Human2Regex
|
# Human2Regex
|
||||||
|
|
||||||
## Purpose
|
## Purpose
|
||||||
|
|
||||||
Generate regular expressions from natural language.
|
Generate regular expressions from natural language.
|
||||||
@ -66,6 +65,14 @@ Running the program should result in the following output:
|
|||||||
|
|
||||||
Which one would you rather debug?
|
Which one would you rather debug?
|
||||||
|
|
||||||
|
## Webpage
|
||||||
|
Human2Regex is hosted on github pages at [https://pdemian.github.io/human2regex/](https://pdemian.github.io/human2regex/)
|
||||||
|
|
||||||
|
## API
|
||||||
|
Human2Regex is available as an embeddable API.
|
||||||
|
|
||||||
|
The API reference is available [here](API.md)
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
Build
|
Build
|
||||||
|
|
||||||
@ -81,5 +88,6 @@ Test
|
|||||||
|
|
||||||
|
|
||||||
## Todo
|
## Todo
|
||||||
- Seperate website and source code. Move to yarn/npm
|
- Return CommonError rather than requiring the user to convert to a CommonError
|
||||||
|
- Move to yarn/npm
|
||||||
- Add more regex options such as back references, subroutines, lookahead/behind, and more character classes (eg, `[:alpha:]`)
|
- Add more regex options such as back references, subroutines, lookahead/behind, and more character classes (eg, `[:alpha:]`)
|
5
docs/bundle.min.css
vendored
5
docs/bundle.min.css
vendored
File diff suppressed because one or more lines are too long
4
docs/bundle.min.js
vendored
4
docs/bundle.min.js
vendored
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
282
lib/generator.d.ts
vendored
Normal file
282
lib/generator.d.ts
vendored
Normal file
@ -0,0 +1,282 @@
|
|||||||
|
/*! Copyright (c) 2020 Patrick Demian; Licensed under MIT */
|
||||||
|
import { IToken } from "chevrotain";
|
||||||
|
/**
|
||||||
|
* List of regular expression dialects we support
|
||||||
|
*/
|
||||||
|
export declare enum RegexDialect {
|
||||||
|
JS = 0,
|
||||||
|
PCRE = 1,
|
||||||
|
DotNet = 2,
|
||||||
|
Java = 3
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Interface for all semantic errors
|
||||||
|
*/
|
||||||
|
export interface ISemanticError {
|
||||||
|
startLine: number;
|
||||||
|
startColumn: number;
|
||||||
|
length: number;
|
||||||
|
message: string;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* The base concrete syntax tree class
|
||||||
|
*
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
export declare abstract class H2RCST {
|
||||||
|
tokens: IToken[];
|
||||||
|
/**
|
||||||
|
* Constructor for H2RCST
|
||||||
|
*
|
||||||
|
* @param tokens Tokens used to calculate where an error occured
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
constructor(tokens: IToken[]);
|
||||||
|
/**
|
||||||
|
* Validate that this is both valid and can be generated in the specified language
|
||||||
|
*
|
||||||
|
* @remarks There is no guarantee toRegex will work unless validate returns no errors
|
||||||
|
*
|
||||||
|
* @param language the regex dialect we're validating
|
||||||
|
* @returns A list of errors
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
abstract validate(language: RegexDialect): ISemanticError[];
|
||||||
|
/**
|
||||||
|
* Generate a regular expression fragment based on this syntax tree
|
||||||
|
*
|
||||||
|
* @remarks There is no guarantee toRegex will work unless validate returns no errors
|
||||||
|
*
|
||||||
|
* @param language the regex dialect we're generating
|
||||||
|
* @returns a regular expression fragment
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
abstract toRegex(language: RegexDialect): string;
|
||||||
|
/**
|
||||||
|
* Creates an ISemanticError with a given message and the tokens provided from the constructor
|
||||||
|
*
|
||||||
|
* @param message the message
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
protected error(message: string): ISemanticError;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Flags for the using statement
|
||||||
|
*
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
export declare enum UsingFlags {
|
||||||
|
Multiline,
|
||||||
|
Global,
|
||||||
|
Sensitive,
|
||||||
|
Insensitive,
|
||||||
|
Exact
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Type of match arguments
|
||||||
|
*
|
||||||
|
* @remarks SingleString means an escaped string
|
||||||
|
* @remarks Between means a range (ex. a-z)
|
||||||
|
* @remarks Anything means .
|
||||||
|
* @remarks Word, Digit, Character, Whitespace, Number, Tab, Linefeed, Newline, and Carriage return are \w+, \d, \w, \s, \d+, \t, \n, \n, \r respectively
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
export declare enum MatchSubStatementType {
|
||||||
|
SingleString = 0,
|
||||||
|
Between = 1,
|
||||||
|
Anything = 2,
|
||||||
|
Word = 3,
|
||||||
|
Digit = 4,
|
||||||
|
Character = 5,
|
||||||
|
Whitespace = 6,
|
||||||
|
Number = 7,
|
||||||
|
Tab = 8,
|
||||||
|
Linefeed = 9,
|
||||||
|
Newline = 10,
|
||||||
|
CarriageReturn = 11,
|
||||||
|
Boundary = 12,
|
||||||
|
Unicode = 13
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Container for match statements
|
||||||
|
*
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
export declare class MatchSubStatementValue {
|
||||||
|
type: MatchSubStatementType;
|
||||||
|
from: string | null;
|
||||||
|
to: string | null;
|
||||||
|
/**
|
||||||
|
* Constructor for MatchSubStatementValue
|
||||||
|
*
|
||||||
|
* @param type the type of this match
|
||||||
|
* @param from optional value or range string
|
||||||
|
* @param to optional range string
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
constructor(type: MatchSubStatementType, from?: string | null, to?: string | null);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Container for MatchStatementValue
|
||||||
|
*
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
export declare class MatchStatementValue {
|
||||||
|
optional: boolean;
|
||||||
|
statement: MatchSubStatementCST;
|
||||||
|
/**
|
||||||
|
* Constructor for MatchStatementValue
|
||||||
|
*
|
||||||
|
* @param optional is this match optional
|
||||||
|
* @param statement the substatement to generate
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
constructor(optional: boolean, statement: MatchSubStatementCST);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* The base class for all statement concrete syntax trees
|
||||||
|
*
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
export declare abstract class StatementCST extends H2RCST {
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Concrete Syntax Tree for Match Sub statements
|
||||||
|
*
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
export declare class MatchSubStatementCST extends H2RCST {
|
||||||
|
private count;
|
||||||
|
private invert;
|
||||||
|
private values;
|
||||||
|
/**
|
||||||
|
* Constructor for MatchSubStatementCST
|
||||||
|
*
|
||||||
|
* @param tokens Tokens used to calculate where an error occured
|
||||||
|
* @param count optional count statement
|
||||||
|
* @param invert is this match inverted (ex, [^a-z] or [a-z])
|
||||||
|
* @param values sub statements to match
|
||||||
|
*/
|
||||||
|
constructor(tokens: IToken[], count: CountSubStatementCST | null, invert: boolean, values: MatchSubStatementValue[]);
|
||||||
|
validate(language: RegexDialect): ISemanticError[];
|
||||||
|
toRegex(language: RegexDialect): string;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Concrete Syntax Tree for Using statements
|
||||||
|
*
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
export declare class UsingStatementCST extends H2RCST {
|
||||||
|
private flags;
|
||||||
|
/**
|
||||||
|
* Constructor for UsingStatementCST
|
||||||
|
*
|
||||||
|
* @param tokens Tokens used to calculate where an error occured
|
||||||
|
* @param flags using flags
|
||||||
|
*/
|
||||||
|
constructor(tokens: IToken[], flags: UsingFlags[]);
|
||||||
|
validate(language: RegexDialect): ISemanticError[];
|
||||||
|
toRegex(language: RegexDialect): string;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Concrete Syntax Tree for Count sub statements
|
||||||
|
*
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
export declare class CountSubStatementCST extends H2RCST {
|
||||||
|
private from;
|
||||||
|
private to;
|
||||||
|
private opt;
|
||||||
|
/**
|
||||||
|
* Constructor for CountSubStatementCST
|
||||||
|
*
|
||||||
|
* @param tokens Tokens used to calculate where an error occured
|
||||||
|
* @param from number to count from
|
||||||
|
* @param to optional number to count to
|
||||||
|
* @param opt option modifier
|
||||||
|
*/
|
||||||
|
constructor(tokens: IToken[], from: number, to?: number | null, opt?: "inclusive" | "exclusive" | "+" | null);
|
||||||
|
validate(language: RegexDialect): ISemanticError[];
|
||||||
|
toRegex(language: RegexDialect): string;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Concrete Syntax Tree for a Match statement
|
||||||
|
*
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
export declare class MatchStatementCST extends StatementCST {
|
||||||
|
private matches;
|
||||||
|
/**
|
||||||
|
* Constructor for MatchStatementCST
|
||||||
|
*
|
||||||
|
* @param tokens Tokens used to calculate where an error occured
|
||||||
|
* @param matches
|
||||||
|
*/
|
||||||
|
constructor(tokens: IToken[], matches: MatchStatementValue[]);
|
||||||
|
validate(language: RegexDialect): ISemanticError[];
|
||||||
|
toRegex(language: RegexDialect): string;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Concrete Syntax Tree for a Repeat statement
|
||||||
|
*
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
export declare class RepeatStatementCST extends StatementCST {
|
||||||
|
private optional;
|
||||||
|
private count;
|
||||||
|
private statements;
|
||||||
|
/**
|
||||||
|
* Constructor for RepeatStatementCST
|
||||||
|
*
|
||||||
|
* @param tokens Tokens used to calculate where an error occured
|
||||||
|
* @param optional is this repetition optional
|
||||||
|
* @param count optional number of times to repeat
|
||||||
|
* @param statements the statements to repeat
|
||||||
|
*/
|
||||||
|
constructor(tokens: IToken[], optional: boolean, count: CountSubStatementCST | null, statements: StatementCST[]);
|
||||||
|
validate(language: RegexDialect): ISemanticError[];
|
||||||
|
toRegex(language: RegexDialect): string;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Conrete Syntax Tree for a group Statement
|
||||||
|
*
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
export declare class GroupStatementCST extends StatementCST {
|
||||||
|
private optional;
|
||||||
|
private name;
|
||||||
|
private statements;
|
||||||
|
/**
|
||||||
|
* Constructor for GroupStatementCST
|
||||||
|
*
|
||||||
|
* @param tokens Tokens used to calculate where an error occured
|
||||||
|
* @param optional is this group optional
|
||||||
|
* @param name optional name for named group
|
||||||
|
* @param statements other statements
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
constructor(tokens: IToken[], optional: boolean, name: string | null, statements: StatementCST[]);
|
||||||
|
validate(language: RegexDialect): ISemanticError[];
|
||||||
|
toRegex(language: RegexDialect): string;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Concrete Syntax Tree for a regular expression
|
||||||
|
*
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
export declare class RegularExpressionCST extends H2RCST {
|
||||||
|
private usings;
|
||||||
|
private statements;
|
||||||
|
/**
|
||||||
|
* Constructor for RegularExpressionCST
|
||||||
|
*
|
||||||
|
* @param tokens Tokens used to calculate where an error occured
|
||||||
|
* @param usings using statements
|
||||||
|
* @param statements other statements
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
constructor(tokens: IToken[], usings: UsingStatementCST, statements: StatementCST[]);
|
||||||
|
validate(language: RegexDialect): ISemanticError[];
|
||||||
|
toRegex(language: RegexDialect): string;
|
||||||
|
}
|
||||||
|
//# sourceMappingURL=generator.d.ts.map
|
1
lib/generator.d.ts.map
Normal file
1
lib/generator.d.ts.map
Normal file
@ -0,0 +1 @@
|
|||||||
|
{"version":3,"file":"generator.d.ts","sourceRoot":"","sources":["../src/generator.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAQ5D,OAAO,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AAEpC;;GAEG;AACH,oBAAY,YAAY;IACpB,EAAE,IAAA;IACF,IAAI,IAAA;IACJ,MAAM,IAAA;IACN,IAAI,IAAA;CACP;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC3B,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAA;CAClB;AAoCD;;;;GAIG;AACH,8BAAsB,MAAM;IAOL,MAAM,EAAE,MAAM,EAAE;IANnC;;;;;OAKG;gBACgB,MAAM,EAAE,MAAM,EAAE;IAInC;;;;;;;;OAQG;aACa,QAAQ,CAAC,QAAQ,EAAE,YAAY,GAAG,cAAc,EAAE;IAElE;;;;;;;;OAQG;aACa,OAAO,CAAC,QAAQ,EAAE,YAAY,GAAG,MAAM;IAEvD;;;;;OAKG;IACH,SAAS,CAAC,KAAK,CAAC,OAAO,EAAE,MAAM,GAAG,cAAc;CAWnD;AAED;;;;GAIG;AACH,oBAAY,UAAU;IAClB,SAAuB;IACvB,MAAoB;IACpB,SAAuB;IACvB,WAAyB;IACzB,KAAmB;CACtB;AAED;;;;;;;;GAQG;AACH,oBAAY,qBAAqB;IAC7B,YAAY,IAAA;IACZ,OAAO,IAAA;IACP,QAAQ,IAAA;IACR,IAAI,IAAA;IACJ,KAAK,IAAA;IACL,SAAS,IAAA;IACT,UAAU,IAAA;IACV,MAAM,IAAA;IACN,GAAG,IAAA;IACH,QAAQ,IAAA;IACR,OAAO,KAAA;IACP,cAAc,KAAA;IACd,QAAQ,KAAA;IACR,OAAO,KAAA;CACV;AAED;;;;GAIG;AACH,qBAAa,sBAAsB;IAUZ,IAAI,EAAE,qBAAqB;IAAS,IAAI,EAAE,MAAM,GAAG,IAAI;IAAgB,EAAE,EAAE,MAAM,GAAG,IAAI;IAR3G;;;;;;;OAOG;gBACgB,IAAI,EAAE,qBAAqB,EAAS,IAAI,GAAE,MAAM,GAAG,IAAW,EAAS,EAAE,GAAE,MAAM,GAAG,IAAW;CAGrH;AAED;;;;GAIG;AACH,qBAAa,mBAAmB;IAST,QAAQ,EAAE,OAAO;IAAS,SAAS,EAAE,oBAAoB;IAP5E;;;;;;OAMG;gBACgB,QAAQ,EAAE,OAAO,EAAS,SAAS,EAAE,oBAAoB;CAG/E;AAED;;;;GAIG;AACH,8BAAsB,YAAa,SAAQ,MAAM;CAChD;AAED;;;;GAIG;AACH,qBAAa,oBAAqB,SAAQ,MAAM;IAUd,OAAO,CAAC,KAAK;IAA+B,OAAO,CAAC,MAAM;IAAmB,OAAO,CAAC,MAAM;IARzH;;;;;;;OAOG;gBACS,MAAM,EAAE,MAAM,EAAE,EAAU,KAAK,EAAE,oBAAoB,GAAG,IAAI,EAAU,MAAM,EAAE,OAAe,EAAU,MAAM,EAAE,sBAAsB,EAAE;IAI5I,QAAQ,CAAC,QAAQ,EAAE,YAAY,GAAG,cAAc,EAAE;IAwDlD,OAAO,CAAC,QAAQ,EAAE,YAAY,GAAG,MAAM;CA2GjD;AAED;;;;GAIG;AACH,qBAAa,iBAAkB,SAAQ,MAAM;IAQX,OAAO,CAAC,KAAK;IAN3C;;;;;OAKG;gBACS,MAAM,EAAE,MAAM,EAAE,EAAU,KAAK,EAAE,UAAU,EAAE;IAIlD,QAAQ,CAAC,QAAQ,EAAE,YAAY,GAAG,cAAc,EAAE;IAoBlD,OAAO,CAAC,QAAQ,EAAE,YAAY,GAAG,MAAM;CAuBjD;AAED;;;;GAIG;AACH,qBAAa,oBAAqB,SAAQ,MAAM;IASd,OAAO,CAAC,IAAI;IAAU,OAAO,CAAC,EAAE;IAAwB,OAAO,CAAC,GAAG;IARjG;;;;;;;OAOG;gBACS,MAAM,EAAE,MAAM,EAAE,EAAU,IAAI,EAAE,MAAM,EAAU,EAAE,GAAE,MAAM,GAAG,IAAW,EAAU,GAAG,GAAE,WAAW,GAAG,WAAW,GAAG,GAAG,GAAG,IAAW;IAIzI,QAAQ,CAAC,QAAQ,EAAE,YAAY,GAAG,cAAc,EAAE;IAelD,OAAO,CAAC,QAAQ,EAAE,YAAY,GAAG,MAAM;CA8BjD;AAED;;;;GAIG;AACH,qBAAa,iBAAkB,SAAQ,YAAY;IAQjB,OAAO,CAAC,OAAO;IAN7C;;;;;OAKG;gBACS,MAAM,EAAE,MAAM,EAAE,EAAU,OAAO,EAAE,mBAAmB,EAAE;IAI7D,QAAQ,CAAC,QAAQ,EAAE,YAAY,GAAG,cAAc,EAAE;IAUlD,OAAO,CAAC,QAAQ,EAAE,YAAY,GAAG,MAAM;CAkBjD;AAED;;;;GAIG;AACH,qBAAa,kBAAmB,SAAQ,YAAY;IAUlB,OAAO,CAAC,QAAQ;IAAW,OAAO,CAAC,KAAK;IAA+B,OAAO,CAAC,UAAU;IARvH;;;;;;;OAOG;gBACS,MAAM,EAAE,MAAM,EAAE,EAAU,QAAQ,EAAE,OAAO,EAAU,KAAK,EAAE,oBAAoB,GAAG,IAAI,EAAU,UAAU,EAAE,YAAY,EAAE;IAIhI,QAAQ,CAAC,QAAQ,EAAE,YAAY,GAAG,cAAc,EAAE;IAclD,OAAO,CAAC,QAAQ,EAAE,YAAY,GAAG,MAAM;CAgBjD;AAED;;;;GAIG;AACH,qBAAa,iBAAkB,SAAQ,YAAY;IAWjB,OAAO,CAAC,QAAQ;IAAW,OAAO,CAAC,IAAI;IAAiB,OAAO,CAAC,UAAU;IATxG;;;;;;;;OAQG;gBACS,MAAM,EAAE,MAAM,EAAE,EAAU,QAAQ,EAAE,OAAO,EAAU,IAAI,EAAE,MAAM,GAAG,IAAI,EAAU,UAAU,EAAE,YAAY,EAAE;IAIjH,QAAQ,CAAC,QAAQ,EAAE,YAAY,GAAG,cAAc,EAAE;IAelD,OAAO,CAAC,QAAQ,EAAE,YAAY,GAAG,MAAM;CAcjD;AAED;;;;GAIG;AACH,qBAAa,oBAAqB,SAAQ,MAAM;IAUd,OAAO,CAAC,MAAM;IAAqB,OAAO,CAAC,UAAU;IARnF;;;;;;;OAOG;gBACS,MAAM,EAAE,MAAM,EAAE,EAAU,MAAM,EAAE,iBAAiB,EAAU,UAAU,EAAE,YAAY,EAAE;IAI5F,QAAQ,CAAC,QAAQ,EAAE,YAAY,GAAG,cAAc,EAAE;IASlD,OAAO,CAAC,QAAQ,EAAE,YAAY,GAAG,MAAM;CAMjD"}
|
616
lib/generator.js
Normal file
616
lib/generator.js
Normal file
@ -0,0 +1,616 @@
|
|||||||
|
"use strict";
|
||||||
|
/*! Copyright (c) 2020 Patrick Demian; Licensed under MIT */
|
||||||
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
|
exports.RegularExpressionCST = exports.GroupStatementCST = exports.RepeatStatementCST = exports.MatchStatementCST = exports.CountSubStatementCST = exports.UsingStatementCST = exports.MatchSubStatementCST = exports.StatementCST = exports.MatchStatementValue = exports.MatchSubStatementValue = exports.MatchSubStatementType = exports.UsingFlags = exports.H2RCST = exports.RegexDialect = void 0;
|
||||||
|
/**
|
||||||
|
* Includes all Concrete Syntax Trees for Human2Regex
|
||||||
|
* @packageDocumentation
|
||||||
|
*/
|
||||||
|
const utilities_1 = require("./utilities");
|
||||||
|
/**
|
||||||
|
* List of regular expression dialects we support
|
||||||
|
*/
|
||||||
|
var RegexDialect;
|
||||||
|
(function (RegexDialect) {
|
||||||
|
RegexDialect[RegexDialect["JS"] = 0] = "JS";
|
||||||
|
RegexDialect[RegexDialect["PCRE"] = 1] = "PCRE";
|
||||||
|
RegexDialect[RegexDialect["DotNet"] = 2] = "DotNet";
|
||||||
|
RegexDialect[RegexDialect["Java"] = 3] = "Java";
|
||||||
|
})(RegexDialect = exports.RegexDialect || (exports.RegexDialect = {}));
|
||||||
|
const unicode_property_codes = [
|
||||||
|
"C", "Cc", "Cf", "Cn", "Co", "Cs",
|
||||||
|
"L", "Ll", "Lm", "Lo", "Lt", "Lu",
|
||||||
|
"M", "Mc", "Me", "Mn", "N", "Nd",
|
||||||
|
"Nl", "No", "P", "Pc", "Pd", "Pe",
|
||||||
|
"Pf", "Pi", "Po", "Ps", "S", "Sc",
|
||||||
|
"Sk", "Sm", "So", "Z", "Zl", "Zp",
|
||||||
|
"Zs"
|
||||||
|
];
|
||||||
|
const unicode_script_codes = [
|
||||||
|
"Arabic", "Armenian", "Avestan", "Balinese", "Bamum",
|
||||||
|
"Batak", "Bengali", "Bopomofo", "Brahmi", "Braille",
|
||||||
|
"Buginese", "Buhid", "Canadian_Aboriginal", "Carian", "Chakma",
|
||||||
|
"Cham", "Cherokee", "Common", "Coptic", "Cuneiform",
|
||||||
|
"Cypriot", "Cyrillic", "Deseret", "Devanagari", "Egyptian_Hieroglyphs",
|
||||||
|
"Ethiopic", "Georgian", "Glagolitic", "Gothic", "Greek",
|
||||||
|
"Gujarati", "Gurmukhi", "Han", "Hangul", "Hanunoo", "Hebrew",
|
||||||
|
"Hiragana", "Imperial_Aramaic", "Inherited", "Inscriptional_Pahlavi",
|
||||||
|
"Inscriptional_Parthian", "Javanese", "Kaithi", "Kannada", "Katakana",
|
||||||
|
"Kayah_Li", "Kharoshthi", "Khmer", "Lao", "Latin", "Lepcha", "Limbu",
|
||||||
|
"Linear_B", "Lisu", "Lycian", "Lydian", "Malayalam", "Mandaic",
|
||||||
|
"Meetei_Mayek", "Meroitic_Cursive", "Meroitic_Hieroglyphs", "Miao",
|
||||||
|
"Mongolian", "Myanmar", "New_Tai_Lue", "Nko", "Ogham", "Old_Italic",
|
||||||
|
"Old_Persian", "Old_South_Arabian", "Old_Turkic", "Ol_Chiki", "Oriya",
|
||||||
|
"Osmanya", "Phags_Pa", "Phoenician", "Rejang", "Runic", "Samaritan",
|
||||||
|
"Saurashtra", "Sharada", "Shavian", "Sinhala", "Sora_Sompeng",
|
||||||
|
"Sundanese", "Syloti_Nagri", "Syriac", "Tagalog", "Tagbanwa", "Tai_Le",
|
||||||
|
"Tai_Tham", "Tai_Viet", "Takri", "Tamil", "Telugu", "Thaana", "Thai",
|
||||||
|
"Tibetan", "Tifinagh", "Ugaritic", "Vai", "Yi"
|
||||||
|
];
|
||||||
|
/**
|
||||||
|
* The base concrete syntax tree class
|
||||||
|
*
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
class H2RCST {
|
||||||
|
/**
|
||||||
|
* Constructor for H2RCST
|
||||||
|
*
|
||||||
|
* @param tokens Tokens used to calculate where an error occured
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
constructor(tokens) {
|
||||||
|
this.tokens = tokens;
|
||||||
|
this.tokens = tokens;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Creates an ISemanticError with a given message and the tokens provided from the constructor
|
||||||
|
*
|
||||||
|
* @param message the message
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
error(message) {
|
||||||
|
var _a, _b, _c;
|
||||||
|
const f = utilities_1.first(this.tokens);
|
||||||
|
const l = utilities_1.last(this.tokens);
|
||||||
|
return {
|
||||||
|
startLine: (_a = f.startLine) !== null && _a !== void 0 ? _a : NaN,
|
||||||
|
startColumn: (_b = f.startColumn) !== null && _b !== void 0 ? _b : NaN,
|
||||||
|
length: ((_c = l.endOffset) !== null && _c !== void 0 ? _c : l.startOffset) - f.startOffset,
|
||||||
|
message: message
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
exports.H2RCST = H2RCST;
|
||||||
|
/**
|
||||||
|
* Flags for the using statement
|
||||||
|
*
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
var UsingFlags;
|
||||||
|
(function (UsingFlags) {
|
||||||
|
UsingFlags[UsingFlags["Multiline"] = utilities_1.makeFlag(0)] = "Multiline";
|
||||||
|
UsingFlags[UsingFlags["Global"] = utilities_1.makeFlag(1)] = "Global";
|
||||||
|
UsingFlags[UsingFlags["Sensitive"] = utilities_1.makeFlag(2)] = "Sensitive";
|
||||||
|
UsingFlags[UsingFlags["Insensitive"] = utilities_1.makeFlag(3)] = "Insensitive";
|
||||||
|
UsingFlags[UsingFlags["Exact"] = utilities_1.makeFlag(4)] = "Exact";
|
||||||
|
})(UsingFlags = exports.UsingFlags || (exports.UsingFlags = {}));
|
||||||
|
/**
|
||||||
|
* Type of match arguments
|
||||||
|
*
|
||||||
|
* @remarks SingleString means an escaped string
|
||||||
|
* @remarks Between means a range (ex. a-z)
|
||||||
|
* @remarks Anything means .
|
||||||
|
* @remarks Word, Digit, Character, Whitespace, Number, Tab, Linefeed, Newline, and Carriage return are \w+, \d, \w, \s, \d+, \t, \n, \n, \r respectively
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
var MatchSubStatementType;
|
||||||
|
(function (MatchSubStatementType) {
|
||||||
|
MatchSubStatementType[MatchSubStatementType["SingleString"] = 0] = "SingleString";
|
||||||
|
MatchSubStatementType[MatchSubStatementType["Between"] = 1] = "Between";
|
||||||
|
MatchSubStatementType[MatchSubStatementType["Anything"] = 2] = "Anything";
|
||||||
|
MatchSubStatementType[MatchSubStatementType["Word"] = 3] = "Word";
|
||||||
|
MatchSubStatementType[MatchSubStatementType["Digit"] = 4] = "Digit";
|
||||||
|
MatchSubStatementType[MatchSubStatementType["Character"] = 5] = "Character";
|
||||||
|
MatchSubStatementType[MatchSubStatementType["Whitespace"] = 6] = "Whitespace";
|
||||||
|
MatchSubStatementType[MatchSubStatementType["Number"] = 7] = "Number";
|
||||||
|
MatchSubStatementType[MatchSubStatementType["Tab"] = 8] = "Tab";
|
||||||
|
MatchSubStatementType[MatchSubStatementType["Linefeed"] = 9] = "Linefeed";
|
||||||
|
MatchSubStatementType[MatchSubStatementType["Newline"] = 10] = "Newline";
|
||||||
|
MatchSubStatementType[MatchSubStatementType["CarriageReturn"] = 11] = "CarriageReturn";
|
||||||
|
MatchSubStatementType[MatchSubStatementType["Boundary"] = 12] = "Boundary";
|
||||||
|
MatchSubStatementType[MatchSubStatementType["Unicode"] = 13] = "Unicode";
|
||||||
|
})(MatchSubStatementType = exports.MatchSubStatementType || (exports.MatchSubStatementType = {}));
|
||||||
|
/**
|
||||||
|
* Container for match statements
|
||||||
|
*
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
class MatchSubStatementValue {
|
||||||
|
/**
|
||||||
|
* Constructor for MatchSubStatementValue
|
||||||
|
*
|
||||||
|
* @param type the type of this match
|
||||||
|
* @param from optional value or range string
|
||||||
|
* @param to optional range string
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
constructor(type, from = null, to = null) {
|
||||||
|
this.type = type;
|
||||||
|
this.from = from;
|
||||||
|
this.to = to;
|
||||||
|
/* empty */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
exports.MatchSubStatementValue = MatchSubStatementValue;
|
||||||
|
/**
|
||||||
|
* Container for MatchStatementValue
|
||||||
|
*
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
class MatchStatementValue {
|
||||||
|
/**
|
||||||
|
* Constructor for MatchStatementValue
|
||||||
|
*
|
||||||
|
* @param optional is this match optional
|
||||||
|
* @param statement the substatement to generate
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
constructor(optional, statement) {
|
||||||
|
this.optional = optional;
|
||||||
|
this.statement = statement;
|
||||||
|
/* empty */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
exports.MatchStatementValue = MatchStatementValue;
|
||||||
|
/**
|
||||||
|
* The base class for all statement concrete syntax trees
|
||||||
|
*
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
class StatementCST extends H2RCST {
|
||||||
|
}
|
||||||
|
exports.StatementCST = StatementCST;
|
||||||
|
/**
|
||||||
|
* Concrete Syntax Tree for Match Sub statements
|
||||||
|
*
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
class MatchSubStatementCST extends H2RCST {
|
||||||
|
/**
|
||||||
|
* Constructor for MatchSubStatementCST
|
||||||
|
*
|
||||||
|
* @param tokens Tokens used to calculate where an error occured
|
||||||
|
* @param count optional count statement
|
||||||
|
* @param invert is this match inverted (ex, [^a-z] or [a-z])
|
||||||
|
* @param values sub statements to match
|
||||||
|
*/
|
||||||
|
constructor(tokens, count, invert = false, values) {
|
||||||
|
super(tokens);
|
||||||
|
this.count = count;
|
||||||
|
this.invert = invert;
|
||||||
|
this.values = values;
|
||||||
|
}
|
||||||
|
validate(language) {
|
||||||
|
let errors = [];
|
||||||
|
if (this.count) {
|
||||||
|
errors = errors.concat(this.count.validate(language));
|
||||||
|
}
|
||||||
|
for (const value of this.values) {
|
||||||
|
if (value.type === MatchSubStatementType.Between) {
|
||||||
|
let from = value.from;
|
||||||
|
let to = value.to;
|
||||||
|
if (!utilities_1.isSingleRegexCharacter(from)) {
|
||||||
|
errors.push(this.error("Between statement must begin with a single character"));
|
||||||
|
}
|
||||||
|
else if (from.startsWith("\\u") || from.startsWith("\\U") || from.startsWith("\\")) {
|
||||||
|
from = JSON.parse(`"${utilities_1.regexEscape(from)}"`);
|
||||||
|
}
|
||||||
|
if (!utilities_1.isSingleRegexCharacter(to)) {
|
||||||
|
errors.push(this.error("Between statement must end with a single character"));
|
||||||
|
}
|
||||||
|
else if (to.startsWith("\\u") || to.startsWith("\\U") || to.startsWith("\\")) {
|
||||||
|
to = JSON.parse(`"${utilities_1.regexEscape(to)}"`);
|
||||||
|
}
|
||||||
|
if (from.charCodeAt(0) >= to.charCodeAt(0)) {
|
||||||
|
errors.push(this.error("Between statement range invalid"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (value.type === MatchSubStatementType.Unicode) {
|
||||||
|
let unicode_class = value.from;
|
||||||
|
// check to see if the given code is supported
|
||||||
|
if (!unicode_property_codes.includes(unicode_class)) {
|
||||||
|
// check to see if the given script is supported
|
||||||
|
// Java and C# requires "Is*"
|
||||||
|
if (language === RegexDialect.DotNet || language === RegexDialect.Java) {
|
||||||
|
if (!unicode_class.startsWith("Is")) {
|
||||||
|
errors.push(this.error("This dialect requires script names to begin with Is, such as IsCyrillic rather than Cyrillic"));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
unicode_class = unicode_class.substr(0, 2);
|
||||||
|
}
|
||||||
|
// attempt with and without "_" characters
|
||||||
|
if (!unicode_script_codes.includes(unicode_class) && !unicode_script_codes.includes(unicode_class.replace("_", ""))) {
|
||||||
|
errors.push(this.error(`Unknown unicode specifier ${value.from}`));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return errors;
|
||||||
|
}
|
||||||
|
toRegex(language) {
|
||||||
|
const str = [];
|
||||||
|
for (const value of this.values) {
|
||||||
|
switch (value.type) {
|
||||||
|
case MatchSubStatementType.SingleString: {
|
||||||
|
const reg = utilities_1.regexEscape(utilities_1.removeQuotes(value.from));
|
||||||
|
str.push(this.invert ? `(?:(?!${reg}))` : reg);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case MatchSubStatementType.Between:
|
||||||
|
str.push(this.invert ? `[^${value.from}-${value.to}]` : `[${value.from}-${value.to}]`);
|
||||||
|
break;
|
||||||
|
case MatchSubStatementType.Unicode:
|
||||||
|
str.push(this.invert ? `\\P{${value.from}}` : `\\p{${value.from}}`);
|
||||||
|
break;
|
||||||
|
case MatchSubStatementType.Boundary:
|
||||||
|
str.push(this.invert ? "\\B" : "\\b");
|
||||||
|
break;
|
||||||
|
case MatchSubStatementType.Word:
|
||||||
|
str.push(this.invert ? "\\W+" : "\\w+");
|
||||||
|
break;
|
||||||
|
case MatchSubStatementType.Digit:
|
||||||
|
str.push(this.invert ? "\\D" : "\\d");
|
||||||
|
break;
|
||||||
|
case MatchSubStatementType.Character:
|
||||||
|
str.push(this.invert ? "\\W" : "\\w");
|
||||||
|
break;
|
||||||
|
case MatchSubStatementType.Whitespace:
|
||||||
|
str.push(this.invert ? "\\S" : "\\s");
|
||||||
|
break;
|
||||||
|
case MatchSubStatementType.Number:
|
||||||
|
str.push(this.invert ? "\\D+" : "\\d+");
|
||||||
|
break;
|
||||||
|
case MatchSubStatementType.Tab:
|
||||||
|
str.push(this.invert ? "[^\\t]" : "\\t");
|
||||||
|
break;
|
||||||
|
case MatchSubStatementType.Newline:
|
||||||
|
case MatchSubStatementType.Linefeed:
|
||||||
|
str.push(this.invert ? "[^\\n]" : "\\n");
|
||||||
|
break;
|
||||||
|
case MatchSubStatementType.CarriageReturn:
|
||||||
|
str.push(this.invert ? "[^\\r]" : "\\r");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
// default: anything
|
||||||
|
str.push(this.invert ? "[^.]" : ".");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let ret = "";
|
||||||
|
let require_grouping = false;
|
||||||
|
let dont_clobber_plus = false;
|
||||||
|
if (str.length === 1) {
|
||||||
|
ret = str[0];
|
||||||
|
if (ret.endsWith("+")) {
|
||||||
|
dont_clobber_plus = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// we can use regex's [] for single chars, otherwise we need a group
|
||||||
|
else if (str.every(utilities_1.isSingleRegexCharacter)) {
|
||||||
|
ret = "[" + str.join("") + "]";
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
//use a no-capture group
|
||||||
|
ret = str.join("|");
|
||||||
|
require_grouping = true;
|
||||||
|
}
|
||||||
|
if (this.count) {
|
||||||
|
if (dont_clobber_plus) {
|
||||||
|
const clobber = this.count.toRegex(language);
|
||||||
|
// + can be ignored as well as a count as long as that count is > 0
|
||||||
|
switch (clobber) {
|
||||||
|
case "*":
|
||||||
|
case "?":
|
||||||
|
ret = "(?:" + ret + ")" + clobber;
|
||||||
|
break;
|
||||||
|
case "+":
|
||||||
|
// ignore
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
if (clobber.startsWith("{0")) {
|
||||||
|
ret = "(?:" + ret + ")" + clobber;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// remove + and replace with count
|
||||||
|
ret.substring(0, ret.length - 1) + clobber;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (require_grouping) {
|
||||||
|
ret = "(?:" + ret + ")";
|
||||||
|
}
|
||||||
|
ret += this.count.toRegex(language);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
exports.MatchSubStatementCST = MatchSubStatementCST;
|
||||||
|
/**
|
||||||
|
* Concrete Syntax Tree for Using statements
|
||||||
|
*
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
class UsingStatementCST extends H2RCST {
|
||||||
|
/**
|
||||||
|
* Constructor for UsingStatementCST
|
||||||
|
*
|
||||||
|
* @param tokens Tokens used to calculate where an error occured
|
||||||
|
* @param flags using flags
|
||||||
|
*/
|
||||||
|
constructor(tokens, flags) {
|
||||||
|
super(tokens);
|
||||||
|
this.flags = flags;
|
||||||
|
}
|
||||||
|
validate(language) {
|
||||||
|
utilities_1.unusedParameter(language, "Using Statement does not change based on language");
|
||||||
|
const errors = [];
|
||||||
|
let flag = this.flags[0];
|
||||||
|
for (let i = 1; i < this.flags.length; i++) {
|
||||||
|
if (utilities_1.hasFlag(flag, this.flags[i])) {
|
||||||
|
errors.push(this.error("Duplicate modifier: " + UsingFlags[this.flags[i]]));
|
||||||
|
}
|
||||||
|
flag = utilities_1.combineFlags(flag, this.flags[i]);
|
||||||
|
}
|
||||||
|
if (utilities_1.hasFlag(flag, UsingFlags.Sensitive) && utilities_1.hasFlag(flag, UsingFlags.Insensitive)) {
|
||||||
|
errors.push(this.error("Cannot be both case sensitive and insensitive"));
|
||||||
|
}
|
||||||
|
return errors;
|
||||||
|
}
|
||||||
|
toRegex(language) {
|
||||||
|
utilities_1.unusedParameter(language, "Using Statement does not change based on language");
|
||||||
|
let str = "";
|
||||||
|
let exact = false;
|
||||||
|
for (const flag of this.flags) {
|
||||||
|
if (utilities_1.hasFlag(flag, UsingFlags.Multiline)) {
|
||||||
|
str += "m";
|
||||||
|
}
|
||||||
|
else if (utilities_1.hasFlag(flag, UsingFlags.Global)) {
|
||||||
|
str += "g";
|
||||||
|
}
|
||||||
|
else if (utilities_1.hasFlag(flag, UsingFlags.Insensitive)) {
|
||||||
|
str += "i";
|
||||||
|
}
|
||||||
|
else if (utilities_1.hasFlag(flag, UsingFlags.Exact)) {
|
||||||
|
exact = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return exact ? "/^{regex}$/" + str : "/{regex}/" + str;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
exports.UsingStatementCST = UsingStatementCST;
|
||||||
|
/**
|
||||||
|
* Concrete Syntax Tree for Count sub statements
|
||||||
|
*
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
class CountSubStatementCST extends H2RCST {
|
||||||
|
/**
|
||||||
|
* Constructor for CountSubStatementCST
|
||||||
|
*
|
||||||
|
* @param tokens Tokens used to calculate where an error occured
|
||||||
|
* @param from number to count from
|
||||||
|
* @param to optional number to count to
|
||||||
|
* @param opt option modifier
|
||||||
|
*/
|
||||||
|
constructor(tokens, from, to = null, opt = null) {
|
||||||
|
super(tokens);
|
||||||
|
this.from = from;
|
||||||
|
this.to = to;
|
||||||
|
this.opt = opt;
|
||||||
|
}
|
||||||
|
validate(language) {
|
||||||
|
utilities_1.unusedParameter(language, "Count does not need checking");
|
||||||
|
const errors = [];
|
||||||
|
if (this.from < 0) {
|
||||||
|
errors.push(this.error("Value cannot be negative"));
|
||||||
|
}
|
||||||
|
else if (this.to !== null && ((this.opt === "exclusive" && (this.to - 1) <= this.from) || this.to <= this.from)) {
|
||||||
|
errors.push(this.error("Values must be in range of eachother"));
|
||||||
|
}
|
||||||
|
return errors;
|
||||||
|
}
|
||||||
|
toRegex(language) {
|
||||||
|
utilities_1.unusedParameter(language, "Count does not change from language");
|
||||||
|
const from = this.from;
|
||||||
|
let to = this.to;
|
||||||
|
// if we only have a count of 1, we can ignore adding any extra text
|
||||||
|
if (to === null) {
|
||||||
|
if (from === 1) {
|
||||||
|
return this.opt === "+" ? "+" : "*";
|
||||||
|
}
|
||||||
|
else if (from === 0) {
|
||||||
|
return this.opt === "+" ? "*" : "{0}";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (to !== null) {
|
||||||
|
if (this.opt === "exclusive") {
|
||||||
|
to--;
|
||||||
|
}
|
||||||
|
return `{${from},${to}}`;
|
||||||
|
}
|
||||||
|
else if (this.opt === "+") {
|
||||||
|
return `{${from},}`;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return `{${from}}`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
exports.CountSubStatementCST = CountSubStatementCST;
|
||||||
|
/**
|
||||||
|
* Concrete Syntax Tree for a Match statement
|
||||||
|
*
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
class MatchStatementCST extends StatementCST {
|
||||||
|
/**
|
||||||
|
* Constructor for MatchStatementCST
|
||||||
|
*
|
||||||
|
* @param tokens Tokens used to calculate where an error occured
|
||||||
|
* @param matches
|
||||||
|
*/
|
||||||
|
constructor(tokens, matches) {
|
||||||
|
super(tokens);
|
||||||
|
this.matches = matches;
|
||||||
|
}
|
||||||
|
validate(language) {
|
||||||
|
let errors = [];
|
||||||
|
for (const match of this.matches) {
|
||||||
|
errors = errors.concat(match.statement.validate(language));
|
||||||
|
}
|
||||||
|
return errors;
|
||||||
|
}
|
||||||
|
toRegex(language) {
|
||||||
|
return this.matches.map((x) => {
|
||||||
|
let match_stmt = x.statement.toRegex(language);
|
||||||
|
// need to group if optional and ungrouped
|
||||||
|
if (x.optional) {
|
||||||
|
if (!utilities_1.isSingleRegexCharacter(match_stmt)) {
|
||||||
|
// don't re-group a group
|
||||||
|
if (match_stmt[0] !== "(" && match_stmt[match_stmt.length - 1] !== ")") {
|
||||||
|
match_stmt = "(?:" + match_stmt + ")";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
match_stmt += "?";
|
||||||
|
}
|
||||||
|
return match_stmt;
|
||||||
|
}).join("");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
exports.MatchStatementCST = MatchStatementCST;
|
||||||
|
/**
|
||||||
|
* Concrete Syntax Tree for a Repeat statement
|
||||||
|
*
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
class RepeatStatementCST extends StatementCST {
|
||||||
|
/**
|
||||||
|
* Constructor for RepeatStatementCST
|
||||||
|
*
|
||||||
|
* @param tokens Tokens used to calculate where an error occured
|
||||||
|
* @param optional is this repetition optional
|
||||||
|
* @param count optional number of times to repeat
|
||||||
|
* @param statements the statements to repeat
|
||||||
|
*/
|
||||||
|
constructor(tokens, optional, count, statements) {
|
||||||
|
super(tokens);
|
||||||
|
this.optional = optional;
|
||||||
|
this.count = count;
|
||||||
|
this.statements = statements;
|
||||||
|
}
|
||||||
|
validate(language) {
|
||||||
|
let errors = [];
|
||||||
|
if (this.count !== null) {
|
||||||
|
errors = errors.concat(this.count.validate(language));
|
||||||
|
}
|
||||||
|
for (const statement of this.statements) {
|
||||||
|
errors = errors.concat(statement.validate(language));
|
||||||
|
}
|
||||||
|
return errors;
|
||||||
|
}
|
||||||
|
toRegex(language) {
|
||||||
|
let str = "(" + this.statements.map((x) => x.toRegex(language)).join("") + ")";
|
||||||
|
if (this.count) {
|
||||||
|
str += this.count.toRegex(language);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
str += "*";
|
||||||
|
}
|
||||||
|
if (this.optional) {
|
||||||
|
str += "?";
|
||||||
|
}
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
exports.RepeatStatementCST = RepeatStatementCST;
|
||||||
|
/**
|
||||||
|
* Conrete Syntax Tree for a group Statement
|
||||||
|
*
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
class GroupStatementCST extends StatementCST {
|
||||||
|
/**
|
||||||
|
* Constructor for GroupStatementCST
|
||||||
|
*
|
||||||
|
* @param tokens Tokens used to calculate where an error occured
|
||||||
|
* @param optional is this group optional
|
||||||
|
* @param name optional name for named group
|
||||||
|
* @param statements other statements
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
constructor(tokens, optional, name, statements) {
|
||||||
|
super(tokens);
|
||||||
|
this.optional = optional;
|
||||||
|
this.name = name;
|
||||||
|
this.statements = statements;
|
||||||
|
}
|
||||||
|
validate(language) {
|
||||||
|
let errors = [];
|
||||||
|
// All languages currently support named groups
|
||||||
|
//if (false) {
|
||||||
|
// errors.push(this.error("This language does not support named groups"));
|
||||||
|
//}
|
||||||
|
for (const statement of this.statements) {
|
||||||
|
errors = errors.concat(statement.validate(language));
|
||||||
|
}
|
||||||
|
return errors;
|
||||||
|
}
|
||||||
|
toRegex(language) {
|
||||||
|
let str = "(";
|
||||||
|
// named group
|
||||||
|
if (this.name !== null) {
|
||||||
|
str += `?<${this.name}>`;
|
||||||
|
}
|
||||||
|
str += this.statements.map((x) => x.toRegex(language)).join("");
|
||||||
|
str += (this.optional ? ")?" : ")");
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
exports.GroupStatementCST = GroupStatementCST;
|
||||||
|
/**
|
||||||
|
* Concrete Syntax Tree for a regular expression
|
||||||
|
*
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
class RegularExpressionCST extends H2RCST {
|
||||||
|
/**
|
||||||
|
* Constructor for RegularExpressionCST
|
||||||
|
*
|
||||||
|
* @param tokens Tokens used to calculate where an error occured
|
||||||
|
* @param usings using statements
|
||||||
|
* @param statements other statements
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
constructor(tokens, usings, statements) {
|
||||||
|
super(tokens);
|
||||||
|
this.usings = usings;
|
||||||
|
this.statements = statements;
|
||||||
|
}
|
||||||
|
validate(language) {
|
||||||
|
let errors = this.usings.validate(language);
|
||||||
|
for (const statement of this.statements) {
|
||||||
|
errors = errors.concat(statement.validate(language));
|
||||||
|
}
|
||||||
|
return errors;
|
||||||
|
}
|
||||||
|
toRegex(language) {
|
||||||
|
const modifiers = this.usings.toRegex(language);
|
||||||
|
const regex = this.statements.map((x) => x.toRegex(language)).join("");
|
||||||
|
return modifiers.replace("{regex}", regex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
exports.RegularExpressionCST = RegularExpressionCST;
|
11
lib/index.d.ts
vendored
Normal file
11
lib/index.d.ts
vendored
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
/*! Copyright (c) 2020 Patrick Demian; Licensed under MIT */
|
||||||
|
/**
|
||||||
|
* Includes all packages
|
||||||
|
* @packageDocumentation
|
||||||
|
*/
|
||||||
|
import "./utilities";
|
||||||
|
import "./tokens";
|
||||||
|
import "./lexer";
|
||||||
|
import "./parser";
|
||||||
|
import "./generator";
|
||||||
|
//# sourceMappingURL=index.d.ts.map
|
1
lib/index.d.ts.map
Normal file
1
lib/index.d.ts.map
Normal file
@ -0,0 +1 @@
|
|||||||
|
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAE5D;;;GAGG;AAEF,OAAO,aAAa,CAAC;AACrB,OAAO,UAAU,CAAC;AAClB,OAAO,SAAS,CAAC;AACjB,OAAO,UAAU,CAAC;AAClB,OAAO,aAAa,CAAC"}
|
12
lib/index.js
Normal file
12
lib/index.js
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
"use strict";
|
||||||
|
/*! Copyright (c) 2020 Patrick Demian; Licensed under MIT */
|
||||||
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
|
/**
|
||||||
|
* Includes all packages
|
||||||
|
* @packageDocumentation
|
||||||
|
*/
|
||||||
|
require("./utilities");
|
||||||
|
require("./tokens");
|
||||||
|
require("./lexer");
|
||||||
|
require("./parser");
|
||||||
|
require("./generator");
|
64
lib/lexer.d.ts
vendored
Normal file
64
lib/lexer.d.ts
vendored
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
/*! Copyright (c) 2020 Patrick Demian; Licensed under MIT */
|
||||||
|
/**
|
||||||
|
* The Lexer for Human2Regex
|
||||||
|
* @packageDocumentation
|
||||||
|
*/
|
||||||
|
import { ILexingResult } from "chevrotain";
|
||||||
|
/**
|
||||||
|
* Defines the type of indents the lexer will allow
|
||||||
|
*/
|
||||||
|
export declare enum IndentType {
|
||||||
|
Tabs = 0,
|
||||||
|
Spaces = 1,
|
||||||
|
Both = 2
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* The options for the Lexer
|
||||||
|
*/
|
||||||
|
export declare class Human2RegexLexerOptions {
|
||||||
|
skip_validations: boolean;
|
||||||
|
type: IndentType;
|
||||||
|
spaces_per_tab: number;
|
||||||
|
/**
|
||||||
|
* Constructor for the Human2RegexLexerOptions
|
||||||
|
*
|
||||||
|
* @param skip_validations If true, the lexer will skip validations (~25% faster)
|
||||||
|
* @param type The type of indents the lexer will allow
|
||||||
|
* @param spaces_per_tab Number of spaces per tab
|
||||||
|
*/
|
||||||
|
constructor(skip_validations?: boolean, type?: IndentType, spaces_per_tab?: number);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Human2Regex Lexer
|
||||||
|
*
|
||||||
|
* @remarks Only 1 lexer instance allowed due to a technical limitation and performance reasons
|
||||||
|
*/
|
||||||
|
export declare class Human2RegexLexer {
|
||||||
|
private static already_init;
|
||||||
|
private lexer;
|
||||||
|
private options;
|
||||||
|
/**
|
||||||
|
* Human2Regex Lexer
|
||||||
|
*
|
||||||
|
* @remarks Only 1 lexer instance allowed due to a technical limitation and performance reasons
|
||||||
|
* @param options options for the lexer
|
||||||
|
* @see Human2RegexLexerOptions
|
||||||
|
*/
|
||||||
|
constructor(options?: Human2RegexLexerOptions);
|
||||||
|
/**
|
||||||
|
* Sets the options for this lexer
|
||||||
|
*
|
||||||
|
* @param options options for the lexer
|
||||||
|
* @see Human2RegexLexerOptions
|
||||||
|
*/
|
||||||
|
setOptions(options: Human2RegexLexerOptions): void;
|
||||||
|
private lexError;
|
||||||
|
/**
|
||||||
|
* Tokenizes the given text
|
||||||
|
*
|
||||||
|
* @param text the text to analyze
|
||||||
|
* @returns a lexing result which contains the token stream and error list
|
||||||
|
*/
|
||||||
|
tokenize(text: string): ILexingResult;
|
||||||
|
}
|
||||||
|
//# sourceMappingURL=lexer.d.ts.map
|
1
lib/lexer.d.ts.map
Normal file
1
lib/lexer.d.ts.map
Normal file
@ -0,0 +1 @@
|
|||||||
|
{"version":3,"file":"lexer.d.ts","sourceRoot":"","sources":["../src/lexer.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAE5D;;;GAGG;AAEH,OAAO,EAAsC,aAAa,EAAgB,MAAM,YAAY,CAAC;AAI7F;;GAEG;AACH,oBAAY,UAAU;IAClB,IAAI,IAAA;IACJ,MAAM,IAAA;IACN,IAAI,IAAA;CACP;AAED;;GAEG;AACH,qBAAa,uBAAuB;IASb,gBAAgB;IAAiB,IAAI,EAAE,UAAU;IAA2B,cAAc,EAAE,MAAM;IAPrH;;;;;;OAMG;gBACgB,gBAAgB,UAAQ,EAAS,IAAI,GAAE,UAA4B,EAAS,cAAc,GAAE,MAAU;CAG5H;AAED;;;;GAIG;AACH,qBAAa,gBAAgB;IACzB,OAAO,CAAC,MAAM,CAAC,YAAY,CAAS;IAEpC,OAAO,CAAC,KAAK,CAAS;IACtB,OAAO,CAAC,OAAO,CAA2B;IAE1C;;;;;;OAMG;gBACS,OAAO,GAAE,uBAAuD;IAU5E;;;;;OAKG;IACI,UAAU,CAAC,OAAO,EAAE,uBAAuB,GAAG,IAAI;IAwBzD,OAAO,CAAC,QAAQ;IAUhB;;;;;OAKG;IACI,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,aAAa;CAkH/C"}
|
200
lib/lexer.js
Normal file
200
lib/lexer.js
Normal file
@ -0,0 +1,200 @@
|
|||||||
|
"use strict";
|
||||||
|
/*! Copyright (c) 2020 Patrick Demian; Licensed under MIT */
|
||||||
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
|
exports.Human2RegexLexer = exports.Human2RegexLexerOptions = exports.IndentType = void 0;
|
||||||
|
/**
|
||||||
|
* The Lexer for Human2Regex
|
||||||
|
* @packageDocumentation
|
||||||
|
*/
|
||||||
|
const chevrotain_1 = require("chevrotain");
|
||||||
|
const utilities_1 = require("./utilities");
|
||||||
|
const tokens_1 = require("./tokens");
|
||||||
|
/**
|
||||||
|
* Defines the type of indents the lexer will allow
|
||||||
|
*/
|
||||||
|
var IndentType;
|
||||||
|
(function (IndentType) {
|
||||||
|
IndentType[IndentType["Tabs"] = 0] = "Tabs";
|
||||||
|
IndentType[IndentType["Spaces"] = 1] = "Spaces";
|
||||||
|
IndentType[IndentType["Both"] = 2] = "Both";
|
||||||
|
})(IndentType = exports.IndentType || (exports.IndentType = {}));
|
||||||
|
/**
|
||||||
|
* The options for the Lexer
|
||||||
|
*/
|
||||||
|
class Human2RegexLexerOptions {
|
||||||
|
/**
|
||||||
|
* Constructor for the Human2RegexLexerOptions
|
||||||
|
*
|
||||||
|
* @param skip_validations If true, the lexer will skip validations (~25% faster)
|
||||||
|
* @param type The type of indents the lexer will allow
|
||||||
|
* @param spaces_per_tab Number of spaces per tab
|
||||||
|
*/
|
||||||
|
constructor(skip_validations = false, type = IndentType.Both, spaces_per_tab = 4) {
|
||||||
|
this.skip_validations = skip_validations;
|
||||||
|
this.type = type;
|
||||||
|
this.spaces_per_tab = spaces_per_tab;
|
||||||
|
/* empty */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
exports.Human2RegexLexerOptions = Human2RegexLexerOptions;
|
||||||
|
/**
|
||||||
|
* Human2Regex Lexer
|
||||||
|
*
|
||||||
|
* @remarks Only 1 lexer instance allowed due to a technical limitation and performance reasons
|
||||||
|
*/
|
||||||
|
class Human2RegexLexer {
|
||||||
|
/**
|
||||||
|
* Human2Regex Lexer
|
||||||
|
*
|
||||||
|
* @remarks Only 1 lexer instance allowed due to a technical limitation and performance reasons
|
||||||
|
* @param options options for the lexer
|
||||||
|
* @see Human2RegexLexerOptions
|
||||||
|
*/
|
||||||
|
constructor(options = new Human2RegexLexerOptions()) {
|
||||||
|
if (Human2RegexLexer.already_init) {
|
||||||
|
throw new Error("Only 1 instance of Human2RegexLexer allowed");
|
||||||
|
}
|
||||||
|
Human2RegexLexer.already_init = true;
|
||||||
|
this.setOptions(options);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Sets the options for this lexer
|
||||||
|
*
|
||||||
|
* @param options options for the lexer
|
||||||
|
* @see Human2RegexLexerOptions
|
||||||
|
*/
|
||||||
|
setOptions(options) {
|
||||||
|
this.options = options;
|
||||||
|
let indent_regex = null;
|
||||||
|
// Generate an index lexer (accepts tabs or spaces or both based on options)
|
||||||
|
if (this.options.type === IndentType.Tabs) {
|
||||||
|
indent_regex = /\t/y;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
let reg = ` {${this.options.spaces_per_tab}}`;
|
||||||
|
if (this.options.type === IndentType.Both) {
|
||||||
|
reg += "|\\t";
|
||||||
|
}
|
||||||
|
indent_regex = new RegExp(reg, "y");
|
||||||
|
}
|
||||||
|
tokens_1.Indent.PATTERN = indent_regex;
|
||||||
|
this.lexer = new chevrotain_1.Lexer(tokens_1.AllTokens, { ensureOptimizations: true, skipValidations: options.skip_validations });
|
||||||
|
}
|
||||||
|
lexError(token) {
|
||||||
|
var _a, _b, _c;
|
||||||
|
return {
|
||||||
|
offset: token.startOffset,
|
||||||
|
line: (_a = token.startLine) !== null && _a !== void 0 ? _a : NaN,
|
||||||
|
column: (_b = token.startColumn) !== null && _b !== void 0 ? _b : NaN,
|
||||||
|
length: (_c = token.endOffset) !== null && _c !== void 0 ? _c : NaN - token.startOffset,
|
||||||
|
message: "Unexpected indentation found"
|
||||||
|
};
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Tokenizes the given text
|
||||||
|
*
|
||||||
|
* @param text the text to analyze
|
||||||
|
* @returns a lexing result which contains the token stream and error list
|
||||||
|
*/
|
||||||
|
tokenize(text) {
|
||||||
|
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p;
|
||||||
|
const lex_result = this.lexer.tokenize(text);
|
||||||
|
if (lex_result.tokens.length === 0) {
|
||||||
|
return lex_result;
|
||||||
|
}
|
||||||
|
const tokens = [];
|
||||||
|
const indent_stack = [0];
|
||||||
|
let curr_indent_level = 0;
|
||||||
|
let start_of_line = true;
|
||||||
|
let had_indents = false;
|
||||||
|
// create Outdents
|
||||||
|
for (let i = 0; i < lex_result.tokens.length; i++) {
|
||||||
|
// EoL? check for indents next (by setting startOfLine = true)
|
||||||
|
if (lex_result.tokens[i].tokenType === tokens_1.EndOfLine) {
|
||||||
|
if (tokens.length === 0 || tokens[tokens.length - 1].tokenType === tokens_1.EndOfLine) {
|
||||||
|
// Ignore multiple EOLs and ignore first EOL
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
start_of_line = true;
|
||||||
|
tokens.push(lex_result.tokens[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// start with 1 indent. Append all other indents
|
||||||
|
else if (lex_result.tokens[i].tokenType === tokens_1.Indent) {
|
||||||
|
had_indents = true;
|
||||||
|
curr_indent_level = 1;
|
||||||
|
const start_token = lex_result.tokens[i];
|
||||||
|
let length = lex_result.tokens[i].image.length;
|
||||||
|
// grab all the indents (and their length)
|
||||||
|
while (lex_result.tokens.length > i && lex_result.tokens[i + 1].tokenType === tokens_1.Indent) {
|
||||||
|
curr_indent_level++;
|
||||||
|
i++;
|
||||||
|
length += lex_result.tokens[i].image.length;
|
||||||
|
}
|
||||||
|
start_token.endOffset = start_token.startOffset + length;
|
||||||
|
start_token.endColumn = lex_result.tokens[i].endColumn;
|
||||||
|
// must be the same line
|
||||||
|
//start_token.endLine = lex_result.tokens[i].endLine;
|
||||||
|
// are we an empty line?
|
||||||
|
if (lex_result.tokens.length > i && lex_result.tokens[i + 1].tokenType === tokens_1.EndOfLine) {
|
||||||
|
// Ignore all indents AND newline
|
||||||
|
// continue;
|
||||||
|
}
|
||||||
|
// new indent is too far ahead
|
||||||
|
else if (!start_of_line || (curr_indent_level > utilities_1.last(indent_stack) + 1)) {
|
||||||
|
lex_result.errors.push(this.lexError(start_token));
|
||||||
|
}
|
||||||
|
// new indent is just 1 above
|
||||||
|
else if (curr_indent_level > utilities_1.last(indent_stack)) {
|
||||||
|
indent_stack.push(curr_indent_level);
|
||||||
|
tokens.push(start_token);
|
||||||
|
}
|
||||||
|
// new indent is below the past indent
|
||||||
|
else if (curr_indent_level < utilities_1.last(indent_stack)) {
|
||||||
|
const index = utilities_1.findLastIndex(indent_stack, curr_indent_level);
|
||||||
|
if (index < 0) {
|
||||||
|
lex_result.errors.push(this.lexError(start_token));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
const number_of_dedents = indent_stack.length - index - 1;
|
||||||
|
for (let j = 0; j < number_of_dedents; j++) {
|
||||||
|
indent_stack.pop();
|
||||||
|
tokens.push(chevrotain_1.createTokenInstance(tokens_1.Outdent, "", start_token.startOffset, start_token.startOffset + length, (_a = start_token.startLine) !== null && _a !== void 0 ? _a : NaN, (_b = start_token.endLine) !== null && _b !== void 0 ? _b : NaN, (_c = start_token.startColumn) !== null && _c !== void 0 ? _c : NaN, ((_d = start_token.startColumn) !== null && _d !== void 0 ? _d : NaN) + length));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// same indent level: don't care
|
||||||
|
// continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (start_of_line && !had_indents) {
|
||||||
|
const tok = lex_result.tokens[i];
|
||||||
|
//add remaining Outdents
|
||||||
|
while (indent_stack.length > 1) {
|
||||||
|
indent_stack.pop();
|
||||||
|
tokens.push(chevrotain_1.createTokenInstance(tokens_1.Outdent, "", tok.startOffset, tok.startOffset, (_e = tok.startLine) !== null && _e !== void 0 ? _e : NaN, NaN, (_f = tok.startColumn) !== null && _f !== void 0 ? _f : NaN, NaN));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
start_of_line = false;
|
||||||
|
had_indents = false;
|
||||||
|
tokens.push(lex_result.tokens[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const tok = utilities_1.last(tokens);
|
||||||
|
// Do we have an EOL marker at the end?
|
||||||
|
if (tokens.length > 0 && tok.tokenType !== tokens_1.EndOfLine) {
|
||||||
|
tokens.push(chevrotain_1.createTokenInstance(tokens_1.EndOfLine, "\n", (_g = tok.endOffset) !== null && _g !== void 0 ? _g : NaN, (_h = tok.endOffset) !== null && _h !== void 0 ? _h : NaN, (_j = tok.startLine) !== null && _j !== void 0 ? _j : NaN, NaN, (_k = tok.startColumn) !== null && _k !== void 0 ? _k : NaN, NaN));
|
||||||
|
}
|
||||||
|
//add remaining Outdents
|
||||||
|
while (indent_stack.length > 1) {
|
||||||
|
indent_stack.pop();
|
||||||
|
tokens.push(chevrotain_1.createTokenInstance(tokens_1.Outdent, "", (_l = tok.endOffset) !== null && _l !== void 0 ? _l : NaN, (_m = tok.endOffset) !== null && _m !== void 0 ? _m : NaN, (_o = tok.startLine) !== null && _o !== void 0 ? _o : NaN, NaN, (_p = tok.startColumn) !== null && _p !== void 0 ? _p : NaN, NaN));
|
||||||
|
}
|
||||||
|
lex_result.tokens = tokens;
|
||||||
|
return lex_result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
exports.Human2RegexLexer = Human2RegexLexer;
|
||||||
|
Human2RegexLexer.already_init = false;
|
32
lib/parser.d.ts
vendored
Normal file
32
lib/parser.d.ts
vendored
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
/*! Copyright (c) 2020 Patrick Demian; Licensed under MIT */
|
||||||
|
/**
|
||||||
|
* The parser for Human2Regex
|
||||||
|
* @packageDocumentation
|
||||||
|
*/
|
||||||
|
import { EmbeddedActionsParser } from "chevrotain";
|
||||||
|
import { RegularExpressionCST } from "./generator";
|
||||||
|
/**
|
||||||
|
* The options for the Parser
|
||||||
|
*/
|
||||||
|
export declare class Human2RegexParserOptions {
|
||||||
|
skip_validations: boolean;
|
||||||
|
/**
|
||||||
|
* Constructor for Human2RegexParserOptions
|
||||||
|
*
|
||||||
|
* @param skip_validations If true, the lexer will skip validations (~25% faster)
|
||||||
|
*/
|
||||||
|
constructor(skip_validations?: boolean);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* The Parser class
|
||||||
|
*
|
||||||
|
* @remarks Only 1 parser instance allowed due to performance reasons
|
||||||
|
*/
|
||||||
|
export declare class Human2RegexParser extends EmbeddedActionsParser {
|
||||||
|
private options;
|
||||||
|
private static already_init;
|
||||||
|
parse: (idxInCallingRule?: number, ...args: unknown[]) => RegularExpressionCST;
|
||||||
|
constructor(options?: Human2RegexParserOptions);
|
||||||
|
setOptions(options: Human2RegexParserOptions): void;
|
||||||
|
}
|
||||||
|
//# sourceMappingURL=parser.d.ts.map
|
1
lib/parser.d.ts.map
Normal file
1
lib/parser.d.ts.map
Normal file
@ -0,0 +1 @@
|
|||||||
|
{"version":3,"file":"parser.d.ts","sourceRoot":"","sources":["../src/parser.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAE5D;;;GAGG;AAEH,OAAO,EAAE,qBAAqB,EAAkB,MAAM,YAAY,CAAC;AAEnE,OAAO,EAA4H,oBAAoB,EAA+F,MAAM,aAAa,CAAC;AAG1Q;;GAEG;AACH,qBAAa,wBAAwB;IAMd,gBAAgB,EAAE,OAAO;IAL5C;;;;OAIG;gBACgB,gBAAgB,GAAE,OAAe;CAGvD;AAaD;;;;GAIG;AACH,qBAAa,iBAAkB,SAAQ,qBAAqB;IAK5C,OAAO,CAAC,OAAO;IAJ3B,OAAO,CAAC,MAAM,CAAC,YAAY,CAAS;IAE7B,KAAK,EAAE,CAAC,gBAAgB,CAAC,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,oBAAoB,CAAC;gBAElE,OAAO,GAAE,wBAAyD;IAmb/E,UAAU,CAAC,OAAO,EAAE,wBAAwB,GAAG,IAAI;CAG7D"}
|
445
lib/parser.js
Normal file
445
lib/parser.js
Normal file
@ -0,0 +1,445 @@
|
|||||||
|
"use strict";
|
||||||
|
/*! Copyright (c) 2020 Patrick Demian; Licensed under MIT */
|
||||||
|
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
||||||
|
if (k2 === undefined) k2 = k;
|
||||||
|
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
|
||||||
|
}) : (function(o, m, k, k2) {
|
||||||
|
if (k2 === undefined) k2 = k;
|
||||||
|
o[k2] = m[k];
|
||||||
|
}));
|
||||||
|
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
||||||
|
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
||||||
|
}) : function(o, v) {
|
||||||
|
o["default"] = v;
|
||||||
|
});
|
||||||
|
var __importStar = (this && this.__importStar) || function (mod) {
|
||||||
|
if (mod && mod.__esModule) return mod;
|
||||||
|
var result = {};
|
||||||
|
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
||||||
|
__setModuleDefault(result, mod);
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
|
exports.Human2RegexParser = exports.Human2RegexParserOptions = void 0;
|
||||||
|
/**
|
||||||
|
* The parser for Human2Regex
|
||||||
|
* @packageDocumentation
|
||||||
|
*/
|
||||||
|
const chevrotain_1 = require("chevrotain");
|
||||||
|
const T = __importStar(require("./tokens"));
|
||||||
|
const generator_1 = require("./generator");
|
||||||
|
const utilities_1 = require("./utilities");
|
||||||
|
/**
|
||||||
|
* The options for the Parser
|
||||||
|
*/
|
||||||
|
class Human2RegexParserOptions {
|
||||||
|
/**
|
||||||
|
* Constructor for Human2RegexParserOptions
|
||||||
|
*
|
||||||
|
* @param skip_validations If true, the lexer will skip validations (~25% faster)
|
||||||
|
*/
|
||||||
|
constructor(skip_validations = false) {
|
||||||
|
this.skip_validations = skip_validations;
|
||||||
|
/* empty */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
exports.Human2RegexParserOptions = Human2RegexParserOptions;
|
||||||
|
class TokenAndValue {
|
||||||
|
constructor(token, value) {
|
||||||
|
this.token = token;
|
||||||
|
this.value = value;
|
||||||
|
/* empty */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
class TokensAndValue {
|
||||||
|
constructor(tokens, value) {
|
||||||
|
this.tokens = tokens;
|
||||||
|
this.value = value;
|
||||||
|
/* empty */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* The Parser class
|
||||||
|
*
|
||||||
|
* @remarks Only 1 parser instance allowed due to performance reasons
|
||||||
|
*/
|
||||||
|
class Human2RegexParser extends chevrotain_1.EmbeddedActionsParser {
|
||||||
|
constructor(options = new Human2RegexParserOptions()) {
|
||||||
|
super(T.AllTokens, { recoveryEnabled: false, maxLookahead: 2, skipValidations: options.skip_validations });
|
||||||
|
this.options = options;
|
||||||
|
if (Human2RegexParser.already_init) {
|
||||||
|
throw new Error("Only 1 instance of Human2RegexParser allowed");
|
||||||
|
}
|
||||||
|
Human2RegexParser.already_init = true;
|
||||||
|
const $ = this;
|
||||||
|
/**
|
||||||
|
* IN REGARDS TO KEEPING TOKENS:
|
||||||
|
* We don't really need to keep each token, only the first and last tokens
|
||||||
|
* This is due to the fact we calculate the difference between those tokens
|
||||||
|
* However, sometimes we have optional starts and ends
|
||||||
|
* Each optional near the start and end MUST be recorded because they may be the first/last token
|
||||||
|
* ex) "optional match 3..." the start token is "optional", but "match 3..."'s start token is "match"
|
||||||
|
* */
|
||||||
|
// number rules
|
||||||
|
let nss_rules = null;
|
||||||
|
const NumberSubStatement = $.RULE("NumberSubStatement", () => {
|
||||||
|
return $.OR(nss_rules || (nss_rules = [
|
||||||
|
{ ALT: () => new TokenAndValue($.CONSUME(T.Zero), 0) },
|
||||||
|
{ ALT: () => new TokenAndValue($.CONSUME(T.One), 1) },
|
||||||
|
{ ALT: () => new TokenAndValue($.CONSUME(T.Two), 2) },
|
||||||
|
{ ALT: () => new TokenAndValue($.CONSUME(T.Three), 3) },
|
||||||
|
{ ALT: () => new TokenAndValue($.CONSUME(T.Four), 4) },
|
||||||
|
{ ALT: () => new TokenAndValue($.CONSUME(T.Five), 5) },
|
||||||
|
{ ALT: () => new TokenAndValue($.CONSUME(T.Six), 6) },
|
||||||
|
{ ALT: () => new TokenAndValue($.CONSUME(T.Seven), 7) },
|
||||||
|
{ ALT: () => new TokenAndValue($.CONSUME(T.Eight), 8) },
|
||||||
|
{ ALT: () => new TokenAndValue($.CONSUME(T.Nine), 9) },
|
||||||
|
{ ALT: () => new TokenAndValue($.CONSUME(T.Ten), 10) },
|
||||||
|
{ ALT: () => {
|
||||||
|
const tok = $.CONSUME(T.NumberLiteral);
|
||||||
|
return new TokenAndValue(tok, parseInt(tok.image));
|
||||||
|
} }
|
||||||
|
]));
|
||||||
|
});
|
||||||
|
// 1, 1..2, between 1 and/to 2 inclusively/exclusively
|
||||||
|
const CountSubStatement = $.RULE("CountSubStatement", () => {
|
||||||
|
return $.OR([
|
||||||
|
// between 1 to 4
|
||||||
|
{ ALT: () => {
|
||||||
|
const tokens = [];
|
||||||
|
tokens.push($.CONSUME(T.Between));
|
||||||
|
const from = $.SUBRULE4(NumberSubStatement);
|
||||||
|
$.OR3([
|
||||||
|
{ ALT: () => $.CONSUME2(T.To) },
|
||||||
|
{ ALT: () => $.CONSUME(T.And) }
|
||||||
|
]);
|
||||||
|
const to = $.SUBRULE5(NumberSubStatement);
|
||||||
|
tokens.push(to.token);
|
||||||
|
$.OPTION4(() => tokens.push($.CONSUME3(T.Times)));
|
||||||
|
const opt = $.OPTION5(() => {
|
||||||
|
return $.OR4([
|
||||||
|
{ ALT: () => {
|
||||||
|
tokens.push($.CONSUME(T.Inclusive));
|
||||||
|
return "inclusive";
|
||||||
|
} },
|
||||||
|
{ ALT: () => {
|
||||||
|
tokens.push($.CONSUME(T.Exclusive));
|
||||||
|
return "exclusive";
|
||||||
|
} }
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
return new generator_1.CountSubStatementCST(tokens, from.value, to.value, opt);
|
||||||
|
} },
|
||||||
|
// from 1 to 4
|
||||||
|
{ ALT: () => {
|
||||||
|
const tokens = [];
|
||||||
|
$.OPTION2(() => tokens.push($.CONSUME(T.From)));
|
||||||
|
const from = $.SUBRULE2(NumberSubStatement);
|
||||||
|
const to = $.OR2([
|
||||||
|
{ ALT: () => new TokenAndValue($.CONSUME(T.OrMore), [null, "+"]) },
|
||||||
|
{ ALT: () => {
|
||||||
|
$.CONSUME(T.To);
|
||||||
|
const val = $.SUBRULE3(NumberSubStatement);
|
||||||
|
return new TokenAndValue(val.token, [val.value, null]);
|
||||||
|
} }
|
||||||
|
]);
|
||||||
|
tokens.push(to.token);
|
||||||
|
$.OPTION3(() => tokens.push($.CONSUME2(T.Times)));
|
||||||
|
return new generator_1.CountSubStatementCST(tokens, from.value, to.value ? to.value[0] : null, to.value ? to.value[1] : null);
|
||||||
|
} },
|
||||||
|
// exactly 2
|
||||||
|
{ ALT: () => {
|
||||||
|
const tokens = [];
|
||||||
|
$.OPTION(() => tokens.push($.CONSUME(T.Exactly)));
|
||||||
|
const from = $.SUBRULE(NumberSubStatement);
|
||||||
|
tokens.push(from.token);
|
||||||
|
$.OPTION6(() => tokens.push($.CONSUME(T.Times)));
|
||||||
|
return new generator_1.CountSubStatementCST(tokens, from.value);
|
||||||
|
} }
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
// match sub rules
|
||||||
|
let mss_rules = null;
|
||||||
|
const MatchSubStatement = $.RULE("MatchSubStatement", () => {
|
||||||
|
let count = null;
|
||||||
|
let invert = false;
|
||||||
|
const values = [];
|
||||||
|
let from = null;
|
||||||
|
let value = null;
|
||||||
|
let to = null;
|
||||||
|
let type = generator_1.MatchSubStatementType.Anything;
|
||||||
|
let tokens = [];
|
||||||
|
count = $.OPTION(() => {
|
||||||
|
const css = $.SUBRULE(CountSubStatement);
|
||||||
|
if (utilities_1.usefulConditional(css.tokens, "due to how chevrotain works, the first run produces a null value")) {
|
||||||
|
tokens.push(utilities_1.first(css.tokens));
|
||||||
|
}
|
||||||
|
return css;
|
||||||
|
});
|
||||||
|
invert = $.OPTION2(() => {
|
||||||
|
tokens.push($.CONSUME(T.Not));
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
$.AT_LEAST_ONE_SEP({
|
||||||
|
SEP: T.Or,
|
||||||
|
DEF: () => {
|
||||||
|
$.OPTION3(() => $.CONSUME(T.A));
|
||||||
|
const result = $.OR(mss_rules || (mss_rules = [
|
||||||
|
// range [a-z]
|
||||||
|
{ ALT: () => {
|
||||||
|
const token0 = $.OPTION4(() => $.CONSUME(T.From));
|
||||||
|
const token1 = $.CONSUME2(T.StringLiteral);
|
||||||
|
from = token1.image;
|
||||||
|
$.CONSUME(T.To);
|
||||||
|
const token2 = $.CONSUME3(T.StringLiteral);
|
||||||
|
to = token2.image;
|
||||||
|
type = generator_1.MatchSubStatementType.Between;
|
||||||
|
if (utilities_1.usefulConditional(token0, "Bug in type definition. Option should return <T|undefined>, but it doesn't")) {
|
||||||
|
return { tokens: [token0, token2], statement: new generator_1.MatchSubStatementValue(type, from, to) };
|
||||||
|
}
|
||||||
|
return { tokens: [token1, token2], statement: new generator_1.MatchSubStatementValue(type, from, to) };
|
||||||
|
} },
|
||||||
|
// range [a-z]
|
||||||
|
{ ALT: () => {
|
||||||
|
const token1 = $.CONSUME(T.Between);
|
||||||
|
from = $.CONSUME4(T.StringLiteral).image;
|
||||||
|
$.CONSUME(T.And);
|
||||||
|
const token2 = $.CONSUME5(T.StringLiteral);
|
||||||
|
to = token2.image;
|
||||||
|
type = generator_1.MatchSubStatementType.Between;
|
||||||
|
return { tokens: [token1, token2], statement: new generator_1.MatchSubStatementValue(type, from, to) };
|
||||||
|
} },
|
||||||
|
// exact string
|
||||||
|
{ ALT: () => {
|
||||||
|
const token = $.CONSUME(T.StringLiteral);
|
||||||
|
value = token.image;
|
||||||
|
type = generator_1.MatchSubStatementType.SingleString;
|
||||||
|
return { tokens: [token], statement: new generator_1.MatchSubStatementValue(type, value) };
|
||||||
|
} },
|
||||||
|
//unicode
|
||||||
|
{ ALT: () => {
|
||||||
|
const token1 = $.CONSUME(T.Unicode);
|
||||||
|
const token2 = $.CONSUME6(T.StringLiteral);
|
||||||
|
value = token2.image;
|
||||||
|
type = generator_1.MatchSubStatementType.Unicode;
|
||||||
|
return { tokens: [token1, token2], statement: new generator_1.MatchSubStatementValue(type, value) };
|
||||||
|
} },
|
||||||
|
{ ALT: () => {
|
||||||
|
const token = $.CONSUME(T.Anything);
|
||||||
|
type = generator_1.MatchSubStatementType.Anything;
|
||||||
|
return { tokens: [token], statement: new generator_1.MatchSubStatementValue(type) };
|
||||||
|
} },
|
||||||
|
{ ALT: () => {
|
||||||
|
const token = $.CONSUME(T.Boundary);
|
||||||
|
type = generator_1.MatchSubStatementType.Boundary;
|
||||||
|
return { tokens: [token], statement: new generator_1.MatchSubStatementValue(type) };
|
||||||
|
} },
|
||||||
|
{ ALT: () => {
|
||||||
|
const token = $.CONSUME(T.Word);
|
||||||
|
type = generator_1.MatchSubStatementType.Word;
|
||||||
|
return { tokens: [token], statement: new generator_1.MatchSubStatementValue(type) };
|
||||||
|
} },
|
||||||
|
{ ALT: () => {
|
||||||
|
const token = $.CONSUME(T.Digit);
|
||||||
|
type = generator_1.MatchSubStatementType.Digit;
|
||||||
|
return { tokens: [token], statement: new generator_1.MatchSubStatementValue(type) };
|
||||||
|
} },
|
||||||
|
{ ALT: () => {
|
||||||
|
const token = $.CONSUME(T.Character);
|
||||||
|
type = generator_1.MatchSubStatementType.Character;
|
||||||
|
return { tokens: [token], statement: new generator_1.MatchSubStatementValue(type) };
|
||||||
|
} },
|
||||||
|
{ ALT: () => {
|
||||||
|
const token = $.CONSUME(T.Whitespace);
|
||||||
|
type = generator_1.MatchSubStatementType.Whitespace;
|
||||||
|
return { tokens: [token], statement: new generator_1.MatchSubStatementValue(type) };
|
||||||
|
} },
|
||||||
|
{ ALT: () => {
|
||||||
|
const token = $.CONSUME(T.Number);
|
||||||
|
type = generator_1.MatchSubStatementType.Number;
|
||||||
|
return { tokens: [token], statement: new generator_1.MatchSubStatementValue(type) };
|
||||||
|
} },
|
||||||
|
{ ALT: () => {
|
||||||
|
const token = $.CONSUME(T.Tab);
|
||||||
|
type = generator_1.MatchSubStatementType.Tab;
|
||||||
|
return { tokens: [token], statement: new generator_1.MatchSubStatementValue(type) };
|
||||||
|
} },
|
||||||
|
{ ALT: () => {
|
||||||
|
const token = $.CONSUME(T.Linefeed);
|
||||||
|
type = generator_1.MatchSubStatementType.Linefeed;
|
||||||
|
return { tokens: [token], statement: new generator_1.MatchSubStatementValue(type) };
|
||||||
|
} },
|
||||||
|
{ ALT: () => {
|
||||||
|
const token = $.CONSUME(T.Newline);
|
||||||
|
type = generator_1.MatchSubStatementType.Newline;
|
||||||
|
return { tokens: [token], statement: new generator_1.MatchSubStatementValue(type) };
|
||||||
|
} },
|
||||||
|
{ ALT: () => {
|
||||||
|
const token = $.CONSUME(T.CarriageReturn);
|
||||||
|
type = generator_1.MatchSubStatementType.CarriageReturn;
|
||||||
|
return { tokens: [token], statement: new generator_1.MatchSubStatementValue(type) };
|
||||||
|
} },
|
||||||
|
]));
|
||||||
|
tokens = tokens.concat(result.tokens);
|
||||||
|
values.push(result.statement);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return new generator_1.MatchSubStatementCST(tokens, count, invert, values);
|
||||||
|
});
|
||||||
|
// optionally match "+" then 1+ words
|
||||||
|
const MatchStatement = $.RULE("MatchStatement", () => {
|
||||||
|
let optional = false;
|
||||||
|
const msv = [];
|
||||||
|
const tokens = [];
|
||||||
|
$.OPTION(() => {
|
||||||
|
tokens.push($.CONSUME(T.Optional));
|
||||||
|
optional = true;
|
||||||
|
});
|
||||||
|
tokens.push($.CONSUME(T.Match));
|
||||||
|
msv.push(new generator_1.MatchStatementValue(optional, $.SUBRULE(MatchSubStatement)));
|
||||||
|
$.MANY(() => {
|
||||||
|
$.OR([
|
||||||
|
{ ALT: () => {
|
||||||
|
$.OPTION2(() => $.CONSUME2(T.And));
|
||||||
|
$.CONSUME(T.Then);
|
||||||
|
} },
|
||||||
|
{ ALT: () => $.CONSUME(T.And) },
|
||||||
|
]);
|
||||||
|
optional = false;
|
||||||
|
$.OPTION3(() => {
|
||||||
|
$.CONSUME2(T.Optional);
|
||||||
|
optional = true;
|
||||||
|
});
|
||||||
|
msv.push(new generator_1.MatchStatementValue(optional, $.SUBRULE2(MatchSubStatement)));
|
||||||
|
});
|
||||||
|
tokens.push($.CONSUME(T.EndOfLine));
|
||||||
|
return new generator_1.MatchStatementCST(tokens, msv);
|
||||||
|
});
|
||||||
|
// using global matching
|
||||||
|
let us_rules = null;
|
||||||
|
const UsingStatement = $.RULE("UsingStatement", () => {
|
||||||
|
const usings = [];
|
||||||
|
const tokens = [$.CONSUME(T.Using)];
|
||||||
|
$.AT_LEAST_ONE_SEP({
|
||||||
|
SEP: T.And,
|
||||||
|
DEF: () => {
|
||||||
|
usings.push($.OR(us_rules || (us_rules = [
|
||||||
|
{ ALT: () => {
|
||||||
|
$.CONSUME(T.Multiline);
|
||||||
|
return generator_1.UsingFlags.Multiline;
|
||||||
|
} },
|
||||||
|
{ ALT: () => {
|
||||||
|
$.CONSUME(T.Global);
|
||||||
|
return generator_1.UsingFlags.Global;
|
||||||
|
} },
|
||||||
|
{ ALT: () => {
|
||||||
|
$.CONSUME(T.CaseInsensitive);
|
||||||
|
return generator_1.UsingFlags.Insensitive;
|
||||||
|
} },
|
||||||
|
{ ALT: () => {
|
||||||
|
$.CONSUME(T.CaseSensitive);
|
||||||
|
return generator_1.UsingFlags.Sensitive;
|
||||||
|
} },
|
||||||
|
{ ALT: () => {
|
||||||
|
$.CONSUME(T.Exact);
|
||||||
|
return generator_1.UsingFlags.Exact;
|
||||||
|
} }
|
||||||
|
])));
|
||||||
|
$.OPTION(() => $.CONSUME(T.Matching));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
tokens.push($.CONSUME(T.EndOfLine));
|
||||||
|
return new TokensAndValue(tokens, usings);
|
||||||
|
});
|
||||||
|
// group rules
|
||||||
|
const GroupStatement = $.RULE("GroupStatement", () => {
|
||||||
|
const tokens = [];
|
||||||
|
let optional = false;
|
||||||
|
let name = null;
|
||||||
|
const statement = [];
|
||||||
|
// position of optional must be OR'd because
|
||||||
|
// otherwise it could appear twice
|
||||||
|
// ex) optional? create an optional? group
|
||||||
|
tokens.push($.OR([
|
||||||
|
{ ALT: () => {
|
||||||
|
optional = true;
|
||||||
|
const first_token = $.CONSUME(T.Optional);
|
||||||
|
$.CONSUME(T.Create);
|
||||||
|
$.CONSUME(T.A);
|
||||||
|
return first_token;
|
||||||
|
} },
|
||||||
|
{ ALT: () => {
|
||||||
|
const first_token = $.CONSUME2(T.Create);
|
||||||
|
$.CONSUME2(T.A);
|
||||||
|
$.OPTION2(() => {
|
||||||
|
$.CONSUME2(T.Optional);
|
||||||
|
optional = true;
|
||||||
|
});
|
||||||
|
return first_token;
|
||||||
|
} }
|
||||||
|
]));
|
||||||
|
$.CONSUME(T.Group);
|
||||||
|
$.OPTION(() => {
|
||||||
|
$.CONSUME(T.Called);
|
||||||
|
name = $.CONSUME(T.Identifier).image;
|
||||||
|
});
|
||||||
|
// Note: Technically not the end token,
|
||||||
|
// BUT this is way more useful than the Outdent for error reporting
|
||||||
|
tokens.push($.CONSUME2(T.EndOfLine));
|
||||||
|
$.CONSUME(T.Indent);
|
||||||
|
$.AT_LEAST_ONE(() => {
|
||||||
|
statement.push($.SUBRULE(Statement));
|
||||||
|
});
|
||||||
|
$.CONSUME(T.Outdent);
|
||||||
|
return new generator_1.GroupStatementCST(tokens, optional, name, statement);
|
||||||
|
});
|
||||||
|
// repeat rules
|
||||||
|
const RepeatStatement = $.RULE("RepeatStatement", () => {
|
||||||
|
const tokens = [];
|
||||||
|
let optional = false;
|
||||||
|
let count = null;
|
||||||
|
const statements = [];
|
||||||
|
$.OPTION3(() => {
|
||||||
|
tokens.push($.CONSUME(T.Optional));
|
||||||
|
optional = true;
|
||||||
|
});
|
||||||
|
tokens.push($.CONSUME(T.Repeat));
|
||||||
|
$.OPTION(() => count = $.SUBRULE(CountSubStatement));
|
||||||
|
$.CONSUME3(T.EndOfLine);
|
||||||
|
$.CONSUME(T.Indent);
|
||||||
|
$.AT_LEAST_ONE(() => {
|
||||||
|
statements.push($.SUBRULE(Statement));
|
||||||
|
});
|
||||||
|
tokens.push($.CONSUME(T.Outdent));
|
||||||
|
return new generator_1.RepeatStatementCST(tokens, optional, count, statements);
|
||||||
|
});
|
||||||
|
// statement super class
|
||||||
|
const Statement = $.RULE("Statement", () => {
|
||||||
|
return $.OR([
|
||||||
|
{ ALT: () => $.SUBRULE(MatchStatement) },
|
||||||
|
{ ALT: () => $.SUBRULE(GroupStatement) },
|
||||||
|
{ ALT: () => $.SUBRULE(RepeatStatement) }
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
// full regex
|
||||||
|
const Regex = $.RULE("Regex", () => {
|
||||||
|
let tokens = [];
|
||||||
|
let usings = [];
|
||||||
|
const statements = [];
|
||||||
|
$.MANY(() => {
|
||||||
|
const using = $.SUBRULE(UsingStatement);
|
||||||
|
tokens = tokens.concat(using.tokens);
|
||||||
|
usings = usings.concat(using.value);
|
||||||
|
});
|
||||||
|
$.MANY2(() => statements.push($.SUBRULE(Statement)));
|
||||||
|
return new generator_1.RegularExpressionCST([], new generator_1.UsingStatementCST(tokens, usings), statements);
|
||||||
|
});
|
||||||
|
this.performSelfAnalysis();
|
||||||
|
this.parse = Regex;
|
||||||
|
}
|
||||||
|
setOptions(options) {
|
||||||
|
utilities_1.unusedParameter(options, "skip_validations is not valid to change once we've already initialized");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
exports.Human2RegexParser = Human2RegexParser;
|
||||||
|
Human2RegexParser.already_init = false;
|
65
lib/tokens.d.ts
vendored
Normal file
65
lib/tokens.d.ts
vendored
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
/*! Copyright (c) 2020 Patrick Demian; Licensed under MIT */
|
||||||
|
/** @internal */ export declare const Zero: import("chevrotain").TokenType;
|
||||||
|
/** @internal */ export declare const One: import("chevrotain").TokenType;
|
||||||
|
/** @internal */ export declare const Two: import("chevrotain").TokenType;
|
||||||
|
/** @internal */ export declare const Three: import("chevrotain").TokenType;
|
||||||
|
/** @internal */ export declare const Four: import("chevrotain").TokenType;
|
||||||
|
/** @internal */ export declare const Five: import("chevrotain").TokenType;
|
||||||
|
/** @internal */ export declare const Six: import("chevrotain").TokenType;
|
||||||
|
/** @internal */ export declare const Seven: import("chevrotain").TokenType;
|
||||||
|
/** @internal */ export declare const Eight: import("chevrotain").TokenType;
|
||||||
|
/** @internal */ export declare const Nine: import("chevrotain").TokenType;
|
||||||
|
/** @internal */ export declare const Ten: import("chevrotain").TokenType;
|
||||||
|
/** @internal */ export declare const Optional: import("chevrotain").TokenType;
|
||||||
|
/** @internal */ export declare const Match: import("chevrotain").TokenType;
|
||||||
|
/** @internal */ export declare const Then: import("chevrotain").TokenType;
|
||||||
|
/** @internal */ export declare const Anything: import("chevrotain").TokenType;
|
||||||
|
/** @internal */ export declare const Or: import("chevrotain").TokenType;
|
||||||
|
/** @internal */ export declare const And: import("chevrotain").TokenType;
|
||||||
|
/** @internal */ export declare const Word: import("chevrotain").TokenType;
|
||||||
|
/** @internal */ export declare const Digit: import("chevrotain").TokenType;
|
||||||
|
/** @internal */ export declare const Character: import("chevrotain").TokenType;
|
||||||
|
/** @internal */ export declare const Whitespace: import("chevrotain").TokenType;
|
||||||
|
/** @internal */ export declare const Boundary: import("chevrotain").TokenType;
|
||||||
|
/** @internal */ export declare const Number: import("chevrotain").TokenType;
|
||||||
|
/** @internal */ export declare const Unicode: import("chevrotain").TokenType;
|
||||||
|
/** @internal */ export declare const Using: import("chevrotain").TokenType;
|
||||||
|
/** @internal */ export declare const Global: import("chevrotain").TokenType;
|
||||||
|
/** @internal */ export declare const Multiline: import("chevrotain").TokenType;
|
||||||
|
/** @internal */ export declare const Exact: import("chevrotain").TokenType;
|
||||||
|
/** @internal */ export declare const Matching: import("chevrotain").TokenType;
|
||||||
|
/** @internal */ export declare const Not: import("chevrotain").TokenType;
|
||||||
|
/** @internal */ export declare const Between: import("chevrotain").TokenType;
|
||||||
|
/** @internal */ export declare const Tab: import("chevrotain").TokenType;
|
||||||
|
/** @internal */ export declare const Linefeed: import("chevrotain").TokenType;
|
||||||
|
/** @internal */ export declare const Group: import("chevrotain").TokenType;
|
||||||
|
/** @internal */ export declare const A: import("chevrotain").TokenType;
|
||||||
|
/** @internal */ export declare const Times: import("chevrotain").TokenType;
|
||||||
|
/** @internal */ export declare const Exactly: import("chevrotain").TokenType;
|
||||||
|
/** @internal */ export declare const Inclusive: import("chevrotain").TokenType;
|
||||||
|
/** @internal */ export declare const Exclusive: import("chevrotain").TokenType;
|
||||||
|
/** @internal */ export declare const From: import("chevrotain").TokenType;
|
||||||
|
/** @internal */ export declare const To: import("chevrotain").TokenType;
|
||||||
|
/** @internal */ export declare const Create: import("chevrotain").TokenType;
|
||||||
|
/** @internal */ export declare const Called: import("chevrotain").TokenType;
|
||||||
|
/** @internal */ export declare const Repeat: import("chevrotain").TokenType;
|
||||||
|
/** @internal */ export declare const Newline: import("chevrotain").TokenType;
|
||||||
|
/** @internal */ export declare const CarriageReturn: import("chevrotain").TokenType;
|
||||||
|
/** @internal */ export declare const CaseInsensitive: import("chevrotain").TokenType;
|
||||||
|
/** @internal */ export declare const CaseSensitive: import("chevrotain").TokenType;
|
||||||
|
/** @internal */ export declare const OrMore: import("chevrotain").TokenType;
|
||||||
|
/** @internal */ export declare const EndOfLine: import("chevrotain").TokenType;
|
||||||
|
/** @internal */ export declare const WS: import("chevrotain").TokenType;
|
||||||
|
/** @internal */ export declare const SingleLineComment: import("chevrotain").TokenType;
|
||||||
|
/** @internal */ export declare const MultilineComment: import("chevrotain").TokenType;
|
||||||
|
/** @internal */ export declare const Identifier: import("chevrotain").TokenType;
|
||||||
|
/** @internal */ export declare const NumberLiteral: import("chevrotain").TokenType;
|
||||||
|
/** @internal */ export declare const StringLiteral: import("chevrotain").TokenType;
|
||||||
|
/** @internal */ export declare const Indent: import("chevrotain").TokenType;
|
||||||
|
/** @internal */ export declare const Outdent: import("chevrotain").TokenType;
|
||||||
|
/**
|
||||||
|
* All the tokens used
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
export declare const AllTokens: import("chevrotain").TokenType[];
|
||||||
|
//# sourceMappingURL=tokens.d.ts.map
|
1
lib/tokens.d.ts.map
Normal file
1
lib/tokens.d.ts.map
Normal file
@ -0,0 +1 @@
|
|||||||
|
{"version":3,"file":"tokens.d.ts","sourceRoot":"","sources":["../src/tokens.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAS5D,gBAAgB,CAAC,eAAO,MAAM,IAAI,gCAAgD,CAAC;AACnF,gBAAgB,CAAC,eAAO,MAAM,GAAG,gCAA8C,CAAC;AAChF,gBAAgB,CAAC,eAAO,MAAM,GAAG,gCAA8C,CAAC;AAChF,gBAAgB,CAAC,eAAO,MAAM,KAAK,gCAAkD,CAAC;AACtF,gBAAgB,CAAC,eAAO,MAAM,IAAI,gCAAgD,CAAC;AACnF,gBAAgB,CAAC,eAAO,MAAM,IAAI,gCAAgD,CAAC;AACnF,gBAAgB,CAAC,eAAO,MAAM,GAAG,gCAA8C,CAAC;AAChF,gBAAgB,CAAC,eAAO,MAAM,KAAK,gCAAkD,CAAC;AACtF,gBAAgB,CAAC,eAAO,MAAM,KAAK,gCAAkD,CAAC;AACtF,gBAAgB,CAAC,eAAO,MAAM,IAAI,gCAAgD,CAAC;AACnF,gBAAgB,CAAC,eAAO,MAAM,GAAG,gCAA8C,CAAC;AAEhF,gBAAgB,CAAC,eAAO,MAAM,QAAQ,gCAA2E,CAAC;AAClH,gBAAgB,CAAC,eAAO,MAAM,KAAK,gCAAuD,CAAC;AAC3F,gBAAgB,CAAC,eAAO,MAAM,IAAI,gCAAgD,CAAC;AACnF,gBAAgB,CAAC,eAAO,MAAM,QAAQ,gCAA4E,CAAC;AACnH,gBAAgB,CAAC,eAAO,MAAM,EAAE,gCAA4C,CAAC;AAC7E,gBAAgB,CAAC,eAAO,MAAM,GAAG,gCAAgD,CAAC;AAClF,gBAAgB,CAAC,eAAO,MAAM,IAAI,gCAA6D,CAAC;AAChG,gBAAgB,CAAC,eAAO,MAAM,KAAK,gCAA+D,CAAC;AACnG,gBAAgB,CAAC,eAAO,MAAM,SAAS,gCAA8E,CAAC;AACtH,gBAAgB,CAAC,eAAO,MAAM,UAAU,gCAAqF,CAAC;AAC9H,gBAAgB,CAAC,eAAO,MAAM,QAAQ,gCAAwE,CAAC;AAC/G,gBAAgB,CAAC,eAAO,MAAM,MAAM,gCAAiE,CAAC;AACtG,gBAAgB,CAAC,eAAO,MAAM,OAAO,gCAAwE,CAAC;AAC9G,gBAAgB,CAAC,eAAO,MAAM,KAAK,gCAAkD,CAAC;AACtF,gBAAgB,CAAC,eAAO,MAAM,MAAM,gCAAoD,CAAC;AACzF,gBAAgB,CAAC,eAAO,MAAM,SAAS,gCAAuE,CAAC;AAC/G,gBAAgB,CAAC,eAAO,MAAM,KAAK,gCAAkD,CAAC;AACtF,gBAAgB,CAAC,eAAO,MAAM,QAAQ,gCAAwD,CAAC;AAC/F,gBAAgB,CAAC,eAAO,MAAM,GAAG,gCAA8C,CAAC;AAChF,gBAAgB,CAAC,eAAO,MAAM,OAAO,gCAAsD,CAAC;AAC5F,gBAAgB,CAAC,eAAO,MAAM,GAAG,gCAA8C,CAAC;AAChF,gBAAgB,CAAC,eAAO,MAAM,QAAQ,gCAAoE,CAAC;AAC3G,gBAAgB,CAAC,eAAO,MAAM,KAAK,gCAAkD,CAAC;AACtF,gBAAgB,CAAC,eAAO,MAAM,CAAC,gCAA+C,CAAC;AAC/E,gBAAgB,CAAC,eAAO,MAAM,KAAK,gCAAkD,CAAC;AACtF,gBAAgB,CAAC,eAAO,MAAM,OAAO,gCAAyD,CAAC;AAC/F,gBAAgB,CAAC,eAAO,MAAM,SAAS,gCAA+D,CAAC;AACvG,gBAAgB,CAAC,eAAO,MAAM,SAAS,gCAA+D,CAAC;AACvG,gBAAgB,CAAC,eAAO,MAAM,IAAI,gCAAgD,CAAC;AACnF,gBAAgB,CAAC,eAAO,MAAM,EAAE,gCAA0E,CAAC;AAC3G,gBAAgB,CAAC,eAAO,MAAM,MAAM,gCAAwD,CAAC;AAC7F,gBAAgB,CAAC,eAAO,MAAM,MAAM,gCAAgE,CAAC;AACrG,gBAAgB,CAAC,eAAO,MAAM,MAAM,gCAA4D,CAAC;AACjG,gBAAgB,CAAC,eAAO,MAAM,OAAO,gCAAiE,CAAC;AACvG,gBAAgB,CAAC,eAAO,MAAM,cAAc,gCAAqE,CAAC;AAClH,gBAAgB,CAAC,eAAO,MAAM,eAAe,gCAAuE,CAAC;AACrH,gBAAgB,CAAC,eAAO,MAAM,aAAa,gCAAmE,CAAC;AAC/G,gBAAgB,CAAC,eAAO,MAAM,MAAM,gCAAwD,CAAC;AAuB7F,gBAAgB,CAAC,eAAO,MAAM,SAAS,gCAA4C,CAAC;AACpF,gBAAgB,CAAC,eAAO,MAAM,EAAE,gCAAgH,CAAC;AACjJ,gBAAgB,CAAC,eAAO,MAAM,iBAAiB,gCAAwF,CAAC;AACxI,gBAAgB,CAAC,eAAO,MAAM,gBAAgB,gCAA4G,CAAC;AAE3J,gBAAgB,CAAC,eAAO,MAAM,UAAU,gCAA0D,CAAC;AACnG,gBAAgB,CAAC,eAAO,MAAM,aAAa,gCAAyD,CAAC;AACrG,gBAAgB,CAAC,eAAO,MAAM,aAAa,gCAA+G,CAAC;AAE3J,gBAAgB,CAAC,eAAO,MAAM,MAAM,gCAAgC,CAAC;AACrE,gBAAgB,CAAC,eAAO,MAAM,OAAO,gCAAiC,CAAC;AAEvE;;;GAGG;AACH,eAAO,MAAM,SAAS,kCA0ErB,CAAC"}
|
165
lib/tokens.js
Normal file
165
lib/tokens.js
Normal file
@ -0,0 +1,165 @@
|
|||||||
|
"use strict";
|
||||||
|
/*! Copyright (c) 2020 Patrick Demian; Licensed under MIT */
|
||||||
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
|
exports.AllTokens = exports.Outdent = exports.Indent = exports.StringLiteral = exports.NumberLiteral = exports.Identifier = exports.MultilineComment = exports.SingleLineComment = exports.WS = exports.EndOfLine = exports.OrMore = exports.CaseSensitive = exports.CaseInsensitive = exports.CarriageReturn = exports.Newline = exports.Repeat = exports.Called = exports.Create = exports.To = exports.From = exports.Exclusive = exports.Inclusive = exports.Exactly = exports.Times = exports.A = exports.Group = exports.Linefeed = exports.Tab = exports.Between = exports.Not = exports.Matching = exports.Exact = exports.Multiline = exports.Global = exports.Using = exports.Unicode = exports.Number = exports.Boundary = exports.Whitespace = exports.Character = exports.Digit = exports.Word = exports.And = exports.Or = exports.Anything = exports.Then = exports.Match = exports.Optional = exports.Ten = exports.Nine = exports.Eight = exports.Seven = exports.Six = exports.Five = exports.Four = exports.Three = exports.Two = exports.One = exports.Zero = void 0;
|
||||||
|
/**
|
||||||
|
* The tokens required for Human2Regex
|
||||||
|
* @packageDocumentation
|
||||||
|
*/
|
||||||
|
const chevrotain_1 = require("chevrotain");
|
||||||
|
/** @internal */ exports.Zero = chevrotain_1.createToken({ name: "Zero", pattern: /zero/i });
|
||||||
|
/** @internal */ exports.One = chevrotain_1.createToken({ name: "One", pattern: /one/i });
|
||||||
|
/** @internal */ exports.Two = chevrotain_1.createToken({ name: "Two", pattern: /two/i });
|
||||||
|
/** @internal */ exports.Three = chevrotain_1.createToken({ name: "Three", pattern: /three/i });
|
||||||
|
/** @internal */ exports.Four = chevrotain_1.createToken({ name: "Four", pattern: /four/i });
|
||||||
|
/** @internal */ exports.Five = chevrotain_1.createToken({ name: "Five", pattern: /five/i });
|
||||||
|
/** @internal */ exports.Six = chevrotain_1.createToken({ name: "Six", pattern: /six/i });
|
||||||
|
/** @internal */ exports.Seven = chevrotain_1.createToken({ name: "Seven", pattern: /seven/i });
|
||||||
|
/** @internal */ exports.Eight = chevrotain_1.createToken({ name: "Eight", pattern: /eight/i });
|
||||||
|
/** @internal */ exports.Nine = chevrotain_1.createToken({ name: "Nine", pattern: /nine/i });
|
||||||
|
/** @internal */ exports.Ten = chevrotain_1.createToken({ name: "Ten", pattern: /ten/i });
|
||||||
|
/** @internal */ exports.Optional = chevrotain_1.createToken({ name: "Optional", pattern: /(optional(ly)?|possibl[ye])/i });
|
||||||
|
/** @internal */ exports.Match = chevrotain_1.createToken({ name: "Match", pattern: /match(es)?/i });
|
||||||
|
/** @internal */ exports.Then = chevrotain_1.createToken({ name: "Then", pattern: /then/i });
|
||||||
|
/** @internal */ exports.Anything = chevrotain_1.createToken({ name: "Anything", pattern: /(any thing|any|anything)(s)?/i });
|
||||||
|
/** @internal */ exports.Or = chevrotain_1.createToken({ name: "Or", pattern: /or/i });
|
||||||
|
/** @internal */ exports.And = chevrotain_1.createToken({ name: "And", pattern: /and|,/i });
|
||||||
|
/** @internal */ exports.Word = chevrotain_1.createToken({ name: "WordSpecifier", pattern: /word(s)?/i });
|
||||||
|
/** @internal */ exports.Digit = chevrotain_1.createToken({ name: "DigitSpecifier", pattern: /digit(s)?/i });
|
||||||
|
/** @internal */ exports.Character = chevrotain_1.createToken({ name: "CharacterSpecifier", pattern: /(character|letter)s?/i });
|
||||||
|
/** @internal */ exports.Whitespace = chevrotain_1.createToken({ name: "WhitespaceSpecifier", pattern: /(white space|whitespace)s?/i });
|
||||||
|
/** @internal */ exports.Boundary = chevrotain_1.createToken({ name: "BoundarySpecifier", pattern: /(word )boundary/i });
|
||||||
|
/** @internal */ exports.Number = chevrotain_1.createToken({ name: "NumberSpecifier", pattern: /number(s)?/i });
|
||||||
|
/** @internal */ exports.Unicode = chevrotain_1.createToken({ name: "UnicodeSpecifier", pattern: /unicode( class)?/i });
|
||||||
|
/** @internal */ exports.Using = chevrotain_1.createToken({ name: "Using", pattern: /using/i });
|
||||||
|
/** @internal */ exports.Global = chevrotain_1.createToken({ name: "Global", pattern: /global/i });
|
||||||
|
/** @internal */ exports.Multiline = chevrotain_1.createToken({ name: "Multiline", pattern: /(multi line|multiline)/i });
|
||||||
|
/** @internal */ exports.Exact = chevrotain_1.createToken({ name: "Exact", pattern: /exact/i });
|
||||||
|
/** @internal */ exports.Matching = chevrotain_1.createToken({ name: "Matching", pattern: /matching/i });
|
||||||
|
/** @internal */ exports.Not = chevrotain_1.createToken({ name: "Not", pattern: /not/i });
|
||||||
|
/** @internal */ exports.Between = chevrotain_1.createToken({ name: "Between", pattern: /between/i });
|
||||||
|
/** @internal */ exports.Tab = chevrotain_1.createToken({ name: "Tab", pattern: /tab/i });
|
||||||
|
/** @internal */ exports.Linefeed = chevrotain_1.createToken({ name: "Linefeed", pattern: /(line feed|linefeed)/i });
|
||||||
|
/** @internal */ exports.Group = chevrotain_1.createToken({ name: "Group", pattern: /group/i });
|
||||||
|
/** @internal */ exports.A = chevrotain_1.createToken({ name: "A", pattern: /a(n)?/i });
|
||||||
|
/** @internal */ exports.Times = chevrotain_1.createToken({ name: "Times", pattern: /times/i });
|
||||||
|
/** @internal */ exports.Exactly = chevrotain_1.createToken({ name: "Exactly", pattern: /exact(ly)?/i });
|
||||||
|
/** @internal */ exports.Inclusive = chevrotain_1.createToken({ name: "Inclusive", pattern: /inclusive(ly)?/i });
|
||||||
|
/** @internal */ exports.Exclusive = chevrotain_1.createToken({ name: "Exclusive", pattern: /exclusive(ly)?/i });
|
||||||
|
/** @internal */ exports.From = chevrotain_1.createToken({ name: "From", pattern: /from/i });
|
||||||
|
/** @internal */ exports.To = chevrotain_1.createToken({ name: "To", pattern: /(to|through|thru|\-|\.\.|\.\.\.)/i });
|
||||||
|
/** @internal */ exports.Create = chevrotain_1.createToken({ name: "Create", pattern: /create(s)?/i });
|
||||||
|
/** @internal */ exports.Called = chevrotain_1.createToken({ name: "Called", pattern: /name(d)?|call(ed)?/i });
|
||||||
|
/** @internal */ exports.Repeat = chevrotain_1.createToken({ name: "Repeat", pattern: /repeat(s|ing)?/i });
|
||||||
|
/** @internal */ exports.Newline = chevrotain_1.createToken({ name: "Newline", pattern: /(new line|newline)/i });
|
||||||
|
/** @internal */ exports.CarriageReturn = chevrotain_1.createToken({ name: "CarriageReturn", pattern: /carriage return/i });
|
||||||
|
/** @internal */ exports.CaseInsensitive = chevrotain_1.createToken({ name: "CaseInsensitive", pattern: /case insensitive/i });
|
||||||
|
/** @internal */ exports.CaseSensitive = chevrotain_1.createToken({ name: "CaseSensitive", pattern: /case sensitive/i });
|
||||||
|
/** @internal */ exports.OrMore = chevrotain_1.createToken({ name: "OrMore", pattern: /\+|or more/i });
|
||||||
|
/*
|
||||||
|
//Not being used currently
|
||||||
|
export const Of = createToken({name: "Of", pattern: /of/i});
|
||||||
|
export const Nothing = createToken({name: "Nothing", pattern: /nothing/i});
|
||||||
|
export const As = createToken({name: "As", pattern: /as/i});
|
||||||
|
export const If = createToken({name: "If", pattern: /if/i});
|
||||||
|
export const Start = createToken({name: "Start", pattern: /start(s) with?/i});
|
||||||
|
export const Ends = createToken({name: "Ends", pattern: /end(s)? with/i});
|
||||||
|
export const Else = createToken({name: "Else", pattern: /(other wise|otherwise|else)/i});
|
||||||
|
export const Unless = createToken({name: "Unless", pattern: /unless/i});
|
||||||
|
export const While = createToken({name: "While", pattern: /while/i});
|
||||||
|
export const More = createToken({name: "More", pattern: /more/i});
|
||||||
|
export const LBracket = createToken({name: "Left Bracket", pattern: /\(/ });
|
||||||
|
export const RBracket = createToken({name: "Right Bracket", pattern: /\)/ });
|
||||||
|
export const None = createToken({name: "None", pattern: /none/i});
|
||||||
|
export const Neither = createToken({name: "Neither", pattern: /neither/i});
|
||||||
|
export const The = createToken({name: "The", pattern: /the/i }); //, longer_alt: Then});
|
||||||
|
export const By = createToken({name: "By", pattern: /by/i});
|
||||||
|
*/
|
||||||
|
/** @internal */ exports.EndOfLine = chevrotain_1.createToken({ name: "EOL", pattern: /\n/ });
|
||||||
|
/** @internal */ exports.WS = chevrotain_1.createToken({ name: "Whitespace", pattern: /[^\S\n]+/, start_chars_hint: [" ", "\r"], group: chevrotain_1.Lexer.SKIPPED });
|
||||||
|
/** @internal */ exports.SingleLineComment = chevrotain_1.createToken({ name: "SingleLineComment", pattern: /(#|\/\/).*/, group: chevrotain_1.Lexer.SKIPPED });
|
||||||
|
/** @internal */ exports.MultilineComment = chevrotain_1.createToken({ name: "MultiLineComment", pattern: /\/\*(.*)\*\//, line_breaks: true, group: chevrotain_1.Lexer.SKIPPED });
|
||||||
|
/** @internal */ exports.Identifier = chevrotain_1.createToken({ name: "Identifier", pattern: /[a-z]\w*/i });
|
||||||
|
/** @internal */ exports.NumberLiteral = chevrotain_1.createToken({ name: "NumberLiteral", pattern: /-?\d+/ });
|
||||||
|
/** @internal */ exports.StringLiteral = chevrotain_1.createToken({ name: "StringLiteral", pattern: /"(?:[^\\"]|\\(?:[bfnrtv"\\/]|u[0-9a-f]{4}|U[0-9a-f]{8}))*"/i });
|
||||||
|
/** @internal */ exports.Indent = chevrotain_1.createToken({ name: "Indent" });
|
||||||
|
/** @internal */ exports.Outdent = chevrotain_1.createToken({ name: "Outdent" });
|
||||||
|
/**
|
||||||
|
* All the tokens used
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
exports.AllTokens = [
|
||||||
|
exports.Zero,
|
||||||
|
exports.One,
|
||||||
|
exports.Two,
|
||||||
|
exports.Three,
|
||||||
|
exports.Four,
|
||||||
|
exports.Five,
|
||||||
|
exports.Six,
|
||||||
|
exports.Seven,
|
||||||
|
exports.Eight,
|
||||||
|
exports.Nine,
|
||||||
|
exports.Ten,
|
||||||
|
exports.Optional,
|
||||||
|
exports.Matching,
|
||||||
|
exports.Match,
|
||||||
|
exports.Then,
|
||||||
|
exports.Anything,
|
||||||
|
exports.And,
|
||||||
|
exports.Boundary,
|
||||||
|
exports.Word,
|
||||||
|
exports.Digit,
|
||||||
|
exports.Character,
|
||||||
|
exports.Whitespace,
|
||||||
|
exports.Number,
|
||||||
|
exports.Unicode,
|
||||||
|
/*
|
||||||
|
Of,
|
||||||
|
As,
|
||||||
|
If,
|
||||||
|
Start,
|
||||||
|
Ends,
|
||||||
|
Else,
|
||||||
|
Unless,
|
||||||
|
While,
|
||||||
|
More,
|
||||||
|
Nothing,
|
||||||
|
By,
|
||||||
|
The,
|
||||||
|
None,
|
||||||
|
Neither,
|
||||||
|
*/
|
||||||
|
exports.Using,
|
||||||
|
exports.Global,
|
||||||
|
exports.Multiline,
|
||||||
|
exports.Exact,
|
||||||
|
exports.Not,
|
||||||
|
exports.Between,
|
||||||
|
exports.Tab,
|
||||||
|
exports.Linefeed,
|
||||||
|
exports.Group,
|
||||||
|
exports.A,
|
||||||
|
exports.Times,
|
||||||
|
exports.Exactly,
|
||||||
|
exports.Inclusive,
|
||||||
|
exports.Exclusive,
|
||||||
|
exports.From,
|
||||||
|
exports.Create,
|
||||||
|
exports.Called,
|
||||||
|
exports.Repeat,
|
||||||
|
exports.Newline,
|
||||||
|
exports.CarriageReturn,
|
||||||
|
exports.CaseInsensitive,
|
||||||
|
exports.CaseSensitive,
|
||||||
|
exports.OrMore,
|
||||||
|
exports.Or,
|
||||||
|
exports.To,
|
||||||
|
exports.EndOfLine,
|
||||||
|
exports.Indent,
|
||||||
|
exports.WS,
|
||||||
|
exports.SingleLineComment,
|
||||||
|
exports.MultilineComment,
|
||||||
|
exports.Identifier,
|
||||||
|
exports.NumberLiteral,
|
||||||
|
exports.StringLiteral,
|
||||||
|
];
|
148
lib/utilities.d.ts
vendored
Normal file
148
lib/utilities.d.ts
vendored
Normal file
@ -0,0 +1,148 @@
|
|||||||
|
/*! Copyright (c) 2020 Patrick Demian; Licensed under MIT */
|
||||||
|
/**
|
||||||
|
* Some utility functions for Human2Regex
|
||||||
|
* @packageDocumentation
|
||||||
|
*/
|
||||||
|
import { ISemanticError } from "./generator";
|
||||||
|
import { IRecognitionException, ILexingError } from "chevrotain";
|
||||||
|
/**
|
||||||
|
* The following section is used because the linter is set up to warn about certain operations
|
||||||
|
* and for good reason! I'd much rather have these functions than accidently use bitwise operations, or
|
||||||
|
* create a bunch of usless conditionals
|
||||||
|
* Plus, it signifies exactly what you wish to do (ex, calling hasFlag means you want to check if the
|
||||||
|
* bitpattern matches a given flag)
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* Fixes linter warnings about unused variables, however requires a reason why it's unused
|
||||||
|
*
|
||||||
|
* @param value the value you want to specify that is unused
|
||||||
|
* @param reason the reason this value is required but unused in this context
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
export declare function unusedParameter<T>(value: T, reason: string): void;
|
||||||
|
/**
|
||||||
|
* Fixes linter warnings about useless conditionals, however requires a reason why it's useless
|
||||||
|
*
|
||||||
|
* @param conditional the supposedly useless conditional
|
||||||
|
* @param reason the reason this value is required but considered useless
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
export declare function usefulConditional<T>(conditional: boolean | T, reason: string): boolean;
|
||||||
|
/**
|
||||||
|
* Generates a bitwise flag based on the value provided
|
||||||
|
*
|
||||||
|
* @param value the number of bits to shift
|
||||||
|
* @returns 1 << value
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
export declare function makeFlag(value: number): number;
|
||||||
|
/**
|
||||||
|
* Checks if value has the given flag
|
||||||
|
*
|
||||||
|
* @param value First flag to compare
|
||||||
|
* @param flag Second flag to compare
|
||||||
|
* @returns value & flag
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
export declare function hasFlag(value: number, flag: number): boolean;
|
||||||
|
/**
|
||||||
|
* Appends the flag to the value
|
||||||
|
*
|
||||||
|
* @param value First flag
|
||||||
|
* @param flag Second flag
|
||||||
|
* @returns value | flag
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
export declare function combineFlags(value: number, flag: number): number;
|
||||||
|
/**
|
||||||
|
* Checks to see if the character is a single regex character
|
||||||
|
*
|
||||||
|
* @remarks unicode and escape characters count as a single character
|
||||||
|
*
|
||||||
|
* @param char the character to check
|
||||||
|
* @returns if the value is exactly 1 character
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
export declare function isSingleRegexCharacter(char: string): boolean;
|
||||||
|
/**
|
||||||
|
* Gets the first element of an array
|
||||||
|
* @remarks does not validate if array has any elements
|
||||||
|
*
|
||||||
|
* @param array an array
|
||||||
|
* @returns first element of an array
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
export declare function first<T>(array: T[]): T;
|
||||||
|
/**
|
||||||
|
* Gets the last element of an array
|
||||||
|
* @remarks does not validate if array has any elements
|
||||||
|
*
|
||||||
|
* @param array an array
|
||||||
|
* @returns last element of an array
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
export declare function last<T>(array: T[]): T;
|
||||||
|
/**
|
||||||
|
* Find the last index of a given value in an array
|
||||||
|
*
|
||||||
|
* @param array an array
|
||||||
|
* @param value the value to find
|
||||||
|
* @returns an index if found or -1 if not found
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
export declare function findLastIndex<T>(array: T[], value: T): number;
|
||||||
|
/**
|
||||||
|
* Removes start and end quotes from a string
|
||||||
|
*
|
||||||
|
* @param input the string to remove quotes from
|
||||||
|
* @returns a string without quote characters
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
export declare function removeQuotes(input: string): string;
|
||||||
|
/**
|
||||||
|
* Escapes a string so it may be used literally in a regular expression
|
||||||
|
*
|
||||||
|
* @param input the string to escape
|
||||||
|
* @returns a regex escaped string
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
export declare function regexEscape(input: string): string;
|
||||||
|
/**
|
||||||
|
* Common Error class that encapsulates information from the lexer, parser, and generator
|
||||||
|
*/
|
||||||
|
export declare class CommonError {
|
||||||
|
type: string;
|
||||||
|
start_line: number;
|
||||||
|
start_column: number;
|
||||||
|
length: number;
|
||||||
|
message: string;
|
||||||
|
private constructor();
|
||||||
|
/**
|
||||||
|
* Creates a common error from a lexing error
|
||||||
|
*
|
||||||
|
* @param error The lexing error
|
||||||
|
* @returns a new CommonError
|
||||||
|
*/
|
||||||
|
static fromLexError(error: ILexingError): CommonError;
|
||||||
|
/**
|
||||||
|
* Creates a common error from a parsing error
|
||||||
|
*
|
||||||
|
* @param error The parsing error
|
||||||
|
* @returns a new CommonError
|
||||||
|
*/
|
||||||
|
static fromParseError(error: IRecognitionException): CommonError;
|
||||||
|
/**
|
||||||
|
* Creates a common error from a semantic error
|
||||||
|
*
|
||||||
|
* @param error The semantic error
|
||||||
|
* @returns a new CommonError
|
||||||
|
*/
|
||||||
|
static fromSemanticError(error: ISemanticError): CommonError;
|
||||||
|
/**
|
||||||
|
* Generates a string representation of a CommonError
|
||||||
|
*
|
||||||
|
* @returns a string representation
|
||||||
|
*/
|
||||||
|
toString(): string;
|
||||||
|
}
|
||||||
|
//# sourceMappingURL=utilities.d.ts.map
|
1
lib/utilities.d.ts.map
Normal file
1
lib/utilities.d.ts.map
Normal file
@ -0,0 +1 @@
|
|||||||
|
{"version":3,"file":"utilities.d.ts","sourceRoot":"","sources":["../src/utilities.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAE5D;;;GAGG;AAEH,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC7C,OAAO,EAAE,qBAAqB,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAGjE;;;;;;GAMG;AAEH;;;;;;GAMG;AAEH,wBAAgB,eAAe,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAEjE;AAED;;;;;;GAMG;AAEH,wBAAgB,iBAAiB,CAAC,CAAC,EAAE,WAAW,EAAE,OAAO,GAAG,CAAC,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAEtF;AAID;;;;;;GAMG;AACH,wBAAgB,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAE9C;AAED;;;;;;;GAOG;AACH,wBAAgB,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAE5D;AAED;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAEhE;AAGD;;;;;;;;GAQG;AACH,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAK5D;AAED;;;;;;;GAOG;AACH,wBAAgB,KAAK,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,GAAG,CAAC,CAEtC;AAED;;;;;;;GAOG;AACH,wBAAgB,IAAI,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,GAAG,CAAC,CAErC;AAED;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE,KAAK,EAAE,CAAC,GAAG,MAAM,CAO7D;AAED;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAElD;AAED;;;;;;GAMG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAEjD;AAED;;GAEG;AACH,qBAAa,WAAW;IACO,IAAI,EAAE,MAAM;IAAS,UAAU,EAAE,MAAM;IAAS,YAAY,EAAE,MAAM;IAAS,MAAM,EAAE,MAAM;IAAS,OAAO,EAAE,MAAM;IAA9I,OAAO;IAIP;;;;;OAKG;WACW,YAAY,CAAC,KAAK,EAAE,YAAY,GAAG,WAAW;IAO5D;;;;;OAKG;WACW,cAAc,CAAC,KAAK,EAAE,qBAAqB,GAAG,WAAW;IAOvE;;;;;OAKG;WACW,iBAAiB,CAAC,KAAK,EAAE,cAAc,GAAG,WAAW;IAInE;;;;OAIG;IACI,QAAQ,IAAI,MAAM;CAG5B"}
|
205
lib/utilities.js
Normal file
205
lib/utilities.js
Normal file
@ -0,0 +1,205 @@
|
|||||||
|
"use strict";
|
||||||
|
/*! Copyright (c) 2020 Patrick Demian; Licensed under MIT */
|
||||||
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
|
exports.CommonError = exports.regexEscape = exports.removeQuotes = exports.findLastIndex = exports.last = exports.first = exports.isSingleRegexCharacter = exports.combineFlags = exports.hasFlag = exports.makeFlag = exports.usefulConditional = exports.unusedParameter = void 0;
|
||||||
|
/**
|
||||||
|
* The following section is used because the linter is set up to warn about certain operations
|
||||||
|
* and for good reason! I'd much rather have these functions than accidently use bitwise operations, or
|
||||||
|
* create a bunch of usless conditionals
|
||||||
|
* Plus, it signifies exactly what you wish to do (ex, calling hasFlag means you want to check if the
|
||||||
|
* bitpattern matches a given flag)
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* Fixes linter warnings about unused variables, however requires a reason why it's unused
|
||||||
|
*
|
||||||
|
* @param value the value you want to specify that is unused
|
||||||
|
* @param reason the reason this value is required but unused in this context
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
|
function unusedParameter(value, reason) {
|
||||||
|
/* empty on purpose */
|
||||||
|
}
|
||||||
|
exports.unusedParameter = unusedParameter;
|
||||||
|
/**
|
||||||
|
* Fixes linter warnings about useless conditionals, however requires a reason why it's useless
|
||||||
|
*
|
||||||
|
* @param conditional the supposedly useless conditional
|
||||||
|
* @param reason the reason this value is required but considered useless
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
|
function usefulConditional(conditional, reason) {
|
||||||
|
return Boolean(conditional);
|
||||||
|
}
|
||||||
|
exports.usefulConditional = usefulConditional;
|
||||||
|
/* eslint-disable no-bitwise */
|
||||||
|
/**
|
||||||
|
* Generates a bitwise flag based on the value provided
|
||||||
|
*
|
||||||
|
* @param value the number of bits to shift
|
||||||
|
* @returns 1 << value
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
function makeFlag(value) {
|
||||||
|
return 1 << value;
|
||||||
|
}
|
||||||
|
exports.makeFlag = makeFlag;
|
||||||
|
/**
|
||||||
|
* Checks if value has the given flag
|
||||||
|
*
|
||||||
|
* @param value First flag to compare
|
||||||
|
* @param flag Second flag to compare
|
||||||
|
* @returns value & flag
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
function hasFlag(value, flag) {
|
||||||
|
return (value & flag) !== 0;
|
||||||
|
}
|
||||||
|
exports.hasFlag = hasFlag;
|
||||||
|
/**
|
||||||
|
* Appends the flag to the value
|
||||||
|
*
|
||||||
|
* @param value First flag
|
||||||
|
* @param flag Second flag
|
||||||
|
* @returns value | flag
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
function combineFlags(value, flag) {
|
||||||
|
return (value | flag);
|
||||||
|
}
|
||||||
|
exports.combineFlags = combineFlags;
|
||||||
|
/* eslint-enable no-bitwise */
|
||||||
|
/**
|
||||||
|
* Checks to see if the character is a single regex character
|
||||||
|
*
|
||||||
|
* @remarks unicode and escape characters count as a single character
|
||||||
|
*
|
||||||
|
* @param char the character to check
|
||||||
|
* @returns if the value is exactly 1 character
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
function isSingleRegexCharacter(char) {
|
||||||
|
return (char.startsWith("\\u") && char.length === 6) ||
|
||||||
|
(char.startsWith("\\U") && char.length === 8) ||
|
||||||
|
(char.startsWith("\\") && char.length === 2) ||
|
||||||
|
char.length === 1;
|
||||||
|
}
|
||||||
|
exports.isSingleRegexCharacter = isSingleRegexCharacter;
|
||||||
|
/**
|
||||||
|
* Gets the first element of an array
|
||||||
|
* @remarks does not validate if array has any elements
|
||||||
|
*
|
||||||
|
* @param array an array
|
||||||
|
* @returns first element of an array
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
function first(array) {
|
||||||
|
return array[0];
|
||||||
|
}
|
||||||
|
exports.first = first;
|
||||||
|
/**
|
||||||
|
* Gets the last element of an array
|
||||||
|
* @remarks does not validate if array has any elements
|
||||||
|
*
|
||||||
|
* @param array an array
|
||||||
|
* @returns last element of an array
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
function last(array) {
|
||||||
|
return array[array.length - 1];
|
||||||
|
}
|
||||||
|
exports.last = last;
|
||||||
|
/**
|
||||||
|
* Find the last index of a given value in an array
|
||||||
|
*
|
||||||
|
* @param array an array
|
||||||
|
* @param value the value to find
|
||||||
|
* @returns an index if found or -1 if not found
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
function findLastIndex(array, value) {
|
||||||
|
for (let index = array.length - 1; index >= 0; index--) {
|
||||||
|
if (array[index] === value) {
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
exports.findLastIndex = findLastIndex;
|
||||||
|
/**
|
||||||
|
* Removes start and end quotes from a string
|
||||||
|
*
|
||||||
|
* @param input the string to remove quotes from
|
||||||
|
* @returns a string without quote characters
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
function removeQuotes(input) {
|
||||||
|
return input.substring(1, input.length - 1);
|
||||||
|
}
|
||||||
|
exports.removeQuotes = removeQuotes;
|
||||||
|
/**
|
||||||
|
* Escapes a string so it may be used literally in a regular expression
|
||||||
|
*
|
||||||
|
* @param input the string to escape
|
||||||
|
* @returns a regex escaped string
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
function regexEscape(input) {
|
||||||
|
return input.replace(/([:\\\-\.\[\]\^\|\(\)\*\+\?\{\}\$\/])/g, "\\$1");
|
||||||
|
}
|
||||||
|
exports.regexEscape = regexEscape;
|
||||||
|
/**
|
||||||
|
* Common Error class that encapsulates information from the lexer, parser, and generator
|
||||||
|
*/
|
||||||
|
class CommonError {
|
||||||
|
constructor(type, start_line, start_column, length, message) {
|
||||||
|
this.type = type;
|
||||||
|
this.start_line = start_line;
|
||||||
|
this.start_column = start_column;
|
||||||
|
this.length = length;
|
||||||
|
this.message = message;
|
||||||
|
/* empty */
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Creates a common error from a lexing error
|
||||||
|
*
|
||||||
|
* @param error The lexing error
|
||||||
|
* @returns a new CommonError
|
||||||
|
*/
|
||||||
|
static fromLexError(error) {
|
||||||
|
// not really fond of --> and <--
|
||||||
|
const new_msg = error.message.replace(/(--?>|<--?)/g, "");
|
||||||
|
return new CommonError("Lexer Error", error.line, error.column, error.length, new_msg);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Creates a common error from a parsing error
|
||||||
|
*
|
||||||
|
* @param error The parsing error
|
||||||
|
* @returns a new CommonError
|
||||||
|
*/
|
||||||
|
static fromParseError(error) {
|
||||||
|
var _a, _b, _c;
|
||||||
|
// not really fond of --> and <--
|
||||||
|
const new_msg = error.name + " - " + error.message.replace(/(--?>|<--?)/g, "");
|
||||||
|
return new CommonError("Parser Error", (_a = error.token.startLine) !== null && _a !== void 0 ? _a : NaN, (_b = error.token.startColumn) !== null && _b !== void 0 ? _b : NaN, (_c = error.token.endOffset) !== null && _c !== void 0 ? _c : NaN - error.token.startOffset, new_msg);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Creates a common error from a semantic error
|
||||||
|
*
|
||||||
|
* @param error The semantic error
|
||||||
|
* @returns a new CommonError
|
||||||
|
*/
|
||||||
|
static fromSemanticError(error) {
|
||||||
|
return new CommonError("Semantic Error", error.startLine, error.startColumn, error.length, error.message);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Generates a string representation of a CommonError
|
||||||
|
*
|
||||||
|
* @returns a string representation
|
||||||
|
*/
|
||||||
|
toString() {
|
||||||
|
return `${this.type} @ (${this.start_line}, ${this.start_column}): ${this.message}`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
exports.CommonError = CommonError;
|
397
package-lock.json
generated
397
package-lock.json
generated
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "human2regex",
|
"name": "human2regex",
|
||||||
"version": "0.9.5",
|
"version": "0.9.6",
|
||||||
"lockfileVersion": 1,
|
"lockfileVersion": 1,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@ -1300,6 +1300,45 @@
|
|||||||
"mkdirp": "^1.0.4"
|
"mkdirp": "^1.0.4"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"@sindresorhus/df": {
|
||||||
|
"version": "2.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@sindresorhus/df/-/df-2.1.0.tgz",
|
||||||
|
"integrity": "sha1-0gjPJ+BvC7R20U197M19cm6ao4k=",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"execa": "^0.2.2"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"execa": {
|
||||||
|
"version": "0.2.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/execa/-/execa-0.2.2.tgz",
|
||||||
|
"integrity": "sha1-4urUcsLDGq1vc/GslW7vReEjIMs=",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"cross-spawn-async": "^2.1.1",
|
||||||
|
"npm-run-path": "^1.0.0",
|
||||||
|
"object-assign": "^4.0.1",
|
||||||
|
"path-key": "^1.0.0",
|
||||||
|
"strip-eof": "^1.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"npm-run-path": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-1.0.0.tgz",
|
||||||
|
"integrity": "sha1-9cMr9ZX+ga6Sfa7FLoL4sACsPI8=",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"path-key": "^1.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"path-key": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/path-key/-/path-key-1.0.0.tgz",
|
||||||
|
"integrity": "sha1-XVPVeAGWRsDWiADbThRua9wqx68=",
|
||||||
|
"dev": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"@sinonjs/commons": {
|
"@sinonjs/commons": {
|
||||||
"version": "1.8.1",
|
"version": "1.8.1",
|
||||||
"resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.1.tgz",
|
"resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.1.tgz",
|
||||||
@ -1318,6 +1357,18 @@
|
|||||||
"@sinonjs/commons": "^1.7.0"
|
"@sinonjs/commons": "^1.7.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"@stroncium/procfs": {
|
||||||
|
"version": "1.2.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@stroncium/procfs/-/procfs-1.2.1.tgz",
|
||||||
|
"integrity": "sha512-X1Iui3FUNZP18EUvysTHxt+Avu2nlVzyf90YM8OYgP6SGzTzzX/0JgObfO1AQQDzuZtNNz29bVh8h5R97JrjxA==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"@types/anymatch": {
|
||||||
|
"version": "1.3.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/anymatch/-/anymatch-1.3.1.tgz",
|
||||||
|
"integrity": "sha512-/+CRPXpBDpo2RK9C68N3b2cOvO0Cf5B9aPijHsoDQTHivnGSObdOF2BRQOYjojWTDy6nQvMjmqRXIxH55VjxxA==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"@types/babel__core": {
|
"@types/babel__core": {
|
||||||
"version": "7.1.12",
|
"version": "7.1.12",
|
||||||
"resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.1.12.tgz",
|
"resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.1.12.tgz",
|
||||||
@ -1480,12 +1531,24 @@
|
|||||||
"integrity": "sha1-a9p9uGU/piZD9e5p6facEaOS46Y=",
|
"integrity": "sha1-a9p9uGU/piZD9e5p6facEaOS46Y=",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"@types/source-list-map": {
|
||||||
|
"version": "0.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/source-list-map/-/source-list-map-0.1.2.tgz",
|
||||||
|
"integrity": "sha512-K5K+yml8LTo9bWJI/rECfIPrGgxdpeNbj+d53lwN4QjW1MCwlkhUms+gtdzigTeUyBr09+u8BwOIY3MXvHdcsA==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"@types/stack-utils": {
|
"@types/stack-utils": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.0.tgz",
|
||||||
"integrity": "sha512-RJJrrySY7A8havqpGObOB4W92QXKJo63/jFLLgpvOtsGUqbQZ9Sbgl35KMm1DjC6j7AvmmU2bIno+3IyEaemaw==",
|
"integrity": "sha512-RJJrrySY7A8havqpGObOB4W92QXKJo63/jFLLgpvOtsGUqbQZ9Sbgl35KMm1DjC6j7AvmmU2bIno+3IyEaemaw==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"@types/tapable": {
|
||||||
|
"version": "1.0.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/tapable/-/tapable-1.0.6.tgz",
|
||||||
|
"integrity": "sha512-W+bw9ds02rAQaMvaLYxAbJ6cvguW/iJXNT6lTssS1ps6QdrMKttqEAMEG/b5CR8TZl3/L7/lH0ZV5nNR1LXikA==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"@types/uglify-js": {
|
"@types/uglify-js": {
|
||||||
"version": "3.11.1",
|
"version": "3.11.1",
|
||||||
"resolved": "https://registry.npmjs.org/@types/uglify-js/-/uglify-js-3.11.1.tgz",
|
"resolved": "https://registry.npmjs.org/@types/uglify-js/-/uglify-js-3.11.1.tgz",
|
||||||
@ -1495,6 +1558,39 @@
|
|||||||
"source-map": "^0.6.1"
|
"source-map": "^0.6.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"@types/webpack": {
|
||||||
|
"version": "4.41.22",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/webpack/-/webpack-4.41.22.tgz",
|
||||||
|
"integrity": "sha512-JQDJK6pj8OMV9gWOnN1dcLCyU9Hzs6lux0wBO4lr1+gyEhIBR9U3FMrz12t2GPkg110XAxEAw2WHF6g7nZIbRQ==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"@types/anymatch": "*",
|
||||||
|
"@types/node": "*",
|
||||||
|
"@types/tapable": "*",
|
||||||
|
"@types/uglify-js": "*",
|
||||||
|
"@types/webpack-sources": "*",
|
||||||
|
"source-map": "^0.6.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"@types/webpack-sources": {
|
||||||
|
"version": "2.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/webpack-sources/-/webpack-sources-2.0.0.tgz",
|
||||||
|
"integrity": "sha512-a5kPx98CNFRKQ+wqawroFunvFqv7GHm/3KOI52NY9xWADgc8smu4R6prt4EU/M4QfVjvgBkMqU4fBhw3QfMVkg==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"@types/node": "*",
|
||||||
|
"@types/source-list-map": "*",
|
||||||
|
"source-map": "^0.7.3"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"source-map": {
|
||||||
|
"version": "0.7.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz",
|
||||||
|
"integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==",
|
||||||
|
"dev": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"@types/yargs": {
|
"@types/yargs": {
|
||||||
"version": "15.0.9",
|
"version": "15.0.9",
|
||||||
"resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-15.0.9.tgz",
|
"resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-15.0.9.tgz",
|
||||||
@ -1947,6 +2043,12 @@
|
|||||||
"integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==",
|
"integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"array-uniq": {
|
||||||
|
"version": "1.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz",
|
||||||
|
"integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"array-unique": {
|
"array-unique": {
|
||||||
"version": "0.3.2",
|
"version": "0.3.2",
|
||||||
"resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz",
|
"resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz",
|
||||||
@ -3011,6 +3113,37 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"cp-file": {
|
||||||
|
"version": "6.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/cp-file/-/cp-file-6.2.0.tgz",
|
||||||
|
"integrity": "sha512-fmvV4caBnofhPe8kOcitBwSn2f39QLjnAnGq3gO9dfd75mUytzKNZB1hde6QHunW2Rt+OwuBOMc3i1tNElbszA==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"graceful-fs": "^4.1.2",
|
||||||
|
"make-dir": "^2.0.0",
|
||||||
|
"nested-error-stacks": "^2.0.0",
|
||||||
|
"pify": "^4.0.1",
|
||||||
|
"safe-buffer": "^5.0.1"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"make-dir": {
|
||||||
|
"version": "2.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz",
|
||||||
|
"integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"pify": "^4.0.1",
|
||||||
|
"semver": "^5.6.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"semver": {
|
||||||
|
"version": "5.7.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
|
||||||
|
"integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
|
||||||
|
"dev": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"create-ecdh": {
|
"create-ecdh": {
|
||||||
"version": "4.0.4",
|
"version": "4.0.4",
|
||||||
"resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.4.tgz",
|
"resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.4.tgz",
|
||||||
@ -3067,6 +3200,43 @@
|
|||||||
"which": "^2.0.1"
|
"which": "^2.0.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"cross-spawn-async": {
|
||||||
|
"version": "2.2.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/cross-spawn-async/-/cross-spawn-async-2.2.5.tgz",
|
||||||
|
"integrity": "sha1-hF/wwINKPe2dFg2sptOQkGuyiMw=",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"lru-cache": "^4.0.0",
|
||||||
|
"which": "^1.2.8"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"lru-cache": {
|
||||||
|
"version": "4.1.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz",
|
||||||
|
"integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"pseudomap": "^1.0.2",
|
||||||
|
"yallist": "^2.1.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"which": {
|
||||||
|
"version": "1.3.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",
|
||||||
|
"integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"isexe": "^2.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"yallist": {
|
||||||
|
"version": "2.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz",
|
||||||
|
"integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=",
|
||||||
|
"dev": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"crypto-browserify": {
|
"crypto-browserify": {
|
||||||
"version": "3.12.0",
|
"version": "3.12.0",
|
||||||
"resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz",
|
"resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz",
|
||||||
@ -5402,6 +5572,12 @@
|
|||||||
"integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==",
|
"integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"is-path-inside": {
|
||||||
|
"version": "3.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.2.tgz",
|
||||||
|
"integrity": "sha512-/2UGPSgmtqwo1ktx8NDHjuPwZWmHhO+gj0f93EkhLB5RgW9RZevWYYlIkS6zePc6U2WpOdQYIwHe9YC4DWEBVg==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"is-plain-object": {
|
"is-plain-object": {
|
||||||
"version": "2.0.4",
|
"version": "2.0.4",
|
||||||
"resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz",
|
"resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz",
|
||||||
@ -8337,6 +8513,31 @@
|
|||||||
"integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==",
|
"integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"mount-point": {
|
||||||
|
"version": "3.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/mount-point/-/mount-point-3.0.0.tgz",
|
||||||
|
"integrity": "sha1-Zly57evoDREOZY21bDHQrvUaj5c=",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"@sindresorhus/df": "^1.0.1",
|
||||||
|
"pify": "^2.3.0",
|
||||||
|
"pinkie-promise": "^2.0.1"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@sindresorhus/df": {
|
||||||
|
"version": "1.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@sindresorhus/df/-/df-1.0.1.tgz",
|
||||||
|
"integrity": "sha1-xptm9S9vzdKHyAffIQMF2694UA0=",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"pify": {
|
||||||
|
"version": "2.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
|
||||||
|
"integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=",
|
||||||
|
"dev": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"move-concurrently": {
|
"move-concurrently": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz",
|
||||||
@ -8371,6 +8572,25 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"move-file": {
|
||||||
|
"version": "1.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/move-file/-/move-file-1.2.0.tgz",
|
||||||
|
"integrity": "sha512-USHrRmxzGowUWAGBbJPdFjHzEqtxDU03pLHY0Rfqgtnq+q8FOIs8wvkkf+Udmg77SJKs47y9sI0jJvQeYsmiCA==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"cp-file": "^6.1.0",
|
||||||
|
"make-dir": "^3.0.0",
|
||||||
|
"path-exists": "^3.0.0"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"path-exists": {
|
||||||
|
"version": "3.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz",
|
||||||
|
"integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=",
|
||||||
|
"dev": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"ms": {
|
"ms": {
|
||||||
"version": "2.1.2",
|
"version": "2.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
|
||||||
@ -8414,6 +8634,12 @@
|
|||||||
"integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==",
|
"integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"nested-error-stacks": {
|
||||||
|
"version": "2.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/nested-error-stacks/-/nested-error-stacks-2.1.0.tgz",
|
||||||
|
"integrity": "sha512-AO81vsIO1k1sM4Zrd6Hu7regmJN1NSiAja10gc4bX3F0wd+9rQmcuHQaHVQCYIEC8iFXnE+mavh23GOt7wBgug==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"nice-try": {
|
"nice-try": {
|
||||||
"version": "1.0.5",
|
"version": "1.0.5",
|
||||||
"resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz",
|
"resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz",
|
||||||
@ -8754,6 +8980,12 @@
|
|||||||
"integrity": "sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc=",
|
"integrity": "sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc=",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"os-homedir": {
|
||||||
|
"version": "1.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz",
|
||||||
|
"integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"p-each-series": {
|
"p-each-series": {
|
||||||
"version": "2.1.0",
|
"version": "2.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/p-each-series/-/p-each-series-2.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/p-each-series/-/p-each-series-2.1.0.tgz",
|
||||||
@ -8960,6 +9192,21 @@
|
|||||||
"integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==",
|
"integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"pinkie": {
|
||||||
|
"version": "2.0.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz",
|
||||||
|
"integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"pinkie-promise": {
|
||||||
|
"version": "2.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz",
|
||||||
|
"integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"pinkie": "^2.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"pirates": {
|
"pirates": {
|
||||||
"version": "4.0.1",
|
"version": "4.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.1.tgz",
|
||||||
@ -9601,6 +9848,12 @@
|
|||||||
"integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=",
|
"integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"pseudomap": {
|
||||||
|
"version": "1.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz",
|
||||||
|
"integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"psl": {
|
"psl": {
|
||||||
"version": "1.8.0",
|
"version": "1.8.0",
|
||||||
"resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz",
|
"resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz",
|
||||||
@ -9820,6 +10073,16 @@
|
|||||||
"integrity": "sha1-VNvzd+UUQKypCkzSdGANP/LYiKk=",
|
"integrity": "sha1-VNvzd+UUQKypCkzSdGANP/LYiKk=",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"remove-files-webpack-plugin": {
|
||||||
|
"version": "1.4.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/remove-files-webpack-plugin/-/remove-files-webpack-plugin-1.4.4.tgz",
|
||||||
|
"integrity": "sha512-vCtIPQRA9Sf6yn90qepj0A8zEMZK4oHxGH+rTG74ELPprDbhJ9Phe74fj9FM6Jc5I11Q5Ah6EogqJDzSqJ6mEA==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"@types/webpack": "4.41.22",
|
||||||
|
"trash": "6.1.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"remove-trailing-separator": {
|
"remove-trailing-separator": {
|
||||||
"version": "1.1.0",
|
"version": "1.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz",
|
||||||
@ -11320,6 +11583,99 @@
|
|||||||
"punycode": "^2.1.1"
|
"punycode": "^2.1.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"trash": {
|
||||||
|
"version": "6.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/trash/-/trash-6.1.1.tgz",
|
||||||
|
"integrity": "sha512-4i56lCmz2RG6WZN018hf4L75L5HboaFuKkHx3wDG/ihevI99e0OgFyl8w6G4ioqBm62V4EJqCy5xw3vQSNXU8A==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"@stroncium/procfs": "^1.0.0",
|
||||||
|
"globby": "^7.1.1",
|
||||||
|
"is-path-inside": "^3.0.2",
|
||||||
|
"make-dir": "^3.0.0",
|
||||||
|
"move-file": "^1.1.0",
|
||||||
|
"p-map": "^3.0.0",
|
||||||
|
"p-try": "^2.2.0",
|
||||||
|
"uuid": "^3.3.2",
|
||||||
|
"xdg-trashdir": "^2.1.1"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"array-union": {
|
||||||
|
"version": "1.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz",
|
||||||
|
"integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"array-uniq": "^1.0.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"dir-glob": {
|
||||||
|
"version": "2.2.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-2.2.2.tgz",
|
||||||
|
"integrity": "sha512-f9LBi5QWzIW3I6e//uxZoLBlUt9kcp66qo0sSCxL6YZKc75R1c4MFCoe/LaZiBGmgujvQdxc5Bn3QhfyvK5Hsw==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"path-type": "^3.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"globby": {
|
||||||
|
"version": "7.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/globby/-/globby-7.1.1.tgz",
|
||||||
|
"integrity": "sha1-+yzP+UAfhgCUXfral0QMypcrhoA=",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"array-union": "^1.0.1",
|
||||||
|
"dir-glob": "^2.0.0",
|
||||||
|
"glob": "^7.1.2",
|
||||||
|
"ignore": "^3.3.5",
|
||||||
|
"pify": "^3.0.0",
|
||||||
|
"slash": "^1.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"ignore": {
|
||||||
|
"version": "3.3.10",
|
||||||
|
"resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.10.tgz",
|
||||||
|
"integrity": "sha512-Pgs951kaMm5GXP7MOvxERINe3gsaVjUWFm+UZPSq9xYriQAksyhg0csnS0KXSNRD5NmNdapXEpjxG49+AKh/ug==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"p-map": {
|
||||||
|
"version": "3.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/p-map/-/p-map-3.0.0.tgz",
|
||||||
|
"integrity": "sha512-d3qXVTF/s+W+CdJ5A29wywV2n8CQQYahlgz2bFiA+4eVNJbHJodPZ+/gXwPGh0bOqA+j8S+6+ckmvLGPk1QpxQ==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"aggregate-error": "^3.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"path-type": {
|
||||||
|
"version": "3.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz",
|
||||||
|
"integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"pify": "^3.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"pify": {
|
||||||
|
"version": "3.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz",
|
||||||
|
"integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"slash": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz",
|
||||||
|
"integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"uuid": {
|
||||||
|
"version": "3.4.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz",
|
||||||
|
"integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==",
|
||||||
|
"dev": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"ts-jest": {
|
"ts-jest": {
|
||||||
"version": "26.4.3",
|
"version": "26.4.3",
|
||||||
"resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-26.4.3.tgz",
|
"resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-26.4.3.tgz",
|
||||||
@ -11626,6 +11982,15 @@
|
|||||||
"integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==",
|
"integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"user-home": {
|
||||||
|
"version": "2.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/user-home/-/user-home-2.0.0.tgz",
|
||||||
|
"integrity": "sha1-nHC/2Babwdy/SGBODwS4tJzenp8=",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"os-homedir": "^1.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"util": {
|
"util": {
|
||||||
"version": "0.11.1",
|
"version": "0.11.1",
|
||||||
"resolved": "https://registry.npmjs.org/util/-/util-0.11.1.tgz",
|
"resolved": "https://registry.npmjs.org/util/-/util-0.11.1.tgz",
|
||||||
@ -12427,6 +12792,36 @@
|
|||||||
"integrity": "sha512-D3RuNkynyHmEJIpD2qrgVkc9DQ23OrN/moAwZX4L8DfvszsJxpjQuUq3LMx6HoYji9fbIOBY18XWBsAux1ZZUA==",
|
"integrity": "sha512-D3RuNkynyHmEJIpD2qrgVkc9DQ23OrN/moAwZX4L8DfvszsJxpjQuUq3LMx6HoYji9fbIOBY18XWBsAux1ZZUA==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"xdg-basedir": {
|
||||||
|
"version": "2.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-2.0.0.tgz",
|
||||||
|
"integrity": "sha1-7byQPMOF/ARSPZZqM1UEtVBNG9I=",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"os-homedir": "^1.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"xdg-trashdir": {
|
||||||
|
"version": "2.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/xdg-trashdir/-/xdg-trashdir-2.1.1.tgz",
|
||||||
|
"integrity": "sha512-KcVhPaOu2ZurYNHSRTf1+ZHORkTZGCQ+u0JHN17QixRISJq4pXOnjt/lQcehvtHL5QAKhSzKgyjrcNnPdkPBHA==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"@sindresorhus/df": "^2.1.0",
|
||||||
|
"mount-point": "^3.0.0",
|
||||||
|
"pify": "^2.2.0",
|
||||||
|
"user-home": "^2.0.0",
|
||||||
|
"xdg-basedir": "^2.0.0"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"pify": {
|
||||||
|
"version": "2.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
|
||||||
|
"integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=",
|
||||||
|
"dev": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"xml-name-validator": {
|
"xml-name-validator": {
|
||||||
"version": "3.0.0",
|
"version": "3.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-3.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-3.0.0.tgz",
|
||||||
|
20
package.json
20
package.json
@ -1,8 +1,9 @@
|
|||||||
{
|
{
|
||||||
"name": "human2regex",
|
"name": "human2regex",
|
||||||
"version": "0.9.5",
|
"version": "0.9.6",
|
||||||
"description": "Humanized Regular Expressions",
|
"description": "Humanized Regular Expressions",
|
||||||
"main": "bundle.min.js",
|
"main": "./lib/index.js",
|
||||||
|
"typings": "./lib/index.d.ts",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/glob": "^7.1.3",
|
"@types/glob": "^7.1.3",
|
||||||
"@types/html-minifier": "^3.5.3",
|
"@types/html-minifier": "^3.5.3",
|
||||||
@ -20,6 +21,7 @@
|
|||||||
"mini-css-extract-plugin": "^1.0.0",
|
"mini-css-extract-plugin": "^1.0.0",
|
||||||
"mustache": "^4.0.1",
|
"mustache": "^4.0.1",
|
||||||
"optimize-css-assets-webpack-plugin": "^5.0.4",
|
"optimize-css-assets-webpack-plugin": "^5.0.4",
|
||||||
|
"remove-files-webpack-plugin": "^1.4.4",
|
||||||
"ts-jest": "^26.4.3",
|
"ts-jest": "^26.4.3",
|
||||||
"ts-loader": "^8.0.9",
|
"ts-loader": "^8.0.9",
|
||||||
"ts-node": "^9.0.0",
|
"ts-node": "^9.0.0",
|
||||||
@ -28,11 +30,16 @@
|
|||||||
"webpack-cli": "^3.3.12"
|
"webpack-cli": "^3.3.12"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "webpack --config webpack.config.js",
|
"build": "tsc && webpack --config webpack.config.js",
|
||||||
"test": "eslint && jest"
|
"test": "eslint && jest",
|
||||||
|
"prepare": "npm run build",
|
||||||
|
"prepublishOnly": "npm t"
|
||||||
},
|
},
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"regex"
|
"regex",
|
||||||
|
"regexp",
|
||||||
|
"regular",
|
||||||
|
"expression"
|
||||||
],
|
],
|
||||||
"author": "Patrick Demian",
|
"author": "Patrick Demian",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
@ -46,5 +53,6 @@
|
|||||||
},
|
},
|
||||||
"bugs": {
|
"bugs": {
|
||||||
"url": "https://github.com/pdemian/human2regex/issues"
|
"url": "https://github.com/pdemian/human2regex/issues"
|
||||||
}
|
},
|
||||||
|
"homepage": "https://pdemian.github.io/human2regex/"
|
||||||
}
|
}
|
||||||
|
9006
src/docs/bootstrap.css
vendored
Normal file
9006
src/docs/bootstrap.css
vendored
Normal file
File diff suppressed because it is too large
Load Diff
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 11 KiB |
@ -128,7 +128,35 @@ code {
|
|||||||
font-style: italic!important;
|
font-style: italic!important;
|
||||||
}
|
}
|
||||||
|
|
||||||
#tutorial {
|
.tutorial-code {
|
||||||
max-width: 80%;
|
display: block;
|
||||||
margin: auto;
|
margin: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 576px) {
|
||||||
|
.contained-container {
|
||||||
|
max-width:540px
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 768px) {
|
||||||
|
.contained-container {
|
||||||
|
max-width:720px
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 992px) {
|
||||||
|
.contained-container {
|
||||||
|
max-width:960px
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 1200px) {
|
||||||
|
.contained-container {
|
||||||
|
max-width:1140px
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
td {
|
||||||
|
font-size: 16px;
|
||||||
}
|
}
|
531
src/docs/tutorial.mustache
Normal file
531
src/docs/tutorial.mustache
Normal file
@ -0,0 +1,531 @@
|
|||||||
|
{{! Copyright (c) 2020 Patrick Demian; Licensed under MIT }}
|
||||||
|
|
||||||
|
{{> header}}
|
||||||
|
<!-- Main Content -->
|
||||||
|
<div class="container contained-container" id="maincontent" role="main">
|
||||||
|
<div id="tutorial">
|
||||||
|
<h2>Tutorial</h2>
|
||||||
|
<br>
|
||||||
|
|
||||||
|
<p class="font-weight-bold">Preface</p>
|
||||||
|
<p>Human2Regex (H2R) is a way to spell out a regular expression in an easy to read, easy to modify language. H2R supports multiple languages as well as many (though not all) different regular expression options such as named groups and quantifiers. You may notice multiple keywords specifying the same thing, and that is intended! H2R is made to be flexible and easy to understand. With a range, do you prefer "...", "through", or "to"? It's up to you to choose, H2R supports all of those!</p>
|
||||||
|
|
||||||
|
<p class="font-weight-bold">Your first Match</p>
|
||||||
|
<p>Every language starts with a "Hello World" program, so let's match the output of those programs. Matching is done using the keyword "match" followed by what you want to match.
|
||||||
|
<span class="tutorial-code"><code class="cm-s-idea">
|
||||||
|
match "Hello World"
|
||||||
|
</code></span>
|
||||||
|
The above statement will generate a regular expression that matches "Hello World". Any invalid characters will automatically be escaped, so you don't need to worry about it.
|
||||||
|
H2R also supports block comments with <code class="cm-s-idea">/**/</code>, or line comments with <code class="cm-s-idea">//</code> or <code class="cm-s-idea">#</code> so you can explain why or what you intend to match.
|
||||||
|
<span class="tutorial-code"><code class="cm-s-idea">
|
||||||
|
match "Hello World" // matches the output of "Hello World" programs
|
||||||
|
</code></span>
|
||||||
|
Now what if we want to match every case variation of "Hello World" like "hello world" or "hELLO wORLD"? H2R supports the <code class="cm-s-idea">or</code> operator which allows you to specify many possible combinations.
|
||||||
|
<span class="tutorial-code"><code class="cm-s-idea">
|
||||||
|
match "Hello World" or "hello world" or "hELLO wORLD"
|
||||||
|
</code></span>
|
||||||
|
Or, you can use a <code class="cm-s-idea">using</code> statement to specify that you want it to be case insensitive.</p>
|
||||||
|
|
||||||
|
<p class="font-weight-bold">Using Specifiers</p>
|
||||||
|
<p>Using statements appear at the beginning. You may have one or more using statements which each can contain one or more specifiers. For example:
|
||||||
|
<span class="tutorial-code"><code class="cm-s-idea">
|
||||||
|
using global and case insensitive matching
|
||||||
|
</code></span>
|
||||||
|
or
|
||||||
|
<span class="tutorial-code"><code class="cm-s-idea">
|
||||||
|
using global
|
||||||
|
</code></span>
|
||||||
|
<span class="tutorial-code"><code class="cm-s-idea">
|
||||||
|
using case insensitive
|
||||||
|
</code></span>
|
||||||
|
The <code class="cm-s-idea">matching</code> keyword is optional. The flags which are available are:</p>
|
||||||
|
|
||||||
|
<table class="table table-striped table-bordered">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th scope="col">Specifier</th>
|
||||||
|
<th scope="col">Description</th>
|
||||||
|
<th scope="col">Regex flag</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td>Multiline</td>
|
||||||
|
<td>Matches can cross line breaks</td>
|
||||||
|
<td>/<your regex>/m</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Global</td>
|
||||||
|
<td>Multiple matches are allowed</td>
|
||||||
|
<td>/<your regex>/g</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Case Sensitive</td>
|
||||||
|
<td>Match must be exact case</td>
|
||||||
|
<td><span class="font-italic">none</span></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Case Insensitive</td>
|
||||||
|
<td>Match may be any case</td>
|
||||||
|
<td>/<your regex>/i</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Exact</td>
|
||||||
|
<td>An exact statement matches a whole line exactly, nothing before, nothing after</td>
|
||||||
|
<td>/^<your regex>$/</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<p>To match any variation of hello world, we would then do the following:
|
||||||
|
<span class="tutorial-code"><code class="cm-s-idea">
|
||||||
|
using case insensitive matching
|
||||||
|
</code></span>
|
||||||
|
<span class="tutorial-code"><code class="cm-s-idea">
|
||||||
|
match "hello world"
|
||||||
|
</code></span></p>
|
||||||
|
|
||||||
|
<p class="font-weight-bold">Matching multiple items</p>
|
||||||
|
<p>H2R comes with 2 options to match multiple items in a row. The first is to simply write multiple seperate <code class="cm-s-idea">match</code> statements like:
|
||||||
|
<span class="tutorial-code"><code class="cm-s-idea">
|
||||||
|
match "hello"
|
||||||
|
</code></span>
|
||||||
|
<span class="tutorial-code"><code class="cm-s-idea">
|
||||||
|
match " "
|
||||||
|
</code></span>
|
||||||
|
<span class="tutorial-code"><code class="cm-s-idea">
|
||||||
|
match "world"
|
||||||
|
</code></span>
|
||||||
|
However, you can also use a comma, <code class="cm-s-idea">and</code>, or <code class="cm-s-idea">then</code> for a more concise match.
|
||||||
|
<span class="tutorial-code"><code class="cm-s-idea">
|
||||||
|
match "hello", " ", "world"
|
||||||
|
</code></span>
|
||||||
|
or
|
||||||
|
<span class="tutorial-code"><code class="cm-s-idea">
|
||||||
|
match "hello" and " " and "world"
|
||||||
|
</code></span>
|
||||||
|
or
|
||||||
|
<span class="tutorial-code"><code class="cm-s-idea">
|
||||||
|
match "hello" then " " then "world"
|
||||||
|
</code></span>
|
||||||
|
or any combination like
|
||||||
|
<span class="tutorial-code"><code class="cm-s-idea">
|
||||||
|
match "hello", " " and then "world"
|
||||||
|
</code></span>
|
||||||
|
|
||||||
|
<p class="font-weight-bold">Optionality</p>
|
||||||
|
<p>Sometimes you wish to match something that may or may not exist. In H2R, this is done via the <code class="cm-s-idea">optional</code> or <code class="cm-s-idea">optionally</code> keyword.
|
||||||
|
<span class="tutorial-code"><code class="cm-s-idea">
|
||||||
|
optionally match "hello world"
|
||||||
|
</code></span>
|
||||||
|
will match 0 or 1 "hello world"'s. This can be used along side matching multiple statements in a single <code class="cm-s-idea">match</code> statement.
|
||||||
|
<span class="tutorial-code"><code class="cm-s-idea">
|
||||||
|
match "hello", optionally " ", "world"
|
||||||
|
</code></span>
|
||||||
|
will match "hello", an optional space if it exists, and "world". However, the start <code class="cm-s-idea">optional</code> is for the entire match statement. Thus,
|
||||||
|
<span class="tutorial-code"><code class="cm-s-idea">
|
||||||
|
optionally match "hello", " ", then "world"
|
||||||
|
</code></span>
|
||||||
|
will actually make the whole "hello world" an optional match rather than just the first "hello". If you want to make the first match optional but keep the rest required, use multiple <code class="cm-s-idea">match</code> statements.</p>
|
||||||
|
|
||||||
|
<p class="font-weight-bold">Negation</p>
|
||||||
|
<p>You can negate a match with the operator <code class="cm-s-idea">not</code>
|
||||||
|
<span class="tutorial-code"><code class="cm-s-idea">
|
||||||
|
match not "hello world"
|
||||||
|
</code></span>
|
||||||
|
will match everything except for "hello world".</p>
|
||||||
|
|
||||||
|
<p class="font-weight-bold">Other matching specifiers</p>
|
||||||
|
<p>Many times you don't know exactly what you wish to match. H2R comes with many specifiers that you can use for your matching. For example, you may wish to match any word. You can do that with:
|
||||||
|
<span class="tutorial-code"><code class="cm-s-idea">
|
||||||
|
match a word
|
||||||
|
</code></span>
|
||||||
|
The <code class="cm-s-idea">a</code> or <code class="cm-s-idea">an</code> is optional. The possible specifiers that H2R supports are the following:</p>
|
||||||
|
<table class="table table-striped table-bordered">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th scope="col">Specifier</th>
|
||||||
|
<th scope="col">Description</th>
|
||||||
|
<th scope="col">Regex alternative</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td>Anything</td>
|
||||||
|
<td>Matches any character</td>
|
||||||
|
<td>.</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Word(s)</td>
|
||||||
|
<td>Matches a word</td>
|
||||||
|
<td>\w+</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Number(s)</td>
|
||||||
|
<td>Matches an integer</td>
|
||||||
|
<td>\d+</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Character(s)</td>
|
||||||
|
<td>Matches any letter character</td>
|
||||||
|
<td>\w</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Digit(s)</td>
|
||||||
|
<td>Matches any digit character</td>
|
||||||
|
<td>\d</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Whitespace(s)</td>
|
||||||
|
<td>Matches any whitespace character</td>
|
||||||
|
<td>\s</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Boundary</td>
|
||||||
|
<td>Boundary between a word</td>
|
||||||
|
<td>\b</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Line Feed</td>
|
||||||
|
<td>Matches a newline</td>
|
||||||
|
<td>\n</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Newline</td>
|
||||||
|
<td>Matches a newline</td>
|
||||||
|
<td>\n</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Carriage Return</td>
|
||||||
|
<td>Matches a carriage return</td>
|
||||||
|
<td>\r</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<p>You can also create ranges of characters to match. Say for example, you wanted to match any characters between a and z, you could write any of the following:
|
||||||
|
<span class="tutorial-code"><code class="cm-s-idea">
|
||||||
|
match from "a" to "z" // from is optional
|
||||||
|
</code></span>
|
||||||
|
or
|
||||||
|
<span class="tutorial-code"><code class="cm-s-idea">
|
||||||
|
match between "a" and "z" // between is optional
|
||||||
|
</code></span>
|
||||||
|
or
|
||||||
|
<span class="tutorial-code"><code class="cm-s-idea">
|
||||||
|
match "a" ... "z" // can use ... or ..
|
||||||
|
</code></span>
|
||||||
|
or
|
||||||
|
<span class="tutorial-code"><code class="cm-s-idea">
|
||||||
|
match "a" - "z"
|
||||||
|
</code></span>
|
||||||
|
or
|
||||||
|
<span class="tutorial-code"><code class="cm-s-idea">
|
||||||
|
match "a" through "z" // can also use thru
|
||||||
|
</code></span>
|
||||||
|
|
||||||
|
<p class="font-weight-bold">Repetition</p>
|
||||||
|
<!--<p>H2R supports 2 types of repetition: single match repetition, or grouped repetition. When using "match" you can specify the number of captures you want just before the text you want to capture. Example: <code class="cm-s-idea">match 2 digits</code> will match any 2 characters in a row. You can also specify a range you wish to capture. Example: <code class="cm-s-idea">match 2..5 digits</code> will match 2, 3, 4, or 5 digits. You can specify if the final number is exclusive with the "exclusive" keyword. Example: <code class="cm-s-idea">match 2 to 5 exclusive digits</code> will only match up to 4 digits. You can group a repetition using the "repeat" keyword. By default, this will match 0 or more of the following statements. The same qualifiers that exist for match exist for repeat. Example: <code class="cm-s-idea">optionally repeat 3...7 times</code></p>
|
||||||
|
|
||||||
|
<p>Optional repeat</p>-->
|
||||||
|
<p>TODO</p>
|
||||||
|
|
||||||
|
<table class="table table-striped table-bordered">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th scope="col">String value</th>
|
||||||
|
<th scope="col">Numeric value</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td>Zero</td><td>0</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>One</td><td>1</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Two</td><td>2</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Three</td><td>3</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Four</td><td>4</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Five</td><td>5</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Six</td><td>6</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Seven</td><td>7</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Eight</td><td>8</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Nine</td><td>9</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Ten</td><td>10</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<p class="font-weight-bold">Grouping</p>
|
||||||
|
<p>TODO</p>
|
||||||
|
<!-- Optional, create a group
|
||||||
|
create a group called
|
||||||
|
-->
|
||||||
|
|
||||||
|
<h3>Miscellaneous features</h3>
|
||||||
|
|
||||||
|
<p class="font-weight-bold">Unicode character properties</p>
|
||||||
|
<p>You can match specific unicode sequences using <code class="cm-s-idea">"\uXXXX"
|
||||||
|
</code> or <code class="cm-s-idea">"\UXXXXXXXX"</code> where X is a hexadecimal character.
|
||||||
|
<span class="tutorial-code"><code class="cm-s-idea">
|
||||||
|
match "\u0669" // matches arabic digit 9 "٩"
|
||||||
|
</code></span>
|
||||||
|
Unicode character classes/scripts can be matched using the <code class="cm-s-idea">unicode</code> keyword.
|
||||||
|
<span class="tutorial-code"><code class="cm-s-idea">
|
||||||
|
match unicode "Latin" // matches any latin character
|
||||||
|
</code></span>
|
||||||
|
<span class="tutorial-code"><code class="cm-s-idea">
|
||||||
|
match unicode "N" // matches any number character
|
||||||
|
</code></span>
|
||||||
|
The following Unicode class specifiers are available:</p>
|
||||||
|
<table class="table table-striped table-bordered">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th scope="col">Class</th>
|
||||||
|
<th scope="col">Description</th>
|
||||||
|
<th scope="col">Class</th>
|
||||||
|
<th scope="col">Description</th>
|
||||||
|
<th scope="col">Class</th>
|
||||||
|
<th scope="col">Description</th>
|
||||||
|
<th scope="col">Class</th>
|
||||||
|
<th scope="col">Description</th>
|
||||||
|
<th scope="col">Class</th>
|
||||||
|
<th scope="col">Description</th>
|
||||||
|
<th scope="col">Class</th>
|
||||||
|
<th scope="col">Description</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td>C</td><td>Other</td>
|
||||||
|
<td>Cc</td><td>Control</td>
|
||||||
|
<td>Cf</td><td>Format</td>
|
||||||
|
<td>Cn</td><td>Unassigned</td>
|
||||||
|
<td>Co</td><td>Private use</td>
|
||||||
|
<td>Cs</td><td>Surrogate</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>L</td><td>Letter</td>
|
||||||
|
<td>Ll</td><td>Lower case letter</td>
|
||||||
|
<td>Lm</td><td>Modifier letter</td>
|
||||||
|
<td>Lo</td><td>Other letter</td>
|
||||||
|
<td>Lt</td><td>Title case letter</td>
|
||||||
|
<td>Lu</td><td>Upper case letter</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>M</td><td>Mark</td>
|
||||||
|
<td>Mc</td><td>Spacing mark</td>
|
||||||
|
<td>Me</td><td>Enclosing mark</td>
|
||||||
|
<td>Mn</td><td>Non-spacing mark</td>
|
||||||
|
<td>N</td><td>Number</td>
|
||||||
|
<td>Nd</td><td>Decimal number</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Nl</td><td>Letter number</td>
|
||||||
|
<td>No</td><td>Other number</td>
|
||||||
|
<td>P</td><td>Punctuation</td>
|
||||||
|
<td>Pc</td><td>Connector punctuation</td>
|
||||||
|
<td>Pd</td><td>Dash punctuation</td>
|
||||||
|
<td>Pe</td><td>Close punctuation</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Pf</td><td>Final punctuation</td>
|
||||||
|
<td>Pi</td><td>Initial punctuation</td>
|
||||||
|
<td>Po</td><td>Other punctuation</td>
|
||||||
|
<td>Ps</td><td>Open punctuation</td>
|
||||||
|
<td>S</td><td>Symbol</td>
|
||||||
|
<td>Sc</td><td>Currency symbol</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Sk</td><td>Modifier symbol</td>
|
||||||
|
<td>Sm</td><td>Mathematical symbol</td>
|
||||||
|
<td>So</td><td>Other symbol</td>
|
||||||
|
<td>Z</td><td>Separator</td>
|
||||||
|
<td>Zl</td><td>Line separator</td>
|
||||||
|
<td>Zp</td><td>Paragraph separator</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Zs</td><td>Space separator</td>
|
||||||
|
<td> </td><td> </td>
|
||||||
|
<td> </td><td> </td>
|
||||||
|
<td> </td><td> </td>
|
||||||
|
<td> </td><td> </td>
|
||||||
|
<td> </td><td> </td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<p>The following Unicode script specifiers are available:</p>
|
||||||
|
<p>Note: Java and .NET require "Is" in front of the script name. For example, "IsLatin" rather than just "Latin"</p>
|
||||||
|
<table class="table table-striped table-bordered">
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td>Arabic</td>
|
||||||
|
<td>Armenian</td>
|
||||||
|
<td>Avestan</td>
|
||||||
|
<td>Balinese</td>
|
||||||
|
<td>Bamum</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Batak</td>
|
||||||
|
<td>Bengali</td>
|
||||||
|
<td>Bopomofo</td>
|
||||||
|
<td>Brahmi</td>
|
||||||
|
<td>Braille</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Buginese</td>
|
||||||
|
<td>Buhid</td>
|
||||||
|
<td>Canadian_Aboriginal</td>
|
||||||
|
<td>Carian</td>
|
||||||
|
<td>Chakma</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Cham</td>
|
||||||
|
<td>Cherokee</td>
|
||||||
|
<td>Common</td>
|
||||||
|
<td>Coptic</td>
|
||||||
|
<td>Cuneiform</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Cypriot</td>
|
||||||
|
<td>Cyrillic</td>
|
||||||
|
<td>Deseret</td>
|
||||||
|
<td>Devanagari</td>
|
||||||
|
<td>Egyptian_Hieroglyphs</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Ethiopic</td>
|
||||||
|
<td>Georgian</td>
|
||||||
|
<td>Glagolitic</td>
|
||||||
|
<td>Gothic</td>
|
||||||
|
<td>Greek</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Gujarati</td>
|
||||||
|
<td>Gurmukhi</td>
|
||||||
|
<td>Han</td>
|
||||||
|
<td>Hangul</td>
|
||||||
|
<td>Hanunoo</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Hebrew</td>
|
||||||
|
<td>Hiragana</td>
|
||||||
|
<td>Imperial_Aramaic</td>
|
||||||
|
<td>Inherited</td>
|
||||||
|
<td>Inscriptional_Pahlavi</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Inscriptional_Parthian</td>
|
||||||
|
<td>Javanese</td>
|
||||||
|
<td>Kaithi</td>
|
||||||
|
<td>Kannada</td>
|
||||||
|
<td>Katakana</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Kayah_Li</td>
|
||||||
|
<td>Kharoshthi</td>
|
||||||
|
<td>Khmer</td>
|
||||||
|
<td>Lao</td>
|
||||||
|
<td>Latin</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Lepcha</td>
|
||||||
|
<td>Limbu</td>
|
||||||
|
<td>Linear_B</td>
|
||||||
|
<td>Lisu</td>
|
||||||
|
<td>Lycian</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Lydian</td>
|
||||||
|
<td>Malayalam</td>
|
||||||
|
<td>Mandaic</td>
|
||||||
|
<td>Meetei_Mayek</td>
|
||||||
|
<td>Meroitic_Cursive</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Meroitic_Hieroglyphs</td>
|
||||||
|
<td>Miao</td>
|
||||||
|
<td>Mongolian</td>
|
||||||
|
<td>Myanmar</td>
|
||||||
|
<td>New_Tai_Lue</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Nko</td>
|
||||||
|
<td>Ogham</td>
|
||||||
|
<td>Old_Italic</td>
|
||||||
|
<td>Old_Persian</td>
|
||||||
|
<td>Old_South_Arabian</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Old_Turkic</td>
|
||||||
|
<td>Ol_Chiki</td>
|
||||||
|
<td>Oriya</td>
|
||||||
|
<td>Osmanya</td>
|
||||||
|
<td>Phags_Pa</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Phoenician</td>
|
||||||
|
<td>Rejang</td>
|
||||||
|
<td>Runic</td>
|
||||||
|
<td>Samaritan</td>
|
||||||
|
<td>Saurashtra</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Sharada</td>
|
||||||
|
<td>Shavian</td>
|
||||||
|
<td>Sinhala</td>
|
||||||
|
<td>Sora_Sompeng</td>
|
||||||
|
<td>Sundanese</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Syloti_Nagri</td>
|
||||||
|
<td>Syriac</td>
|
||||||
|
<td>Tagalog</td>
|
||||||
|
<td>Tagbanwa</td>
|
||||||
|
<td>Tai_Le</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Tai_Tham</td>
|
||||||
|
<td>Tai_Viet</td>
|
||||||
|
<td>Takri</td>
|
||||||
|
<td>Tamil</td>
|
||||||
|
<td>Telugu</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Thaana</td>
|
||||||
|
<td>Thai</td>
|
||||||
|
<td>Tibetan</td>
|
||||||
|
<td>Tifinagh</td>
|
||||||
|
<td>Ugaritic</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Vai</td>
|
||||||
|
<td>Yi</td>
|
||||||
|
<td> </td>
|
||||||
|
<td> </td>
|
||||||
|
<td> </td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{{> footer}}
|
12
src/index.ts
Normal file
12
src/index.ts
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
/*! Copyright (c) 2020 Patrick Demian; Licensed under MIT */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Includes all packages
|
||||||
|
* @packageDocumentation
|
||||||
|
*/
|
||||||
|
|
||||||
|
import "./utilities";
|
||||||
|
import "./tokens";
|
||||||
|
import "./lexer";
|
||||||
|
import "./parser";
|
||||||
|
import "./generator";
|
@ -10,10 +10,10 @@ import "codemirror/addon/mode/simple";
|
|||||||
import "codemirror/addon/runmode/runmode";
|
import "codemirror/addon/runmode/runmode";
|
||||||
import "codemirror/addon/lint/lint";
|
import "codemirror/addon/lint/lint";
|
||||||
|
|
||||||
import "./webpage/bootstrap.css";
|
import "./docs/bootstrap.css";
|
||||||
import "./webpage/cleanblog.css";
|
import "./docs/cleanblog.css";
|
||||||
import "./webpage/codemirror.css";
|
import "./docs/codemirror.css";
|
||||||
import "./webpage/style.css";
|
import "./docs/style.css";
|
||||||
|
|
||||||
interface CodeMirror {
|
interface CodeMirror {
|
||||||
defineSimpleMode: (name: string, value: Record<string, unknown>) => void;
|
defineSimpleMode: (name: string, value: Record<string, unknown>) => void;
|
||||||
|
2209
src/webpage/bootstrap.css
vendored
2209
src/webpage/bootstrap.css
vendored
File diff suppressed because it is too large
Load Diff
@ -1,19 +0,0 @@
|
|||||||
{{! Copyright (c) 2020 Patrick Demian; Licensed under MIT }}
|
|
||||||
|
|
||||||
{{> header}}
|
|
||||||
<!-- Main Content -->
|
|
||||||
<div class="container" id="maincontent" role="main">
|
|
||||||
<div id="tutorial">
|
|
||||||
<h2>Tutorial</h2>
|
|
||||||
<br>
|
|
||||||
<p class="font-weight-bold">Preface</p>
|
|
||||||
<p>Human2Regex (H2R) is a way to spell out a regular expression in an easy to read, easy to modify language. H2R supports multiple languages as well as many (though not all) different regular expression types such as named groups and quantifiers. You may notice multiple keywords specifying the same thing, and that is intended! H2R is made to be flexible and easy to understand. With a range, do you prefer "...", "through", or "to"? It's up to you to choose, H2R supports all of those!</p>
|
|
||||||
<p class="font-weight-bold">Matching</p>
|
|
||||||
<p>Match using the keyword "match" followed by what you want to match. Example: <code class="cm-s-idea">match "hello world"</code> will generate a regex that matches "hello world". You can chain multiple matches with the keyword "then", or use a newline and another match statement. Example: <code class="cm-s-idea">match "hello" then " world"</code>. Matches that have a few possibilities can be matched with "or". Example: <code class="cm-s-idea">match "hello world" or "hello"</code> will match either of those two. Matches which are optional can be done using the keyword "optional(ly)". Example: <code class="cm-s-idea">optionally match "world"</code>. Anything inside the quoted string will be escaped to become a valid regular expression. H2R also comes with some convenience keywords "word(s)", "digit(s)", "character(s)", "whitespace(s)", and "number(s)" to capture words, single digits, characters, whitespace, and multiple digits respectively. Example: <code class="cm-s-idea">match a word</code>. H2R can also capture a range of characters with the keywords from/to or between/and. Examples: <code class="cm-s-idea">match from "a" to "z" then between "a" to "z"</code></p>
|
|
||||||
<p class="font-weight-bold">Repetition</p>
|
|
||||||
<p>H2R supports 2 types of repetition: single match repetition, or grouped repetition. When using "match" you can specify the number of captures you want just before the text you want to capture. Example: <code class="cm-s-idea">match 2 digits</code> will match any 2 characters in a row. You can also specify a range you wish to capture. Example: <code class="cm-s-idea">match 2..5 digits</code> will match 2, 3, 4, or 5 digits. You can specify if the final number is exclusive with the "exclusive" keyword. Example: <code class="cm-s-idea">match 2 to 5 exclusive digits</code> will only match up to 4 digits. You can group a repetition using the "repeat" keyword. By default, this will match 0 or more of the following statements. The same qualifiers that exist for match exist for repeat. Example: <code class="cm-s-idea">optionally repeat 3...7 times</code>
|
|
||||||
<p class="font-weight-bold">Grouping</p>
|
|
||||||
<p>Groups in H2R are created using the "create a group" phrase. With groups, you can specify if it is optional with the "optional" keyword, or if it has a name with "called" or "named". Example: <code class="cm-s-idea">create an optional group called "MyGroup"</code>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{{> footer}}
|
|
@ -1,59 +1,22 @@
|
|||||||
{
|
{
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
/* Basic Options */
|
|
||||||
"target": "es2017", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017','ES2018' or 'ESNEXT'. */
|
"target": "es2017", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017','ES2018' or 'ESNEXT'. */
|
||||||
"module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */
|
"module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */
|
||||||
"lib": ["es2017", "dom"], /* Specify library files to be included in the compilation. */
|
"lib": ["es2017", "dom"], /* Specify library files to be included in the compilation. */
|
||||||
// "allowJs": true, /* Allow javascript files to be compiled. */
|
"declaration": true, /* Generates corresponding '.d.ts' file. */
|
||||||
// "checkJs": true, /* Report errors in .js files. */
|
"declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */
|
||||||
// "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */
|
"outDir": "./lib/", /* Redirect output structure to the directory. */
|
||||||
// "declaration": true, /* Generates corresponding '.d.ts' file. */
|
|
||||||
// "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */
|
|
||||||
// "sourceMap": true, /* Generates corresponding '.map' file. */
|
|
||||||
// "outFile": "./", /* Concatenate and emit output to single file. */
|
|
||||||
// "outDir": "./build/", /* Redirect output structure to the directory. */
|
|
||||||
"rootDir": "./src/", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */
|
"rootDir": "./src/", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */
|
||||||
// "composite": true, /* Enable project compilation */
|
|
||||||
// "removeComments": true, /* Do not emit comments to output. */
|
|
||||||
// "noEmit": true, /* Do not emit outputs. */
|
|
||||||
// "importHelpers": true, /* Import emit helpers from 'tslib'. */
|
|
||||||
// "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */
|
|
||||||
// "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */
|
|
||||||
|
|
||||||
/* Strict Type-Checking Options */
|
|
||||||
"strict": true, /* Enable all strict type-checking options. */
|
"strict": true, /* Enable all strict type-checking options. */
|
||||||
"noImplicitAny": false, /* Raise error on expressions and declarations with an implied 'any' type. */
|
"noImplicitAny": false, /* Raise error on expressions and declarations with an implied 'any' type. */
|
||||||
"strictNullChecks": true, /* Enable strict null checks. */
|
"strictNullChecks": true, /* Enable strict null checks. */
|
||||||
"strictFunctionTypes": true, /* Enable strict checking of function types. */
|
"strictFunctionTypes": true, /* Enable strict checking of function types. */
|
||||||
// "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */
|
|
||||||
// "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */
|
|
||||||
// "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */
|
|
||||||
|
|
||||||
/* Additional Checks */
|
|
||||||
// "noUnusedLocals": true, /* Report errors on unused locals. */
|
|
||||||
// "noUnusedParameters": true, /* Report errors on unused parameters. */
|
|
||||||
// "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */
|
|
||||||
// "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */
|
|
||||||
|
|
||||||
/* Module Resolution Options */
|
|
||||||
// "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */
|
|
||||||
// "baseUrl": "./", /* Base directory to resolve non-absolute module names. */
|
|
||||||
// "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */
|
|
||||||
// "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */
|
|
||||||
// "typeRoots": [], /* List of folders to include type definitions from. */
|
|
||||||
// "types": [], /* Type declaration files to be included in compilation. */
|
|
||||||
// "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */
|
|
||||||
"esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */
|
"esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */
|
||||||
// "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */
|
},
|
||||||
|
"include": [
|
||||||
/* Source Map Options */
|
"src/**/*.ts"
|
||||||
// "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */
|
],
|
||||||
// "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */
|
"exclude": [
|
||||||
// "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */
|
"src/script.ts"
|
||||||
// "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */
|
]
|
||||||
|
|
||||||
/* Experimental Options */
|
|
||||||
// "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */
|
|
||||||
// "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */
|
|
||||||
}
|
|
||||||
}
|
}
|
@ -12,6 +12,7 @@ const MiniCssExtractPlugin = require("mini-css-extract-plugin");
|
|||||||
const OptimizeCSSAssetsPlugin = require("optimize-css-assets-webpack-plugin");
|
const OptimizeCSSAssetsPlugin = require("optimize-css-assets-webpack-plugin");
|
||||||
const WebpackBeforeBuildPlugin = require("before-build-webpack");
|
const WebpackBeforeBuildPlugin = require("before-build-webpack");
|
||||||
const TerserPlugin = require("terser-webpack-plugin");
|
const TerserPlugin = require("terser-webpack-plugin");
|
||||||
|
const RemovePlugin = require('remove-files-webpack-plugin');
|
||||||
|
|
||||||
const config = {
|
const config = {
|
||||||
prod: true,
|
prod: true,
|
||||||
@ -40,12 +41,12 @@ function build_mustache() {
|
|||||||
compress_html = (input) => config.prod ? minify(input, config.compression_config.html) : input;
|
compress_html = (input) => config.prod ? minify(input, config.compression_config.html) : input;
|
||||||
|
|
||||||
// get views
|
// get views
|
||||||
const files = glob.sync(path.join(config.src, "webpage", "*.json"));
|
const files = glob.sync(path.join(config.src, "docs", "*.json"));
|
||||||
|
|
||||||
// get partials
|
// get partials
|
||||||
const partials = {
|
const partials = {
|
||||||
header: readFileSync(path.join(config.src, "webpage", "header.mustache"), "utf8"),
|
header: readFileSync(path.join(config.src, "docs", "header.mustache"), "utf8"),
|
||||||
footer: readFileSync(path.join(config.src, "webpage", "footer.mustache"), "utf8")
|
footer: readFileSync(path.join(config.src, "docs", "footer.mustache"), "utf8")
|
||||||
};
|
};
|
||||||
|
|
||||||
// build main mustache files
|
// build main mustache files
|
||||||
@ -53,7 +54,7 @@ function build_mustache() {
|
|||||||
const filename = path.basename(item, ".json");
|
const filename = path.basename(item, ".json");
|
||||||
const view = read_json_file(item);
|
const view = read_json_file(item);
|
||||||
const to = path.join(config.dst, filename + ".html");
|
const to = path.join(config.dst, filename + ".html");
|
||||||
const template = readFileSync(path.join(config.src, "webpage", filename + ".mustache"), "utf8");
|
const template = readFileSync(path.join(config.src, "docs", filename + ".mustache"), "utf8");
|
||||||
|
|
||||||
writeFileSync(to, compress_html(render(template, view, partials)));
|
writeFileSync(to, compress_html(render(template, view, partials)));
|
||||||
}
|
}
|
||||||
@ -82,7 +83,7 @@ module.exports = {
|
|||||||
plugins: [
|
plugins: [
|
||||||
new CopyPlugin({
|
new CopyPlugin({
|
||||||
patterns: [
|
patterns: [
|
||||||
{ from: config.src + "webpage/" + "!(*.css|*.mustache|*.json)", to: "", flatten: true}
|
{ from: config.src + "docs/" + "!(*.css|*.mustache|*.json)", to: "", flatten: true}
|
||||||
]
|
]
|
||||||
}),
|
}),
|
||||||
new MiniCssExtractPlugin({ filename: "bundle.min.css" }),
|
new MiniCssExtractPlugin({ filename: "bundle.min.css" }),
|
||||||
@ -90,6 +91,15 @@ module.exports = {
|
|||||||
build_mustache();
|
build_mustache();
|
||||||
callback();
|
callback();
|
||||||
}),
|
}),
|
||||||
|
new RemovePlugin({
|
||||||
|
after: {
|
||||||
|
root: "./lib",
|
||||||
|
include: [
|
||||||
|
"script.d.ts",
|
||||||
|
"script.d.ts.map"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
})
|
||||||
],
|
],
|
||||||
resolve: {
|
resolve: {
|
||||||
extensions: [ ".ts", ".js" ]
|
extensions: [ ".ts", ".js" ]
|
||||||
|
Loading…
x
Reference in New Issue
Block a user