sortOps :: Show a => PrecEnv -> SrcLoc -> Ops a -> Ops a
sortOps precs loc input = out where
  (out, []) = parse minPrec Nothing toks
  parse p Nothing (Left l : rest) =
    parse p (Just (OpAtom l)) rest
  parse p (Just l) mid@(Right (o,p') : rest) =
    case orderPrec p p' of
        NonFix -> err o
        LeftFix -> (l, mid)
        RightFix -> parse p (Just $ OpBin o l r) rest' where
          (r, rest') = parse p' Nothing rest
  parse p Nothing (Right (o,p') : rest) =
    parse p (Just (OpUn o r)) rest'
    where
      (r, rest') = parse (max p' p) Nothing rest
  parse _ (Just l) [] = (l, [])
  parse _ _ _ = error "parseOps"
  toks = map (fmap (\o -> (o, prec o))) $ otoks input []
  otoks (OpAtom a) t = Left a : t
  otoks (OpUn o r) t = Right o : otoks r t
  otoks (OpBin o l r) t = otoks l (Right o : otoks r t)
  prec o = fromMaybe defaultPrec $ Map.lookup o precs
  err o = parseError loc $ "ambiguous operator expression involving" <+> quoted o
sortOps :: Show a => PrecEnv -> SrcLoc -> Ops a -> Ops a
sortOps precs loc input = out where
  (out, []) = parse minPrec Nothing toks
  parse p Nothing (Left l : rest) =
    parse p (Just (OpAtom l)) rest
  parse p (Just l) mid@(Right (o,p') : rest) =
    case orderPrec p p' of
        NonFix -> err o
        LeftFix -> (l, mid)
        RightFix -> parse p (Just $ OpBin o l r) rest' where
          (r, rest') = parse p' Nothing rest
  parse p Nothing (Right (o,p') : rest) =
    parse p (Just (OpUn o r)) rest'
    where
      (r, rest') = parse (max p' p) Nothing rest
  parse _ (Just l) [] = (l, [])
  parse _ _ _ = error "parseOps"
  toks = map (fmap (\o -> (o, prec o))) $ otoks input []
  otoks (OpAtom a) t = Left a : t
  otoks (OpUn o r) t = Right o : otoks r t
  otoks (OpBin o l r) t = otoks l (Right o : otoks r t)
  prec o = fromMaybe defaultPrec $ Map.lookup o precs
  err o = parseError loc $ "ambiguous operator expression involving" <+> quoted o
sortOps precs loc input = out where
  (out, []) = parse minPrec Nothing toks
  parse p Nothing (Left l : rest) =
    parse p (Just (OpAtom l)) rest
  parse p (Just l) mid@(Right (o,p') : rest) =
    case orderPrec p p' of
        NonFix -> err o
        LeftFix -> (l, mid)
        RightFix -> parse p (Just $ OpBin o l r) rest' where
          (r, rest') = parse p' Nothing rest
  parse p Nothing (Right (o,p') : rest) =
    parse p (Just (OpUn o r)) rest'
    where
      (r, rest') = parse (max p' p) Nothing rest
  parse _ (Just l) [] = (l, [])
  parse _ _ _ = error "parseOps"
  toks = map (fmap (\o -> (o, prec o))) $ otoks input []
  otoks (OpAtom a) t = Left a : t
  otoks (OpUn o r) t = Right o : otoks r t
  otoks (OpBin o l r) t = otoks l (Right o : otoks r t)
  prec o = fromMaybe defaultPrec $ Map.lookup o precs
  err o = parseError loc $ "ambiguous operator expression involving" <+> quoted o