toylang
Version:
A toy programming language built with TypeScript for learning purposes
167 lines (166 loc) • 7.7 kB
JavaScript
;
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;