@xaendar/compiler 0.0.3 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +19 -11
- package/xaendar-compiler.es.d.ts +199 -0
- package/xaendar-compiler.es.js +505 -0
- package/xaendar-compiler.es.js.map +1 -0
- package/src/costants/chars.constants.ts +0 -188
- package/src/costants/tags/base-tags.constants.ts +0 -106
- package/src/costants/tags/not-alllowed-tags.constants.ts +0 -13
- package/src/costants/tags/not-allowed-chars.constants.ts +0 -24
- package/src/lexer/lexer.ts +0 -91
- package/src/lexer/models/current-char.type.ts +0 -17
- package/src/lexer/models/current-position.type.ts +0 -13
- package/src/lexer/models/lexer-cursor.model.ts +0 -192
- package/src/lexer/models/lexer-state.enum.ts +0 -13
- package/src/lexer/models/token-type.enum.ts +0 -17
- package/src/lexer/models/token.type.ts +0 -62
- package/src/lexer/models/transition-function/transition-function-context.type.ts +0 -27
- package/src/lexer/models/transition-function/transition-function-return-type.type.ts +0 -48
- package/src/lexer/models/transition-function/transition-function.type.ts +0 -36
- package/src/lexer/states/attribute.state.ts +0 -47
- package/src/lexer/states/event.state.ts +0 -38
- package/src/lexer/states/interpolation-expression.state.ts +0 -68
- package/src/lexer/states/interpolation-literal.state.ts +0 -71
- package/src/lexer/states/interpolation.state.ts +0 -31
- package/src/lexer/states/tag-body.state.ts +0 -43
- package/src/lexer/states/tag-close.state.ts +0 -46
- package/src/lexer/states/tag-open-end.state.ts +0 -40
- package/src/lexer/states/tag-open-name.state.ts +0 -50
- package/src/lexer/states/text.state.ts +0 -61
- package/src/parser/models/ast.type.ts +0 -34
- package/src/parser/models/current-token.type.ts +0 -6
- package/src/parser/models/node.enum.ts +0 -5
- package/src/parser/models/parser-cursor.model.ts +0 -133
- package/src/parser/parser.ts +0 -225
- package/src/public-api.ts +0 -3
- package/src/render-generator/render-generator.model.ts +0 -73
- package/src/utils/chars.utils.ts +0 -70
- package/src/utils/tags.utils.ts +0 -36
- package/tsconfig.json +0 -3
- package/vite.config.ts +0 -4
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
import { TokenType } from './token-type.enum';
|
|
2
|
-
|
|
3
|
-
export type Token =
|
|
4
|
-
| TagOpenNameToken
|
|
5
|
-
| TagSelfCloseToken
|
|
6
|
-
| TagCloseToken
|
|
7
|
-
| TagCloseNameToken
|
|
8
|
-
| AttributeToken
|
|
9
|
-
| EventToken
|
|
10
|
-
| TextToken
|
|
11
|
-
| InterpolationExpressionToken
|
|
12
|
-
| InterpolationLiteralToken
|
|
13
|
-
| EOFToken
|
|
14
|
-
|
|
15
|
-
export type TagOpenNameToken = {
|
|
16
|
-
type: TokenType.TAG_OPEN_NAME;
|
|
17
|
-
parts: [string];
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
export type EventToken = {
|
|
21
|
-
type: TokenType.EVENT
|
|
22
|
-
parts: [string]
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
export type AttributeToken = {
|
|
26
|
-
type: TokenType.ATTRIBUTE
|
|
27
|
-
parts: [string]
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
export type TextToken = {
|
|
31
|
-
type: TokenType.TEXT,
|
|
32
|
-
parts: [string]
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
export type InterpolationExpressionToken = {
|
|
36
|
-
type: TokenType.INTERPOLATION_EXPRESSION;
|
|
37
|
-
parts: [string];
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
export type InterpolationLiteralToken = {
|
|
41
|
-
type: TokenType.INTERPOLATION_LITERAL;
|
|
42
|
-
parts: [string];
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
export type TagSelfCloseToken = {
|
|
46
|
-
type: TokenType.TAG_SELF_CLOSE,
|
|
47
|
-
parts: []
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
export type TagCloseNameToken = {
|
|
51
|
-
type: TokenType.TAG_CLOSE_NAME,
|
|
52
|
-
parts: [string]
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
export type TagCloseToken = {
|
|
56
|
-
type: TokenType.TAG_OPEN_END,
|
|
57
|
-
parts: []
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
export type EOFToken = {
|
|
61
|
-
type: TokenType.EOF
|
|
62
|
-
}
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
import { LexerState } from '../lexer-state.enum'
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Context object passed by the Lexer engine to each
|
|
5
|
-
* lexer transition function.
|
|
6
|
-
*
|
|
7
|
-
* This context exposes read-only information about the
|
|
8
|
-
* internal execution state of the lexer, without allowing
|
|
9
|
-
* direct mutation of the engine.
|
|
10
|
-
*/
|
|
11
|
-
export type LexerTransitionFunctionContext = {
|
|
12
|
-
/**
|
|
13
|
-
* Read-only view of the lexer state stack.
|
|
14
|
-
*
|
|
15
|
-
* The stack represents the execution history of the lexer
|
|
16
|
-
* and is used to support nested or temporary states
|
|
17
|
-
* (e.g. interpolations, embedded expressions, attribute values).
|
|
18
|
-
*
|
|
19
|
-
* Conceptually, the lexer behaves as a Pushdown Automaton (PDA),
|
|
20
|
-
* where this stack allows the engine to return to a previous
|
|
21
|
-
* state after completing a nested transition.
|
|
22
|
-
*
|
|
23
|
-
* The array is ordered from bottom (oldest state)
|
|
24
|
-
* to top (most recent state).
|
|
25
|
-
*/
|
|
26
|
-
history: Array<LexerState>
|
|
27
|
-
}
|
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
import { LexerState } from '../lexer-state.enum'
|
|
2
|
-
import { Token } from '../token.type'
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Result returned by a lexer state transition function.
|
|
6
|
-
*
|
|
7
|
-
* Each lexer state is implemented as a pure function that:
|
|
8
|
-
* - consumes characters from the cursor
|
|
9
|
-
* - optionally emits tokens
|
|
10
|
-
* - decides the next lexer state
|
|
11
|
-
* - optionally manipulates the lexer state stack
|
|
12
|
-
*/
|
|
13
|
-
export type LexerTransitionFunctionReturnType = {
|
|
14
|
-
|
|
15
|
-
/**
|
|
16
|
-
* The next state the lexer should transition to.
|
|
17
|
-
*
|
|
18
|
-
* This is always required and represents the logical continuation
|
|
19
|
-
* of the lexing process after the current state has finished consuming input.
|
|
20
|
-
*/
|
|
21
|
-
state: LexerState
|
|
22
|
-
/**
|
|
23
|
-
* Tokens produced while consuming input in the current state.
|
|
24
|
-
*
|
|
25
|
-
* This field is optional because some state transitions
|
|
26
|
-
* may only advance the cursor or change state without
|
|
27
|
-
* emitting any tokens.
|
|
28
|
-
*/
|
|
29
|
-
tokens?: Token[]
|
|
30
|
-
/**
|
|
31
|
-
* Whether the lexer should pop the previous state from the state stack
|
|
32
|
-
* after this transition.
|
|
33
|
-
*
|
|
34
|
-
* This is typically used for temporary or nested states
|
|
35
|
-
* such as interpolations, where the lexer needs to return
|
|
36
|
-
* to the state it was in before entering the nested context.
|
|
37
|
-
*/
|
|
38
|
-
popState?: boolean
|
|
39
|
-
/**
|
|
40
|
-
* Whether the lexer should push the current state onto the state stack
|
|
41
|
-
* before transitioning to the next state.
|
|
42
|
-
*
|
|
43
|
-
* This is useful when entering a nested or contextual state
|
|
44
|
-
* (e.g. interpolations or embedded expressions) where the lexer
|
|
45
|
-
* must remember where it came from in order to resume correctly.
|
|
46
|
-
*/
|
|
47
|
-
pushState?: boolean
|
|
48
|
-
}
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
import { LexerCursor } from '../lexer-cursor.model';
|
|
2
|
-
import { LexerTransitionFunctionContext } from './transition-function-context.type';
|
|
3
|
-
import { LexerTransitionFunctionReturnType } from './transition-function-return-type.type';
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* A lexer transition function.
|
|
7
|
-
*
|
|
8
|
-
* A transition function is responsible for:
|
|
9
|
-
* - Reading characters from the input stream via the {@link LexerCursor}
|
|
10
|
-
* - Emitting zero or more tokens
|
|
11
|
-
* - Deciding the next lexer state
|
|
12
|
-
*
|
|
13
|
-
* Transition functions must be **pure with respect to the lexer engine**:
|
|
14
|
-
* they must not mutate the engine state directly, but instead communicate
|
|
15
|
-
* their intent through the returned {@link LexerTransitionFunctionReturnType}.
|
|
16
|
-
*
|
|
17
|
-
* The lexer engine executes transition functions as part of a
|
|
18
|
-
* Pushdown Automaton (PDA), allowing nested states such as interpolations
|
|
19
|
-
* or embedded expressions.
|
|
20
|
-
*
|
|
21
|
-
* @param cursor
|
|
22
|
-
* Cursor used to inspect and consume characters from the input stream.
|
|
23
|
-
* The cursor encapsulates all low-level navigation logic (peek, advance,
|
|
24
|
-
* position tracking, EOF handling).
|
|
25
|
-
*
|
|
26
|
-
* @param context
|
|
27
|
-
* Read-only contextual information provided by the lexer engine,
|
|
28
|
-
* including the current state stack and execution history.
|
|
29
|
-
*
|
|
30
|
-
* @returns
|
|
31
|
-
* An object describing the outcome of the transition:
|
|
32
|
-
* - the next lexer state
|
|
33
|
-
* - any emitted tokens
|
|
34
|
-
* - optional stack operations (push / pop)
|
|
35
|
-
*/
|
|
36
|
-
export type LexerTransitionFunction = (cursor: LexerCursor, context: LexerTransitionFunctionContext) => LexerTransitionFunctionReturnType;
|
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
import { GREATER_THEN, LEFT_BRACE, SLASH, SPACE } from '../../costants/chars.constants';
|
|
2
|
-
import { LexerCursor } from '../models/lexer-cursor.model';
|
|
3
|
-
import { LexerState } from '../models/lexer-state.enum';
|
|
4
|
-
import { TokenType } from '../models/token-type.enum';
|
|
5
|
-
import { LexerTransitionFunctionContext } from '../models/transition-function/transition-function-context.type';
|
|
6
|
-
import { LexerTransitionFunctionReturnType } from '../models/transition-function/transition-function-return-type.type';
|
|
7
|
-
|
|
8
|
-
export function consumeAttribute(cursor: LexerCursor, _context: LexerTransitionFunctionContext): LexerTransitionFunctionReturnType {
|
|
9
|
-
let read = true;
|
|
10
|
-
let attribute = '';
|
|
11
|
-
let retVal!: LexerTransitionFunctionReturnType;
|
|
12
|
-
|
|
13
|
-
while (read) {
|
|
14
|
-
switch (cursor.peek()) {
|
|
15
|
-
case SPACE:
|
|
16
|
-
case SLASH:
|
|
17
|
-
case GREATER_THEN:
|
|
18
|
-
retVal = {
|
|
19
|
-
state: LexerState.TAG_BODY,
|
|
20
|
-
tokens: [{
|
|
21
|
-
type: TokenType.ATTRIBUTE,
|
|
22
|
-
parts: [attribute]
|
|
23
|
-
}]
|
|
24
|
-
};
|
|
25
|
-
read = false;
|
|
26
|
-
break;
|
|
27
|
-
|
|
28
|
-
case LEFT_BRACE:
|
|
29
|
-
retVal = {
|
|
30
|
-
state: LexerState.INTERPOLATION,
|
|
31
|
-
tokens: [{
|
|
32
|
-
type: TokenType.ATTRIBUTE,
|
|
33
|
-
parts: [attribute]
|
|
34
|
-
}],
|
|
35
|
-
pushState: true
|
|
36
|
-
};
|
|
37
|
-
read = false;
|
|
38
|
-
break;
|
|
39
|
-
|
|
40
|
-
default:
|
|
41
|
-
cursor.advance();
|
|
42
|
-
attribute = `${attribute}${cursor.currentChar.value}`
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
return retVal;
|
|
47
|
-
}
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
import { GREATER_THEN, SLASH, SPACE } from '../../costants/chars.constants';
|
|
2
|
-
import { LexerCursor } from '../models/lexer-cursor.model';
|
|
3
|
-
import { LexerState } from '../models/lexer-state.enum';
|
|
4
|
-
import { TokenType } from '../models/token-type.enum';
|
|
5
|
-
import { LexerTransitionFunctionContext } from '../models/transition-function/transition-function-context.type';
|
|
6
|
-
import { LexerTransitionFunctionReturnType } from '../models/transition-function/transition-function-return-type.type';
|
|
7
|
-
|
|
8
|
-
export function consumeEvent(cursor: LexerCursor, _context: LexerTransitionFunctionContext): LexerTransitionFunctionReturnType {
|
|
9
|
-
let read = true;
|
|
10
|
-
let event = '';
|
|
11
|
-
let retVal!: LexerTransitionFunctionReturnType;
|
|
12
|
-
|
|
13
|
-
// Consume '@' character
|
|
14
|
-
cursor.advance();
|
|
15
|
-
|
|
16
|
-
while (read) {
|
|
17
|
-
switch (cursor.peek()) {
|
|
18
|
-
case SPACE:
|
|
19
|
-
case SLASH:
|
|
20
|
-
case GREATER_THEN:
|
|
21
|
-
retVal = {
|
|
22
|
-
state: LexerState.TAG_BODY,
|
|
23
|
-
tokens: [{
|
|
24
|
-
type: TokenType.EVENT,
|
|
25
|
-
parts: [event]
|
|
26
|
-
}]
|
|
27
|
-
};
|
|
28
|
-
read = false;
|
|
29
|
-
break;
|
|
30
|
-
|
|
31
|
-
default:
|
|
32
|
-
cursor.advance();
|
|
33
|
-
event = `${event}${cursor.currentChar.value}`
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
return retVal;
|
|
38
|
-
}
|
|
@@ -1,68 +0,0 @@
|
|
|
1
|
-
import { LEFT_BRACE, RIGHT_BRACE, SPACE } from '../../costants/chars.constants';
|
|
2
|
-
import { LexerCursor } from '../models/lexer-cursor.model';
|
|
3
|
-
import { LexerState } from '../models/lexer-state.enum';
|
|
4
|
-
import { TokenType } from '../models/token-type.enum';
|
|
5
|
-
import { LexerTransitionFunctionContext } from '../models/transition-function/transition-function-context.type';
|
|
6
|
-
import { LexerTransitionFunctionReturnType } from '../models/transition-function/transition-function-return-type.type';
|
|
7
|
-
|
|
8
|
-
export function consumeInterpolationExpression(cursor: LexerCursor, context: LexerTransitionFunctionContext): LexerTransitionFunctionReturnType {
|
|
9
|
-
let read = true;
|
|
10
|
-
let interpolation = '';
|
|
11
|
-
let deep = 1
|
|
12
|
-
let retVal!: LexerTransitionFunctionReturnType;
|
|
13
|
-
|
|
14
|
-
while (read) {
|
|
15
|
-
switch (cursor.peek()) {
|
|
16
|
-
case LEFT_BRACE:
|
|
17
|
-
deep++;
|
|
18
|
-
interpolation = addCharacter(cursor, interpolation);
|
|
19
|
-
break;
|
|
20
|
-
|
|
21
|
-
case RIGHT_BRACE:
|
|
22
|
-
deep--;
|
|
23
|
-
|
|
24
|
-
if (deep === 0) {
|
|
25
|
-
cursor.advance();
|
|
26
|
-
/*
|
|
27
|
-
After an interpolation we have to understanad where to transite
|
|
28
|
-
The next state depends from the previous state
|
|
29
|
-
*/
|
|
30
|
-
const previousState = context.history.pop();
|
|
31
|
-
let state!: LexerState;
|
|
32
|
-
|
|
33
|
-
switch (previousState) {
|
|
34
|
-
case LexerState.ATTRIBUTE:
|
|
35
|
-
state = LexerState.TAG_BODY
|
|
36
|
-
break;
|
|
37
|
-
|
|
38
|
-
case LexerState.TEXT:
|
|
39
|
-
state = LexerState.TEXT
|
|
40
|
-
};
|
|
41
|
-
|
|
42
|
-
retVal = {
|
|
43
|
-
state,
|
|
44
|
-
tokens: [{
|
|
45
|
-
type: TokenType.INTERPOLATION_EXPRESSION,
|
|
46
|
-
parts: [interpolation]
|
|
47
|
-
}],
|
|
48
|
-
popState: true
|
|
49
|
-
}
|
|
50
|
-
read = false;
|
|
51
|
-
} else {
|
|
52
|
-
interpolation = addCharacter(cursor, interpolation);
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
break;
|
|
56
|
-
|
|
57
|
-
default:
|
|
58
|
-
interpolation = addCharacter(cursor, interpolation);
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
return retVal;
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
function addCharacter(cursor: LexerCursor, interpolation: string): string {
|
|
66
|
-
cursor.advance(1);
|
|
67
|
-
return `${interpolation}${cursor.currentChar.value}`;
|
|
68
|
-
}
|
|
@@ -1,71 +0,0 @@
|
|
|
1
|
-
import { GRAVE_ACCENT, RIGHT_BRACE } from '../../costants/chars.constants';
|
|
2
|
-
import { LexerCursor } from '../models/lexer-cursor.model';
|
|
3
|
-
import { LexerState } from '../models/lexer-state.enum';
|
|
4
|
-
import { TokenType } from '../models/token-type.enum';
|
|
5
|
-
import { LexerTransitionFunctionContext } from '../models/transition-function/transition-function-context.type';
|
|
6
|
-
import { LexerTransitionFunctionReturnType } from '../models/transition-function/transition-function-return-type.type';
|
|
7
|
-
|
|
8
|
-
export function consumeInterpolationliteral(cursor: LexerCursor, context: LexerTransitionFunctionContext): LexerTransitionFunctionReturnType {
|
|
9
|
-
let read = true;
|
|
10
|
-
let interpolation = '';
|
|
11
|
-
let retVal!: LexerTransitionFunctionReturnType;
|
|
12
|
-
|
|
13
|
-
// Consume '`' character
|
|
14
|
-
cursor.advance();
|
|
15
|
-
|
|
16
|
-
while (read) {
|
|
17
|
-
switch (cursor.peek()) {
|
|
18
|
-
case GRAVE_ACCENT:
|
|
19
|
-
cursor.advance();
|
|
20
|
-
|
|
21
|
-
if (cursor.peek() === RIGHT_BRACE) {
|
|
22
|
-
cursor.advance();
|
|
23
|
-
/*
|
|
24
|
-
After an interpolation we have to understanad where to transite
|
|
25
|
-
The next state depends from the previous state
|
|
26
|
-
*/
|
|
27
|
-
const previousState = context.history.pop();
|
|
28
|
-
let state!: LexerState;
|
|
29
|
-
|
|
30
|
-
switch (previousState) {
|
|
31
|
-
case LexerState.ATTRIBUTE:
|
|
32
|
-
state = LexerState.TAG_BODY
|
|
33
|
-
break;
|
|
34
|
-
|
|
35
|
-
case LexerState.TEXT:
|
|
36
|
-
state = LexerState.TEXT
|
|
37
|
-
};
|
|
38
|
-
|
|
39
|
-
retVal = {
|
|
40
|
-
state,
|
|
41
|
-
tokens: [{
|
|
42
|
-
type: TokenType.INTERPOLATION_LITERAL,
|
|
43
|
-
parts: [interpolation]
|
|
44
|
-
}],
|
|
45
|
-
popState: true
|
|
46
|
-
}
|
|
47
|
-
read = false;
|
|
48
|
-
} else {
|
|
49
|
-
/*
|
|
50
|
-
If ` is not followed by }, it means the interpolation is not closed
|
|
51
|
-
and ` is part of the interpolated string
|
|
52
|
-
|
|
|
53
|
-
˅
|
|
54
|
-
Example: {`text ${var} ` text`}
|
|
55
|
-
*/
|
|
56
|
-
interpolation = `${interpolation}${cursor.currentChar.value}`
|
|
57
|
-
}
|
|
58
|
-
break;
|
|
59
|
-
|
|
60
|
-
default:
|
|
61
|
-
interpolation = addCharacter(cursor, interpolation);
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
return retVal;
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
function addCharacter(cursor: LexerCursor, interpolation: string): string {
|
|
69
|
-
cursor.advance(1);
|
|
70
|
-
return `${interpolation}${cursor.currentChar.value}`;
|
|
71
|
-
}
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
import { GRAVE_ACCENT, SPACE } from '../../costants/chars.constants';
|
|
2
|
-
import { isJSIdentifierStart } from '../../utils/chars.utils';
|
|
3
|
-
import { LexerCursor } from '../models/lexer-cursor.model';
|
|
4
|
-
import { LexerState } from '../models/lexer-state.enum';
|
|
5
|
-
import { LexerTransitionFunctionContext } from '../models/transition-function/transition-function-context.type';
|
|
6
|
-
import { LexerTransitionFunctionReturnType } from '../models/transition-function/transition-function-return-type.type';
|
|
7
|
-
|
|
8
|
-
export function consumeInterpolation(cursor: LexerCursor, _context: LexerTransitionFunctionContext): LexerTransitionFunctionReturnType {
|
|
9
|
-
let retVal!: LexerTransitionFunctionReturnType;
|
|
10
|
-
|
|
11
|
-
// Consume '{' characters
|
|
12
|
-
cursor.advance();
|
|
13
|
-
|
|
14
|
-
/*
|
|
15
|
-
Skip all the spaces between '{' and the actual interpolation content
|
|
16
|
-
Ex: '{ label}
|
|
17
|
-
*/
|
|
18
|
-
cursor.skipSpaces();
|
|
19
|
-
|
|
20
|
-
const nextChar = cursor.peek();
|
|
21
|
-
|
|
22
|
-
if (nextChar === GRAVE_ACCENT) {
|
|
23
|
-
retVal = { state: LexerState.INTERPOLATION_LITERAL };
|
|
24
|
-
} else if (isJSIdentifierStart(nextChar)) {
|
|
25
|
-
retVal = { state: LexerState.INTERPOLATION_EXPRESSION };
|
|
26
|
-
} else {
|
|
27
|
-
throw new Error(`Unrecognized First Character ${String.fromCharCode(nextChar)} in interpolation`);
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
return retVal;
|
|
31
|
-
}
|
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
import { AT_SIGN, GREATER_THEN, SLASH, SPACE } from '../../costants/chars.constants';
|
|
2
|
-
import { LexerCursor } from '../models/lexer-cursor.model';
|
|
3
|
-
import { LexerState } from '../models/lexer-state.enum';
|
|
4
|
-
import { LexerTransitionFunctionContext } from '../models/transition-function/transition-function-context.type';
|
|
5
|
-
import { LexerTransitionFunctionReturnType } from '../models/transition-function/transition-function-return-type.type';
|
|
6
|
-
|
|
7
|
-
export function consumeTagBody(cursor: LexerCursor, _context: LexerTransitionFunctionContext): LexerTransitionFunctionReturnType {
|
|
8
|
-
let read = true;
|
|
9
|
-
let retVal!: LexerTransitionFunctionReturnType;
|
|
10
|
-
|
|
11
|
-
while (read) {
|
|
12
|
-
const nextChar = cursor.peek();
|
|
13
|
-
|
|
14
|
-
switch (nextChar) {
|
|
15
|
-
case AT_SIGN:
|
|
16
|
-
retVal = {
|
|
17
|
-
state: LexerState.EVENT
|
|
18
|
-
}
|
|
19
|
-
read = false;
|
|
20
|
-
break;
|
|
21
|
-
|
|
22
|
-
case SPACE:
|
|
23
|
-
cursor.advance();
|
|
24
|
-
break;
|
|
25
|
-
|
|
26
|
-
case GREATER_THEN:
|
|
27
|
-
case SLASH:
|
|
28
|
-
retVal = {
|
|
29
|
-
state: LexerState.TAG_OPEN_END
|
|
30
|
-
}
|
|
31
|
-
read = false;
|
|
32
|
-
break;
|
|
33
|
-
|
|
34
|
-
default:
|
|
35
|
-
retVal = {
|
|
36
|
-
state: LexerState.ATTRIBUTE
|
|
37
|
-
}
|
|
38
|
-
read = false;
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
return retVal
|
|
43
|
-
}
|
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
import { GREATER_THEN, SPACE } from '../../costants/chars.constants';
|
|
2
|
-
import { LexerCursor } from '../models/lexer-cursor.model';
|
|
3
|
-
import { LexerState } from '../models/lexer-state.enum';
|
|
4
|
-
import { TokenType } from '../models/token-type.enum';
|
|
5
|
-
import { LexerTransitionFunctionContext } from '../models/transition-function/transition-function-context.type';
|
|
6
|
-
import { LexerTransitionFunctionReturnType } from '../models/transition-function/transition-function-return-type.type';
|
|
7
|
-
|
|
8
|
-
export function consumeTagClose(cursor: LexerCursor, _context: LexerTransitionFunctionContext): LexerTransitionFunctionReturnType {
|
|
9
|
-
let read = true;
|
|
10
|
-
let tagName = '';
|
|
11
|
-
let retVal!: LexerTransitionFunctionReturnType;
|
|
12
|
-
|
|
13
|
-
// Skip '</'
|
|
14
|
-
cursor.advance(2);
|
|
15
|
-
|
|
16
|
-
/*
|
|
17
|
-
Skip all the spaces between '</' and the actual tag name
|
|
18
|
-
Ex: '</ div>
|
|
19
|
-
*/
|
|
20
|
-
cursor.skipSpaces();
|
|
21
|
-
|
|
22
|
-
while (read) {
|
|
23
|
-
switch (cursor.peek()) {
|
|
24
|
-
case GREATER_THEN:
|
|
25
|
-
cursor.advance();
|
|
26
|
-
retVal = {
|
|
27
|
-
state: LexerState.TEXT,
|
|
28
|
-
tokens: [{
|
|
29
|
-
type: TokenType.TAG_CLOSE_NAME,
|
|
30
|
-
parts: [tagName]
|
|
31
|
-
}]
|
|
32
|
-
};
|
|
33
|
-
read = false;
|
|
34
|
-
break;
|
|
35
|
-
|
|
36
|
-
case SPACE:
|
|
37
|
-
throw new Error('Tag Close Name cannot contains spaces');
|
|
38
|
-
|
|
39
|
-
default:
|
|
40
|
-
cursor.advance();
|
|
41
|
-
tagName = `${tagName}${cursor.currentChar.value}`;
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
return retVal;
|
|
46
|
-
}
|
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
import { GREATER_THEN } from '../../costants/chars.constants';
|
|
2
|
-
import { LexerCursor } from '../models/lexer-cursor.model';
|
|
3
|
-
import { LexerState } from '../models/lexer-state.enum';
|
|
4
|
-
import { TokenType } from '../models/token-type.enum';
|
|
5
|
-
import { LexerTransitionFunctionContext } from '../models/transition-function/transition-function-context.type';
|
|
6
|
-
import { LexerTransitionFunctionReturnType } from '../models/transition-function/transition-function-return-type.type';
|
|
7
|
-
|
|
8
|
-
export function consumeTagOpenEnd(cursor: LexerCursor, _context: LexerTransitionFunctionContext): LexerTransitionFunctionReturnType {
|
|
9
|
-
let retVal!: LexerTransitionFunctionReturnType
|
|
10
|
-
|
|
11
|
-
// We arrive in this point by reading '>' or '/' at the end of a Open Tag
|
|
12
|
-
if (cursor.peek() === GREATER_THEN) {
|
|
13
|
-
cursor.advance();
|
|
14
|
-
retVal = {
|
|
15
|
-
state: LexerState.TEXT,
|
|
16
|
-
tokens: [{
|
|
17
|
-
type: TokenType.TAG_OPEN_END,
|
|
18
|
-
parts: []
|
|
19
|
-
}]
|
|
20
|
-
};
|
|
21
|
-
} else {
|
|
22
|
-
cursor.advance();
|
|
23
|
-
const nextChar = cursor.peek();
|
|
24
|
-
|
|
25
|
-
if (nextChar === GREATER_THEN) {
|
|
26
|
-
cursor.advance();
|
|
27
|
-
retVal = {
|
|
28
|
-
state: LexerState.TEXT,
|
|
29
|
-
tokens: [{
|
|
30
|
-
type: TokenType.TAG_SELF_CLOSE,
|
|
31
|
-
parts: []
|
|
32
|
-
}]
|
|
33
|
-
};
|
|
34
|
-
} else {
|
|
35
|
-
throw new Error(`Unexpected character ${nextChar} for closing tag.\nExpected />\nRead of /${String.fromCharCode(nextChar)}\nAt line ${cursor.position.row + 1} col ${cursor.position.column + 1}`)
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
return retVal
|
|
40
|
-
}
|
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
import { GREATER_THEN, SLASH, SPACE } from '../../costants/chars.constants';
|
|
2
|
-
import { LexerCursor } from '../models/lexer-cursor.model';
|
|
3
|
-
import { LexerState } from '../models/lexer-state.enum';
|
|
4
|
-
import { TokenType } from '../models/token-type.enum';
|
|
5
|
-
import { LexerTransitionFunctionContext } from '../models/transition-function/transition-function-context.type';
|
|
6
|
-
import { LexerTransitionFunctionReturnType } from '../models/transition-function/transition-function-return-type.type';
|
|
7
|
-
|
|
8
|
-
export function consumeTagOpenName(cursor: LexerCursor, _context: LexerTransitionFunctionContext): LexerTransitionFunctionReturnType {
|
|
9
|
-
let read = true;
|
|
10
|
-
let tagName = '';
|
|
11
|
-
let retVal!: LexerTransitionFunctionReturnType
|
|
12
|
-
|
|
13
|
-
// Consume '<' character
|
|
14
|
-
cursor.advance();
|
|
15
|
-
|
|
16
|
-
/*
|
|
17
|
-
Skip all the spaces between '<' and the actual tag name
|
|
18
|
-
Ex: '< div>
|
|
19
|
-
*/
|
|
20
|
-
cursor.skipSpaces();
|
|
21
|
-
|
|
22
|
-
/*
|
|
23
|
-
Keep read input until:
|
|
24
|
-
- Space: <span
|
|
25
|
-
- GT: <span>
|
|
26
|
-
- Slash (Self Closing tag) <span / or <span/
|
|
27
|
-
*/
|
|
28
|
-
while (read) {
|
|
29
|
-
switch (cursor.peek()) {
|
|
30
|
-
case SPACE:
|
|
31
|
-
case SLASH:
|
|
32
|
-
case GREATER_THEN:
|
|
33
|
-
retVal = {
|
|
34
|
-
state: LexerState.TAG_BODY,
|
|
35
|
-
tokens: [{
|
|
36
|
-
type: TokenType.TAG_OPEN_NAME,
|
|
37
|
-
parts: [tagName]
|
|
38
|
-
}]
|
|
39
|
-
}
|
|
40
|
-
read = false;
|
|
41
|
-
break;
|
|
42
|
-
|
|
43
|
-
default:
|
|
44
|
-
cursor.advance();
|
|
45
|
-
tagName = `${tagName}${cursor.currentChar.value}`
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
return retVal
|
|
50
|
-
}
|
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
import { CR, LEFT_BRACE, LESS_THAN, LF, SLASH, SPACE } from '../../costants/chars.constants';
|
|
2
|
-
import { isNotBlank } from '../../utils/chars.utils';
|
|
3
|
-
import { LexerCursor } from '../models/lexer-cursor.model';
|
|
4
|
-
import { LexerState } from '../models/lexer-state.enum';
|
|
5
|
-
import { TokenType } from '../models/token-type.enum';
|
|
6
|
-
import { LexerTransitionFunctionContext } from '../models/transition-function/transition-function-context.type';
|
|
7
|
-
import { LexerTransitionFunctionReturnType } from '../models/transition-function/transition-function-return-type.type';
|
|
8
|
-
|
|
9
|
-
export function consumeText(cursor: LexerCursor, _context: LexerTransitionFunctionContext): LexerTransitionFunctionReturnType {
|
|
10
|
-
let read = true;
|
|
11
|
-
let text = '';
|
|
12
|
-
let retVal!: LexerTransitionFunctionReturnType
|
|
13
|
-
|
|
14
|
-
while (read) {
|
|
15
|
-
switch (cursor.peek()) {
|
|
16
|
-
case LESS_THAN:
|
|
17
|
-
// If after '<' we read a '/', we suppose we're approaching a ClosureTag, otherwise an OpenTag
|
|
18
|
-
const nextState = cursor.peek(1, { offset: 1 }) === SLASH ? LexerState.TAG_CLOSE : LexerState.TAG_OPEN_NAME;
|
|
19
|
-
retVal = { state: nextState }
|
|
20
|
-
read = false;
|
|
21
|
-
break;
|
|
22
|
-
|
|
23
|
-
case LEFT_BRACE:
|
|
24
|
-
retVal = {
|
|
25
|
-
state: LexerState.INTERPOLATION,
|
|
26
|
-
pushState: true
|
|
27
|
-
};
|
|
28
|
-
read = false;
|
|
29
|
-
break;
|
|
30
|
-
|
|
31
|
-
case SPACE:
|
|
32
|
-
case LF:
|
|
33
|
-
case CR:
|
|
34
|
-
cursor.advance();
|
|
35
|
-
break;
|
|
36
|
-
|
|
37
|
-
default:
|
|
38
|
-
cursor.advance();
|
|
39
|
-
text = `${text}${cursor.currentChar.value}`;
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
/*
|
|
45
|
-
If the first read character trigger a StateChange
|
|
46
|
-
The cumulative `text` variable will be empty
|
|
47
|
-
|
|
48
|
-
In this case we must NOT add any token
|
|
49
|
-
|
|
50
|
-
Ex:
|
|
51
|
-
Template starts with a tag:
|
|
52
|
-
`<div ...`
|
|
53
|
-
Or an interpolation:
|
|
54
|
-
`{ myVariable }`
|
|
55
|
-
*/
|
|
56
|
-
retVal.tokens = isNotBlank(text)
|
|
57
|
-
? [{ type: TokenType.TEXT, parts: [text] }]
|
|
58
|
-
: undefined;
|
|
59
|
-
|
|
60
|
-
return retVal
|
|
61
|
-
}
|