grammar-composer 0.5.0 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,7 @@
1
1
  export declare class Timer {
2
- startTime: number;
3
- constructor();
2
+ private readonly logger;
3
+ private startTime;
4
+ constructor(logger?: TimerLogger);
4
5
  restart(): void;
5
6
  get elapsedTime(): number;
6
7
  get elapsedTimeSeconds(): number;
@@ -8,7 +9,10 @@ export declare class Timer {
8
9
  logAndRestart(title: string, timePrecision?: number): number;
9
10
  static get currentTime(): number;
10
11
  static get microsecondTimestamp(): number;
11
- private static createGlobalTimestampFunction;
12
12
  private static timestampFunc;
13
+ private static createTimestampFunction;
13
14
  }
15
+ export declare function roundToDigits(value: number, digits: number): number;
16
+ type TimerLogger = (msg: string) => void;
17
+ export {};
14
18
  //# sourceMappingURL=Timer.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"Timer.d.ts","sourceRoot":"","sources":["../../src/utilities/Timer.ts"],"names":[],"mappings":"AAKA,qBAAa,KAAK;IACjB,SAAS,SAAI;IAEb,cAEC;IAED,OAAO,SAEN;IAED,IAAI,WAAW,IAAI,MAAM,CAGxB;IAED,IAAI,kBAAkB,IAAI,MAAM,CAG/B;IAED,wBAAwB,IAAI,MAAM,CAKjC;IAED,aAAa,CAAC,KAAK,EAAE,MAAM,EAAE,aAAa,SAAI,GAAG,MAAM,CAYtD;IAED,MAAM,KAAK,WAAW,IAAI,MAAM,CAM/B;IAED,MAAM,KAAK,oBAAoB,IAAI,MAAM,CAExC;IAED,OAAO,CAAC,MAAM,CAAC,6BAA6B;IAkC5C,OAAO,CAAC,MAAM,CAAC,aAAa,CAAc;CAC1C"}
1
+ {"version":3,"file":"Timer.d.ts","sourceRoot":"","sources":["../../src/utilities/Timer.ts"],"names":[],"mappings":"AAAA,qBAAa,KAAK;IACjB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAa;IAEpC,OAAO,CAAC,SAAS,CAAI;IAErB,YAAY,MAAM,CAAC,EAAE,WAAW,EAQ/B;IAGD,OAAO,IAAI,IAAI,CAEd;IAGD,IAAI,WAAW,IAAI,MAAM,CAExB;IAGD,IAAI,kBAAkB,IAAI,MAAM,CAE/B;IAGD,wBAAwB,IAAI,MAAM,CAKjC;IAGD,aAAa,CAAC,KAAK,EAAE,MAAM,EAAE,aAAa,SAAI,GAAG,MAAM,CAMtD;IAGD,MAAM,KAAK,WAAW,IAAI,MAAM,CAE/B;IAGD,MAAM,KAAK,oBAAoB,IAAI,MAAM,CAExC;IAGD,OAAO,CAAC,MAAM,CAAC,aAAa,CAAgD;IAE5E,OAAO,CAAC,MAAM,CAAC,uBAAuB;CA4BtC;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAInE;AAED,KAAK,WAAW,GAAG,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAA"}
@@ -1,70 +1,72 @@
1
- import { roundToDigits } from './Utilities.js';
2
1
  export class Timer {
2
+ logger;
3
3
  startTime = 0;
4
- constructor() {
4
+ constructor(logger) {
5
+ if (logger) {
6
+ this.logger = logger;
7
+ }
8
+ else {
9
+ this.logger = console.log;
10
+ }
5
11
  this.restart();
6
12
  }
13
+ // Resets the timer to the current time.
7
14
  restart() {
8
15
  this.startTime = Timer.currentTime;
9
16
  }
17
+ // Elapsed time in milliseconds (monotonic where supported).
10
18
  get elapsedTime() {
11
- // Elapsed time (milliseconds)
12
19
  return Timer.currentTime - this.startTime;
13
20
  }
21
+ // Elapsed time in seconds.
14
22
  get elapsedTimeSeconds() {
15
- // Elapsed time (seconds)
16
23
  return this.elapsedTime / 1000;
17
24
  }
25
+ // Returns elapsed ms and restarts the timer.
18
26
  getElapsedTimeAndRestart() {
19
- const elapsedTime = this.elapsedTime;
27
+ const elapsed = this.elapsedTime;
20
28
  this.restart();
21
- return elapsedTime;
29
+ return elapsed;
22
30
  }
31
+ // Logs elapsed time (in ms) and restarts the timer.
23
32
  logAndRestart(title, timePrecision = 3) {
24
- const elapsedTime = this.elapsedTime;
25
- //
26
- const message = `${title}: ${roundToDigits(elapsedTime, timePrecision)}ms`;
27
- console.log(message);
28
- //
33
+ const elapsedMs = this.elapsedTime;
34
+ this.logger(`${title}: ${roundToDigits(elapsedMs, timePrecision)}ms`);
29
35
  this.restart();
30
- return elapsedTime;
36
+ return elapsedMs;
31
37
  }
38
+ // Current high-resolution timestamp in milliseconds since Unix epoch.
32
39
  static get currentTime() {
33
- if (!this.timestampFunc) {
34
- this.createGlobalTimestampFunction();
35
- }
36
40
  return this.timestampFunc();
37
41
  }
42
+ // Current timestamp in microseconds (integer).
38
43
  static get microsecondTimestamp() {
39
44
  return Math.floor(Timer.currentTime * 1000);
40
45
  }
41
- static createGlobalTimestampFunction() {
42
- if (typeof process === 'object' && typeof process.hrtime === 'function') {
43
- let baseTimestamp = 0;
44
- this.timestampFunc = () => {
45
- const nodeTimeStamp = process.hrtime();
46
- const millisecondTime = (nodeTimeStamp[0] * 1000) + (nodeTimeStamp[1] / 1000000);
47
- return baseTimestamp + millisecondTime;
48
- };
49
- baseTimestamp = Date.now() - this.timestampFunc();
46
+ // Private Static Clock Setup
47
+ static timestampFunc = Timer.createTimestampFunction();
48
+ static createTimestampFunction() {
49
+ const g = globalThis;
50
+ // 1. Modern standard: performance.now() (Browsers & Node 16+)
51
+ if (typeof g.performance === 'object' && typeof g.performance.now === 'function') {
52
+ const timeOrigin = g.performance.timeOrigin ?? (Date.now() - g.performance.now());
53
+ return () => timeOrigin + g.performance.now();
50
54
  }
51
- else if (typeof chrome === 'object' && chrome.Interval) {
52
- const baseTimestamp = Date.now();
53
- const chromeIntervalObject = new chrome.Interval();
54
- chromeIntervalObject.start();
55
- this.timestampFunc = () => baseTimestamp + chromeIntervalObject.microseconds() / 1000;
55
+ // 2. Node.js high resolution timer (BigInt variant, Node 10.4+)
56
+ if (typeof g.process === 'object' && typeof g.process.hrtime === 'function') {
57
+ const startNs = g.process.hrtime.bigint();
58
+ const epochBaseMs = Date.now() - (Number(startNs) / 1e6);
59
+ return () => epochBaseMs + Number(g.process.hrtime.bigint()) / 1e6;
56
60
  }
57
- else if (typeof performance === 'object' && performance.now) {
58
- const baseTimestamp = Date.now() - performance.now();
59
- this.timestampFunc = () => baseTimestamp + performance.now();
60
- }
61
- else if (Date.now) {
62
- this.timestampFunc = () => Date.now();
63
- }
64
- else {
65
- this.timestampFunc = () => (new Date()).getTime();
61
+ // 3. Last-resort fallback (non-monotonic)
62
+ if (typeof Date.now === 'function') {
63
+ return () => Date.now();
66
64
  }
65
+ return () => new Date().getTime();
67
66
  }
68
- static timestampFunc;
67
+ }
68
+ export function roundToDigits(value, digits) {
69
+ const factor = 10 ** digits;
70
+ return Math.round(value * factor) / factor;
69
71
  }
70
72
  //# sourceMappingURL=Timer.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"Timer.js","sourceRoot":"","sources":["../../src/utilities/Timer.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"Timer.js","sourceRoot":"","sources":["../../src/utilities/Timer.ts"],"names":[],"mappings":"AAAA,MAAM,OAAO,KAAK;IACA,MAAM,CAAa;IAE5B,SAAS,GAAG,CAAC,CAAA;IAErB,YAAY,MAAoB;QAC/B,IAAI,MAAM,EAAE,CAAC;YACZ,IAAI,CAAC,MAAM,GAAG,MAAM,CAAA;QACrB,CAAC;aAAM,CAAC;YACP,IAAI,CAAC,MAAM,GAAG,OAAO,CAAC,GAAG,CAAA;QAC1B,CAAC;QAED,IAAI,CAAC,OAAO,EAAE,CAAA;IACf,CAAC;IAED,wCAAwC;IACxC,OAAO;QACN,IAAI,CAAC,SAAS,GAAG,KAAK,CAAC,WAAW,CAAA;IACnC,CAAC;IAED,4DAA4D;IAC5D,IAAI,WAAW;QACd,OAAO,KAAK,CAAC,WAAW,GAAG,IAAI,CAAC,SAAS,CAAA;IAC1C,CAAC;IAED,2BAA2B;IAC3B,IAAI,kBAAkB;QACrB,OAAO,IAAI,CAAC,WAAW,GAAG,IAAI,CAAA;IAC/B,CAAC;IAED,6CAA6C;IAC7C,wBAAwB;QACvB,MAAM,OAAO,GAAG,IAAI,CAAC,WAAW,CAAA;QAChC,IAAI,CAAC,OAAO,EAAE,CAAA;QAEd,OAAO,OAAO,CAAA;IACf,CAAC;IAED,oDAAoD;IACpD,aAAa,CAAC,KAAa,EAAE,aAAa,GAAG,CAAC;QAC7C,MAAM,SAAS,GAAG,IAAI,CAAC,WAAW,CAAA;QAClC,IAAI,CAAC,MAAM,CAAC,GAAG,KAAK,KAAK,aAAa,CAAC,SAAS,EAAE,aAAa,CAAC,IAAI,CAAC,CAAA;QACrE,IAAI,CAAC,OAAO,EAAE,CAAA;QAEd,OAAO,SAAS,CAAA;IACjB,CAAC;IAED,sEAAsE;IACtE,MAAM,KAAK,WAAW;QACrB,OAAO,IAAI,CAAC,aAAa,EAAE,CAAA;IAC5B,CAAC;IAED,+CAA+C;IAC/C,MAAM,KAAK,oBAAoB;QAC9B,OAAO,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,WAAW,GAAG,IAAI,CAAC,CAAA;IAC5C,CAAC;IAED,6BAA6B;IACrB,MAAM,CAAC,aAAa,GAAiB,KAAK,CAAC,uBAAuB,EAAE,CAAA;IAEpE,MAAM,CAAC,uBAAuB;QACrC,MAAM,CAAC,GAAG,UAAiB,CAAA;QAE3B,8DAA8D;QAC9D,IAAI,OAAO,CAAC,CAAC,WAAW,KAAK,QAAQ,IAAI,OAAO,CAAC,CAAC,WAAW,CAAC,GAAG,KAAK,UAAU,EAAE,CAAC;YAClF,MAAM,UAAU,GACf,CAAC,CAAC,WAAW,CAAC,UAAU,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,WAAW,CAAC,GAAG,EAAE,CAAC,CAAA;YAE/D,OAAO,GAAG,EAAE,CAAC,UAAU,GAAG,CAAC,CAAC,WAAW,CAAC,GAAG,EAAE,CAAA;QAC9C,CAAC;QAED,gEAAgE;QAChE,IAAI,OAAO,CAAC,CAAC,OAAO,KAAK,QAAQ,IAAI,OAAO,CAAC,CAAC,OAAO,CAAC,MAAM,KAAK,UAAU,EAAE,CAAC;YAC7E,MAAM,OAAO,GAAG,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,CAAA;YAEzC,MAAM,WAAW,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,GAAG,GAAG,CAAC,CAAA;YAExD,OAAO,GAAG,EAAE,CACX,WAAW,GAAG,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,GAAG,GAAG,CAAA;QACvD,CAAC;QAED,0CAA0C;QAC1C,IAAI,OAAO,IAAI,CAAC,GAAG,KAAK,UAAU,EAAE,CAAC;YACpC,OAAO,GAAG,EAAE,CAAC,IAAI,CAAC,GAAG,EAAE,CAAA;QACxB,CAAC;QAED,OAAO,GAAG,EAAE,CAAC,IAAI,IAAI,EAAE,CAAC,OAAO,EAAE,CAAA;IAClC,CAAC;CACD;AAED,MAAM,UAAU,aAAa,CAAC,KAAa,EAAE,MAAc;IAC1D,MAAM,MAAM,GAAG,EAAE,IAAI,MAAM,CAAA;IAE3B,OAAO,IAAI,CAAC,KAAK,CAAC,KAAK,GAAG,MAAM,CAAC,GAAG,MAAM,CAAA;AAC3C,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "grammar-composer",
3
- "version": "0.5.0",
3
+ "version": "0.6.0",
4
4
  "description": "Creates and generates parsers from composable grammar definitions. Includes advanced features like lexer-free parsing, selective packrat memoization and static analysis.",
5
5
  "author": "Rotem Dan",
6
6
  "license": "MIT",
@@ -32,9 +32,9 @@
32
32
  "test": "node dist/tests/Test.js"
33
33
  },
34
34
  "dependencies": {
35
- "regexp-composer": "~0.4.0"
35
+ "regexp-composer": "~0.5.0"
36
36
  },
37
37
  "devDependencies": {
38
- "@types/node": "~26.2.0"
38
+ "@types/node": "~26.4.0"
39
39
  }
40
40
  }
@@ -1,95 +1,97 @@
1
- import { roundToDigits } from './Utilities.js'
1
+ export class Timer {
2
+ private readonly logger: TimerLogger
2
3
 
3
- declare const chrome: any
4
- declare const process: any
4
+ private startTime = 0
5
5
 
6
- export class Timer {
7
- startTime = 0
6
+ constructor(logger?: TimerLogger) {
7
+ if (logger) {
8
+ this.logger = logger
9
+ } else {
10
+ this.logger = console.log
11
+ }
8
12
 
9
- constructor() {
10
13
  this.restart()
11
14
  }
12
15
 
13
- restart() {
16
+ // Resets the timer to the current time.
17
+ restart(): void {
14
18
  this.startTime = Timer.currentTime
15
19
  }
16
20
 
21
+ // Elapsed time in milliseconds (monotonic where supported).
17
22
  get elapsedTime(): number {
18
- // Elapsed time (milliseconds)
19
23
  return Timer.currentTime - this.startTime
20
24
  }
21
25
 
26
+ // Elapsed time in seconds.
22
27
  get elapsedTimeSeconds(): number {
23
- // Elapsed time (seconds)
24
28
  return this.elapsedTime / 1000
25
29
  }
26
30
 
31
+ // Returns elapsed ms and restarts the timer.
27
32
  getElapsedTimeAndRestart(): number {
28
- const elapsedTime = this.elapsedTime
33
+ const elapsed = this.elapsedTime
29
34
  this.restart()
30
35
 
31
- return elapsedTime
36
+ return elapsed
32
37
  }
33
38
 
39
+ // Logs elapsed time (in ms) and restarts the timer.
34
40
  logAndRestart(title: string, timePrecision = 3): number {
35
- const elapsedTime = this.elapsedTime
36
-
37
- //
38
- const message = `${title}: ${roundToDigits(elapsedTime, timePrecision)}ms`
39
-
40
- console.log(message)
41
- //
42
-
41
+ const elapsedMs = this.elapsedTime
42
+ this.logger(`${title}: ${roundToDigits(elapsedMs, timePrecision)}ms`)
43
43
  this.restart()
44
44
 
45
- return elapsedTime
45
+ return elapsedMs
46
46
  }
47
47
 
48
+ // Current high-resolution timestamp in milliseconds since Unix epoch.
48
49
  static get currentTime(): number {
49
- if (!this.timestampFunc) {
50
- this.createGlobalTimestampFunction()
51
- }
52
-
53
50
  return this.timestampFunc()
54
51
  }
55
52
 
53
+ // Current timestamp in microseconds (integer).
56
54
  static get microsecondTimestamp(): number {
57
55
  return Math.floor(Timer.currentTime * 1000)
58
56
  }
59
57
 
60
- private static createGlobalTimestampFunction() {
61
- if (typeof process === 'object' && typeof process.hrtime === 'function') {
62
- let baseTimestamp = 0
58
+ // Private Static Clock Setup
59
+ private static timestampFunc: () => number = Timer.createTimestampFunction()
63
60
 
64
- this.timestampFunc = () => {
65
- const nodeTimeStamp = process.hrtime()
66
- const millisecondTime = (nodeTimeStamp[0] * 1000) + (nodeTimeStamp[1] / 1000000)
61
+ private static createTimestampFunction(): () => number {
62
+ const g = globalThis as any
67
63
 
68
- return baseTimestamp + millisecondTime
69
- }
64
+ // 1. Modern standard: performance.now() (Browsers & Node 16+)
65
+ if (typeof g.performance === 'object' && typeof g.performance.now === 'function') {
66
+ const timeOrigin =
67
+ g.performance.timeOrigin ?? (Date.now() - g.performance.now())
70
68
 
71
- baseTimestamp = Date.now() - this.timestampFunc()
69
+ return () => timeOrigin + g.performance.now()
72
70
  }
73
- else if (typeof chrome === 'object' && chrome.Interval) {
74
- const baseTimestamp = Date.now()
75
71
 
76
- const chromeIntervalObject = new chrome.Interval()
77
- chromeIntervalObject.start()
72
+ // 2. Node.js high resolution timer (BigInt variant, Node 10.4+)
73
+ if (typeof g.process === 'object' && typeof g.process.hrtime === 'function') {
74
+ const startNs = g.process.hrtime.bigint()
78
75
 
79
- this.timestampFunc = () => baseTimestamp + chromeIntervalObject.microseconds() / 1000
80
- }
81
- else if (typeof performance === 'object' && performance.now) {
82
- const baseTimestamp = Date.now() - performance.now()
76
+ const epochBaseMs = Date.now() - (Number(startNs) / 1e6)
83
77
 
84
- this.timestampFunc = () => baseTimestamp + performance.now()
85
- }
86
- else if (Date.now) {
87
- this.timestampFunc = () => Date.now()
78
+ return () =>
79
+ epochBaseMs + Number(g.process.hrtime.bigint()) / 1e6
88
80
  }
89
- else {
90
- this.timestampFunc = () => (new Date()).getTime()
81
+
82
+ // 3. Last-resort fallback (non-monotonic)
83
+ if (typeof Date.now === 'function') {
84
+ return () => Date.now()
91
85
  }
86
+
87
+ return () => new Date().getTime()
92
88
  }
89
+ }
90
+
91
+ export function roundToDigits(value: number, digits: number): number {
92
+ const factor = 10 ** digits
93
93
 
94
- private static timestampFunc: () => number
94
+ return Math.round(value * factor) / factor
95
95
  }
96
+
97
+ type TimerLogger = (msg: string) => void