@@ -2,16 +2,16 @@ const Scanner = require('./scanner')
22const { isWhitespace, isNewline, isParens } = require ( './type-checks' )
33
44/*
5- * <message> ::= <summary>, <newline>* , <body>, <newline>* , <footer>+
6- * | <summary>, <newline>* , <footer>+
5+ * <message> ::= <summary>, <newline>+ , <body>, ( <newline>+ , <footer>)*
6+ * | <summary>, ( <newline>+ , <footer>)*
77 * | <summary>, <newline>*
88 *
99 */
1010function message ( commitText ) {
1111 const scanner = new Scanner ( commitText . trim ( ) )
1212 const node = scanner . enter ( 'message' , [ ] )
1313
14- // <summary>
14+ // <summary> ...
1515 const s = summary ( scanner )
1616 if ( s instanceof Error ) {
1717 throw s
@@ -22,27 +22,49 @@ function message (commitText) {
2222 return scanner . exit ( node )
2323 }
2424
25- // <summary> <newline>* <body>
26- if ( isNewline ( scanner . peek ( ) ) ) {
27- // TODO(@byCedric): include <newline>* in AST .
28- while ( isNewline ( scanner . peek ( ) ) ) {
29- scanner . next ( )
30- }
25+ let nl
26+ let b
27+ // ... <newline>* <body> .. .
28+ nl = newline ( scanner )
29+ if ( nl instanceof Error ) {
30+ throw nl
3131 } else {
32- throw scanner . abort ( node )
32+ node . children . push ( nl )
33+ b = body ( scanner )
34+ if ( b instanceof Error ) {
35+ b = null
36+ } else {
37+ node . children . push ( b )
38+ }
3339 }
34- const b = body ( scanner )
35- if ( ! ( b instanceof Error ) ) {
36- node . children . push ( b )
40+ if ( scanner . eof ( ) ) {
41+ return scanner . exit ( node )
3742 }
38- // TODO(@byCedric): include <newline>* in AST.
39- while ( isNewline ( scanner . peek ( ) ) ) {
40- scanner . next ( )
43+
44+ // ... <newline>* <footer>+
45+ if ( b ) {
46+ nl = newline ( scanner )
47+ if ( nl instanceof Error ) {
48+ throw nl
49+ } else {
50+ node . children . push ( nl )
51+ }
4152 }
4253 while ( ! scanner . eof ( ) ) {
4354 const f = footer ( scanner )
44- if ( ! ( f instanceof Error ) ) node . children . push ( f )
55+ if ( f instanceof Error ) {
56+ break
57+ } else {
58+ node . children . push ( f )
59+ }
60+ nl = newline ( scanner )
61+ if ( nl instanceof Error ) {
62+ break
63+ } else {
64+ node . children . push ( nl )
65+ }
4566 }
67+
4668 return scanner . exit ( node )
4769}
4870
@@ -189,10 +211,13 @@ function body (scanner) {
189211 const t = text ( scanner )
190212 node . children . push ( t )
191213 // <newline>, <body>*
192- if ( isNewline ( scanner . peek ( ) ) ) {
193- scanner . next ( )
214+ const nl = newline ( scanner )
215+ if ( ! ( nl instanceof Error ) ) {
194216 const b = body ( scanner )
195- if ( ! ( b instanceof Error ) ) {
217+ if ( b instanceof Error ) {
218+ scanner . abort ( nl )
219+ } else {
220+ node . children . push ( nl )
196221 Array . prototype . push . apply ( node . children , b . children )
197222 }
198223 }
@@ -204,19 +229,17 @@ function body (scanner) {
204229 */
205230function preFooter ( scanner ) {
206231 const node = scanner . enter ( 'pre-footer' , [ ] )
207- while ( isNewline ( scanner . peek ( ) ) ) {
208- scanner . next ( )
209- }
210232 let f
211233 while ( ! scanner . eof ( ) ) {
234+ newline ( scanner )
212235 f = footer ( scanner )
213236 if ( f instanceof Error ) return scanner . abort ( node )
214237 }
215238 return scanner . exit ( node )
216239}
217240
218241/*
219- * <footer> ::= <token> <separator> <whitespace>* <value> <newline>?
242+ * <footer> ::= <token> <separator> <whitespace>* <value>
220243 */
221244function footer ( scanner ) {
222245 const node = scanner . enter ( 'footer' , [ ] )
@@ -231,6 +254,7 @@ function footer (scanner) {
231254 // <separator>
232255 const s = separator ( scanner )
233256 if ( s instanceof Error ) {
257+ scanner . abort ( node )
234258 return s
235259 } else {
236260 node . children . push ( s )
@@ -242,16 +266,15 @@ function footer (scanner) {
242266 node . children . push ( ws )
243267 }
244268
245- // <value> <newline>?
269+ // <value>
246270 const v = value ( scanner )
247271 if ( v instanceof Error ) {
272+ scanner . abort ( node )
248273 return v
249274 } else {
250275 node . children . push ( v )
251276 }
252- if ( isNewline ( scanner . peek ( ) ) ) {
253- scanner . next ( )
254- }
277+
255278 return scanner . exit ( node )
256279}
257280
@@ -330,18 +353,24 @@ function value (scanner) {
330353 */
331354function continuation ( scanner ) {
332355 const node = scanner . enter ( 'continuation' , [ ] )
333- if ( isNewline ( scanner . peek ( ) ) ) {
334- scanner . next ( )
335- const ws = whitespace ( scanner )
336- if ( ws instanceof Error ) {
337- return ws
338- } else {
339- node . children . push ( ws )
340- node . children . push ( text ( scanner ) )
341- }
356+ // <newline>
357+ const nl = newline ( scanner )
358+ if ( nl instanceof Error ) {
359+ return nl
342360 } else {
343- return scanner . abort ( node )
361+ node . children . push ( nl )
362+ }
363+
364+ // <whitespace> <text>
365+ const ws = whitespace ( scanner )
366+ if ( ws instanceof Error ) {
367+ scanner . abort ( node )
368+ return ws
369+ } else {
370+ node . children . push ( ws )
371+ node . children . push ( text ( scanner ) )
344372 }
373+
345374 return scanner . exit ( node )
346375}
347376
@@ -385,4 +414,18 @@ function whitespace (scanner) {
385414 return scanner . exit ( node )
386415}
387416
417+ /*
418+ * <newline>+ ::= [<CR>], <LF>
419+ */
420+ function newline ( scanner ) {
421+ const node = scanner . enter ( 'newline' , '' )
422+ while ( isNewline ( scanner . peek ( ) ) ) {
423+ node . value += scanner . next ( )
424+ }
425+ if ( node . value === '' ) {
426+ return scanner . abort ( node , [ '<CR><LF>' , '<LF>' ] )
427+ }
428+ return scanner . exit ( node )
429+ }
430+
388431module . exports = message
0 commit comments