, чтобы узнать немного больше о Haskell (особенно Monads). Я пытаюсь создать проверку орфографии. Моя цель - пройти через документ LaTeX и сделать что-то на словах, которые не входят в список словарей.haskell parser с проверкой орфографии
Я уже написал синтаксический анализатор (строка для АСТ), код которого я вставляю ниже. Он в основном возвращает источник LaTeX, размещенный в соответствующих фрагментах (текст, формулы, команды и т. Д.). Я хотел бы знать, как создать такую программу, чтобы на каждом слове, не найденном в списке, мы спрашиваем у пользователя, какое слово заменить.
(То, что мы действительно заботимся о LaTeX является то, что у нас есть некоторая часть исходного кода, которые являются текст и должны быть проверки правописания, и другие части, которые являются формулы, а не простой английский)
Пусть мне объяснить это более ясно с некоторыми примерами желаемого поведения (для простоты формулы между $ HERE IS THE FORMULA $
)
Источник:
This is my frst file and here
we have a formula: $\forall x \quad x$
Desir изд поведение:
In file 'first.tex' at line 1: 'frst' unknown
1 This is my **frst** file and here
2 we have a formula: $\forall x \quad x$
Action [Add word to dictionary/Change word]?
Основная проблема, после того как я разобран файл, я осталась с AST и не имею больше ссылок на линию, так что я не мог показать им, как выше пример.
Код для синтаксического анализатора:
import System.Environment
import Text.Parsec (ParseError)
import Text.Parsec.String (Parser, parseFromFile)
import Text.Parsec.String.Parsec (try)
import Text.Parsec.String.Char (oneOf, char, digit, string, letter, satisfy, noneOf, anyChar)
import Text.Parsec.String.Combinator (many1, choice, chainl1, between, count, option, optionMaybe, optional, manyTill, eof, lookAhead)
import Control.Applicative ((<$>), (<*>), (<*), (*>), (<|>), many, (<$))
import Control.Monad (void, ap, mzero)
import Data.Char (isLetter, isDigit)
import FunctionsAndTypesForParsing
data TexFile = Items [TexTerm]
deriving (Eq, Show)
data TexTerm = Comment String
| Formula String
| Command String [TexFile]
| Text String
| Block TexFile
deriving (Eq, Show)
-- We get the AST as output
texFile :: Parser TexFile
texFile = Items <$> (many texTerm) <* (optional (try $ eof))
texTerm :: Parser TexTerm
texTerm = lexeme $ (try comment <|> text <|> formula <|> command <|> block)
whitespace :: Parser()
whitespace = void $ try $ oneOf " \n\t"
lexeme :: Parser a -> Parser a
lexeme p = p <* (many $ whitespace)
comment :: Parser TexTerm
comment = Comment <$> between (string "%") (string "\n") (many $ noneOf "\n")
formula :: Parser TexTerm
formula = Formula <$> (try singledollar <|> doubledollar <|> equation <|> align)
where
singledollar = between (string "$") (string "$") (many1 $ noneOf "$")
doubledollar = between (string "$$") (string "$$") (many1 $ noneOf "$$")
equation = try $ between (try $ string "\\begin{equation}") (string "\\end{equation}") (manyTill anyChar (lookAhead $ try $ string "\\end{equation}"))
align = try $ between (try $ string "\\begin{align*}") (string "\\end{align*}") (manyTill anyChar (lookAhead $ try $ string "\\end{align*}"))
command :: Parser TexTerm
command = Command <$> com <*> (many arg)
where
com = char '\\' *> (manyTill (try letter <|> oneOf "*") (lookAhead $ try $ oneOf "[{ \\\n\t"))
arg = (try (between (string "{") (string "}") texFile)
<|> (between (string "[") (string "]") texFile)
)
text :: Parser TexTerm
text = Text <$> many1 textualchars
where
textualchars = try letter <|> digit <|> oneOf " \n\t\r,.*:;-<>#@()`_!'?"
block :: Parser TexTerm
block = Block <$> between (string "{") (string "}") texFile
Принимается, потому что он лучше подходит для того, что я уже сделал. Когда у меня будет больше времени, я также проверю megaparsec, как советует другой ответ – trenta3