@@ -2,6 +2,9 @@ import { readFile, readdir } from "node:fs/promises";
2
2
3
3
const SPEC_DIR = new URL ( "../spec" , import . meta. url ) . pathname ;
4
4
5
+ /** @see {@link https://spec-md.com/#sec-Value-Literals } */
6
+ const valueLiteralsRegexp = / \{ ( (?: [ ^ { } ] | (?: \{ [ ^ { } ] * \} ) ) + ) \} / g;
7
+
5
8
process . exitCode = 0 ;
6
9
const filenames = await readdir ( SPEC_DIR ) ;
7
10
for ( const filename of filenames ) {
@@ -23,13 +26,16 @@ for (const filename of filenames) {
23
26
{
24
27
// Is it an algorithm definition?
25
28
const matches = line . match ( / ^ ( [ a - z 0 - 9 A - Z ] + ) ( \s * ) \( ( [ ^ ) ] * ) \) ( \s * ) : ( \s * ) $ / ) ;
29
+ const grammarMatches =
30
+ filename === "Section 2 -- Language.md" &&
31
+ line . match ( / ^ ( [ A - Z a - z 0 - 9 ] + ) : \s + ( ( \S ) .* ) $ / ) ;
26
32
if ( matches ) {
27
33
const [ , algorithmName , ns1 , _args , ns2 , ns3 ] = matches ;
28
34
if ( ns1 || ns2 || ns3 ) {
29
35
console . log (
30
36
`Bad whitespace in definition of ${ algorithmName } in '${ filename } ':`
31
37
) ;
32
- console . log ( line ) ;
38
+ console . dir ( line ) ;
33
39
console . log ( ) ;
34
40
process . exitCode = 1 ;
35
41
}
@@ -47,7 +53,7 @@ for (const filename of filenames) {
47
53
console . log (
48
54
`Bad algorithm ${ algorithmName } step in '${ filename } ':`
49
55
) ;
50
- console . log ( step ) ;
56
+ console . dir ( step ) ;
51
57
console . log ( ) ;
52
58
process . exitCode = 1 ;
53
59
}
@@ -57,18 +63,45 @@ for (const filename of filenames) {
57
63
console . log (
58
64
`Bad formatting for '${ algorithmName } ' step (does not end in '.' or ':') in '${ filename } ':`
59
65
) ;
60
- console . log ( step ) ;
66
+ console . dir ( step ) ;
61
67
console . log ( ) ;
62
68
process . exitCode = 1 ;
63
69
}
64
70
if ( step . match ( / ^ \s * ( - | [ 0 - 9 ] \. ) \s + [ a - z ] / ) ) {
65
71
console . log (
66
72
`Bad formatting of '${ algorithmName } ' step (should start with a capital) in '${ filename } ':`
67
73
) ;
68
- console . log ( step ) ;
74
+ console . dir ( step ) ;
69
75
console . log ( ) ;
70
76
process . exitCode = 1 ;
71
77
}
78
+
79
+ const stepWithoutValueLiterals = step . replace (
80
+ valueLiteralsRegexp ,
81
+ ""
82
+ ) ;
83
+ if ( stepWithoutValueLiterals . match ( / \b [ A - Z ] [ A - Z a - z 0 - 9 ] + \( / ) ) {
84
+ console . log (
85
+ `Bad formatting of '${ algorithmName } ' step (algorithm call should be wrapped in braces: \`{MyAlgorithm(a, b, c)}\`) in '${ filename } ':`
86
+ ) ;
87
+ console . dir ( step ) ;
88
+ console . log ( ) ;
89
+ process . exitCode = 1 ;
90
+ }
91
+
92
+ const valueLiterals = step . matchAll ( valueLiteralsRegexp , "" ) ;
93
+ for ( const lit of valueLiterals ) {
94
+ const inner = lit [ 1 ] ;
95
+ if ( inner . includes ( "{" ) ) {
96
+ console . log (
97
+ `Bad formatting of '${ algorithmName } ' step (algorithm call should not contain braces: \`${ lit } \`) in '${ filename } ':`
98
+ ) ;
99
+ console . dir ( step ) ;
100
+ console . log ( ) ;
101
+ process . exitCode = 1 ;
102
+ }
103
+ }
104
+
72
105
const trimmedInnerLine = step . replace ( / \s + / g, " " ) ;
73
106
if (
74
107
trimmedInnerLine . match (
@@ -79,7 +112,67 @@ for (const filename of filenames) {
79
112
console . log (
80
113
`Potential bad formatting of '${ algorithmName } ' step (true/false/null should be wrapped in curly braces, e.g. '{true}') in '${ filename } ':`
81
114
) ;
82
- console . log ( step ) ;
115
+ console . dir ( step ) ;
116
+ console . log ( ) ;
117
+ process . exitCode = 1 ;
118
+ }
119
+ }
120
+ } else if ( grammarMatches ) {
121
+ // This is super loosey-goosey
122
+ const [ , grammarName , rest ] = grammarMatches ;
123
+ if ( rest . trim ( ) === "one of" ) {
124
+ // Still grammar, not algorithm
125
+ continue ;
126
+ }
127
+ if ( rest . trim ( ) === "" && lines [ i + 1 ] !== "" ) {
128
+ console . log (
129
+ `No empty space after grammar ${ grammarName } header in '${ filename } '`
130
+ ) ;
131
+ console . log ( ) ;
132
+ process . exitCode = 1 ;
133
+ }
134
+ if ( ! lines [ i + 2 ] . startsWith ( "- " ) ) {
135
+ // Not an algorithm; probably more grammar
136
+ continue ;
137
+ }
138
+ for ( let j = i + 2 ; j < l ; j ++ ) {
139
+ const step = lines [ j ] ;
140
+ if ( ! step . match ( / ^ \s * ( - | [ 0 - 9 ] + \. ) / ) ) {
141
+ if ( step !== "" ) {
142
+ console . log ( `Bad grammar ${ grammarName } step in '${ filename } ':` ) ;
143
+ console . dir ( step ) ;
144
+ console . log ( ) ;
145
+ process . exitCode = 1 ;
146
+ }
147
+ break ;
148
+ }
149
+ if ( ! step . match ( / [ . : ] $ / ) ) {
150
+ console . log (
151
+ `Bad formatting for '${ grammarName } ' step (does not end in '.' or ':') in '${ filename } ':`
152
+ ) ;
153
+ console . dir ( step ) ;
154
+ console . log ( ) ;
155
+ process . exitCode = 1 ;
156
+ }
157
+ if ( step . match ( / ^ \s * ( - | [ 0 - 9 ] \. ) \s + [ a - z ] / ) ) {
158
+ console . log (
159
+ `Bad formatting of '${ grammarName } ' step (should start with a capital) in '${ filename } ':`
160
+ ) ;
161
+ console . dir ( step ) ;
162
+ console . log ( ) ;
163
+ process . exitCode = 1 ;
164
+ }
165
+ const trimmedInnerLine = step . replace ( / \s + / g, " " ) ;
166
+ if (
167
+ trimmedInnerLine . match (
168
+ / (?: [ r R ] e t u r n | i s (?: n o t ) ? ) ( t r u e | f a l s e | n u l l ) \b /
169
+ ) &&
170
+ ! trimmedInnerLine . match ( / n u l l o r e m p t y / )
171
+ ) {
172
+ console . log (
173
+ `Potential bad formatting of '${ grammarName } ' step (true/false/null should be wrapped in curly braces, e.g. '{true}') in '${ filename } ':`
174
+ ) ;
175
+ console . dir ( step ) ;
83
176
console . log ( ) ;
84
177
process . exitCode = 1 ;
85
178
}
0 commit comments