-- <<<- ------------------------------------------------------------------------ -- Network ORiented Markup Language parser. -- Don Hopkins, Kaleida Labs. -- -- NORML is designed to be a very simple markup language, -- that lets you format text with paragraphs, links and outlines, -- with a minimum of syntax. -- Text that begins on the left margin is filled. -- A blank line inserts a paragraph break. -- Indented text is nested into an outline. -- A link is defined by a line with a label, a star, and a URL. -- Links may be indented in outlines. -- A command line begins with a star. function parseNorml str -> ( local result := new WebGroup local cursor := result local outlines := new SortedKeyedArray local outlineIndent := 0 local justDidParagraph := false if (not (isReadable str)) do ( str := str as ByteStream ) local c := undefined local l := new String local stars := new Array local indent := 0 function closeOutlines -> ( local levelsToClose := new Array local lastOutline := undefined local lastOutlineLevel := 0 forEachBinding outlines (outlineLevel outline xxx -> if (outlineLevel > indent) then ( append levelsToClose outlineLevel ) else ( lastOutline := outline lastOutlineLevel := outlineLevel ) ) ok forEach levelsToClose (level xxx -> deleteKeyOne outlines level ) ok if (lastOutlineLevel == indent) then ( outlineIndent := lastOutlineLevel ) else ( local newOutline := new WebBulletedList if ((size outlines) == 0) then ( append result newOutline ) else ( local lastOutline := outlines[outlineIndent] append (getLast lastOutline) (object (WebGroup) contents newOutline end) ) outlineIndent := indent outlines[outlineIndent] := newOutline ) ) function writeOut out -> ( if (indent == 0) then ( closeOutlines() append result out ) else ( if (indent != outlineIndent) do ( if (indent > outlineIndent) then ( local newOutline := new WebBulletedList if (outlineIndent == 0) then ( append result newOutline ) else ( local lastOutline := outlines[outlineIndent] append (getLast lastOutline) (object (WebGroup) contents newOutline end) ) outlineIndent := indent outlines[outlineIndent] := newOutline ) else ( closeOutlines() ) ) local outline := outlines[outlineIndent] append outline (object (WebGroup) contents out end) ) ) function stripWhite str -> ( repeat while (str[1] == 32) do (pop str) repeat while (str[size str] == 32) do ( deleteNth str (size str) ) str ) function doLine -> ( -- print #("indent", indent, "stars", stars, "line", l) if ((size l) == 0) then ( if (not justDidParagraph) do ( writeOut (new WebParagraph) ) justDidParagraph := true ) else ( justDidParagraph := false if ((size stars) == 0) then ( append l 13 writeOut (copy l) ) else ( if (stars[1] == 1) then ( local s2 := stars[2] if ((s2 == empty) or (s2 == 2)) then ( local level := size stars local heading := getRange l \ (stars[level] + 1) \ 999 heading := stripWhite heading -- print #("heading", level, heading) local heading := object (WebHeading) level: level contents heading end writeOut heading ) else ( local args := new Array append stars ((size l) + 1) for i := 2 to (size stars) do ( local arg := getRange l \ (stars[i - 1] + 1) \ (stars[i] - 1) append args (stripWhite arg) ) local cmd := pop args print #("command", cmd, args) writeOut (object (WebBulletedList) contents object (WebGroup) contents cmd args | WebBulletedList end end) ) ) else ( local label := stripWhite (getRange l 1 (stars[1] - 1)) local url := stripWhite (getRange l (stars[1] + 1) 9999) -- print #("Link", label, url) local link := object (WebLink) url: url contents label end writeOut link ) ) ) emptyOut l emptyOut stars indent := 0 ) repeat while (not (isPastEnd str)) do ( c := read str case c of 13: ( -- return doLine() ) 9: ( -- tab if ((size l) == 0) then ( indent := indent + 1 ) else ( append l c ) ) 42: ( -- star * append l c append stars (size l) ) otherwise: ( append l c ) end ) c := undefined doLine() return result ) ------------------------------------------------------------------------ "norml.sx" -- >>>