UNPKG

q-sharp-ts

Version:

A parser for Q# language features, implemented in TypeScript.

629 lines (628 loc) 23.5 kB
"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;