en Custom Syntax - chiba233/yumeDSL GitHub Wiki
API Reference | Custom Tag Name Characters
Default syntax is $$tag(content)$$. Want @@tag(content)@@ or <<tag[content]>>? Change the syntax option.
Inline: $$tag(content)$$
↑↑ ↑ ↑↑
tagPrefix tagOpen endTag
$$tag(arg | content)$$
↑
tagDivider
Raw: $$tag(arg)%
↑ raw content (no parsing)
rawOpen
%end$$
↑
rawClose
Block: $$tag(arg)*
↑ block content (recursive parsing)
blockOpen
*end$$
↑
blockClose
Escape: \) \\ \|
↑
escapeChar
Want to customize syntax?
│
├─ Most cases → createEasySyntax (recommended)
│ Change base tokens, compounds auto-derive
│
└─ Full manual → createSyntax
Plain shallow merge, you manage everything
function createEasySyntax(
overrides?: Partial<SyntaxInput> & { closeMiddle?: string }
): SyntaxConfigYou only change the easy-layer base inputs, compound tokens derive automatically:
| Base token | Default | What you change |
|---|---|---|
tagPrefix |
$$ |
Tag prefix |
tagOpen |
( |
Argument opener |
tagClose |
) |
Argument closer |
tagDivider |
| |
Pipe separator |
escapeChar |
\ |
Escape character |
closeMiddle |
end |
Shared middle literal inside rawClose / blockClose
|
escapeChargotcha: The default is"\\"in JavaScript source — but that is a single\character. The length of the string is what the user types in the DSL text.escapeChar: "\\"→ user types\|to get a literal|(one keystroke).escapeChar: "~~"→ user types~~|to get a literal|(two keystrokes). If you set a multi-character escape, users must type the full sequence every time they escape.
| Compound token | Derivation rule | Default result |
|---|---|---|
endTag |
tagClose + tagPrefix
|
)$$ |
rawOpen |
tagClose + %
|
)% |
blockOpen |
tagClose + *
|
)* |
rawClose |
% + end + tagPrefix
|
%end$$ |
blockClose |
* + end + tagPrefix
|
*end$$ |
Change prefix — compounds follow:
createEasySyntax({ tagPrefix: "@@" });
// endTag → ")@@" rawClose → "%end@@" blockClose → "*end@@"Change prefix + closer:
createEasySyntax({ tagPrefix: "@@", tagClose: "]" });
// endTag → "]@@" rawOpen → "]%" blockOpen → "]*"Change the shared close middle:
createEasySyntax({ tagPrefix: "@@", closeMiddle: "fin" });
// rawClose → "%fin@@" blockClose → "*fin@@"Just the divider:
createEasySyntax({ tagDivider: ";" });
// $$tag(arg1;arg2)$$Explicit compound override wins over derivation:
createEasySyntax({
tagPrefix: "@@",
rawClose: "<<ENDRAW>>", // explicit, derivation skipped
});
// endTag → ")@@" (derived) rawClose → "<<ENDRAW>>" (your override)function createSyntax(overrides?: Partial<SyntaxInput>): SyntaxConfigPlain shallow merge with DEFAULT_SYNTAX. No auto-derivation, no validation. For fully irregular protocols.
const syntax = createSyntax({
tagPrefix: "<<",
tagOpen: "[",
tagClose: "]",
tagDivider: ";",
endTag: "]>>",
rawOpen: "]#",
blockOpen: "]*",
rawClose: "#end>>",
blockClose: "*end>>",
escapeChar: "~",
});
// <<bold[hello]>> <<code[ts]#\nconst x = 1;\n#end>>Warning: If you only override
tagPrefixwithout updatingendTag, inline tags won't close —endTagis still)$$but tags open with the new prefix.
Hard constraint in the parser — break these and tags stop working:
Core rule: endTag, rawOpen, blockOpen must start with tagClose.
Why? The parser balances tagOpen/tagClose nesting in the argument section, lands on tagClose, then looks ahead to determine the tag form. If compound tokens don't start with tagClose, the lookahead never matches.
| Token | Constraint |
|---|---|
endTag |
Must start with tagClose
|
rawOpen |
Must start with tagClose
|
blockOpen |
Must start with tagClose
|
tagOpen/tagClose
|
Must pair |
| Others | Independent, change freely |
Using createEasySyntax guarantees these constraints automatically. closeMiddle only affects easy derivation; it does not relax these parser requirements.
DEFAULT_SYNTAX.tagPrefix === "$$"
DEFAULT_SYNTAX.tagOpen === "("
DEFAULT_SYNTAX.tagClose === ")"
DEFAULT_SYNTAX.tagDivider === "|"
DEFAULT_SYNTAX.endTag === ")$$"
DEFAULT_SYNTAX.rawOpen === ")%"
DEFAULT_SYNTAX.blockOpen === ")*"
DEFAULT_SYNTAX.rawClose === "%end$$"
DEFAULT_SYNTAX.blockClose === "*end$$"
DEFAULT_SYNTAX.escapeChar === "\\"