Skip to content

Commit e592b29

Browse files
panglesdjonludlam
authored andcommitted
Warn new lines in markup nested in light tables
New lines inside markup (such as `{e ...}`) were not detected, although it breaks the light table format. Add a warning for such cases. Signed-off-by: Paul-Elliot <[email protected]>
1 parent 68338a1 commit e592b29

File tree

4 files changed

+99
-28
lines changed

4 files changed

+99
-28
lines changed

src/lexer.mll

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -402,10 +402,10 @@ rule token input = parse
402402
{ emit input (`Begin_list_item `Dash) }
403403

404404
| "{table"
405-
{ emit input (`Begin_table `Heavy) }
405+
{ emit input (`Begin_table_heavy) }
406406

407407
| "{t"
408-
{ emit input (`Begin_table `Light) }
408+
{ emit input (`Begin_table_light) }
409409

410410
| "{tr"
411411
{ emit input `Begin_table_row }

src/syntax.ml

Lines changed: 50 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,11 @@ type token_that_always_begins_an_inline_element =
156156
let _check_subset : token_that_always_begins_an_inline_element -> Token.t =
157157
fun t -> (t :> Token.t)
158158

159+
(* The different contexts in which the inline parser [inline_element] and
160+
[delimited_inline_parser] can be called. The inline parser's behavior depends
161+
somewhat on the context: new lines are forbidden in light tables. *)
162+
type inline_context = In_light_table | Outside_light_table
163+
159164
(* Consumes tokens that make up a single non-link inline element:
160165
161166
- a horizontal space ([`Space], significant in inline elements),
@@ -177,8 +182,12 @@ let _check_subset : token_that_always_begins_an_inline_element -> Token.t =
177182
178183
This function consumes exactly the tokens that make up the element. *)
179184
let rec inline_element :
180-
input -> Loc.span -> _ -> Ast.inline_element with_location =
181-
fun input location next_token ->
185+
input ->
186+
Loc.span ->
187+
context:inline_context ->
188+
_ ->
189+
Ast.inline_element with_location =
190+
fun input location ~context next_token ->
182191
match next_token with
183192
| `Space _ as token ->
184193
junk input;
@@ -208,7 +217,8 @@ let rec inline_element :
208217
in
209218
let content, brace_location =
210219
delimited_inline_element_list ~parent_markup
211-
~parent_markup_location:location ~requires_leading_whitespace input
220+
~parent_markup_location:location ~requires_leading_whitespace ~context
221+
input
212222
in
213223

214224
let location = Loc.span [ location; brace_location ] in
@@ -236,7 +246,7 @@ let rec inline_element :
236246
let content, brace_location =
237247
delimited_inline_element_list ~parent_markup
238248
~parent_markup_location:location ~requires_leading_whitespace:false
239-
input
249+
~context input
240250
in
241251

242252
let location = Loc.span [ location; brace_location ] in
@@ -274,7 +284,7 @@ let rec inline_element :
274284
let content, brace_location =
275285
delimited_inline_element_list ~parent_markup
276286
~parent_markup_location:location ~requires_leading_whitespace:false
277-
input
287+
~context input
278288
in
279289

280290
`Link (u, content) |> Loc.at (Loc.span [ location; brace_location ])
@@ -305,9 +315,11 @@ and delimited_inline_element_list :
305315
parent_markup:[< Token.t ] ->
306316
parent_markup_location:Loc.span ->
307317
requires_leading_whitespace:bool ->
318+
context:inline_context ->
308319
input ->
309320
Ast.inline_element with_location list * Loc.span =
310-
fun ~parent_markup ~parent_markup_location ~requires_leading_whitespace input ->
321+
fun ~parent_markup ~parent_markup_location ~requires_leading_whitespace
322+
~context input ->
311323
(* [~at_start_of_line] is used to interpret [`Minus] and [`Plus]. These are
312324
word tokens if not the first non-whitespace tokens on their line. Then,
313325
they are allowed in a non-link element list. *)
@@ -330,10 +342,17 @@ and delimited_inline_element_list :
330342
it is an internal space, and we want to add it to the non-link inline
331343
element list. *)
332344
| (`Space _ | #token_that_always_begins_an_inline_element) as token ->
333-
let acc = inline_element input next_token.location token :: acc in
345+
let acc =
346+
inline_element input next_token.location ~context token :: acc
347+
in
334348
consume_elements ~at_start_of_line:false acc
335-
| `Single_newline ws ->
349+
| `Single_newline ws as blank ->
336350
junk input;
351+
if context = In_light_table then
352+
Parse_error.not_allowed ~what:(Token.describe blank)
353+
~in_what:(Token.describe `Begin_table_light)
354+
next_token.location
355+
|> add_warning input;
337356
let element = Loc.same next_token (`Space ws) in
338357
consume_elements ~at_start_of_line:true (element :: acc)
339358
| `Blank_line ws as blank ->
@@ -356,7 +375,9 @@ and delimited_inline_element_list :
356375
~suggestion next_token.location
357376
|> add_warning input);
358377

359-
let acc = inline_element input next_token.location bullet :: acc in
378+
let acc =
379+
inline_element input next_token.location ~context bullet :: acc
380+
in
360381
consume_elements ~at_start_of_line:false acc
361382
| other_token ->
362383
Parse_error.not_allowed
@@ -438,7 +459,10 @@ let paragraph : input -> Ast.nestable_block_element with_location =
438459
match next_token.value with
439460
| (`Space _ | `Minus | `Plus | #token_that_always_begins_an_inline_element)
440461
as token ->
441-
let element = inline_element input next_token.location token in
462+
let element =
463+
inline_element input next_token.location ~context:Outside_light_table
464+
token
465+
in
442466
paragraph_line (element :: acc)
443467
| _ -> acc
444468
in
@@ -703,7 +727,7 @@ let rec block_element_list :
703727
| { value = `Begin_table_row as token; location } ->
704728
let suggestion =
705729
Printf.sprintf "move %s into %s." (Token.print token)
706-
(Token.describe (`Begin_table `Heavy))
730+
(Token.describe `Begin_table_heavy)
707731
in
708732
Parse_error.not_allowed ~what:(Token.describe token)
709733
~in_what:(Token.describe parent_markup)
@@ -729,7 +753,7 @@ let rec block_element_list :
729753
| { value = `Bar as token; location } ->
730754
let suggestion =
731755
Printf.sprintf "move %s into %s." (Token.print token)
732-
(Token.describe (`Begin_table `Light))
756+
(Token.describe `Begin_table_light)
733757
in
734758
Parse_error.not_allowed ~what:(Token.describe token)
735759
~in_what:(Token.describe parent_markup)
@@ -942,16 +966,19 @@ let rec block_element_list :
942966
let block = Loc.at location block in
943967
let acc = block :: acc in
944968
consume_block_elements ~parsed_a_tag `After_text acc
945-
| { value = `Begin_table syntax as token; location } as next_token ->
969+
| { value = (`Begin_table_light | `Begin_table_heavy) as token; location }
970+
as next_token ->
946971
warn_if_after_tags next_token;
947972
warn_if_after_text next_token;
948973
junk input;
949974
let block, brace_location =
950975
let parent_markup = token in
951976
let parent_markup_location = location in
952-
match syntax with
953-
| `Light -> light_table input ~parent_markup ~parent_markup_location
954-
| `Heavy -> heavy_table input ~parent_markup ~parent_markup_location
977+
match token with
978+
| `Begin_table_light ->
979+
light_table input ~parent_markup ~parent_markup_location
980+
| `Begin_table_heavy ->
981+
heavy_table input ~parent_markup ~parent_markup_location
955982
in
956983
let location = Loc.span [ location; brace_location ] in
957984
let block = accepted_in_all_contexts context (`Table block) in
@@ -995,7 +1022,7 @@ let rec block_element_list :
9951022
let content, brace_location =
9961023
delimited_inline_element_list ~parent_markup:token
9971024
~parent_markup_location:location ~requires_leading_whitespace:true
998-
input
1025+
~context:Outside_light_table input
9991026
in
10001027
let location = Loc.span [ location; brace_location ] in
10011028
let paragraph =
@@ -1035,7 +1062,8 @@ let rec block_element_list :
10351062
let content, brace_location =
10361063
delimited_inline_element_list ~parent_markup:token
10371064
~parent_markup_location:location
1038-
~requires_leading_whitespace:true input
1065+
~requires_leading_whitespace:true ~context:Outside_light_table
1066+
input
10391067
in
10401068
if content = [] then
10411069
Parse_error.should_not_be_empty ~what:(Token.describe token)
@@ -1052,7 +1080,7 @@ let rec block_element_list :
10521080
let content, brace_location =
10531081
delimited_inline_element_list ~parent_markup:token
10541082
~parent_markup_location:location ~requires_leading_whitespace:true
1055-
input
1083+
~context:Outside_light_table input
10561084
in
10571085
let location = Loc.span [ location; brace_location ] in
10581086

@@ -1278,7 +1306,9 @@ and light_table_row ~parent_markup ~last_loc input =
12781306
let acc_row = if new_line then [] else List.rev acc_cell :: acc_row in
12791307
consume_row acc_row [] ~new_line:false ~last_loc
12801308
| #token_that_always_begins_an_inline_element as token ->
1281-
let i = inline_element input next_token.location token in
1309+
let i =
1310+
inline_element input next_token.location ~context:In_light_table token
1311+
in
12821312
consume_row acc_row (i :: acc_cell) ~new_line:false
12831313
~last_loc:next_token.location
12841314
| other_token ->

src/token.ml

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,8 @@ type t =
7070
`Begin_list of [ `Unordered | `Ordered ]
7171
| `Begin_list_item of [ `Li | `Dash ]
7272
| (* Table markup. *)
73-
`Begin_table of [ `Light | `Heavy ]
73+
`Begin_table_light
74+
| `Begin_table_heavy
7475
| `Begin_table_row
7576
| `Begin_table_cell of [ `Header | `Data ]
7677
| `Minus
@@ -92,9 +93,8 @@ let print : [< t ] -> string = function
9293
| `Begin_link_with_replacement_text _ -> "'{{:'"
9394
| `Begin_list_item `Li -> "'{li ...}'"
9495
| `Begin_list_item `Dash -> "'{- ...}'"
95-
| `Begin_table syntax ->
96-
let syntax = match syntax with `Light -> "t" | `Heavy -> "table" in
97-
Printf.sprintf "'{%s'" syntax
96+
| `Begin_table_light -> "{t"
97+
| `Begin_table_heavy -> "{table"
9898
| `Begin_table_row -> "'{tr'"
9999
| `Begin_table_cell `Header -> "'{th'"
100100
| `Begin_table_cell `Data -> "'{td'"
@@ -154,8 +154,8 @@ let describe : [< t | `Comment ] -> string = function
154154
| `Begin_list `Ordered -> "'{ol ...}' (numbered list)"
155155
| `Begin_list_item `Li -> "'{li ...}' (list item)"
156156
| `Begin_list_item `Dash -> "'{- ...}' (list item)"
157-
| `Begin_table `Light -> "'{t ...}' (table)"
158-
| `Begin_table `Heavy -> "'{table ...}' (table)"
157+
| `Begin_table_light -> "'{t ...}' (table)"
158+
| `Begin_table_heavy -> "'{table ...}' (table)"
159159
| `Begin_table_row -> "'{tr ...}' (table row)"
160160
| `Begin_table_cell `Header -> "'{th ... }' (table header cell)"
161161
| `Begin_table_cell `Data -> "'{td ... }' (table data cell)"

test/test_tables.ml

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -470,6 +470,47 @@ let%expect_test _ =
470470
(align (center center center center))))))
471471
(warnings ())) |}]
472472

473+
let light_table_markup_with_newlines =
474+
test
475+
{|
476+
{t | h1 | h2 |
477+
|--------------|-------------|
478+
| {e with
479+
newlines} | {b d} [foo] |
480+
}
481+
|};
482+
[%expect {|
483+
((output
484+
(((f.ml (2 6) (6 7))
485+
(table (syntax light)
486+
(data
487+
((row
488+
((header
489+
(((f.ml (2 11) (2 13))
490+
(paragraph (((f.ml (2 11) (2 13)) (word h1)))))))
491+
(header
492+
(((f.ml (2 26) (2 28))
493+
(paragraph (((f.ml (2 26) (2 28)) (word h2)))))))))
494+
(row
495+
((data
496+
(((f.ml (4 11) (5 23))
497+
(paragraph
498+
(((f.ml (4 11) (5 23))
499+
(emphasis
500+
(((f.ml (4 14) (4 18)) (word with))
501+
((f.ml (4 18) (5 14)) space)
502+
((f.ml (5 14) (5 22)) (word newlines))))))))))
503+
(data
504+
(((f.ml (5 26) (5 31))
505+
(paragraph
506+
(((f.ml (5 26) (5 31)) (bold (((f.ml (5 29) (5 30)) (word d))))))))
507+
((f.ml (5 32) (5 37))
508+
(paragraph (((f.ml (5 32) (5 37)) (code_span foo)))))))))))
509+
(align (center center))))))
510+
(warnings
511+
( "File \"f.ml\", line 4, character 18 to line 5, character 14:\
512+
\nLine break is not allowed in '{t ...}' (table)."))) |}]
513+
473514
let no_space =
474515
test
475516
{|

0 commit comments

Comments
 (0)