1

我必须做一个软件来识别 C 中的令牌。我有这个代码:

*main = do
   x <- readFile "progc.c"
   let resultado = lexCmm X
   print resultado
lexCmm :: String -> [Tok]
  lexCmm X = case X of
    c:cs   | isSpace c     -> lexCmm cs
    c:cs   | isAlpha c     -> getId s
    c:cs   | isDigit c     -> getInt s
    c:d:cs | isSymb [c,d]  -> TS [c,d] : lexCmm cs
    c:cs   | isSymb [c]    -> TS [c]   : lexCmm cs
    _                      -> []  
   where
    getId s  = lx i : lexCmm cs where (i,cs) = span isIdChar s
    getInt s = TI (read i) : lexCmm cs where (i,cs) = span isDigit s
    isIdChar c = isAlpha c || isDigit c
    lx i = if isReservedWord i then TS i else TI i

  isSymb s = elem s $ words "++ -- == <= >= ++ { } = , ; + * - ( ) < >"

  isReservedWord w = elem w $ words "else if int main printInt return while"*

错误是:

file:{Hugs}\prog.hs:7 - Syntax error in input (unexpected `=')
4

2 回答 2

5

除了上面提到X的变量名使用大写的错误之外,你还有一个缩进错误,定义方程lexCmm是缩进的,但它应该从最左边的列开始。

如果您取消缩进该行

lexCmm :: String -> [Tok]
lexCmm x = case x of

以及 and 的定义isSymbisReservedWord你会得到一些其他的错误。

表达式的替代项case必须比case关键字缩进更多。

c:cs   | isAlpha c     -> getId s
c:cs   | isDigit c     -> getInt s

您使用的实体s不在范围内(因此您可能应该将 to 的参数更改lexCmms,或将这两个s更改为x.

getInt s = TI (read i) : lexCmm cs where (i,cs) = span isDigit s

强烈建议 的构造函数TI接受Tok一个Int参数,但是

lx i = if isReservedWord i then TS i else TI i

尝试将其应用于String. 你可能想要TI (read i)那里。

下面的代码,包含一个Tok类型的快速模型编译:

module Toks where

import Data.Char

data Tok
    = TS String
    | TI Int
      deriving Show

main = do
   x <- readFile "progc.c"
   let resultado = lexCmm x
   print resultado

lexCmm :: String -> [Tok]
lexCmm s = case s of       -- No indentation for function definition
            c:cs   | isSpace c     -> lexCmm cs    -- alternatives indented further
            c:cs   | isAlpha c     -> getId s      -- than the `case', all to the same level
            c:cs   | isDigit c     -> getInt s
            c:d:cs | isSymb [c,d]  -> TS [c,d] : lexCmm cs
            c:cs   | isSymb [c]    -> TS [c]   : lexCmm cs
            _                      -> []  
      where  -- `where' indented less than the `case', so that it scopes over all alternatives
        getId s  = lx i : lexCmm cs where (i,cs) = span isIdChar s
        getInt s = TI (read i) : lexCmm cs where (i,cs) = span isDigit s
        isIdChar c = isAlpha c || isDigit c
        lx i = if isReservedWord i then TS i else TI (read i)

isSymb s = elem s $ words "++ -- == <= >= ++ { } = , ; + * - ( ) < >"

isReservedWord w = elem w $ words "else if int main printInt return while"
于 2012-12-24T00:01:54.673 回答
1

Haskell 变量必须以小写字母开头。以大写字母开头的标识符被解释为类型。

大写X可能会导致您出现问题:

  lexCmm X = case X of

在这里你混合了小写和大写x

  x <- readFile "progc.c"
  let resultado = lexCmm X

用小写替换所有这些x可能会解决您的问题。

于 2012-12-23T23:52:26.510 回答