Paragraph Support

This commit is contained in:
Nathan McCarty 2025-02-21 03:20:46 -05:00
parent 98ed90a9bc
commit f60e209073
2 changed files with 136 additions and 60 deletions

View file

@ -31,6 +31,9 @@ data Inline : Type where
public export public export
data Block : Type where data Block : Type where
Paragraph : (contents : List1 Inline) -> Block
%runElab derive "Block" [Show, Eq]
--***************************************** --*****************************************
--* Character Classes and String Escaping * --* Character Classes and String Escaping *
@ -83,9 +86,12 @@ escapedChar = do
-- Line Qualifying And Whitespace -- -- Line Qualifying And Whitespace --
------------------------------------ ------------------------------------
space : PS Char
space = theseChars horizontalWhitespaceChars
spaces : PS Nat spaces : PS Nat
spaces = do spaces = do
xs <- many $ theseChars horizontalWhitespaceChars xs <- many space
pure $ length xs pure $ length xs
nonTerminal : PS Char nonTerminal : PS Char
@ -106,7 +112,7 @@ terminal = do
line : PS (List Char) line : PS (List Char)
line = do line = do
cs <- many nonTerminal cs <- many nonTerminal
terminal _ <- lineEnding
pure cs pure cs
isHorizontalWhitespace : Char -> Bool isHorizontalWhitespace : Char -> Bool
@ -119,12 +125,26 @@ blankLine = do
False => throw "nonblank line" False => throw "nonblank line"
True => pure cs True => pure cs
blankLineOrEnd : PS ()
blankLineOrEnd = do
Nothing <- tryMaybe blankLine
| Just _ => pure ()
eof <- parseEoF
case eof of
False => throw "Expected newline or end of document"
True => pure ()
blankLines : PS ()
blankLines = do
xs <- many blankLine
if length xs > 0
then pure ()
else blankLineOrEnd
--***************************************** --*****************************************
--* Inline syntax * --* Inline syntax *
--***************************************** --*****************************************
inlineElement : PS Inline
------------------------ ------------------------
-- Escaped Whitespace -- -- Escaped Whitespace --
------------------------ ------------------------
@ -176,34 +196,52 @@ text = do
-- Overall Inline Parser -- -- Overall Inline Parser --
--------------------------- ---------------------------
inlineElement = oneOfE "" [ inlineElementsNoNewlines : PS Inline
hardLineBreak inlineElementsNoNewlines = oneOfE "" [
, nbsp nbsp
, escapedText , escapedText
, softLineBreak
-- Text is last so that anything can superseed it -- Text is last so that anything can superseed it
, text , text
] ]
inlineElement : PS Inline
inlineElement = oneOfE "" [
hardLineBreak
, softLineBreak
, inlineElementsNoNewlines
]
inline : PS (List1 Inline) inline : PS (List1 Inline)
inline = atLeastOne "Expected Inline Content" inlineElement inline = atLeastOne "Expected Inline Content" inlineElement
--***************************************** --*****************************************
--* Utility Functions * --* Block Syntax *
--***************************************** --*****************************************
------------------ ---------------
-- Constructors -- -- Paragraph --
------------------ ---------------
namespace Inline paragraph : PS Block
export paragraph = do
fromString : String -> List (Inline) inlines <- inline
fromString str with (asList str) blankLineOrEnd
fromString "" | [] = [] pure $ Paragraph inlines
fromString (strCons c str) | (c :: x) =
Text c :: fromString str | x --------------------------
-- Overall Block Parser --
--------------------------
block : PS Block
block = do
-- eat up any blank lines
_ <- many blankLine
oneOfE "" [
paragraph
]
blocks : PS (List Block)
blocks = many block
--***************************************** --*****************************************
--* Unit Tests * --* Unit Tests *
@ -228,6 +266,18 @@ golden input ref parser = do
putStrLn "Output: \{show x}" putStrLn "Output: \{show x}"
pure $ x == ref pure $ x == ref
inlineFromString : String -> List (Inline)
inlineFromString str with (asList str)
inlineFromString "" | [] = []
inlineFromString (strCons c str) | (c :: x) =
Text c :: inlineFromString str | x
inlineFromString' : String -> List1 (Inline)
inlineFromString' str =
case inlineFromString str of
[] => assert_total $ idris_crash "Bad unit test fromString"
(x :: xs) => x ::: xs
------------------------- -------------------------
-- Inline Syntax Tests -- -- Inline Syntax Tests --
------------------------- -------------------------
@ -242,26 +292,47 @@ inlineTextSmoke =
inlineEscapedSmoke : IO Bool inlineEscapedSmoke : IO Bool
inlineEscapedSmoke = inlineEscapedSmoke =
let input = "Hello\\n\\*World" let input = "Hello\\n\\*World"
ref = fromString "Hello" ++ [Text '\n', Text '*'] ++ fromString "World" ref = inlineFromString "Hello" ++ [Text '\n', Text '*'] ++ inlineFromString "World"
in golden input ref (map forget inline) in golden input ref (map forget inline)
-- @@test Hard Line Break -- @@test Hard Line Break
inlineHardBreakSmoke : IO Bool inlineHardBreakSmoke : IO Bool
inlineHardBreakSmoke = inlineHardBreakSmoke =
let input = "Hello\\\nWorld" let input = "Hello\\\nWorld"
ref = fromString "Hello" ++ [HardLineBreak] ++ fromString "World" ref = inlineFromString "Hello" ++ [HardLineBreak] ++ inlineFromString "World"
in golden input ref (map forget inline) in golden input ref (map forget inline)
-- @@test Soft Line Break -- @@test Soft Line Break
inlineSoftBreakSmoke : IO Bool inlineSoftBreakSmoke : IO Bool
inlineSoftBreakSmoke = inlineSoftBreakSmoke =
let input = "Hello\nWorld" let input = "Hello\nWorld"
ref = fromString "Hello" ++ [SoftLineBreak] ++ fromString "World" ref = inlineFromString "Hello" ++ [SoftLineBreak] ++ inlineFromString "World"
in golden input ref (map forget inline) in golden input ref (map forget inline)
-- @@test Nonbreaking Space -- @@test Nonbreaking Space
inlineNbspSmoke : IO Bool inlineNbspSmoke : IO Bool
inlineNbspSmoke = inlineNbspSmoke =
let input = "Hello\\ World" let input = "Hello\\ World"
ref = fromString "Hello" ++ [NonBreakingSpace] ++ fromString "World" ref = inlineFromString "Hello" ++ [NonBreakingSpace] ++ inlineFromString "World"
in golden input ref (map forget inline) in golden input ref (map forget inline)
------------------------
-- Block Syntax Tests --
------------------------
-- @@test Paragraph
blockParagraphSmoke : IO Bool
blockParagraphSmoke =
let input = "Hello World"
ref = [Paragraph (inlineFromString' "Hello World")]
in golden input ref blocks
-- @@test Two Paragraph
blockTwoParagraphSmoke : IO Bool
blockTwoParagraphSmoke =
let input = "Hello World\n\nHello Again"
ref = [
Paragraph (inlineFromString' "Hello World")
, Paragraph (inlineFromString' "Hello Again")
]
in golden input ref blocks

View file

@ -8,45 +8,50 @@ Decided to rename =Tag= to =Html=, and =Raw= to =Text=, which makes this make se
** TODO Refine =location= in =ParserLocation= ** TODO Refine =location= in =ParserLocation=
** TODO Error messages ** TODO Error messages
** TODO Combinators for predictive parsing ** TODO Combinators for predictive parsing
* Djot [2/40] * Djot [3/42]
:PROPERTIES: :PROPERTIES:
:COOKIE_DATA: recursive :COOKIE_DATA: recursive
:END: :END:
** Inline Syntax [2/18] ** Parsing
*** DONE Ordinary Text *** Inline Syntax [2/18]
*** TODO Link **** DONE Ordinary Text
*** TODO Image **** TODO Link
*** TODO Autolink **** TODO Image
*** TODO Verbatim **** TODO Autolink
*** TODO Emphasis/strong **** TODO Verbatim
*** TODO Highlighted **** TODO Emphasis/strong
*** TODO Super/subscript **** TODO Highlighted
*** TODO Insert/delete **** TODO Super/subscript
*** TODO Smart punctuation **** TODO Insert/delete
*** TODO Math **** TODO Smart punctuation
*** TODO Footnote reference **** TODO Math
*** DONE Linebreak **** TODO Footnote reference
*** TODO Comment **** DONE Linebreak
*** TODO Symbols **** TODO Comment
*** TODO Raw inline **** TODO Symbols
*** TODO Span **** TODO Raw inline
*** TODO Inline attributes **** TODO Span
** Block Syntax [0/15] **** TODO Inline attributes
*** TODO Paragraph *** Block Syntax [1/16]
*** TODO Heading **** DONE Paragraph
*** TODO Block quote **** Heading
*** TODO List item ***** TODO Multiline without leading count
*** TODO List ***** TODO Basic
*** TODO Code block **** TODO Block quote
*** TODO Thematic break **** TODO List item
*** TODO Raw block **** TODO List
*** TODO Div **** TODO Code block
*** TODO Pipe table **** TODO Thematic break
*** TODO Reference link **** TODO Raw block
*** TODO definition **** TODO Div
*** TODO Footnote **** TODO Pipe table
*** TODO Block attributes **** TODO Reference link
*** TODO Links to headings **** TODO definition
**** TODO Footnote
**** TODO Block attributes
**** TODO Links to headings
** TODO Rendering
** Bugs [0/0]
** TODO Predictive parsing ** TODO Predictive parsing
** TODO Support all types of whitespace ** TODO Support all types of whitespace
*** TODO Escaping *** TODO Escaping