Elixir grammar for the Lezer parser system, enabling syntax highlighting and parsing of Elixir code in CodeMirror-based editors
npx @tessl/cli install tessl/npm-lezer-elixir@1.1.00
# Lezer Elixir
1
2
Lezer Elixir provides an Elixir grammar implementation for the Lezer parser system, which is used in CodeMirror editors for syntax highlighting and parsing. Based directly on tree-sitter-elixir, it offers specialized syntax tree nodes optimized for Lezer's performance requirements while providing comprehensive support for Elixir's unique syntax features.
3
4
## Package Information
5
6
- **Package Name**: lezer-elixir
7
- **Package Type**: npm
8
- **Language**: JavaScript/TypeScript
9
- **Installation**: `npm install lezer-elixir`
10
11
## Core Imports
12
13
```typescript
14
import { parser } from "lezer-elixir";
15
```
16
17
For CommonJS:
18
19
```javascript
20
const { parser } = require("lezer-elixir");
21
```
22
23
**Note**: The package exports only the main `parser` instance. Syntax highlighting is built into the parser and accessed via CodeMirror's language integration.
24
25
## Basic Usage
26
27
```typescript
28
import { parser } from "lezer-elixir";
29
import { EditorView, basicSetup } from "codemirror";
30
import { EditorState } from "@codemirror/state";
31
import { LRLanguage } from "@codemirror/language";
32
import { styleTags, tags as t } from "@lezer/highlight";
33
import { syntaxHighlighting, defaultHighlightStyle } from "@codemirror/language";
34
35
// Create Elixir language instance with highlighting
36
const elixir = LRLanguage.define({
37
parser: parser,
38
languageData: {
39
commentTokens: { line: "#" },
40
indentOnInput: /^\s*end\s*$/
41
}
42
});
43
44
// Create CodeMirror editor with Elixir support
45
const elixirCode = `
46
def fibonacci(n) when n <= 1, do: n
47
def fibonacci(n), do: fibonacci(n - 1) + fibonacci(n - 2)
48
49
IO.puts fibonacci(10)
50
`;
51
52
const view = new EditorView({
53
state: EditorState.create({
54
doc: elixirCode,
55
extensions: [
56
basicSetup,
57
elixir,
58
syntaxHighlighting(defaultHighlightStyle)
59
]
60
}),
61
parent: document.body
62
});
63
```
64
65
## Architecture
66
67
Lezer Elixir is built around several key components:
68
69
- **Parser**: Core LR parser instance for parsing Elixir syntax trees
70
- **Grammar Definition**: Generated from `elixir.grammar` file using `@lezer/generator`
71
- **Tokenizers**: Specialized external tokenizers for complex Elixir syntax elements
72
- **Highlighting**: Built-in syntax highlighting configuration using `@lezer/highlight`
73
- **Language Support**: Integrates with CodeMirror's language system for syntax highlighting
74
75
The grammar provides a superset of tree-sitter-elixir's syntax tree with additional specialized nodes for Lezer's performance requirements.
76
77
### Internal Tokenizers
78
79
The parser includes several external tokenizers for handling complex Elixir syntax:
80
81
- **Quoted Content Tokenizers**: Handle various string and sigil delimiters (parentheses, brackets, braces, etc.)
82
- **Sigil Tokenizers**: Process sigil syntax with modifiers
83
- **Identifier Tokenizers**: Distinguish between regular, underscored, and special identifiers
84
- **Operator Tokenizers**: Handle context-sensitive operators like `@` for attributes
85
- **Newline Tokenizers**: Manage whitespace-sensitive parsing
86
87
These tokenizers are automatically used by the parser and are not directly exposed to users.
88
89
## Capabilities
90
91
### Parser
92
93
The main Lezer parser instance for parsing Elixir code into syntax trees with built-in syntax highlighting support.
94
95
```typescript { .api }
96
/**
97
* The main Lezer parser instance for parsing Elixir code
98
* Generated from elixir.grammar using @lezer/generator
99
* Includes built-in syntax highlighting configuration and specialized tokenizers
100
*/
101
export const parser: LRParser;
102
```
103
104
## Types
105
106
```typescript { .api }
107
/**
108
* Lezer LR parser instance with Elixir grammar and highlighting
109
* Imported from @lezer/lr
110
*/
111
interface LRParser {
112
/** Parse input text into a syntax tree */
113
parse(input: Input | string): Tree;
114
/** Start incremental parsing for large documents */
115
startParse(
116
input: Input,
117
fragments?: readonly TreeFragment[],
118
ranges?: readonly {from: number, to: number}[]
119
): PartialParse;
120
/** Configure parser with additional options */
121
configure(config: ParserConfig): LRParser;
122
/** Check if parser has recovery information for error handling */
123
get hasWrappers(): boolean;
124
/** Get the parser's name for debugging */
125
get name(): string;
126
/** Create a Language instance for CodeMirror integration */
127
get language(): Language;
128
}
129
130
/**
131
* Input interface for parser
132
*/
133
interface Input {
134
/** Get character code at position */
135
get(pos: number): number;
136
/** Read characters into string from range */
137
read(from: number, to: number): string;
138
/** Length of the input text */
139
get length(): number;
140
/** Get line information at position */
141
lineAfter(pos: number): string;
142
/** Cursor for efficient navigation */
143
cursor(pos?: number): Cursor;
144
}
145
146
/**
147
* Parser configuration options
148
*/
149
interface ParserConfig {
150
/** Custom node properties for syntax highlighting and behavior */
151
props?: readonly NodeProp<any>[];
152
/** Override top-level rule */
153
top?: string;
154
/** Add wrapper parsers for mixed-language support */
155
wrap?: ParseWrapper;
156
/** Strict mode for error reporting */
157
strict?: boolean;
158
}
159
160
/**
161
* Syntax tree representation
162
*/
163
interface Tree {
164
/** Total length of the parsed text */
165
get length(): number;
166
/** String representation for debugging */
167
toString(): string;
168
/** Iterate over tree nodes */
169
iterate(config: IterateConfig): TreeCursor;
170
/** Get cursor at specific position */
171
cursorAt(pos: number, side?: -1 | 0 | 1): TreeCursor;
172
/** Resolve position to node */
173
resolve(pos: number, side?: -1 | 0 | 1): SyntaxNode;
174
}
175
```
176
177
## Specialized Syntax Tree Nodes
178
179
The grammar includes specialized nodes beyond the standard tree-sitter-elixir implementation:
180
181
### Identifier Specializations
182
- **SpecialIdentifier**: `__MODULE__` and similar special identifiers
183
- **UnderscoredIdentifier**: Variables starting with underscore (`_x`)
184
185
### Call Specializations
186
- **FunctionDefinitionCall**: Function definitions (`def fun(x), do: 1`)
187
- **KernelCall**: Kernel built-ins (`if`, `case`, etc.)
188
189
### Operator Specializations
190
- **AtOperator**: Module attributes (`@x`)
191
- **DocOperator**: Documentation attributes (`@doc "..."`)
192
- **CaptureOperator**: Function captures (`&fun/1`)
193
- **CaptureOperand**: Capture references (`&1`)
194
- **WhenOperator**: Guard clauses (`left when right`)
195
- **PipeOperator**: Pipe operations (`left |> right`)
196
197
### Sigil Specializations
198
- **StringSigil**: String sigils (`~s"string"`, `~S"string"`)
199
200
### Named Operator Groups
201
- **Operator**: Standard operators (`+`, `-`, `*`, etc.)
202
- **WordOperator**: Word-based operators (`and`, `or`, `when`)
203
204
## Error Handling
205
206
The parser handles malformed Elixir code gracefully, producing partial syntax trees that can still be used for highlighting and basic analysis. Invalid syntax is marked with error nodes in the syntax tree.
207
208
Common error scenarios:
209
- Unterminated strings or sigils
210
- Mismatched delimiters
211
- Invalid operator usage
212
- Incomplete function definitions
213
214
## Integration Notes
215
216
- Designed specifically for CodeMirror 6+ integration
217
- Requires `@lezer/lr` and `@lezer/highlight` as dependencies
218
- Grammar is generated during build process from `src/elixir.grammar` using `@lezer/generator`
219
- Supports both ES modules and CommonJS imports
220
- Full TypeScript type definitions included in distribution
221
- Works with standard CodeMirror highlighting extensions
222
- Built-in highlighting configuration optimized for Elixir syntax
223
224
### Dependencies
225
226
**Runtime Dependencies:**
227
- `@lezer/lr` - Core LR parser functionality
228
- `@lezer/highlight` - Syntax highlighting system
229
230
**Build Dependencies:**
231
- `@lezer/generator` - Grammar compilation (development only)
232
233
### CodeMirror Integration
234
235
To use with CodeMirror, you'll typically want to combine the parser with CodeMirror's language support:
236
237
```typescript
238
import { parser } from "lezer-elixir";
239
import { LRLanguage, LanguageSupport } from "@codemirror/language";
240
import { styleTags, tags as t } from "@lezer/highlight";
241
242
// Create language definition
243
const elixirLanguage = LRLanguage.define({
244
parser: parser,
245
languageData: {
246
commentTokens: { line: "#" },
247
indentOnInput: /^\\s*(end|catch|rescue|after|else)\\s*$/,
248
closeBrackets: { brackets: ["(", "[", "{", "\"", "'"] }
249
}
250
});
251
252
// Create full language support
253
export function elixir() {
254
return new LanguageSupport(elixirLanguage);
255
}
256
```