module Language.JS.Operators where
import qualified Text.Parsec.Expr as P
import qualified Text.Parsec as P
import Language.JS.Types
import Language.JS.Common
opNotFollowedBy op p = keywordB op <* P.notFollowedBy p
table :: P.Stream s m Char => Bool -> P.ParsecT s u m Expression -> [[P.Operator s u m Expression]]
table withComma exp' = [[ P.Postfix (UnaryUpdate <$> keywordB "++" <*> pure False )
, P.Postfix (UnaryUpdate <$> keywordB "--" <*> pure False )]
,[ P.Prefix (Unary <$> P.try (opNotFollowedBy "!" (P.char '=')) )
, P.Prefix (Unary <$> keywordB "~" )
, P.Prefix (Unary <$> P.try (opNotFollowedBy "+" (P.oneOf "+=")) )
, P.Prefix (Unary <$> P.try (opNotFollowedBy "-" (P.oneOf "-=")) )
, P.Prefix (UnaryUpdate <$> keywordB "++" <*> pure True )
, P.Prefix (UnaryUpdate <$> keywordB "--" <*> pure True )
, P.Prefix (Unary <$> keywordB "typeof" )
, P.Prefix (Unary <$> keywordB "void" )
, P.Prefix (Unary <$> keywordB "delete" )
, P.Prefix (Unary <$> keywordB "await" )]
,[ P.Infix (Operation <$> P.try (opNotFollowedBy "**" (P.char '=')) ) P.AssocRight]
,[ P.Infix (Operation <$> P.try (opNotFollowedBy "*" (P.oneOf "*=")) ) P.AssocLeft
, P.Infix (Operation <$> P.try (opNotFollowedBy "/" (P.oneOf "*=")) ) P.AssocLeft
, P.Infix (Operation <$> P.try (opNotFollowedBy "%" (P.oneOf "/=")) ) P.AssocLeft]
,[ P.Infix (Operation <$> P.try (opNotFollowedBy "+" (P.oneOf "+=")) ) P.AssocLeft
, P.Infix (Operation <$> P.try (opNotFollowedBy "-" (P.oneOf "-=")) ) P.AssocLeft]
,[ P.Infix (Operation <$> P.try (opNotFollowedBy "<<" (P.oneOf "=")) ) P.AssocLeft
, P.Infix (Operation <$> P.try (opNotFollowedBy ">>" (P.oneOf ">=")) ) P.AssocLeft
, P.Infix (Operation <$> P.try (opNotFollowedBy ">>>" (P.char '=')) ) P.AssocLeft]
,[ P.Infix (Operation <$> P.try (opNotFollowedBy "<" (P.oneOf "<=")) ) P.AssocLeft
, P.Infix (Operation <$> keywordB "<=" ) P.AssocLeft
, P.Infix (Operation <$> P.try (opNotFollowedBy ">" (P.oneOf ">=")) ) P.AssocLeft
, P.Infix (Operation <$> keywordB ">=" ) P.AssocLeft
, P.Infix (Operation <$> P.try (opNotFollowedBy "in" (P.char 's')) ) P.AssocLeft
, P.Infix (Operation <$> keywordB "instanceof" ) P.AssocLeft]
,[ P.Infix (Operation <$> P.try (opNotFollowedBy "==" (P.char '=')) ) P.AssocLeft
, P.Infix (Operation <$> P.try (opNotFollowedBy "!=" (P.char '=')) ) P.AssocLeft
, P.Infix (Operation <$> keywordB "===" ) P.AssocLeft
, P.Infix (Operation <$> keywordB "!==" ) P.AssocLeft]
,[ P.Infix (Operation <$> P.try (opNotFollowedBy "&" (P.oneOf "&=")) ) P.AssocLeft]
,[ P.Infix (Operation <$> keywordB "^" ) P.AssocLeft]
,[ P.Infix (Operation <$> P.try (opNotFollowedBy "|" (P.oneOf "|=")) ) P.AssocLeft]
,[ P.Infix (Operation <$> P.try (opNotFollowedBy "&&" (P.char '=')) ) P.AssocLeft]
,[ P.Infix (Operation <$> keywordB "||" ) P.AssocLeft]
,[ P.Infix (flip Condition <$> (keywordB "?" *> lexeme exp' <* keywordB ":")) P.AssocNone]
,[ P.Infix (Assignment <$> P.try (opNotFollowedBy "=" (P.oneOf ">=")) ) P.AssocRight
, P.Infix (Assignment <$> keywordB "+=" ) P.AssocRight
, P.Infix (Assignment <$> keywordB "-=" ) P.AssocRight
, P.Infix (Assignment <$> keywordB "**=" ) P.AssocRight
, P.Infix (Assignment <$> keywordB "*=" ) P.AssocRight
, P.Infix (Assignment <$> keywordB "/=" ) P.AssocRight
, P.Infix (Assignment <$> keywordB "%=" ) P.AssocRight
, P.Infix (Assignment <$> keywordB "<<=" ) P.AssocRight
, P.Infix (Assignment <$> keywordB ">>=" ) P.AssocRight
, P.Infix (Assignment <$> keywordB ">>>=" ) P.AssocRight
, P.Infix (Assignment <$> keywordB "&=" ) P.AssocRight
, P.Infix (Assignment <$> keywordB "^=" ) P.AssocRight
, P.Infix (Assignment <$> keywordB "|=" ) P.AssocRight]
,[ P.Prefix (Unary <$> keywordB "yield" )]
,if withComma then ([ P.Infix (Comma <$ keywordB ",") P.AssocLeft]) else []
]
operationExp withComma exp' p = P.buildExpressionParser (table withComma exp') (lexeme p) P.<?> "[operations]"