packages feed

uuagc-0.9.50: src-ag/SemHsTokens.ag

INCLUDE "HsToken.ag"

imports
{
import qualified Data.Sequence as Seq
import Data.Sequence(Seq,empty,singleton,(><))
import Data.Foldable(toList)
import Pretty

import TokenDef
import HsToken
import ErrorMessages
}

ATTR HsTokensRoot
     [
     | |
       errors    USE {Seq.><} {Seq.empty}:{Seq Error}
       usedLocals:{[Identifier]}
       usedAttrs :{[(Identifier,Identifier)]}
       textLines  :{[String]}
       usedFields:{[Identifier]}
     ]

-------------------------------------------------------------------------------
--  Context information
-------------------------------------------------------------------------------
ATTR HsTokensRoot
     HsTokens HsToken [ nt,con    : {Identifier}
                        allfields : {[(Identifier,Type,ChildKind)]}
                        allnts    : {[Identifier]}
                        attrs     : {[(Identifier,Identifier)]}
                        options   : {Options}
                      ||
                      ]

ATTR HsTokens HsToken [ fieldnames : {[Identifier]} | | ]
SEM HsTokensRoot
  | HsTokensRoot tokens.fieldnames = map (\(n,_,_) -> n) @lhs.allfields

-------------------------------------------------------------------------------
--  Errors
-------------------------------------------------------------------------------
ATTR HsTokens HsToken [ | |  errors USE {Seq.><} {Seq.empty}:{Seq Error}  ]

-------------------------------------------------------------------------------
-- Syntax errors
-------------------------------------------------------------------------------

SEM HsToken
  | Err lhs.errors = let m = text @mesg
                     in Seq.singleton (CustomError False @pos m)

-------------------------------------------------------------------------------
--  Undefined variables
-------------------------------------------------------------------------------

{
isNTname allnts (Just (NT nt _ _)) = nt `elem` allnts
isNTname allnts _                  = False
}


-- An AGLocal is either a local variable or a terminal
SEM HsToken
  | AGLocal   loc.tkAsLocal = AGLocal @var @pos @rdesc        -- refers to the terminal
              loc.tkAsField = AGField _LOC @var @pos @rdesc   -- refers to the (local) attribute
              loc.(errors,output,tok,usedLocals) =
                     if @var `elem` @lhs.fieldnames   -- check if @var occurs as a terminal
                     then if  isNTname @lhs.allnts (lookup @var (map (\(n,t,_) -> (n,t)) @lhs.allfields))
                          then (Seq.singleton(ChildAsLocal @lhs.nt @lhs.con @var), @loc.tkAsLocal,(@pos,fieldname @var), []    )
                          else (Seq.empty, @loc.tkAsLocal, (@pos,fieldname @var), []    )
                     else if (_LOC,@var) `elem` @lhs.attrs
                          then (Seq.empty                                      , @loc.tkAsField, (@pos,locname @lhs.options @var), [@var])
                          else (Seq.singleton(UndefLocal @lhs.nt @lhs.con @var), @loc.tkAsField, (@pos,locname @lhs.options @var), []    )

SEM HsToken
  | AGField   lhs.errors = if (@field,@attr) `elem` @lhs.attrs
                           then Seq.empty
                           else if not(@field `elem` (_LHS : _LOC: @lhs.fieldnames))
                                then Seq.singleton (UndefChild @lhs.nt @lhs.con @field)
                                else Seq.singleton (UndefAttr @lhs.nt @lhs.con @field @attr False)

-------------------------------------------------------------------------------
--         Used variables
-------------------------------------------------------------------------------

ATTR HsTokens HsToken [ | | usedLocals USE {++} {[]} : {[Identifier]}
                            usedAttrs  USE {++} {[]} : {[(Identifier,Identifier)]} ]

SEM HsToken
  | AGField (lhs.usedAttrs,lhs.usedLocals)
              = if @field == _LOC
                then ([], [@attr])
                else ([(@field,@attr)], [])


-------------------------------------------------------------------------------
--         Used fields
-------------------------------------------------------------------------------
ATTR HsTokens HsToken [ | | usedFields USE {Seq.><} {Seq.empty} : {Seq Identifier} ]

SEM HsToken
  | AGLocal lhs.usedFields = if @var `elem` @lhs.fieldnames
                              then Seq.singleton @var
                              else Seq.empty
SEM HsTokensRoot
  | HsTokensRoot lhs.usedFields = toList @tokens.usedFields

-------------------------------------------------------------------------------
--  Pretty printing
-------------------------------------------------------------------------------

SEM HsTokensRoot
  | HsTokensRoot lhs.textLines = showTokens @tokens.tks

SEM HsTokens [ || tks : {[(Pos,String)]} ]
  | Cons lhs.tks = @hd.tok : @tl.tks
  | Nil  lhs.tks = []

SEM HsToken [ || tok:{(Pos,String)}]
   | AGField
       loc.addTrace = case @rdesc of
                        Just d  -> \x -> "(trace " ++ show (d ++ " -> " ++ show @field ++ "." ++ show @attr) ++ " (" ++ x ++ "))"
                        Nothing -> id
       lhs.tok = (@pos, @loc.addTrace $ attrname @lhs.options True @field @attr)

   | HsToken lhs.tok = (@pos, @value)

   | CharToken lhs.tok = (@pos, if null @value
                                   then ""
                                   else showCharShort (head @value)
                         )

   | StrToken  lhs.tok = (@pos, showStrShort @value)
   | Err       lhs.tok = (@pos, "")

-------------------------------------------------------------------------------
--  Desugar (resolve AGLocals to explicit AGFields)
-------------------------------------------------------------------------------

ATTR HsTokensRoot [ | | output : {[HsToken]} ]
ATTR HsTokens HsToken [ | | output : SELF ]