Plan 9 from Bell Labs’s /usr/web/sources/contrib/fernan/nhc98/src/compiler98/Parse/LexPre.hs

Copyright © 2021 Plan 9 Foundation.
Distributed under the MIT License.
Download the Plan 9 distribution.


module Parse.LexPre(lexPre,PosTokenPre) where

import Char(isSpace,isDigit,isAlpha,isAlphaNum)

import Parse.Lex
import Parse.LexLow
import Parse.LexStr   -- includes: tab,lexChr
import SysDeps(PackedString,packString)
import TokenId(t_List,t_Arrow,t_Tuple)
import Util.Extra(Pos,toPos)

type PosTokenPre = (PackedString,Pos,Int,Lex)
                -- filename, position, column, lexem
                -- column is that of position start
                -- repeated here for easy access

lexPre :: Bool -> PackedString -> String -> [PosTokenPre]
lexPre u file l = iPreLex u file 1 1 l

------- local

iPreLex :: Bool -> PackedString -> Int -> Int -> String -> [PosTokenPre]
                -- filename       line   column   input
iPreLex u file r c []              = [(file,toPos r 0 r 0,0,L_EOF)]
iPreLex u file r c ('\n':xs)       = iPreLex u file (r+1) 1 xs
iPreLex u file r c ('\^M':'\n':xs) = iPreLex u file (r+1) 1 xs  -- DOS line-end
iPreLex u file r c ('\^M':xs)      = iPreLex u file (r+1) 1 xs  -- Mac line-end
iPreLex u file r c (' ':xs)        = iPreLex u file r (c+1) xs
iPreLex u file r c ('\xa0':xs)     = iPreLex u file r (c+1) xs  --  
iPreLex u file r c ('\t':xs)       = iPreLex u file r (tab c) xs
iPreLex u file r c ('-':'-':xs)
  | null munch || isSpace nextchr || nextchr `elem` ",()[]{};\"'`_"
     || isAlphaNum nextchr = skipline (iPreLex u file (r+1) 1) xs
        where
                munch = dropWhile (=='-') xs
                nextchr = head munch
                skipline :: (String->[PosTokenPre]) -> String -> [PosTokenPre]
                skipline cont [] = cont []
                skipline cont ('\n':r) = cont r
                skipline cont (_:r) = skipline cont r
iPreLex u file r c ('{':'-':'#':xs) =
                case words xs of
                  ("LINE":lineno:newfile:"#-}":_) | all isDigit lineno ->
                          case lexInteger 10 0 lineno of
                            (_,newr,_) ->
                               iPreLex u (packString newfile)
                                         (fromInteger newr) 1
                                         (tail (dropWhile (/='\n') xs))
                  ("NEED":_) ->
                          (file,toPos r c r (c+2),c,L_LANNOT) 
                          : iPreLex u file r (c+3) xs
                  ("#-}":_) ->
                          (file,toPos r c r (c+2),c,L_LANNOT) 
                           : iPreLex u file r (c+3) xs
                  (name:_) | all isDigit name ->        -- e.g. fn arity
                          (file,toPos r c r (c+2),c,L_LANNOT) 
                           : iPreLex u file r (c+3) xs
                  _ ->    skipcomment u file 0 r (c+3) xs
iPreLex u file r c ('#':'-':'}':xs) =
                (file,toPos r c r (c+2),c,L_RANNOT): iPreLex u file r (c+3) xs

iPreLex u file r c ('{':'-':xs)     = skipcomment u file 0 r (c+2) xs
iPreLex u file r c ('(':xs) | isTupleId xs =
   case span (==',') xs of
     (commas,')':xs) -> 
        case length commas of
        -- unit ()
          0 -> (file,toPos r c r (c+2),c,L_ACONID (t_Tuple 0))
               : iPreLex u file r (c+3) xs
        -- (n+1)-tuple 
          n -> (file,toPos r c r (c+n+1),c,L_ACONID (t_Tuple (n+1)))
               : iPreLex u file r (c+n+2) xs
 where
   isTupleId xs =
      case dropWhile (==',') xs of
        (')':_) -> True
        _ -> False

iPreLex u file r c ('(':'-':'>':')':xs) = 
  (file,toPos r c r (c+3),c,L_ACONID t_Arrow) : iPreLex u file r (c+4) xs
iPreLex u file r c ('(':xs) = 
  (file,toPos r c r c,c,L_LPAR) : iPreLex u file r (c+1) xs
iPreLex u file r c (')':xs) = 
  (file,toPos r c r c,c,L_RPAR) : iPreLex u file r (c+1) xs
iPreLex u file r c (',':xs) = 
  (file,toPos r c r c,c,L_COMMA) : iPreLex u file r (c+1) xs
iPreLex u file r c ('{':xs) = 
  (file,toPos r c r c,c,L_LCURL) : iPreLex u file r (c+1) xs
iPreLex u file r c ('}':xs) = 
  (file,toPos r c r c,c,L_RCURL) : iPreLex u file r (c+1) xs
iPreLex u file r c ('[':']':xs) = 
  (file,toPos r c r (c+1),c,L_ACONID t_List) : iPreLex u file r (c+2) xs
iPreLex u file r c ('[':xs) = 
  (file,toPos r c r c,c,L_LBRACK) : iPreLex u file r (c+1) xs
iPreLex u file r c (']':xs) = 
  (file,toPos r c r c,c,L_RBRACK) : iPreLex u file r (c+1) xs
iPreLex u file r c ('`':xs) = 
  (file,toPos r c r c,c,L_BACKTICK) : iPreLex u file r (c+1) xs
iPreLex u file r c (';':xs) = 
  (file,toPos r c r c,c,L_SEMI) : iPreLex u file r (c+1) xs
iPreLex u file r c ('#':xs) | c == 1 =
       case span ('\n' /=) xs of
         (line,xs) ->
            case words line of
              ("line":line:file:_) | all isDigit line ->
                case lexInteger 10 0 line of
                  (_,r,_) ->
                      iPreLex u (packString file) (fromInteger r) 1 (tail xs)
              (line:file:_) | all isDigit line ->
                case lexInteger 10 0 line of
                  (_,r,_) ->
                      iPreLex u (packString file) (fromInteger r) 1 (tail xs)
              ("pragma":_) -> iPreLex u file r c xs  -- skip verbiage
              _ -> error ("Unknown preprocessor directive at line " ++ show r
                         ++ ( case show file of {
                                "\"\"" -> [];
                                file   -> " in file " ++ file } )
                         ++ "\n" ++ line ++ "\n")
-- both lexStr, lexChr, lexId etc return c' > 1 
iPreLex u file r c ('"':xs) = 
  (file,toPos r c r' (c'-1),c,L_STRING st) : iPreLex u file r' c' xs'
        where (r',c',st,xs') = lexStr r (c+1) xs
iPreLex u file r c ('\'':xs)= 
  (file,toPos r c r' (c'-1),c,L_CHAR ch) : iPreLex u file r' c' xs'
        where (r',c',ch,xs') = lexChr r (c+1) xs

iPreLex u file r c ('_':[]) = 
  (file,toPos r c r c,c,L_Underscore) : iPreLex u file r (c+1) []
iPreLex u file r c xxs@('_':xs@(x:_)) =
  if isNhcId x
    then case lexId u r c xxs of
           (r,c',lex,xs) -> 
             (file,toPos r c r (c'-1),c,lex) : iPreLex u file r c' xs
    else (file,toPos r c r c,c,L_Underscore) : iPreLex u file r (c+1) xs
iPreLex u file r c (xs@(x:s))=
  if isLexId x
    then case lexId u r c xs of
           (r,c',lex,xs) -> 
             (file,toPos r c r (c'-1),c,lex) : iPreLex u file r c' xs
    else if isDigit x
    then case lexNum r c xs of
           (r,c',lex,xs) -> 
             (file,toPos r c r (c'-1),c,lex) : iPreLex u file r c' xs
    else (file,toPos r c r c,c,L_ERROR x) : iPreLex u file r c s




-- Auxiliary used by more than one clause of iPreLex (originally a local defn)
skipcomment :: Bool -> PackedString ->Int ->Int ->Int ->String ->[PosTokenPre]
skipcomment u file n r c xs = skip n r c xs
  where
    skip :: Int -> Int -> Int -> String -> [PosTokenPre]
    skip n r c []           = iPreLex u file r c []
    skip n r c ('-':'}':xs) = if n > 0 
                                 then skip (n-1) r (c+2) xs
                                 else iPreLex u file r (c+2) xs
    skip n r c ('{':'-':xs) = skip (n+1) r   (c+2) xs
    skip n r c ('\n':xs)    = skip n    (r+1)    1 xs
    skip n r c ('\t':xs)    = skip n     r (tab c) xs
    skip n r c (_:xs)       = skip n     r   (c+1) xs

Bell Labs OSI certified Powered by Plan 9

(Return to Plan 9 Home Page)

Copyright © 2021 Plan 9 Foundation. All Rights Reserved.
Comments to webmaster@9p.io.