1

I am new to haskell and I need to create a simple word processor. It needs to read text from the cmd and implement functions that would edit functions found in the text so some other text.All functions in the text are odered. Each function i.e section,table,figures and ref must be located and numbered independently based on the order of occurence. Since tables and figures are within the sections function(just like a book), when a new section is encountered you will reset the value of tables and figures. So i did a loop where the tables and figures are inside the section loop when searching for the functions. The functions all start with this '' character (escape character) and must be replaced with text using this method: \Section{title}{id}: -> "Section n: title". Where n is the section number. \table{title}{id} : -> "Table n.m : title". Where n is the number of the last section encountered and m is the table number. And so on. So I first imported a text document from the command line using this code:

import System.Environment (getArgs)
import System.IO (openFile, ReadWriteMode, hGetContents)
import Text.Format
import Data.Text.Internal.Search
import Data.Text
main = do
        args <- getArgs -- reading and writing files from CMD
        file <- openFile (head args) ReadWriteMode
        text <- hGetContents file

Then, I counted the number of times section,tables and figures appeard on the text so that I could implement a loop:

s = count . "section" -- count number of occurences of a certain word
t = count . "table"
f = count .  "Figure"
r = count . "ref"    

I finally implemented a formart text function inside a loop changing the functions according to the number of times they appeared:

i = 1
 
for i in range s format "\Section{title}{id}" [show i, show {title}] --change the text

    for j in range t format "\table{title}{id}" [show i.j, show {title}]

    for k in range f format "\figure{title}{id}" [show i.k, show {title}]

I however know this code is wrong and I'm stuck and need help.

  • Please edit the question to limit it to a specific problem with enough detail to identify an adequate answer. – Community Oct 25 '21 at 06:51

1 Answers1

0

Avoid the for loop and the mutating state.

module Main where
-- The function doNumbering replaces \functions in the input by numbered text
-- Parameters:
-- 1. String - the input (the unprocessed part, in my code often called xs or x:xs)
-- 2. Int - the next section number (in my code often called s)
-- 3. Int - the table number (in my code often called t)
-- 4. Int - the figure number (in my code often called f)
-- 5. String - the output (the finished part, the return value of the function)
doNumbering :: String -> Int -> Int -> Int -> String
-- If there is \Section... at the top of the input, then put Section s: ... to the output
-- and change state like (tail xs) s+1 1 1
doNumbering ('\\':'S':'e':'c':'t':'i':'o':'n':xs) s t f
  = "Section " ++ (show s)
    ++ ": " ++ getStr1 (tail xs) (s+1) 1 1 
-- If there is \Table... at the top of the input, then put Table s-1.t: ... to the output
-- and change state like (tail xs) s t+1 f
doNumbering ('\\':'T':'a':'b':'l':'e':xs) s t f
  = "Table " ++ (show (s-1)) ++ "." ++ (show t)
    ++ ": " ++ getStr1 (tail xs) s (t+1) f
-- If there is \Figure... in the input, then put Figure s-1.f: ... to the output
-- and change state like (tail xs) s t (f+1)
doNumbering ('\\':'F':'i':'g':'u':'r':'e':xs) s t f
  = "Figure " ++ (show (s-1)) ++ "." ++ (show f)
    ++ ": " ++ getStr1 (tail xs) s t (f+1)

-- No template above matches, so we move the character at the top of the input to output.
doNumbering (x:xs) s t f = [x] ++ doNumbering xs s t f
doNumbering "" _ _ _ = "" -- The input string is empty (the end)

-- The functions `getStr1` copy the text from first parameter of \function to output  
getStr1 :: String -> Int -> Int -> Int -> String
getStr1 ('}':xs) s t f = getStr2 xs s t f
getStr1 (x:xs) s t f = [x] ++ getStr1 xs s t f

-- The function `getStr2` skips the yet meaningless second parameter in brackets and call doNumbering.
-- It probably should be improved for the `ref` function.
getStr2 :: String -> Int -> Int -> Int -> String
getStr2 ('}':xs) s t f = doNumbering xs s t f
getStr2 (x:xs) s t f = getStr2 xs s t f

main = putStrLn $ doNumbering input 1 1 1

input :: String
input =
        "\\Section{sss}{sss}\n"
     ++ "Text text text text.\n"
     ++ "\\Table{ttt}{ttt}\n"
     ++ "Text text text text.\n"
     ++ "\\Figure{fff}{fff}\n"
     ++ "Text text text text.\n"
     ++ "\\Figure{fff}{fff}\n"
     ++ "Text text text text.\n"
     ++ "\\Table{ttt}{ttt}\n"
     ++ "Text text text text.\n"
     ++ "\\Figure{fff}{fff}\n"
     ++ "Text text text text.\n"
     ++ "\\Section{sss}{sss}\n"
     ++ "Text text text text.\n"
     ++ "\\Figure{fff}{fff}\n"
     ++ "Text text text text.\n"
     ++ "\\Figure{fff}{fff}\n"
     ++ "Text text text text.\n"
     ++ "\\Table{ttt}{ttt}\n"
     ++ "Text text text text.\n"
     ++ "\\Figure{fff}{fff}\n"
     ++ "Text text text text.\n"
     ++ "\\Table{ttt}{ttt}\n"
     ++ "Text text text text.\n"
     ++ "\\Section{sss}{sss}\n"
     ++ "\\Table{ttt}{ttt}\n"
     ++ "Text text text text.\n"
     ++ "\\Figure{fff}{fff}\n"
     ++ "Text text text text.\n"
     ++ "\\Table{ttt}{ttt}\n"
     ++ "Text text text text.\n"

Output:

Section 1: sss
Text text text text.
Table 1.1: ttt
Text text text text.
Figure 1.1: fff
Text text text text.
Figure 1.2: fff
Text text text text.
Table 1.2: ttt
Text text text text.
Figure 1.3: fff
Text text text text.
Section 2: sss
Text text text text.
Figure 2.1: fff
Text text text text.
Figure 2.2: fff
Text text text text.
Table 2.1: ttt
Text text text text.
Figure 2.3: fff
Text text text text.
Table 2.2: ttt
Text text text text.
Section 3: sss
Table 3.1: ttt
Text text text text.
Figure 3.1: fff
Text text text text.
Table 3.2: ttt
Text text text text.

There is one ugly thing in my code. In my code, it looks like s t f after every call of the parsing functions. It is due to referential transparency. It can be treated with monads. See do notation.

David Lukas
  • 1,184
  • 2
  • 8
  • 21
  • Thanks David for the help. Could you please explain to me a bit how the code works as I am new to haskell. I'll appreciate the assistance. – Dennis Gaita Nov 10 '21 at 17:07
  • @DennisGaita I've added some notes to the code. For more details about Haskell, I recommend: http://learnyouahaskell.com/. – David Lukas Nov 11 '21 at 07:16