同步KDL工程源码到云仓库

This commit is contained in:
wangdequan
2026-06-27 08:45:38 -04:00
parent 93d8ede54b
commit 95c684fc4d
93 changed files with 25712 additions and 0 deletions

View File

@@ -0,0 +1,94 @@
import { describe, expect, it } from "vitest";
import { GRL_KEYWORDS, lexGrl, normalizeUnitLiteral, normalizeUnitValue } from "../../src/grl/lexer/index.js";
import type { GrlNumberToken } from "../../src/grl/lexer/index.js";
function numbers(source: string): GrlNumberToken[] {
return lexGrl(source).filter((token): token is GrlNumberToken => token.kind === "number");
}
describe("GRL lexer", () => {
it("recognizes comments, keywords, identifiers, and source positions", () => {
const tokens = lexGrl(`// generated\nlanguage grl 0.1\nmodule Main\n proc main()\n end\nend\n`);
expect(tokens[0]).toMatchObject({
kind: "comment",
style: "line",
value: " generated",
range: {
start: { line: 1, column: 1 },
end: { line: 1, column: 13 }
}
});
expect(tokens.filter((token) => token.kind === "keyword").map((token) => token.raw)).toEqual([
"language",
"module",
"proc",
"end",
"end"
]);
expect(tokens.find((token) => token.raw === "Main")).toMatchObject({
kind: "identifier",
range: {
start: { line: 3, column: 8 }
}
});
expect(tokens.at(-1)).toMatchObject({ kind: "eof" });
});
it("normalizes numeric literals with GRL units into SI values", () => {
const found = numbers("100 mm 0.25 m 180 deg 3.14159 rad 300 mm/s 50 % 200 ms 2.5 kg 500 mm/s2");
expect(found.map((token) => token.unit?.raw)).toEqual([
"mm",
"m",
"deg",
"rad",
"mm/s",
"%",
"ms",
"kg",
"mm/s2"
]);
expect(found[0]?.unit?.normalizedValue).toBeCloseTo(0.1);
expect(found[1]?.unit?.normalizedValue).toBeCloseTo(0.25);
expect(found[2]?.unit?.normalizedValue).toBeCloseTo(Math.PI);
expect(found[3]?.unit?.normalizedValue).toBeCloseTo(3.14159);
expect(found[4]?.unit?.normalizedValue).toBeCloseTo(0.3);
expect(found[5]?.unit?.normalizedValue).toBeCloseTo(0.5);
expect(found[6]?.unit?.normalizedValue).toBeCloseTo(0.2);
expect(found[7]?.unit?.normalizedValue).toBeCloseTo(2.5);
expect(found[8]?.unit?.normalizedValue).toBeCloseTo(0.5);
});
it("keeps unit raw text on number tokens", () => {
const [token] = numbers("linear(300 mm/s)");
expect(token).toMatchObject({
kind: "number",
raw: "300 mm/s",
value: 300,
unit: {
raw: "mm/s",
kind: "linear_velocity",
siUnit: "m/s"
}
});
});
it("exposes the full reserved keyword set from the specification", () => {
expect(GRL_KEYWORDS).toContain("movej");
expect(GRL_KEYWORDS).toContain("run_operation");
expect(GRL_KEYWORDS).toContain("post_hint");
expect(GRL_KEYWORDS).toContain("continuous");
expect(GRL_KEYWORDS).toHaveLength(85);
});
it("provides direct unit helpers for parser and semantic layers", () => {
expect(normalizeUnitLiteral("deg/s")).toMatchObject({
kind: "angular_velocity",
siUnit: "rad/s"
});
expect(normalizeUnitValue(90, "deg/s")).toBeCloseTo(Math.PI / 2);
expect(() => normalizeUnitLiteral("inch")).toThrow("Unknown GRL unit");
});
});