Simple usage
Our goal will be making a simple language that convert the text to a LineNode[] array
That are simple objects that tell us the content of each line of the text.
To do that we will need to define 3 classes for our language Nodes, Processors and a Parser
1 - Defining language a nodes
Is recommended to have an base node with shared methods, and sub nodes with specific methods
Tokens are simple javascript objects that represents the text.
You can know more about they in Lexer
// LineNode.ts
import { BaseNode } from '@language-kit/core'
export class BaseLineNode extends BaseNode {
public type = 'BaseLine'
public sharedMethod() {
// code
}
}
export class FirstLineNode extends BaseLineNode {
public type = 'FirstLine'
public customMethodForFirstLineOnly() {
// code
}
}
2 - Define Processor
Next we have to create an processor to convert tokens to this nodes
// LineProcessor.ts
import { BaseLineNode, FirstLineNode } from './line-node'
import { BaseProcessor } from '@language-kit/core'
export class LineProcessor extends BaseProcessor<BaseLineNode> {
public process() {
// current token being processed
const token = this.tokens[0]
// search for the end of line token: token.type = "BreakLine"
const endOfLineTokenIndex = this.tokens.findIndex((t) => t.type === 'BreakLine')
// if not found, return false
if (endOfLineTokenIndex === -1) return false
// get all tokens until the end of line token
const tokens = this.tokens.slice(this.tokens.indexOf(token), endOfLineTokenIndex + 1)
let node = new BaseLineNode()
if (this.nodes.length === 0) {
node = new FirstLineNode()
}
node.tokens = tokens
// add node instance to result nodes
this.nodes.push(node)
// remove tokens processed
this.tokens.splice(0, tokens.length)
// return true to indicate that the processor have processed some tokens and changed the state
return true
}
}
3 - Define parser
Finally we can create an parser with the created classes.
import { BaseParser } from '@language-kit/core'
import { BaseLineNode } from './LineNode'
import { LineProcessor } from './LineProcessor'
export class LineParser extends BaseParser<BaseLineNode> {
constructor() {
super()
this.setProcessors([
LineProcessor
])
}
public onUnhandledToken: BaseParser['onUnhandledToken'] = (token) => {
console.error('unhandled token', token)
}
}
4 - Use the Parse
Now we can parse any string and have an the output desired
// Sample.ts
import { LineParser } from './LineParser'
import { FirstLineNode } from './line-node'
const parser = new LineParser()
const payload = ['Hello', '', 'This is a paragraph'].join('\n')
const [firstLine, normalLine] = parser.toNodes(payload) // result [FirstLineNode, BaseLineNode]
normalLine.sharedMethod()
if (firstLine instanceof FirstLineNode) {
firstLine.customMethodForFirstLineOnly()
}