Hello,
I am new to CodeMirror and Lezer and I am trying to create a custom language parser for ABL (OpenEdge) syntax, with Lezer, and use it in the CodeMirror editor, for the highlighting feature.
Here is what I have until now:
- in package.json:
"@ctrl/ngx-codemirror": "^7.0.0",
"codemirror": "^5.65.15",
"@types/codemirror": "^5.60.12",
"lezer-generator": "^0.13.4",
"@lezer/generator": "^1.1.1",
"@lezer/highlight": "^1.1.6",
- openedge.grammar file:
@top Program { expression* }
@skip { space | LineComment }
expression {
Identifier |
String |
Boolean |
Application { "(" expression* ")" }
}
@tokens {
Identifier { $[a-zA-Z_\-0-9]+ }
String { '"' (!["\\] | "\\" _)* '"' }
Boolean { "#t" | "#f" }
LineComment { /\/\*\*(?!\/)/, '\\*/' }
space { $[ \t\n\r]+ }
"(" ")"
}
@detectDelim
- the parser in openedge.ts file (this was generated using the command “npx @lezer/generator openedge.grammar -o openedge.js”):
import {LRParser} from "@lezer/lr"
export const parser = LRParser.deserialize({
version: 14,
states: "!WQYQPOOOhQPO'#CdOOQO'#Ci'#CiOOQO'#Ce'#CeQYQPOOOOQO,59O,59OOyQPO,59OOOQO-E6c-E6cOOQO1G.j1G.j",
stateData: "![~O[OSPOS~ORQOSQOTQOVPO~ORQOSQOTQOUTOVPO~ORQOSQOTQOUWOVPO~O",
goto: "u^PPPPPPPP_ePPPoXQOPSUQSOQUPTVSUXROPSU",
nodeNames: "⚠ LineComment Program Identifier String Boolean ) ( Application",
maxTerm: 13,
nodeProps: [
["openedBy", 6,"("],
["closedBy", 7,")"]
],
skippedNodes: [0,1],
repeatNodeCount: 1,
tokenData: "%c~R^XY}YZ}]^}pq}rs!`st#|xy$[yz$a}!O$f!Q![$f!]!^$z!c!}$f#R#S$f#T#o$f~!SS[~XY}YZ}]^}pq}~!cVOr!`rs!xs#O!`#O#P!}#P;'S!`;'S;=`#v<%lO!`~!}OS~~#QRO;'S!`;'S;=`#Z;=`O!`~#^WOr!`rs!xs#O!`#O#P!}#P;'S!`;'S;=`#v;=`<%l!`<%lO!`~#yP;=`<%l!`~$PQ#Y#Z$V#h#i$V~$[OT~~$aOV~~$fOU~~$kTR~}!O$f!Q![$f!c!}$f#R#S$f#T#o$f~%PSP~OY$zZ;'S$z;'S;=`%]<%lO$z~%`P;=`<%l$z",
tokenizers: [0],
topRules: {"Program":[0,2]},
tokenPrec: 0
})
- the openedge.language.ts file:
import { parser } from './openedge';
import { LRLanguage, LanguageSupport, indentNodeProp, foldNodeProp, foldInside, delimitedIndent } from '@codemirror/language';
import { styleTags, tags as t } from '@lezer/highlight';
export const OpenedgeLanguage = LRLanguage.define({
parser: parser.configure({
props: [
indentNodeProp.add({
Application: delimitedIndent({closing: ")", align: false})
}),
foldNodeProp.add({
Application: foldInside
}),
styleTags({
Identifier: t.variableName,
Boolean: t.bool,
String: t.string,
LineComment: t.lineComment,
"( )": t.paren
})
]
}),
languageData: {
commentTokens: {line: ";"},
keywords: {
tokens: 'RE::/(message|error)\\b/i', // "message" and "error" are the keywords that need to be highlighted for now
autocomplete: ['message', 'error'],
caseInsensitive: true}
},
})
export function Openedge() {
return new LanguageSupport(OpenedgeLanguage)
}
- the component that contains the CodeMirror editor:
import { LanguageSupport, language } from '@codemirror/language';
import { CodemirrorComponent } from '@ctrl/ngx-codemirror';
import { Openedge } from './openedge-grammar/openedge.language';
import { basicSetup } from "@codemirror/basic-setup";
@Component({
selector: "abl-editor-codemirror",
templateUrl: "./abl-editor-codemirror.component.html",
styleUrls: ["./abl-editor-codemirror.component.css"]
})
export class AblEditorCodeMirrorComponent implements OnInit, AfterViewInit {
private _openedge: LanguageSupport;
public openedgeOptions: any;
// ...
ngOnInit(): void {
this._openedge = Openedge();
this.openedgeOptions = {
extensions: [
basicSetup,
language.of(this._openedge.language)
],
lineNumbers: true,
}
}
}
- the component template containing the CodeMirror editor:
<ngx-codemirror
#editor
[options]="openedgeOptions"
[autoFocus]="true"
></ngx-codemirror>
The editor is currently only highlighting comments (single/multiline) and strings.
Do I have a correct setup?
Where can I add the custom language keywords (e.g.“message”, “error”, “block-level”) to be highlighted?