module C-Constants
exports
  sorts Constant StringLiteralList
  context-free syntax
    IntLiteral   -> Constant {cons("IntConst")}
    HexLiteral   -> Constant {cons("HexConst")}
    OctLiteral   -> Constant {cons("OctConst")}
    FloatLiteral -> Constant {cons("FloatConst")}    
    CharLiteral  -> Constant {cons("CharConst")}

    %%% TODO: Why a list??
    StringLiteral+ -> StringLiteralList {cons("StringLit")}

  sorts StringLiteral CharLiteral IntLiteral HexLiteral OctLiteral FloatLiteral
        Char StringChar OctalEsc IntFlags FloatFlags
  lexical syntax
    [L]? "\"" StringChar* "\"" -> StringLiteral
    [L]? "'" Char "'"          -> CharLiteral    
    
    [1-9][0-9]*            IntFlags? -> IntLiteral
    "0"                    IntFlags? -> IntLiteral
    "0" [xX] [0-9a-fA-F]+  IntFlags? -> HexLiteral
    "0" [0-7]+             IntFlags? -> OctLiteral    
        
    "." [0-9]+ ( [eE] "-"? [0-9]+ )?        FloatFlags? -> FloatLiteral
    [0-9]+ "." [0-9]* ( [eE] "-"? [0-9]+ )? FloatFlags? -> FloatLiteral
    [0-9]+ [eE] "-"? [0-9]+                 FloatFlags? -> FloatLiteral

    ~[\\\'\n]                  -> Char
    [\\] [ntvbrfa\\\?\'\"]     -> Char
    [\\] [x] [0-9A-E] [0-9A-E] -> Char
    OctalEsc                   -> Char

    ~[\\\"\n]                  -> StringChar
    [\\] [ntvbrfa\\\?\"]       -> StringChar
    [\\] [x] [0-9A-E] [0-9A-E] -> StringChar
    OctalEsc                   -> StringChar
    
    [\\] [0-7] [0-7]? [0-7]?   -> OctalEsc
    
    [uUlL]   -> IntFlags
    [uU][lL] -> IntFlags
    
    [lLfF]   -> FloatFlags
    [lL][fF] -> FloatFlags
    
  lexical restrictions
    FloatLiteral -/- [0-9lLfF]
    IntLiteral   -/- [0-9UuLl]
    HexLiteral   -/- [0-9a-zA-F]
    OctLiteral   -/- [0-9a-zA-F]