尝试在Haskell中构建词法分析程序
我正在开始这个项目,但进展甚微。我只是从haskell开始,所以我只想使用我自己实现的函数,这样我就能把我的大脑投入到行动中 我想要两个字符串列表,一个表示代码,另一个为给定语言保留名称。我希望能够从第一个列表中筛选出所说的单词尝试在Haskell中构建词法分析程序,haskell,Haskell,我正在开始这个项目,但进展甚微。我只是从haskell开始,所以我只想使用我自己实现的函数,这样我就能把我的大脑投入到行动中 我想要两个字符串列表,一个表示代码,另一个为给定语言保留名称。我希望能够从第一个列表中筛选出所说的单词 resNames = ["function","while","for","const","let","this","true","false",";","=", "()", "var"] findVal :: [String]->String->[St
resNames = ["function","while","for","const","let","this","true","false",";","=", "()", "var"]
findVal :: [String]->String->[String]
findVal z " " = z
findVal [] value = []
findVal (x:y) value = if x == value then findVal y value
else x:(findVal y value)
filterResNames :: [String]->[String]->[String]
filterResNames z [] = z
filterResNames [] z = []
filterResNames (x:y) (u:v) = if x== u then findVal (x:y) (u) else x:(filterResNames y (u:v))```
This obviously doesn't work because the program stops as soon as it finds a match...
如果我正确理解你的想法,这可能是一个可行的解决方案:
resNames = ["function","while","for","const","let","this","true","false",";","=", "()", "var"]
-- Determine whether an element is in a list
findVal :: String->[String]->Bool
findVal _ [] = False
findVal x (namesH:namesT) =
if x == namesH
then True
else (findVal x namesT)
-- Loop over input list and for each element, if not in reserved list, add to accumulator
filterResNamesAcc :: [String]->[String]->[String]->[String]
filterResNamesAcc _ [] acc = acc
filterResNamesAcc [] _ acc = acc
filterResNamesAcc (inH:inT) names acc =
if (findVal inH names)
then (filterResNamesAcc inT names acc)
else (filterResNamesAcc inT names (inH:acc))
-- Invoke filterResNamesAcc with empty accumulator
filterResNames :: [String]->[String]->[String]
filterResNames inL names = reverse (filterResNamesAcc inL names [])
main = do
print (filterResNames ["hello", "for", "the", "world"] resNames)
我们在这里使用的是函数式语言中使用的典型累加器模式。filterResNamesAcc
的“问题”是,使用:
预先添加到累加器会导致结果被反转,因此调用reverse
左“给读者”:
filterResNames
的签名以获取单个字符串并进行标记化最好通过手工实现来学习标准库,因此您可以:
filter
标准函数:
filter :: (a -> Bool) -> [a] -> [a]
filter _ [] = []
filter cond (x : xs) = let tail = filter cond xs
in if cond x
then x:tail
else tail
elem :: (Eq a) => a -> [a] -> Bool
elem _ [] = False
elem x (y:ys) = x == y || elem x ys
这里我们只留下这样的x
,它们具有cond x
等于True
。例如,偶数过滤[1..10]==[2,4,6,8,10]
我们将使用它只过滤掉保留字。现在我们需要构造条件。所以我们需要检查保留列表中是否有一个单词。这是标准的elem
功能:
filter :: (a -> Bool) -> [a] -> [a]
filter _ [] = []
filter cond (x : xs) = let tail = filter cond xs
in if cond x
then x:tail
else tail
elem :: (Eq a) => a -> [a] -> Bool
elem _ [] = False
elem x (y:ys) = x == y || elem x ys
在这里,我们需要这样的调用,即“您只能将其用于支持==
检查的类型”String
就是这种情况,因此您可以这样使用它:
elem "if" ["for", "if", "else", "function"] == True
现在,我们已经准备好使用我们的工具获得结果:
filterResNames :: [String] -> [String] -> [String]
filterResNames toCheck resNames = filter (`elem` resNames) toCheck
这里我们使用一些技巧:
+
或==
:
elem x lst
相当于x`elem`lst
x someOperator y
的表达式,将其括在括号中(x someOperator y)
,并省略其中一个操作数(someOperator y)
,则会自动获得一个函数,该函数将此“省略”的操作数“粘贴”到表达式中。一些例子:
-取一个值并将其增加1(+1)
-取一个值并检查它是否等于(==x)
x
-给定一些(2^)
获得n
的2次方n
-获取一个值并检查它是否包含在(`elem`someList)
someList
对不起,你有两个答案(一个是我的),你会接受其中任何一个吗?