• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// Copyright 2019 Google LLC
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15import { assert } from "chai";
16import Lexer from "./lexer";
17import { TokenType } from "./token";
18
19describe("lexer", () => {
20  describe("skipped content", () => {
21    it("skips whitespace", () => {
22      let input = " \t\r\n\t  \tOpKill\t\n\t  \r  ";
23      let l = new Lexer(input);
24
25      let t = l.next();
26      assert.equal(t.type, TokenType.kOp);
27      assert.equal(t.line, 2);
28      assert.equal(t.data.name, "OpKill");
29
30      t = l.next();
31      assert.equal(t.type, TokenType.kEOF);
32      assert.equal(t.line, 3);
33    });
34
35    it("skips ; comments", () => {
36      let input = `; start with comment
37OpKill ; end of line comment
38; another comment
39%1`;
40
41      let l = new Lexer(input);
42      let t = l.next();
43      assert.equal(t.type, TokenType.kOp);
44      assert.equal(t.data.name, "OpKill");
45      assert.equal(t.line, 2);
46
47      t = l.next();
48      assert.equal(t.type, TokenType.kResultId);
49      assert.equal(t.data.name, "1");
50      assert.equal(t.data.val, 1);
51      assert.equal(t.line, 4);
52    });
53  });
54
55  describe("numerics", () => {
56    it("parses floats", () => {
57      let input = ["0.0", "0.", ".0", "5.7", "5.", ".7", "-0.0", "-.0",
58        "-0.", "-5.7", "-5.", "-.7"];
59
60      let results = [0.0, 0.0, 0.0, 5.7, 5.0, 0.7, 0.0, 0.0, 0.0, -5.7, -5.0,
61        -0.7];
62      input.forEach((val, idx) => {
63        let l = new Lexer(val);
64        let t = l.next();
65
66        assert.equal(t.type, TokenType.kFloatLiteral,
67          `expected ${val} to be a float got ${t.type}`);
68        assert.equal(t.data, results[idx],
69          `expected ${results[idx]} === ${t.data}`);
70
71        t = l.next();
72        assert.equal(t.type, TokenType.kEOF);
73        assert.equal(t.data, undefined);
74      });
75    });
76
77    it("handles invalid floats", () => {
78      let input = [".", "-."];
79      input.forEach((val) => {
80        let l = new Lexer(val);
81        let t = l.next();
82
83        assert.notEqual(t.type, TokenType.kFloatLiteral,
84          `expect ${val} to not match type float`);
85      });
86    });
87
88    it("parses integers", () => {
89      let input = ["0", "-0", "123", "-123", "2147483647", "-2147483648",
90        "4294967295", "0x00", "0x24"];
91      let results = [0, 0, 123, -123,2147483647, -2147483648, 4294967295,
92        0x0, 0x24];
93
94      input.forEach((val, idx) => {
95        let l = new Lexer(val);
96        let t = l.next();
97
98        assert.equal(t.type, TokenType.kIntegerLiteral,
99          `expected ${val} to be an integer got ${t.type}`);
100        assert.equal(t.data, results[idx],
101          `expected ${results[idx]} === ${t.data}`);
102
103        t = l.next();
104        assert.equal(t.type, TokenType.kEOF);
105        assert.equal(t.data, undefined);
106      });
107    });
108  });
109
110  it("matches result_ids", () => {
111    let input = `%123
112%001
113%main
114%_a_b_c`;
115
116    let result = [
117      {name: "123", val: 123},
118      {name: "001", val: 1},
119      {name: "main", val: undefined},
120      {name: "_a_b_c", val: undefined}
121    ];
122
123    let l = new Lexer(input);
124    for (let i = 0; i < result.length; ++i) {
125      let t = l.next();
126      assert.equal(t.type, TokenType.kResultId);
127      assert.equal(t.data.name, result[i].name);
128      assert.equal(t.data.val, result[i].val);
129    }
130  });
131
132  it("matches punctuation", () => {
133    let input = "=";
134    let results = [TokenType.kEqual];
135
136    let l = new Lexer(input);
137    for (let i = 0; i < results.length; ++i) {
138      let t = l.next();
139      assert.equal(t.type, results[i]);
140      assert.equal(t.line, i + 1);
141    }
142
143    let t = l.next();
144    assert.equal(t.type, TokenType.kEOF);
145  });
146
147  describe("strings", () => {
148    it("matches strings", () => {
149      let input = "\"GLSL.std.450\"";
150
151      let l = new Lexer(input);
152      let t = l.next();
153      assert.equal(t.type, TokenType.kStringLiteral);
154      assert.equal(t.data, "GLSL.std.450");
155    });
156
157    it("handles unfinished strings", () => {
158      let input = "\"GLSL.std.450";
159
160      let l = new Lexer(input);
161      let t = l.next();
162      assert.equal(t.type, TokenType.kError);
163    });
164
165    it("handles escapes", () => {
166      let input = `"embedded\\"quote"
167"embedded\\\\slash"
168"embedded\\nchar"`;
169      let results = [`embedded\"quote`, `embedded\\slash`, `embeddednchar`];
170
171      let l = new Lexer(input);
172      for (let i = 0; i < results.length; ++i) {
173        let t = l.next();
174        assert.equal(t.type, TokenType.kStringLiteral, results[i]);
175        assert.equal(t.data, results[i]);
176      }
177    });
178  });
179
180  it("matches keywords", () => {
181    let input = "GLSL Function";
182    let results = ["GLSL", "Function"];
183
184    let l = new Lexer(input);
185    for (let i = 0; i < results.length; ++i) {
186      let t = l.next();
187      assert.equal(t.type, TokenType.kIdentifier, results[i]);
188      assert.equal(t.data, results[i]);
189    }
190  });
191});
192