q-sharp-ts
Version:
A parser for Q# language features, implemented in TypeScript.
629 lines (628 loc) • 23.5 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var token_js_1 = require("./token.js");
/**
* Returns whether a given character could be an element of a numeric value.
* @param c - The character.
* @return Whether the character is numeric.
*/
function isNumeric(c) {
return (c == '.') || !isNaN(parseInt(c));
}
/**
* Returns whether a given character is a letter.
* @param c - The character.
* @return Whether the character is a letter.
*/
function isLetter(c) {
if (c.match(/[a-z]/i)) {
return true;
}
return false;
}
/**
* Returns whether a given character is alphanumeric.
* @param c - The character.
* @return Whether the character is alphanumeric.
*/
function isAlpha(c) {
if (c.match(/^[_0-9a-zA-Z]+$/)) {
return true;
}
return false;
}
/**
* Returns whether a given character is a newline character.
* @param c - The character.
* @return Whether the character is a newline.
*/
function isNewline(c) {
if (c.match(/\n|\r(?!\n)|\u2028|\u2029|\r\n/g)) {
return true;
}
return false;
}
/** Class representing a lexer. */
var Lexer = /** @class */ (function () {
/**
* Creates a lexer.
* @param input - The string to lex.
* @param cursor - The starting cursor position.
*/
function Lexer(input, cursor) {
if (cursor === void 0) { cursor = 0; }
var _this = this;
/**
* Calling this method lexes the code represented by the provided string.
* @return An array of tokens and their corresponding values.
*/
this.lex = function () {
var tokens = [];
var token;
while (_this.cursor < _this.input.length) {
var empty = true;
var i = 0;
while (empty) {
if (_this.peek(i) && isNewline(_this.peek(i))) {
tokens.push([token_js_1.Token.Newline]);
i++;
}
else {
empty = false;
}
}
token = _this.nextToken();
if (token) {
tokens.push(token);
}
}
return tokens;
};
/**
* Reads a character and advances the cursor.
* @param num - Optional cursor position modifier.
*/
this.readChar = function (num) {
if (num === void 0) { num = 1; }
_this.cursor += num;
return _this.input[_this.cursor - num];
};
/**
* Reads a comment.
* @return The comment string.
*/
this.readComment = function () {
var char = _this.peek();
var comment = '';
while (char && !isNewline(char)) {
_this.readChar();
comment += char;
char = _this.peek();
}
return comment;
};
/**
* Determines whether the next character to process equals a given character.
* @param c - The given character.
* @return Whether the next character equals the given character.
*/
this.peekEq = function (c) { return (_this.peek() == c); };
/**
* Reads a character without advancing the cursor.
* @param index - Optional peek position offset.
*/
this.peek = function (index) {
if (index === void 0) { index = 0; }
return _this.input[_this.cursor + index];
};
/**
* Reads a numeric value.
* @return The numeric value as a string.
*/
this.readNumeric = function () {
var num = '';
while (isNumeric(_this.peek())) {
if (_this.peek() == '.' && _this.peek(1) == '.') {
break;
}
num += _this.readChar();
}
return num;
};
/**
* Reads an alphanumeric value.
* @return The alphanumeric value as a string.
*/
this.readAlpha = function () {
var alpha = '';
while (isAlpha(_this.peek())) {
alpha += _this.readChar();
}
return alpha;
};
/**
* Reads a string literal.
* @param terminator - The literal's termination character.
* @return The literal as a string.
*/
this.readStringLiteral = function (terminator) {
var lit = '';
var char = '';
while (!(terminator == char)) {
char = _this.readChar();
lit += char;
}
return lit;
};
/**
* Advances the cusor past the next block of whitespace.
*/
this.skipWhitespace = function () {
while (' \t\n\r\v'.indexOf(_this.peek()) > -1) {
_this.cursor += 1;
}
return null;
};
/**
* Lexes the next token.
* @return The next token and its corresponding value.
*/
this.nextToken = function () {
_this.skipWhitespace();
if (_this.cursor == _this.input.length) {
return [token_js_1.Token.EndOfFile];
}
var char = _this.peek();
_this.readChar();
if (char == '.') {
if (_this.peek() == '.') {
_this.readChar();
if (_this.peek() == '.') {
_this.readChar();
return [token_js_1.Token.Continue];
}
else {
return [token_js_1.Token.Range];
}
}
return [token_js_1.Token.Period];
}
if (char == '*') {
return [token_js_1.Token.Times];
}
if (char == '^') {
if (_this.peek() == '^') {
_this.readChar();
if (_this.peek() == '^') {
_this.readChar();
return [token_js_1.Token.BitwiseXor];
}
}
return [token_js_1.Token.Exp];
}
if (char == ',') {
return [token_js_1.Token.Comma];
}
if (char == ':') {
return [token_js_1.Token.Colon];
}
if (char == '?') {
return [token_js_1.Token.IfTurnary];
}
if (char == '|') {
if (_this.peek() == '|') {
_this.readChar();
if (_this.peek() == '|') {
_this.readChar();
return [token_js_1.Token.BitwiseOr];
}
}
return [token_js_1.Token.ElseTurnary];
}
if (char == '/') {
if (_this.peek() == '/') {
_this.readChar();
return [token_js_1.Token.Comment, _this.readComment()];
}
return [token_js_1.Token.Divide];
}
if (char == '-') {
if (_this.peek() == '>') {
_this.readChar();
return [token_js_1.Token.FunctionLambda];
}
if (_this.peek() == '=') {
_this.readChar();
return [token_js_1.Token.Meq];
}
return [token_js_1.Token.Minus];
}
if (char == '>') {
if (_this.peek() == '>') {
_this.readChar();
if (_this.peek() == '>') {
_this.readChar();
return [token_js_1.Token.Right];
}
}
else if (_this.peek() == '=') {
_this.readChar();
return [token_js_1.Token.Geq];
}
return [token_js_1.Token.More];
}
if (char == '<') {
if (_this.peek() == '<') {
_this.readChar();
if (_this.peek() == '<') {
_this.readChar();
return [token_js_1.Token.Left];
}
}
else if (_this.peek() == '=') {
_this.readChar();
return [token_js_1.Token.Leq];
}
else if (_this.peek() == '-') {
_this.readChar();
return [token_js_1.Token.Assign];
}
return [token_js_1.Token.Less];
}
if (char == '=') {
if (_this.peek() == '=') {
_this.readChar();
return [token_js_1.Token.Eq];
}
else if (_this.peek() == '>') {
_this.readChar();
return [token_js_1.Token.OperationLambda];
}
return [token_js_1.Token.Eq];
}
if (char == '_') {
return [token_js_1.Token.Dummy];
}
if (char == ';') {
return [token_js_1.Token.Semi];
}
if (char == 'w') {
if (_this.peek() == '\\') {
_this.readChar();
return [token_js_1.Token.With];
}
}
if (char == '+') {
if (_this.peek() == '=') {
_this.readChar();
return [token_js_1.Token.Peq];
}
return [token_js_1.Token.Plus];
}
if (char == '\"') {
var stringLiteral = char + _this.readStringLiteral('\"');
return [token_js_1.Token.String, new String(stringLiteral)];
}
if (char == '\'') {
return [token_js_1.Token.SingleQuote];
}
if (char == '$') {
var literal = char + _this.readAlpha();
return [token_js_1.Token.String, literal];
}
if (char == '&') {
if (_this.peek() == '&') {
_this.readChar();
if (_this.peek() == '&') {
_this.readChar();
return [token_js_1.Token.BitwiseAnd];
}
}
}
if (char == '~') {
if (_this.peek() == '~') {
_this.readChar();
if (_this.peek() == '~') {
_this.readChar();
return [token_js_1.Token.BitwiseNot];
}
}
}
if (char == '!') {
if (_this.peek() == '=') {
_this.readChar();
return [token_js_1.Token.Neq];
}
return [token_js_1.Token.Unwrap];
}
if (char == '(') {
return [token_js_1.Token.Lbrac];
}
if (char == '(') {
return [token_js_1.Token.Rbrac];
}
if (char == '[') {
return [token_js_1.Token.Lsqbrac];
}
if (char == ']') {
return [token_js_1.Token.Rsqbrac];
}
if (char == '{') {
return [token_js_1.Token.Lcurlbrac];
}
if (char == '}') {
return [token_js_1.Token.Rcurlbrac];
}
if (char == '%') {
return [token_js_1.Token.Mod];
}
if (isLetter(char)) {
var literal = char + _this.readAlpha();
if (literal.toLowerCase() == 'true') {
return [token_js_1.Token.True];
}
else if (literal.toLowerCase() == 'false') {
return [token_js_1.Token.False];
}
else if (literal.toLowerCase() == 'Zero') {
return [token_js_1.Token.Zero];
}
else if (literal.toLowerCase() == 'One') {
return [token_js_1.Token.One];
}
else if (literal.toLowerCase() == 'PauliX') {
return [token_js_1.Token.PauliX];
}
else if (literal.toLowerCase() == 'PauliY') {
return [token_js_1.Token.PauliY];
}
else if (literal.toLowerCase() == 'PauliZ') {
return [token_js_1.Token.PauliZ];
}
else if (literal.toLowerCase() == 'if') {
return [token_js_1.Token.If];
}
else if (literal.toLowerCase() == 'elif') {
return [token_js_1.Token.Elif];
}
else if (literal.toLowerCase() == 'else') {
return [token_js_1.Token.Else];
}
else if (literal.toLowerCase() == 'or') {
return [token_js_1.Token.Or];
}
else if (literal.toLowerCase() == 'and') {
return [token_js_1.Token.And];
}
else if (literal.toLowerCase() == 'not') {
return [token_js_1.Token.Not];
}
else if (literal.toLowerCase() == 'let') {
return [token_js_1.Token.Let];
}
else if (literal.toLowerCase() == 'mutable') {
return [token_js_1.Token.Mutable];
}
else if (literal.toLowerCase() == 'new') {
return [token_js_1.Token.New];
}
else if (literal.toLowerCase() == 'function') {
return [token_js_1.Token.Function];
}
else if (literal.toLowerCase() == 'operation') {
return [token_js_1.Token.Operation];
}
else if (literal.toLowerCase() == 'use') {
return [token_js_1.Token.Use];
}
else if (literal.toLowerCase() == 'borrow') {
return [token_js_1.Token.Borrow];
}
else if (literal.toLowerCase() == 'adjoint') {
return [token_js_1.Token.Adjoint];
}
else if (literal.toLowerCase() == 'controlled') {
return [token_js_1.Token.Controlled];
}
else if (literal.toLowerCase() == 'adj') {
return [token_js_1.Token.Adjoint];
}
else if (literal.toLowerCase() == 'ctl') {
return [token_js_1.Token.Controlled];
}
else if (literal.toLowerCase() == 'return') {
return [token_js_1.Token.Return];
}
else if (literal.toLowerCase() == 'fail') {
return [token_js_1.Token.Fail];
}
else if (literal.toLowerCase() == 'for') {
return [token_js_1.Token.For];
}
else if (literal.toLowerCase() == 'repeat') {
return [token_js_1.Token.Repeat];
}
else if (literal.toLowerCase() == 'until') {
return [token_js_1.Token.Until];
}
else if (literal.toLowerCase() == 'fixup') {
return [token_js_1.Token.Fixup];
}
else if (literal.toLowerCase() == 'while') {
return [token_js_1.Token.While];
}
else if (literal.toLowerCase() == 'in') {
return [token_js_1.Token.In];
}
else if (literal.toLowerCase() == 'within') {
return [token_js_1.Token.Within];
}
else if (literal.toLowerCase() == 'apply') {
return [token_js_1.Token.Apply];
}
else if (literal.toLowerCase() == 'is') {
return [token_js_1.Token.Is];
}
else if (literal.toLowerCase() == 'and') {
return [token_js_1.Token.AND];
}
else if (literal.toLowerCase() == 'ccnot') {
return [token_js_1.Token.CCNOT];
}
else if (literal.toLowerCase() == 'cnot') {
return [token_js_1.Token.CNOT];
}
else if (literal.toLowerCase() == 'exp') {
return [token_js_1.Token.Ex];
}
else if (literal.toLowerCase() == 'h') {
return [token_js_1.Token.H];
}
else if (literal.toLowerCase() == 'i') {
return [token_js_1.Token.I];
}
else if (literal.toLowerCase() == 'm') {
return [token_js_1.Token.M];
}
else if (literal.toLowerCase() == 'measure') {
return [token_js_1.Token.Measure];
}
else if (literal.toLowerCase() == 'r') {
return [token_js_1.Token.R];
}
else if (literal.toLowerCase() == 'r1') {
return [token_js_1.Token.R1];
}
else if (literal.toLowerCase() == 'r1frac') {
return [token_js_1.Token.R1Frac];
}
else if (literal.toLowerCase() == 'reset') {
return [token_js_1.Token.Reset];
}
else if (literal.toLowerCase() == 'resetall') {
return [token_js_1.Token.ResetAll];
}
else if (literal.toLowerCase() == 'rfrac') {
return [token_js_1.Token.RFrac];
}
else if (literal.toLowerCase() == 'rx') {
return [token_js_1.Token.Rx];
}
else if (literal.toLowerCase() == 'rxx') {
return [token_js_1.Token.Rxx];
}
else if (literal.toLowerCase() == 'ry') {
return [token_js_1.Token.Ry];
}
else if (literal.toLowerCase() == 'ryy') {
return [token_js_1.Token.Ryy];
}
else if (literal.toLowerCase() == 'rz') {
return [token_js_1.Token.Rz];
}
else if (literal.toLowerCase() == 'rzz') {
return [token_js_1.Token.Rzz];
}
else if (literal.toLowerCase() == 's') {
return [token_js_1.Token.S];
}
else if (literal.toLowerCase() == 'swap') {
return [token_js_1.Token.SWAP];
}
else if (literal.toLowerCase() == 't') {
return [token_js_1.Token.T];
}
else if (literal.toLowerCase() == 'x') {
return [token_js_1.Token.X];
}
else if (literal.toLowerCase() == 'y') {
return [token_js_1.Token.Y];
}
else if (literal.toLowerCase() == 'z') {
return [token_js_1.Token.Z];
}
else if (literal.toLowerCase() == 'applyunitary') {
return [token_js_1.Token.ApplyUnitary];
}
else if (literal.toLowerCase() == 'message') {
return [token_js_1.Token.Message];
}
else if (literal.toLowerCase() == 'unit') {
return [token_js_1.Token.UnitType];
}
else if (literal.toLowerCase() == 'int') {
return [token_js_1.Token.IntType];
}
else if (literal.toLowerCase() == 'bigint') {
return [token_js_1.Token.BigIntType];
}
else if (literal.toLowerCase() == 'double') {
return [token_js_1.Token.DoubleType];
}
else if (literal.toLowerCase() == 'bool') {
return [token_js_1.Token.BoolType];
}
else if (literal.toLowerCase() == 'string') {
return [token_js_1.Token.StringType];
}
else if (literal.toLowerCase() == 'qubit') {
return [token_js_1.Token.QubitType];
}
else if (literal.toLowerCase() == 'result') {
return [token_js_1.Token.ResultType];
}
else if (literal.toLowerCase() == 'pauli') {
return [token_js_1.Token.PauliType];
}
else if (literal.toLowerCase() == 'range') {
return [token_js_1.Token.RangeType];
}
else if (literal.toLowerCase() == 'array') {
return [token_js_1.Token.ArrayType];
}
else if (literal.toLowerCase() == 'tuple') {
return [token_js_1.Token.TupleType];
}
else if (literal.toLowerCase() == 'struct') {
return [token_js_1.Token.StructType];
}
else if (literal.toLowerCase() == 'operation') {
return [token_js_1.Token.OperationType];
}
else if (literal.toLowerCase() == 'function') {
return [token_js_1.Token.FunctionType];
}
else if (literal.toLowerCase() == 'import') {
return [token_js_1.Token.Import];
}
return [token_js_1.Token.Identifier, literal.toString()];
}
else if (!isNumeric(char)) {
var look = (0, token_js_1.lookup)(char);
if (look != token_js_1.Token.Identifier) {
return [(0, token_js_1.lookup)(char)];
}
else {
return [token_js_1.Token.Illegal];
}
}
else {
var num = char + _this.readNumeric();
var parsed = parseFloat(num);
if (num.indexOf('.') != -1) {
return [token_js_1.Token.Double, parsed];
}
else if (parsed <= 9223372036854775807) {
return [token_js_1.Token.Int, parsed];
}
else if (parsed > 9223372036854775807) {
return [token_js_1.Token.BigInt, parsed];
}
}
};
this.input = input;
this.cursor = cursor;
}
return Lexer;
}());
exports.default = Lexer;