123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104 |
- const Error = require('./Error')
-
- const AST = require('./ast')
-
- const tokenTypes = require('./tokenTypes')
-
- module.exports = class Parser {
- constructor(tokenStream) {
- this.tokenStream = tokenStream
- }
-
- parse() {
- let tree = []
- while (this.tokenStream.peek().type !== tokenTypes.EOF) {
- tree.push(this.expr())
- if (this.tokenStream.error) {
- return {
- error: this.tokenStream.error,
- }
- }
- }
- return tree
- }
-
- expr() {
- let token = this.tokenStream.peek()
- switch (token.type) {
- case tokenTypes.ATTRIBUTE:
- return this.attribute()
- case tokenTypes.BOOLEAN:
- return this.bool()
- case tokenTypes.IDENTIFIER:
- return this.identifier()
- case tokenTypes.NUMBER:
- return this.number()
- case tokenTypes.QUOTE:
- return this.string()
- case tokenTypes.SYMBOL:
- return this.symbol()
- case tokenTypes.OPAREN:
- return this.form()
- default:
- this.tokenStream.error = `Unexpected ${token.type} on line ${token.line}`
- break;
- }
- }
-
- form() {
- this.tokenStream.eat(tokenTypes.OPAREN)
-
- let node = new AST.Application()
-
- node.functionName = this.identifier()
- node.args = []
-
- while (this.tokenStream.peek().type !== tokenTypes.CPAREN) {
- node.args.push(this.expr())
- }
-
- this.tokenStream.eat(tokenTypes.CPAREN)
-
- return node
- }
-
- attribute() {
- return new AST.Attribute({
- name: this.tokenStream.eat(tokenTypes.ATTRIBUTE).value,
- value: this.expr()
- })
- }
-
- bool() {
- return new AST.Boolean({
- value: this.tokenStream.eat(tokenTypes.BOOLEAN).value
- })
- }
-
- identifier() {
- return new AST.Identifier({
- name: this.tokenStream.eat(tokenTypes.IDENTIFIER).value
- })
- }
-
- number() {
- return new AST.Number({
- value: this.tokenStream.eat(tokenTypes.NUMBER).value
- })
- }
-
- string() {
- this.tokenStream.eat(tokenTypes.QUOTE)
- let node = new AST.String({
- value: this.tokenStream.eat(tokenTypes.LITERAL).value
- })
- this.tokenStream.eat(tokenTypes.QUOTE)
- return node
- }
-
- symbol() {
- return new AST.Symbol({
- value: this.tokenStream.eat(tokenTypes.SYMBOL).value
- })
- }
- }
|