UNPKG

toylang

Version:

A toy programming language built with TypeScript for learning purposes

167 lines (166 loc) 7.7 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.parseThisExpression = exports.parseNewExpression = exports.parseParenthesizedExpression = exports.parseMemberExpression = exports.parseCallExpression = exports.parseCallMemberExpression = exports.parseLeftHandSideExpression = exports.parseUnaryExpression = exports.isAssignmentOperator = exports.checkValidAssignmentTarget = exports.parseAssignmentOperator = exports.parseAssignmentExpression = exports.parsePrimaryExpression = exports.parseExpression = void 0; var Tokenizer_1 = require("../Tokenizer"); var typings_1 = require("../typings"); var binop_1 = require("./binop"); var identifiers_1 = require("./identifiers"); var literals_1 = require("./literals"); var statement_1 = require("./statement"); function parseExpression(parser) { return parseAssignmentExpression(parser); } exports.parseExpression = parseExpression; function parsePrimaryExpression(parser) { var _a, _b; if (literals_1.isLiteral((_a = parser._lookahead) === null || _a === void 0 ? void 0 : _a.type)) { return literals_1.parseLiteral(parser); } switch ((_b = parser._lookahead) === null || _b === void 0 ? void 0 : _b.type) { case Tokenizer_1.TokenTypes.PAREN_START: return parseParenthesizedExpression(parser); case Tokenizer_1.TokenTypes.IDENTIFIER: return identifiers_1.parseIdentifier(parser); case Tokenizer_1.TokenTypes.this: return parseThisExpression(parser); case Tokenizer_1.TokenTypes.new: return parseNewExpression(parser); default: return parseLeftHandSideExpression(parser); } } exports.parsePrimaryExpression = parsePrimaryExpression; // LefthandSideExpression ASSIGNMENT_OPERATOR AssignmentExpression function parseAssignmentExpression(parser) { var _a; var left = binop_1.parseLogicalORExpression(parser); if (!isAssignmentOperator((_a = parser._lookahead) === null || _a === void 0 ? void 0 : _a.type)) { return left; } return parser.factory.AssignmentExpression({ operator: parseAssignmentOperator(parser).value, left: checkValidAssignmentTarget(left), right: parseAssignmentExpression(parser), }); } exports.parseAssignmentExpression = parseAssignmentExpression; function parseAssignmentOperator(parser) { var _a; if (((_a = parser._lookahead) === null || _a === void 0 ? void 0 : _a.type) === Tokenizer_1.TokenTypes.SIMPLE_ASSIGNMENT) { return parser._eat(Tokenizer_1.TokenTypes.SIMPLE_ASSIGNMENT); } return parser._eat(Tokenizer_1.TokenTypes.COMPLEX_ASSIGNMENT); } exports.parseAssignmentOperator = parseAssignmentOperator; function checkValidAssignmentTarget(node) { if (node.type === typings_1.tl.SyntaxKind.Identifier || node.type === typings_1.tl.SyntaxKind.MemberExpression) { return node; } throw new SyntaxError("Invalid left-hand side in assignment expression, expected \"Identifier\" but got \"" + node.type + "\""); } exports.checkValidAssignmentTarget = checkValidAssignmentTarget; function isAssignmentOperator(type) { return (type === Tokenizer_1.TokenTypes.SIMPLE_ASSIGNMENT || type === Tokenizer_1.TokenTypes.COMPLEX_ASSIGNMENT); } exports.isAssignmentOperator = isAssignmentOperator; function parseUnaryExpression(parser) { var _a; var operator; switch ((_a = parser._lookahead) === null || _a === void 0 ? void 0 : _a.type) { case Tokenizer_1.TokenTypes.ADDITITIVE_OPERATOR: operator = parser._eat(Tokenizer_1.TokenTypes.ADDITITIVE_OPERATOR).value; break; case Tokenizer_1.TokenTypes.LOGICAL_NOT: operator = parser._eat(Tokenizer_1.TokenTypes.LOGICAL_NOT).value; break; } if (operator) { return parser.factory.UnaryExpression(operator, parseUnaryExpression(parser)); } return parseLeftHandSideExpression(parser); } exports.parseUnaryExpression = parseUnaryExpression; function parseLeftHandSideExpression(parser) { return parseCallMemberExpression(parser); } exports.parseLeftHandSideExpression = parseLeftHandSideExpression; // | MemberExpression // | CallExpression function parseCallMemberExpression(parser) { var _a, _b; if (((_a = parser._lookahead) === null || _a === void 0 ? void 0 : _a.type) === Tokenizer_1.TokenTypes.super) { return parseCallExpression(parser, identifiers_1.parseSuper(parser)); } var member = parseMemberExpression(parser); if (((_b = parser._lookahead) === null || _b === void 0 ? void 0 : _b.type) === Tokenizer_1.TokenTypes.PAREN_START) { return parseCallExpression(parser, member); } return member; } exports.parseCallMemberExpression = parseCallMemberExpression; function parseCallExpression(parser, callee) { var _a; var callExpression = { type: typings_1.tl.SyntaxKind.CallExpression, callee: callee, arguments: statement_1.parseArguments(parser), }; if (((_a = parser._lookahead) === null || _a === void 0 ? void 0 : _a.type) === Tokenizer_1.TokenTypes.PAREN_START) { callExpression = parseCallExpression(parser, callExpression); } return callExpression; } exports.parseCallExpression = parseCallExpression; // PrimaryExpression // MemberExpression `.` Identifier // MemberExpression `[` Expression `]` function parseMemberExpression(parser) { var _a, _b, _c, _d; var object = parsePrimaryExpression(parser); while (((_a = parser._lookahead) === null || _a === void 0 ? void 0 : _a.type) === Tokenizer_1.TokenTypes.DOT || ((_b = parser._lookahead) === null || _b === void 0 ? void 0 : _b.type) === Tokenizer_1.TokenTypes.BRACKET_START) { if (((_c = parser._lookahead) === null || _c === void 0 ? void 0 : _c.type) === Tokenizer_1.TokenTypes.DOT) { parser._eat(Tokenizer_1.TokenTypes.DOT); var property = identifiers_1.parseIdentifier(parser); object = { type: typings_1.tl.SyntaxKind.MemberExpression, computed: false, object: object, property: property, }; } if (((_d = parser._lookahead) === null || _d === void 0 ? void 0 : _d.type) === Tokenizer_1.TokenTypes.BRACKET_START) { parser._eat(Tokenizer_1.TokenTypes.BRACKET_START); var property = parseExpression(parser); parser._eat(Tokenizer_1.TokenTypes.BRACKET_END); object = { type: typings_1.tl.SyntaxKind.MemberExpression, computed: true, object: object, property: property, }; } } return object; } exports.parseMemberExpression = parseMemberExpression; // ( Expression ) function parseParenthesizedExpression(parser) { parser._eat(Tokenizer_1.TokenTypes.PAREN_START); var expression = parseExpression(parser); parser._eat(Tokenizer_1.TokenTypes.PAREN_END); return expression; } exports.parseParenthesizedExpression = parseParenthesizedExpression; function parseNewExpression(parser) { parser._eat(Tokenizer_1.TokenTypes.new); return parser.factory.NewExpression(parseMemberExpression(parser), statement_1.parseArguments(parser)); } exports.parseNewExpression = parseNewExpression; function parseThisExpression(parser) { parser._eat(Tokenizer_1.TokenTypes.this); return parser.factory.ThisExpression(); } exports.parseThisExpression = parseThisExpression;