123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115 |
- 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 value = "";
-
- if (this.tokenStream.peek().type === tokenTypes.LITERAL) {
- value = this.tokenStream.eat(tokenTypes.LITERAL).value;
- }
-
- let node = new AST.String({
- value: value
- });
-
- this.tokenStream.eat(tokenTypes.QUOTE);
-
- return node;
- }
-
- symbol() {
- return new AST.Symbol({
- value: this.tokenStream.eat(tokenTypes.SYMBOL).value
- });
- }
- };
|