UNPKG

@artemis-lang/parser

Version:

The artemis language parser

107 lines (87 loc) 2.31 kB
import { Token } from 'moo'; import IParserPlugin from '../types/parser-plugin'; import NodeTypes from '../node/node-types'; import Program from '../types/program'; import error from '../error'; import plugins from '../plugins'; import Lexer from '@artemis-lang/lexer'; class Parser { tokens: Token[]; current: number; plugins: IParserPlugin[]; input: string; constructor(lexer: Lexer) { this.tokens = this.init(lexer.tokenize().tokens); this.input = lexer.code; this.current = 0; this.plugins = plugins; } init(tokens: moo.Token[]) { return tokens.filter( (v) => v.type !== 'ws' && v.type !== 'nl' && v.type !== 'multilineComment' && v.type !== 'singlelineComment' ); } isAtEnd() { return this.current >= this.tokens.length; } isAtStart() { return this.current <= 0; } peek() { return this.tokens[this.current]; } previous() { return this.tokens[this.current - 1]; } advance() { if (!this.isAtEnd()) this.current++; return this.previous(); } match(type: string, value?: string) { if (this.isAtEnd()) return false; if (value) return this.peek().type === type && this.peek().value === value; return this.peek().type === type; } consume(type: string, message: string) { if (this.match(type)) return this.advance(); throw error(message, this.peek(), this.input); } plugin(plugin: IParserPlugin) { this.plugins.push(plugin); } add(...plugins: IParserPlugin[]) { this.plugins.push(...plugins); } next() { if (!this.isAtEnd()) return this.tokens[this.current++]; return this.tokens[this.current]; } nextBy(n: number) { if (!this.isAtEnd()) return this.tokens[this.current + n]; return this.tokens[this.current]; } nextByType(n: number) { return this.nextBy(n).type; } parse() { const program: Program = { type: NodeTypes.Program, body: [] }; while (!this.isAtEnd()) { program.body.push(this.parseExpression()); } return program; } parseExpression() { for (const plugin of this.plugins) { if (plugin.matcher(this)) return plugin.handler(this); } throw error('Unexpected token', this.peek(), this.input); } } export default Parser;