Я пишу на простом языке, но столкнулся с проблемой в том, что арифметические выражения c не ожидают своих операторов, несмотря на то, что они определены в языке. С тех пор я вернулся к express своей программе, более простой. На данный момент единственное сложное выражение, которое у меня есть, это арифмети c. Я могу разбирать целые числа, строки, логические значения и списки. Он может распознавать такие выражения, как «5 Добавить 5», но только в форме списка «[5 Добавить 5]».
Я подозреваю, что он не анализирует, когда его нет в списке, из-за того, как анализируются атомы. Парсер атома разбирает логические, а затем произвольный атом. Если выражение arithmeti c помещается в строку, оно также будет правильно проанализировано.
Я не уверен, почему он не оценивается правильно. У меня есть функция оценки, которая имеет дело с выражениями arithmeti c, но она не работает, когда я пытаюсь передать ей аргументы через командную строку. Когда я загружаю его в GHCI, я могу использовать его отлично, поэтому я знаю, что функция оценки arithmeti c работает, но я не понимаю, почему она не выполняет оценку, когда я даю ей аргументы командной строки. Любое выражение arithmeti c дает только само выражение, а не значение, которое должно быть возвращено.
Единственная причина, по которой я могу думать, это то, что когда выражение анализируется, оно не анализируется как выражение c arithmeti, а вместо этого анализируется как список или строка.
data HenryVal = Integer Integer
| Bool Bool
| Atom String
| String String
| List [HenryVal]
| ABinOp ABinOp
| Ad HenryVal HenryVal
| ABinary ABinOp HenryVal HenryVal
data ABinOp = Add
| Subtract
| Multiply
| Divide
deriving (Show)
evalABinOp :: HenryVal -> ABinOp -> HenryVal -> HenryVal
evalABinOp (Integer a) Add (Integer b) = Integer (a +b)
evalABinOp (Integer a) Multiply (Integer b) = Integer (a * b)
evalABinOp (Integer a) Divide (Integer b) = Integer (a `div` b)
evalABinOp (Integer a) Subtract (Integer b) = Integer (a - b)
eval :: HenryVal -> HenryVal
eval val@(Atom _) = val
eval val@(String _) = val
eval val@(Integer _) = val
eval val@(Bool _) = val
eval (List [Atom "quote", val]) = val
eval val@(List _) = val
eval (ABinary op x y) = evalABinOp (eval x) op (eval y)
spaces :: Parser ()
spaces = skipMany1 space
parseString :: Parser HenryVal
parseString = do
char '"'
x <- many (noneOf "\"")
char '"'
return $ String x
parseList :: Parser HenryVal
parseList = liftM List $ sepBy parseExpr spaces
parseNumber :: Parser HenryVal
parseNumber = liftM (Integer . read) $ many1 digit
parseAtom :: Parser HenryVal
parseAtom = do
first <- letter
rest <- many (letter <|> digit)
let atom = first:rest
return $ case atom of
"True" -> Bool True
"False" -> Bool False
_ -> Atom atom
parseExpr :: Parser HenryVal
parseExpr = parseNumber <|>
parseAtom <|>
parseString <|>
do
_ <- char '['
x <- try parseList
_ <- char ']'
return x
readExpr :: String -> HenryVal
readExpr input = case parse parseExpr "Henry" input of
Left error -> String $ "No Match: " ++ show error
Right val -> val
main :: IO ()
main = getArgs >>= print . eval . readExpr . head