192 lines
5.2 KiB
JavaScript
192 lines
5.2 KiB
JavaScript
// Copyright 2019 Google LLC
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
import { assert } from "chai";
|
|
import Lexer from "./lexer";
|
|
import { TokenType } from "./token";
|
|
|
|
describe("lexer", () => {
|
|
describe("skipped content", () => {
|
|
it("skips whitespace", () => {
|
|
let input = " \t\r\n\t \tOpKill\t\n\t \r ";
|
|
let l = new Lexer(input);
|
|
|
|
let t = l.next();
|
|
assert.equal(t.type, TokenType.kOp);
|
|
assert.equal(t.line, 2);
|
|
assert.equal(t.data.name, "OpKill");
|
|
|
|
t = l.next();
|
|
assert.equal(t.type, TokenType.kEOF);
|
|
assert.equal(t.line, 3);
|
|
});
|
|
|
|
it("skips ; comments", () => {
|
|
let input = `; start with comment
|
|
OpKill ; end of line comment
|
|
; another comment
|
|
%1`;
|
|
|
|
let l = new Lexer(input);
|
|
let t = l.next();
|
|
assert.equal(t.type, TokenType.kOp);
|
|
assert.equal(t.data.name, "OpKill");
|
|
assert.equal(t.line, 2);
|
|
|
|
t = l.next();
|
|
assert.equal(t.type, TokenType.kResultId);
|
|
assert.equal(t.data.name, "1");
|
|
assert.equal(t.data.val, 1);
|
|
assert.equal(t.line, 4);
|
|
});
|
|
});
|
|
|
|
describe("numerics", () => {
|
|
it("parses floats", () => {
|
|
let input = ["0.0", "0.", ".0", "5.7", "5.", ".7", "-0.0", "-.0",
|
|
"-0.", "-5.7", "-5.", "-.7"];
|
|
|
|
let results = [0.0, 0.0, 0.0, 5.7, 5.0, 0.7, 0.0, 0.0, 0.0, -5.7, -5.0,
|
|
-0.7];
|
|
input.forEach((val, idx) => {
|
|
let l = new Lexer(val);
|
|
let t = l.next();
|
|
|
|
assert.equal(t.type, TokenType.kFloatLiteral,
|
|
`expected ${val} to be a float got ${t.type}`);
|
|
assert.equal(t.data, results[idx],
|
|
`expected ${results[idx]} === ${t.data}`);
|
|
|
|
t = l.next();
|
|
assert.equal(t.type, TokenType.kEOF);
|
|
assert.equal(t.data, undefined);
|
|
});
|
|
});
|
|
|
|
it("handles invalid floats", () => {
|
|
let input = [".", "-."];
|
|
input.forEach((val) => {
|
|
let l = new Lexer(val);
|
|
let t = l.next();
|
|
|
|
assert.notEqual(t.type, TokenType.kFloatLiteral,
|
|
`expect ${val} to not match type float`);
|
|
});
|
|
});
|
|
|
|
it("parses integers", () => {
|
|
let input = ["0", "-0", "123", "-123", "2147483647", "-2147483648",
|
|
"4294967295", "0x00", "0x24"];
|
|
let results = [0, 0, 123, -123,2147483647, -2147483648, 4294967295,
|
|
0x0, 0x24];
|
|
|
|
input.forEach((val, idx) => {
|
|
let l = new Lexer(val);
|
|
let t = l.next();
|
|
|
|
assert.equal(t.type, TokenType.kIntegerLiteral,
|
|
`expected ${val} to be an integer got ${t.type}`);
|
|
assert.equal(t.data, results[idx],
|
|
`expected ${results[idx]} === ${t.data}`);
|
|
|
|
t = l.next();
|
|
assert.equal(t.type, TokenType.kEOF);
|
|
assert.equal(t.data, undefined);
|
|
});
|
|
});
|
|
});
|
|
|
|
it("matches result_ids", () => {
|
|
let input = `%123
|
|
%001
|
|
%main
|
|
%_a_b_c`;
|
|
|
|
let result = [
|
|
{name: "123", val: 123},
|
|
{name: "001", val: 1},
|
|
{name: "main", val: undefined},
|
|
{name: "_a_b_c", val: undefined}
|
|
];
|
|
|
|
let l = new Lexer(input);
|
|
for (let i = 0; i < result.length; ++i) {
|
|
let t = l.next();
|
|
assert.equal(t.type, TokenType.kResultId);
|
|
assert.equal(t.data.name, result[i].name);
|
|
assert.equal(t.data.val, result[i].val);
|
|
}
|
|
});
|
|
|
|
it("matches punctuation", () => {
|
|
let input = "=";
|
|
let results = [TokenType.kEqual];
|
|
|
|
let l = new Lexer(input);
|
|
for (let i = 0; i < results.length; ++i) {
|
|
let t = l.next();
|
|
assert.equal(t.type, results[i]);
|
|
assert.equal(t.line, i + 1);
|
|
}
|
|
|
|
let t = l.next();
|
|
assert.equal(t.type, TokenType.kEOF);
|
|
});
|
|
|
|
describe("strings", () => {
|
|
it("matches strings", () => {
|
|
let input = "\"GLSL.std.450\"";
|
|
|
|
let l = new Lexer(input);
|
|
let t = l.next();
|
|
assert.equal(t.type, TokenType.kStringLiteral);
|
|
assert.equal(t.data, "GLSL.std.450");
|
|
});
|
|
|
|
it("handles unfinished strings", () => {
|
|
let input = "\"GLSL.std.450";
|
|
|
|
let l = new Lexer(input);
|
|
let t = l.next();
|
|
assert.equal(t.type, TokenType.kError);
|
|
});
|
|
|
|
it("handles escapes", () => {
|
|
let input = `"embedded\\"quote"
|
|
"embedded\\\\slash"
|
|
"embedded\\nchar"`;
|
|
let results = [`embedded\"quote`, `embedded\\slash`, `embeddednchar`];
|
|
|
|
let l = new Lexer(input);
|
|
for (let i = 0; i < results.length; ++i) {
|
|
let t = l.next();
|
|
assert.equal(t.type, TokenType.kStringLiteral, results[i]);
|
|
assert.equal(t.data, results[i]);
|
|
}
|
|
});
|
|
});
|
|
|
|
it("matches keywords", () => {
|
|
let input = "GLSL Function";
|
|
let results = ["GLSL", "Function"];
|
|
|
|
let l = new Lexer(input);
|
|
for (let i = 0; i < results.length; ++i) {
|
|
let t = l.next();
|
|
assert.equal(t.type, TokenType.kIdentifier, results[i]);
|
|
assert.equal(t.data, results[i]);
|
|
}
|
|
});
|
|
});
|