diff options
Diffstat (limited to 'source/Syntax/Concrete.hs')
| -rw-r--r-- | source/Syntax/Concrete.hs | 1032 |
1 files changed, 0 insertions, 1032 deletions
diff --git a/source/Syntax/Concrete.hs b/source/Syntax/Concrete.hs deleted file mode 100644 index 62d1f92..0000000 --- a/source/Syntax/Concrete.hs +++ /dev/null @@ -1,1032 +0,0 @@ -{-# LANGUAGE NoImplicitPrelude #-} -{-# LANGUAGE RecordWildCards #-} -{-# LANGUAGE RecursiveDo #-} - --- | Concrete syntax of the surface language. -module Syntax.Concrete where - -import Base -import Syntax.Abstract -import Syntax.Concrete.Keywords -import Syntax.Lexicon - ( Lexicon(..) - , SignatureHeadForm(..) - , concreteSignatureHeadForms - , lexiconAdjs - , splitOnVariableSlot - ) -import Syntax.Token -import Report.Location - -import Data.List.NonEmpty qualified as NonEmpty -import Data.Map.Strict qualified as Map -import Text.Earley (Grammar, Prod, (<?>), rule, satisfy, terminal) -import Syntax.Mixfix - - -grammar :: Lexicon -> Grammar r (Prod r Text (Located Token) Block) -grammar lexicon@Lexicon{..} = mdo - let patternToProd :: Pattern -> Holey (Prod r Text (Located Token) (Located Token)) - patternToProd pat = map (fmap tokenLocated) (patternToHoley pat) - makeMixfixOp item = (patternToProd (mixfixPattern item), mixfixAssoc item, \parts args -> ExprOp (mixfixLoc parts args) item args) - mixfixItems = toList (Map.elems <$> lexiconMixfixTable) - mixfixOps = map (map makeMixfixOp) mixfixItems - makeConn (pat, assoc) = (map (fmap tokenLocated) pat, assoc) - conns = map (map makeConn) lexiconConnectives - - integerWithLoc <- rule (terminal maybeIntTokenWithLoc <?> "integer") - relatorWithLoc <- rule $ asum - [ (,) <$> tokenPos (relationSymbolToken item) <*> pure item - | item <- lexiconRelationSymbols - ] <?> "relator" - relator <- rule (snd <$> relatorWithLoc) - varSymbol <- rule (terminal maybeVarToken <?> "variable") - varSymbols <- rule (commaList varSymbol) - cmd <- rule (terminal maybeCmdToken <?> "TEX command") --- --- Formulas have three levels: --- --- + Expressions: atoms or operators applied to atoms. --- + Chains: comma-lists of expressions, separated by relators. --- + Formulas: chains or connectives applied to chains. --- --- For example, the formula @x, y < z \implies x, y < z + 1@ consist of the --- connective @\implies@ applied to two chains @x, y < z@ and @x, y < z + 1@. --- In turn, the chain @x, y < z + 1@ consist of three expressions, --- @x@, @y@, and @z + 1@. Finally, @z + 1@ consist the operator @+@ --- applied to two atoms, the variable @z@ and the number literal @1@. --- --- This split is due to the different behaviour of relators compared to --- operators and connectives. Relators can chain (@x < y < z@) and allow --- lists as arguments, as in the above example. Operators and connectives --- instead have precedence and fixity. The only syntactic difference between --- an operator and a connective is the relative precedence compared to relators. --- - replaceBound <- rule $ (,) <$> varSymbol <* _in <*> expr - replaceBounds <- rule $ commaList replaceBound - comprStmt <- rule $ (StmtFormula <$> formula) <|> text stmt - - let replaceFun = (\e bounds mstmt loc -> ExprReplace loc e bounds mstmt) <$> expr <* _pipe <*> replaceBounds <*> optional (_pipe *> comprStmt) - replacePredSymbolic = (\y x xBound st loc -> ExprReplacePred loc y x xBound st) <$> varSymbol <* _pipe <*> (command "exists" *> varSymbol) <* _in <*> expr <* _dot <*> (StmtFormula <$> formula) - replacePredText = (\y x xBound st loc -> ExprReplacePred loc y x xBound st) <$> varSymbol <* _pipe <*> (begin "text" *> _exists *> beginMath *> varSymbol <* _in) <*> expr <* endMath <* _suchThat <*> stmt <* end "text" - replacePred = replacePredSymbolic <|> replacePredText - - let exprStructOpOf ann = foldr alg empty lexiconStructFun - where - alg s prod = prod <|> (uncurry ExprStructOp <$> structSymbolPos s <*> ann) - - exprStructOp <- rule (exprStructOpOf (optional (bracket expr))) - - let bracedArgs1 ar arg = count1 ar $ group arg - let prefixPredicateOf f arg symb@(PrefixPredicate c ar) = f <$> pure symb <* command c <*> bracedArgs1 ar arg - - - exprParen <- rule $ paren expr - exprInteger <- rule $ uncurry ExprInteger <$> integerWithLoc - exprVar <- rule $ ExprVar <$> varSymbol - exprTuple <- rule do - loc <- tokenPos ParenL - es <- commaList2 expr <* token ParenR - pure (makeTuple loc es) - exprSep <- rule do - loc <- tokenPos VisibleBraceL - x <- varSymbol <* _in - bound <- expr <* _pipe - phi <- comprStmt <* token VisibleBraceR - pure (ExprSep loc x bound phi) - exprReplace <- rule do - (\loc mk -> mk loc) <$> tokenPos VisibleBraceL <*> (replaceFun <|> replacePred) <* token VisibleBraceR - exprFinSet <- rule do - loc <- tokenPos VisibleBraceL - es <- exprs <* token VisibleBraceR - pure (ExprFiniteSet loc es) - exprBase <- rule $ asum [exprVar, exprInteger, exprStructOp, exprParen, exprTuple, exprSep, exprReplace, exprFinSet] - exprApp <- rule $ (\e1 e2 -> ExprApp (locate e1) e1 e2) <$> exprBase <*> (paren expr <|> exprTuple) - expr <- mixfixExpressionSeparate mixfixOps (exprBase <|> exprApp) - exprs <- rule $ commaList expr - - relationSign <- rule $ pure Positive <|> (Negative <$ command "not") - relationExpr <- rule $ RelationExpr <$> command "mathrel" <*> group expr - relation <- rule $ (uncurry Relation <$> relatorWithLoc <*> many (group expr)) <|> relationExpr - chainBase <- rule $ (\es sign rel es' -> ChainBase es sign rel es') <$> exprs <*> relationSign <*> relation <*> exprs - chainCons <- rule $ (\es sign rel ch -> ChainCons es sign rel ch) <$> exprs <*> relationSign <*> relation <*> chain - chain <- rule $ chainCons <|> chainBase - - formulaPredicate <- rule $ asum - [ (\loc es -> FormulaPredicate loc symb marker es) <$> command c <*> bracedArgs1 ar expr - | (symb@(PrefixPredicate c ar), marker) <- lexiconPrefixPredicates - ] - formulaChain <- rule $ FormulaChain <$> chain - formulaBottom <- rule $ PropositionalConstant <$> command "bot" <*> pure IsBottom <?> "\"\\bot\"" - formulaTop <- rule $ PropositionalConstant <$> command "top" <*> pure IsTop <?> "\"\\top\"" - formulaExists <- rule $ FormulaQuantified <$> command "exists" <*> pure Existentially <*> varSymbols <*> maybeBounded <* _dot <*> formula - formulaAll <- rule $ FormulaQuantified <$> command "forall" <*> pure Universally <*> varSymbols <*> maybeBounded <* _dot <*> formula - formulaQuantified <- rule $ formulaExists <|> formulaAll - formulaBase <- rule $ asum [formulaChain, formulaPredicate, formulaBottom, formulaTop, paren formula] - formulaConn <- mixfixExpression conns formulaBase makeConnective - formula <- rule $ formulaQuantified <|> formulaConn - --- These are asymmetric formulas (only variables are allowed on one side). --- They express judgements. --- - assignment <- rule $ (,) <$> varSymbol <* (_eq <|> _defeq) <*> expr - typing <- rule $ (,) <$> varSymbols <* (_in <|> _colon) <*> expr - - adjL <- rule $ adjLOf lexicon term - adjR <- rule $ adjROf lexicon term - adj <- rule $ adjOf lexicon term - adjVar <- rule $ adjOf lexicon var - - var <- rule $ math varSymbol - vars <- rule $ math varSymbols - - verb <- rule $ verbOf lexicon sg term - verbPl <- rule $ verbOf lexicon pl term - verbVar <- rule $ verbOf lexicon sg var - - let nounTrieSg = nounTrieOf sg lexiconNouns - nounTriePl = nounTrieOf pl lexiconNouns - structNounTrieSg = nounTrieOf sg lexiconStructNouns - - noun <- rule $ nounOfTrie nounTrieSg term nounName -- Noun with optional variable name. - nounList <- rule $ nounOfTrie nounTrieSg term nounNames -- Noun with a list of names. - nounVar <- rule $ fst <$> nounOfTrie nounTrieSg var (pure Nameless) -- No names in defined nouns. - nounPl <- rule $ nounOfTrie nounTriePl term nounNames - nounPlMay <- rule $ nounOfTrie nounTriePl term nounName - - - structNoun <- rule $ structNounOfTrie structNounTrieSg var var - structNounNameless <- rule $ fst <$> structNounOfTrie structNounTrieSg var (pure Nameless) - - - fun <- rule $ funOf lexicon sg term - funVar <- rule $ funOf lexicon sg var - - attrRThat <- rule $ AttrRThat <$> thatVerbPhrase - attrRThats <- rule $ ((:[]) <$> attrRThat) <|> ((\a a' -> [a,a']) <$> attrRThat <* _and <*> attrRThat) <|> pure [] - attrRs <- rule $ ((:[]) <$> adjR) <|> ((\a a' -> [a,a']) <$> adjR <* _and <*> adjR) <|> pure [] - attrRight <- rule $ (<>) <$> attrRs <*> attrRThats - - verbPhraseVerbSg <- rule $ VPVerb <$> verb - verbPhraseVerbNotSg <- rule $ VPVerbNot <$> (_does *> _not *> verbPl) - verbPhraseAdjSg <- rule $ VPAdj . (:|[]) <$> (_is *> adj) - verbPhraseAdjAnd <- rule do {_is; a1 <- adj; _and; a2 <- adj; pure (VPAdj (a1 :| [a2]))} - verbPhraseAdjNotSg <- rule $ VPAdjNot . (:|[]) <$> (_is *> _not *> adj) - verbPhraseNotSg <- rule $ verbPhraseVerbNotSg <|> verbPhraseAdjNotSg - verbPhraseSg <- rule $ verbPhraseVerbSg <|> verbPhraseAdjSg <|> verbPhraseAdjAnd <|> verbPhraseNotSg - - -- LATER can cause technical ambiguities? verbPhraseVerbPl <- rule $ VPVerb <$> verbPl - verbPhraseVerbNotPl <- rule $ VPVerbNot <$> (_do *> _not *> verbPl) - verbPhraseAdjPl <- rule $ VPAdj . (:|[]) <$> (_are *> adj) - verbPhraseAdjNotPl <- rule $ VPAdjNot . (:|[]) <$> (_are *> _not *> adj) - verbPhraseNotPl <- rule $ verbPhraseVerbNotPl <|> verbPhraseAdjNotPl - verbPhrasePl <- rule $ verbPhraseAdjPl <|> verbPhraseNotPl -- LATER <|> verbPhraseVerbPl - - - - thatVerbPhrase <- rule $ _that *> verbPhraseSg - - nounName <- rule $ optional (math varSymbol) - nounNames <- rule $ math (commaList_ varSymbol) <|> pure [] - nounPhrase <- rule $ makeNounPhrase <$> many adjL <*> noun <*> attrRight <*> optional suchStmt - nounPhrase' <- rule $ makeNounPhrase <$> many adjL <*> nounList <*> attrRight <*> optional suchStmt - nounPhrasePl <- rule $ makeNounPhrase <$> many adjL <*> nounPl <*> attrRight <*> optional suchStmt - nounPhrasePlMay <- rule $ makeNounPhrase <$> many adjL <*> nounPlMay <*> attrRight <*> optional suchStmt - nounPhraseMay <- rule $ makeNounPhrase <$> many adjL <*> noun <*> attrRight <*> optional suchStmt - - -- Quantification phrases for quantification and indfinite terms. - quantAll <- rule $ QuantPhrase Universally <$> (_forEvery *> nounPhrase' <|> _forAll *> nounPhrasePl) - quantSome <- rule $ QuantPhrase Existentially <$> (_some *> (nounPhrase' <|> nounPhrasePl)) - quantNone <- rule $ QuantPhrase Nonexistentially <$> (_no *> (nounPhrase' <|> nounPhrasePl)) - quant <- rule $ quantAll <|> quantSome <|> quantNone -- <|> quantUniq - - - termExpr <- rule $ math do - e <- expr - pure (TermExpr e) - termFun <- rule $ TermFun <$> (optional _the *> fun) - termIota <- rule $ TermIota <$> _the <*> var <* _suchThat <*> stmt - termAll <- rule $ TermQuantified Universally <$> _every <*> nounPhraseMay - termSome <- rule $ TermQuantified Existentially <$> _some <*> nounPhraseMay - termNo <- rule $ TermQuantified Nonexistentially <$> _no <*> nounPhraseMay - termQuantified <- rule $ termAll <|> termSome <|> termNo - term <- rule $ termExpr <|> termFun <|> termQuantified <|> termIota - --- Basic statements @stmt'@ are statements without any conjunctions or quantifiers. --- - let singletonTerm = (:| []) <$> term - nonemptyTerms = andList1 term - stmtVerbSg <- rule $ StmtVerbPhrase <$> singletonTerm <*> verbPhraseSg - stmtVerbPl <-rule $ StmtVerbPhrase <$> andList1 term <*> verbPhrasePl - stmtVerb <- rule $ stmtVerbSg <|> stmtVerbPl - stmtNounIs <- rule do - ts <- singletonTerm - np <- _is *> _an *> nounPhrase - pure (StmtNoun ts np) - stmtNounAre <- rule do - ts <- nonemptyTerms <* _are - np <- nounPhrasePlMay - pure (StmtNoun ts np) - stmtNounIsNot <- rule do - ts <- singletonTerm - np <- _is *> _not *> _an *> nounPhrase - pure let t :| _ = ts in (StmtNeg (locate t) (StmtNoun ts np)) - stmtNounAreNot <- rule do - ts <- nonemptyTerms - np <- _are *> _not *> nounPhrasePlMay - pure let t :| _ = ts in (StmtNeg (locate t) (StmtNoun ts np)) - stmtNoun <- rule $ stmtNounIs <|> stmtNounIsNot <|> stmtNounAre <|> stmtNounAreNot - stmtStruct <- rule do - t <- term - s <- _is *> _an *> structNounNameless - pure (StmtStruct t s) - stmtExists <- rule $ StmtExists <$> _exists <*> (_an *> nounPhrase') - stmtExist <- rule $ StmtExists <$> _exist <*> nounPhrasePl - stmtExistsNot <- rule do - p <- _exists *> _no - np <- nounPhrase' - pure (StmtNeg p (StmtExists p np)) - stmtFormula <- rule $ math do - phi <- formula - pure (StmtFormula phi) - stmtFormualNeg <- rule do - loc <- _not - phi <- math formula - pure (StmtNeg loc (StmtFormula phi)) - stmtAtom <- rule $ - stmtVerb - <|> stmtNoun - <|> stmtStruct - <|> stmtFormula - <|> stmtFormualNeg - <|> paren stmt - - -- Textual connectives use the same precedence and associativity as - -- symbolic connectives. Prefix negation and quantifiers scope over the - -- complete statement that follows them. - let connect conn lhs rhs = - StmtConnected conn Nothing lhs rhs - appendScoped conn lhs rhs scoped = - let connected = foldl' (connect conn) lhs rhs - in maybe connected (connect conn connected) scoped - stmtAnd <- rule do - lhs <- stmtAtom - rhs <- many (_and *> stmtAtom) - scoped <- optional (_and *> stmtScoped) - pure (appendScoped Conjunction lhs rhs scoped) - stmtXor <- rule $ - StmtConnected ExclusiveOr - <$> (Just <$> _either) - <*> stmtAnd - <* _or - <*> stmtAnd - stmtNor <- rule $ - StmtConnected NegatedDisjunction - <$> (Just <$> _neither) - <*> stmtAnd - <* _nor - <*> stmtAnd - stmtOrBase <- rule $ stmtXor <|> stmtNor <|> stmtAnd - stmtOr <- rule do - lhs <- stmtOrBase - rhs <- many (_or *> stmtOrBase) - scoped <- optional (_or *> stmtScoped) - pure (appendScoped Disjunction lhs rhs scoped) - stmtIf <- rule $ - StmtConnected Implication - <$> (Just <$> _if) - <*> stmtIfAntecedent - <* optional _comma - <* _then - <*> stmtImpRhs - stmtImp <- rule $ stmtIf <|> stmtOr - stmtIff <- rule do - lhs <- stmtImp - rhs <- optional (_iff *> stmtImpRhs) - pure case rhs of - Nothing -> lhs - Just rhs' -> connect Equivalence lhs rhs' - stmtNeg <- rule $ StmtNeg <$> _itIsWrong <*> stmt - - stmtQuantPhrase <- rule $ StmtQuantPhrase <$> _for <*> quant <* optional _comma <* optional _have <*> stmt - - suchStmt <- rule $ _suchThat *> stmt <* optional _comma - - -- Symbolic quantifications with or without generalized bounds. - symbolicForall <- rule do - p <- _forAll <|> _forEvery - xs <- beginMath *> varSymbols - b <- maybeBounded <* endMath - ms <- optional suchStmt - s <- optional _have *> stmt - pure (SymbolicForall p xs b ms s) - symbolicExists <- rule do - loc1 <- _exists <|> _exist - xs <- beginMath *> varSymbols - b <- maybeBounded - loc2 <- endMath - ms <- optional (_suchThat *> stmt) - pure (SymbolicExists loc1 xs b (ms ?? StmtFormula (PropositionalConstant loc2 IsTop))) - symbolicNotExists <- rule do - p <- _exists *> _no - xs <- beginMath *> varSymbols - b <- maybeBounded <* endMath - s <- _suchThat *> stmt - pure (makeSymbolicNotExists p xs b s) - symbolicBound <- rule $ (\sign rel e -> Bounded (locate rel) sign rel e) <$> relationSign <*> relation <*> expr - maybeBounded <- rule (pure Unbounded <|> symbolicBound) - - symbolicQuantified <- rule $ symbolicForall <|> symbolicExists <|> symbolicNotExists - - stmtScoped <- rule $ - asum - [ stmtNeg - , stmtExists - , stmtExist - , stmtExistsNot - , stmtQuantPhrase - , symbolicQuantified - ] - stmtIfAntecedent <- rule $ stmtScoped <|> stmtOr - stmtImpRhs <- rule $ stmtScoped <|> stmtImp - stmt :: Prod r Text (Located Token) Stmt <- rule $ - (stmtScoped <|> stmtIff) <?> "a statement" - - - asmLetIn <- rule $ uncurry AsmLetIn <$> (_let *> math typing) - asmLetNoun <- rule $ AsmLetNoun <$> (_let *> fmap pure var <* (_be <|> _denote) <* _an) <*> nounPhrase - asmLetNouns <- rule $ AsmLetNoun <$> (_let *> vars <* (_be <|> _denote)) <*> nounPhrasePlMay - asmLetEq <- rule $ uncurry AsmLetEq <$> (_let *> math assignment) - asmLetThe <- rule $ AsmLetThe <$> (_let *> var <* _be <* _the) <*> fun - asmLetStruct <- rule $ AsmLetStruct <$> (_let *> var <* _be <* _an) <*> structNounNameless - asmLet <- rule $ asmLetNoun <|> asmLetNouns <|> asmLetIn <|> asmLetEq <|> asmLetThe <|> asmLetStruct - asmSuppose <- rule $ AsmSuppose <$> (_suppose *> stmt) - asm <- rule $ andList1_ (asmLet <|> asmSuppose) <* _dot - asms <- rule $ concat <$> many asm - - axiom <- rule $ Axiom <$> asms <* optional _then <*> stmt <* _dot - - claim <- rule $ (,) <$> asms <* optional _then <*> stmt <* _dot - - defnAdj <- rule $ DefnAdj <$> optional (_an *> nounPhrase) <*> var <* _is <*> adjVar - defnVerb <- rule $ DefnVerb <$> optional (_an *> nounPhrase) <*> var <*> verbVar - defnNoun <- rule $ DefnNoun <$> var <* _is <* _an <*> nounVar - defnRel <- rule $ DefnRel <$> (beginMath *> varSymbol) <*> relator <*> many (group varSymbol) <*> varSymbol <* endMath - defnSymbolicPredicate <- rule $ math $ asum $ do - (predi, marker) <- lexiconPrefixPredicates - pure (prefixPredicateOf (\predi' args -> DefnSymbolicPredicate predi' marker args) varSymbol predi) - defnHead <- rule $ optional _write *> asum [defnAdj, defnVerb, defnNoun, defnRel, defnSymbolicPredicate] - - defnIf <- rule $ Defn <$> asms <*> defnHead <* (_iff <|> _if) <*> stmt <* _dot - defnFunSymb <- rule $ _comma *> termExpr <* _comma -- Optional symbolic equivalent. - defnFun <- rule $ DefnFun <$> asms <*> (optional _the *> funVar) <*> optional defnFunSymb <* _is <*> term <* _dot - - symbolicPatternEqTerm <- rule do - pat <- beginMath *> symbolicPattern <* _eq - e <- expr <* endMath <* _dot - pure (pat, e) - defnOp <- rule $ uncurry DefnOp <$> symbolicPatternEqTerm - - defn <- rule $ defnIf <|> defnFun <|> defnOp - - abbreviationVerb <- rule $ AbbreviationVerb <$> var <*> verbVar <* (_iff <|> _if) <*> stmt <* _dot - abbreviationAdj <- rule $ AbbreviationAdj <$> var <* _is <*> adjVar <* (_iff <|> _if) <*> stmt <* _dot - abbreviationNoun <- rule $ AbbreviationNoun <$> var <* _is <* _an <*> nounVar <* (_iff <|> _if) <*> stmt <* _dot - abbreviationRel <- rule $ AbbreviationRel <$> (beginMath *> varSymbol) <*> relator <*> many (group varSymbol) <*> varSymbol <* endMath <* (_iff <|> _if) <*> stmt <* _dot - abbreviationFun <- rule $ AbbreviationFun <$> (_the *> funVar) <* (_is <|> _denotes) <*> term <* _dot - abbreviationEq <- rule $ uncurry AbbreviationEq <$> symbolicPatternEqTerm - abbreviation <- rule $ (abbreviationVerb <|> abbreviationAdj <|> abbreviationNoun <|> abbreviationRel <|> abbreviationFun <|> abbreviationEq) - - datatypePremise <- rule $ math $ (,) <$> varSymbol <* _in <*> expr - datatypeClause <- rule $ - (\(constructorExpr, targetExpr) premises -> DatatypeClause - { datatypeClauseConstructorExpr = constructorExpr - , datatypeClauseTargetExpr = targetExpr - , datatypeClausePremises = premises ?? [] - }) <$> math ((,) <$> expr <* _in <*> expr) - <*> optional (_for *> andList1_ datatypePremise) - <* _dot - datatypeHead <- rule $ _define *> math expr <* optional _inductively <* optional _asFollows <* _dot - datatype <- rule $ Datatype <$> datatypeHead <*> enumerated1 datatypeClause - - unconditionalIntro <- rule $ IntroRule [] <$> math formula - conditionalIntro <- rule $ IntroRule <$> (_if *> andList1_ (math formula)) <* _comma <* _then <*> math formula - inductiveIntro <- rule $ (unconditionalIntro <|> conditionalIntro) <* _dot - inductiveDomain <- rule $ math $ (,) <$> symbolicPattern <* _subseteq <*> expr - inductiveHead <- rule $ _define *> inductiveDomain <* optional _inductively <* optional _asFollows <* _dot - inductive <- rule $ uncurry Inductive <$> inductiveHead <*> enumerated1 inductiveIntro - - signatureAdj <- rule $ SignatureAdj <$> var <* _can <* _be <*> adjOf lexicon var - symbolicPattern <- symbolicPatternOf mixfixItems varSymbol - signatureSymbolic <- rule $ SignatureSymbolic <$> math symbolicPattern <* _is <* _an <*> nounPhrase - signatureHead <- rule $ asum - [ case form of - AdjectiveSignatureHead -> signatureAdj - SymbolicSignatureHead -> signatureSymbolic - | form <- concreteSignatureHeadForms - ] - signature <- rule $ - (,) <$> asms <* optional _then <*> signatureHead <* _dot - - structFix <- rule do - beginMath - rawCmd <- cmd - endMath - pure (StructSymbol rawCmd) - structDefn <- rule $ do - _an - ~(structPhrase, structLabel) <- structNoun - _extends - structParents <- andList1_ (_an *> structNounNameless) - maybeFixes <- optional (_equipped *> enumerated structFix) - structAssumes <- (_suchThat *> enumeratedMarked (stmt <* _dot)) <|> ([] <$ _dot) - pure StructDefn - { structPhrase = structPhrase - , structLabel = structLabel - , structParents = structParents - , structFixes = maybeFixes ?? [] - , structAssumes = structAssumes - } - - justificationSet <- rule $ JustificationSetExt <$ _bySetExt - justificationRef <- rule $ JustificationRef <$> (_by *> ref) - justificationLocal <- rule $ JustificationLocal <$ (_by *> (_assumption <|> _definition)) - justification <- rule (justificationSet <|> justificationRef <|> justificationLocal <|> pure JustificationEmpty) - - trivial <- rule $ Qed . Just <$> _trivial <* _dot <*> pure JustificationEmpty - omitted <- rule $ Omitted <$> _omitted <* _dot - qedJustified <- rule $ Qed . Just <$> _follows <*> (justification <* _dot) - qed <- rule $ qedJustified <|> trivial <|> omitted <|> pure (Qed Nothing JustificationEmpty) - contradiction <- rule $ Contradiction <$> _contradiction <*> justification <* _dot - - let alignedEq = symbol "&=" <?> "\"&=\"" - explanation <- rule $ (text justification) <|> pure JustificationEmpty - equationItem <- rule $ (,) <$> (alignedEq *> expr) <*> explanation - equations <- rule $ Equation <$> expr <*> (many1 equationItem) - - let alignedIff = symbol "&" *> command "iff" <?> "\"&\\iff\"" - biconditionalItem <- rule $ (,) <$> (alignedIff *> formula) <*> explanation - biconditionals <- rule $ Biconditionals <$> formula <*> (many1 biconditionalItem) <* optional _dot - - - calcQuantifier <- rule do - loc <- _forAll <|> _forEvery - xs <- beginMath *> varSymbols - mb <- maybeBounded <* endMath - st <- optional suchStmt - optional _have - pure (loc, CalcQuantifier xs mb st) - - calc <- rule do - mquant <- optional calcQuantifier - psteps <- align (equations <|> biconditionals) - pf <- proof - pure let (loc2, steps) = psteps in case mquant of - Nothing -> Calc loc2 Nothing steps pf - Just (loc, q) -> Calc loc (Just q) steps pf - - caseOf <- rule $ command "caseOf" *> token InvisibleBraceL *> stmt <* _dot <* token InvisibleBraceR - byCases <- rule $ uncurry ByCase <$> envPos_ "byCase" (many1_ (Case <$> caseOf <*> proof)) - byContradiction <- rule $ ByContradiction <$> _suppose <* _not <* _dot <*> proof - bySetInduction <- rule $ uncurry BySetInduction <$> proofBy (_in *> word "-induction" *> optional (word "on" *> term)) <*> proof - byOrdInduction <- rule $ ByOrdInduction . fst <$> proofBy (word "transfinite" *> word "induction") <*> proof - assume <- rule $ Assume <$> _suppose <*> (stmt <* _dot) <*> proof - - fixSymbolic <- rule $ FixSymbolic <$> _fix <*> (beginMath *> varSymbols) <*> maybeBounded <* endMath <* _dot <*> proof - fixSuchThat <- rule $ FixSuchThat <$> _fix <*> math varSymbols <* _suchThat <*> stmt <* _dot <*> proof - fix <- rule $ fixSymbolic <|> fixSuchThat - - takeVar <- rule $ TakeVar <$> _take <*> (beginMath *> varSymbols) <*> maybeBounded <* endMath <* _suchThat <*> stmt <*> justification <* _dot <*> proof - takeNoun <- rule $ TakeNoun <$> _take <*> (_an *> (nounPhrase' <|> nounPhrasePl)) <*> justification <* _dot <*> proof - take <- rule $ takeVar <|> takeNoun - suffices <- rule $ Suffices <$> _sufficesThat <*> stmt <*> (justification <* _dot) <*> proof - subclaim <- rule $ Subclaim <$> _show <*> (stmt <* _dot) <*> env_ "subproof" proof <*> proof - have <- rule do - msince <- optional ((,) <$> _since <*> stmt <* _comma <* _have) - mpos <- optional _haveIntro - s <- stmt - j <- justification <* _dot - pf <- proof - pure - let pos = case (msince, mpos) of - (Just (p, _), _) -> p - (_, Just p) -> p - _ -> locate s - in (Have pos (snd <$> msince) s j pf) - - - define <- rule $ Define <$> _let <*> (beginMath *> varSymbol <* _eq) <*> expr <* endMath <* _dot <*> proof - defineFunction <- rule $ DefineFunction <$> _let <*> (beginMath *> varSymbol) <*> paren varSymbol <* _eq <*> expr <* endMath <* _for <* beginMath <*> varSymbol <* _in <*> expr <* endMath <* _dot <*> proof - - proof <- rule $ asum [byContradiction, byCases, bySetInduction, byOrdInduction, calc, subclaim, assume, fix, take, have, suffices, define, defineFunction, contradiction, qed] - - - blockAxiom <- rule $ (\(p, title, m, a) -> BlockAxiom p title m a) <$> envPos "axiom" axiom - blockClaim <- rule $ claimEnv claim - blockProof <- rule $ uncurry3 BlockProof <$> envStartEndLocation "proof" proof - blockDefn <- rule $ (\(p, title, m, d) -> BlockDefn p title m d) <$> envPos "definition" defn - blockAbbr <- rule $ (\(p, title, m, a) -> BlockAbbr p title m a) <$> envPos "abbreviation" abbreviation - blockData <- rule $ (\(p, title, m, d) -> BlockData p title m d) <$> envPos "datatype" datatype - blockInd <- rule $ (\(p, title, m, i) -> BlockInductive p title m i) <$> envPos "inductive" inductive - blockSig <- rule $ (\(p, title, m, (a, s)) -> BlockSig p title m a s) <$> envPos "signature" signature - blockStruct <- rule $ (\(p, title, m, s) -> BlockStruct p title m s) <$> envPos "struct" structDefn - block <- rule $ asum [blockAxiom, blockClaim, blockDefn, blockAbbr, blockData, blockInd, blockSig, blockStruct, blockProof] - - -- Starting category. - pure block - - -proofBy :: Prod r Text (Located Token) a -> Prod r Text (Located Token) (Location, a) -proofBy method = bracket do - pos <- word "proof" *> word "by" - a <- method - pure (pos, a) - -claimEnv :: Prod r Text (Located Token) (([Asm], Stmt)) -> Prod r Text (Located Token) Block -claimEnv content = asum - [ make Theorem <$> envPos "theorem" content - , make Lemma <$> envPos "lemma" content - , make Corollary <$> envPos "corollary" content - , make PlainClaim <$> envPos "claim" content - , make Proposition <$> envPos "proposition" content - ] - where - make kind = (\ (loc, title, m, (asms, stmt)) -> BlockClaim kind loc title m (Claim asms stmt)) - --- | A disjunctive list with at least two items: --- * 'a or b' --- * 'a, b, or c' --- * 'a, b, c, or d' --- -orList2 :: Prod r Text (Located Token) a -> Prod r Text (Located Token) (NonEmpty a) -orList2 item = ((:|) <$> item <*> many (_commaOr *> item)) - <|> ((\i j -> i:|[j]) <$> item <* _or <*> item) - - --- | Nonempty textual lists of the form "a, b, c, and d". --- The final comma is mandatory, 'and' is not. --- Also allows "a and b". Should therefore be avoided in contexts where --- a logical conjunction would also be possible. --- Currently also allows additional 'and's after each comma... --- -andList1 :: Prod r Text (Located Token) a -> Prod r Text (Located Token) (NonEmpty a) -andList1 item = ((:|) <$> item <*> many (_commaAnd *> item)) - <|> ((\i j -> i:|[j]) <$> item <* _and <*> item) - --- | Like 'andList1', but drops the information about nonemptiness. -andList1_ :: Prod r Text (Located Token) a -> Prod r Text (Located Token) [a] -andList1_ item = NonEmpty.toList <$> andList1 item - - -commaList :: Prod r Text (Located Token) a -> Prod r Text (Located Token) (NonEmpty a) -commaList item = (:|) <$> item <*> many (_comma *> item) - --- | Like 'commaList', but drops the information about nonemptiness. -commaList_ :: Prod r Text (Located Token) a -> Prod r Text (Located Token) [a] -commaList_ item = NonEmpty.toList <$> commaList item - --- | Like 'commaList', but requires at least two items (and hence at least one comma). -commaList2 :: Prod r Text (Located Token) a -> Prod r Text (Located Token) (NonEmpty a) -commaList2 item = (:|) <$> item <* _comma <*> commaList_ item - - -enumerated :: Prod r Text (Located Token) a -> Prod r Text (Located Token) [a] -enumerated p = NonEmpty.toList <$> enumerated1 p - -enumerated1 :: Prod r Text (Located Token) a -> Prod r Text (Located Token) (NonEmpty a) -enumerated1 p = begin "enumerate" *> many1 (command "item" *> p) <* end "enumerate" <?> "\"\\begin{enumerate} ...\"" - - -enumeratedMarked :: Prod r Text (Located Token) a -> Prod r Text (Located Token) [(Marker, a)] -enumeratedMarked p = NonEmpty.toList <$> enumeratedMarked1 p - -enumeratedMarked1 :: Prod r Text (Located Token) a -> Prod r Text (Located Token) (NonEmpty (Marker, a)) -enumeratedMarked1 p = begin "enumerate" *> many1 ((,) <$> (command "item" *> label) <*> p) <* end "enumerate" <?> "\"\\begin{enumerate}\\item\\label{...}...\"" - - - --- This function could be rewritten, so that it can be used directly in the grammar, --- instead of with specialized variants. --- -phraseOf - :: forall pat a b r. Locatable a - => (Location -> pat -> [a] -> b) - -> Lexicon - -> (Lexicon -> [pat]) - -> (pat -> LexicalPhrase) - -> Prod r Text (Located Token) a - -> Prod r Text (Located Token) b -phraseOf constr lexicon selector proj arg = - uncurry3 constr <$> buildPhraseTrie arg trie - where - pats :: [pat] - pats = selector lexicon - - trie :: Trie PhraseStep pat - trie = trieFromList - [ (phraseSteps (proj pat), pat) - | pat <- pats - ] - -adjLOf :: Locatable arg => Lexicon -> Prod r Text (Located Token) arg -> Prod r Text (Located Token) (AdjLOf arg) -adjLOf lexicon arg = phraseOf AdjL lexicon lexiconAdjLs lexicalItemPhrase arg <?> "a left adjective" - -adjROf :: Locatable arg =>Lexicon -> Prod r Text (Located Token) arg -> Prod r Text (Located Token) (AdjROf arg) -adjROf lexicon arg = phraseOf AdjR lexicon lexiconAdjRs lexicalItemPhrase arg <?> "a right adjective" - -adjOf :: Locatable arg =>Lexicon -> Prod r Text (Located Token) arg -> Prod r Text (Located Token) (AdjOf arg) -adjOf lexicon arg = phraseOf Adj lexicon lexiconAdjs lexicalItemPhrase arg <?> "an adjective" - -verbOf - :: Locatable a => Lexicon - -> (SgPl LexicalPhrase -> LexicalPhrase) - -> Prod r Text (Located Token) a - -> Prod r Text (Located Token) (VerbOf a) -verbOf lexicon proj arg = phraseOf Verb lexicon lexiconVerbs (proj . lexicalItemSgPlPhrase) arg - -funOf - :: Locatable a => Lexicon - -> (SgPl LexicalPhrase -> LexicalPhrase) - -> Prod r Text (Located Token) a - -> Prod r Text (Located Token) (FunOf a) -funOf lexicon proj arg = phraseOf Fun lexicon lexiconFuns (proj . lexicalItemSgPlPhrase) arg <?> "functional phrase" - - --- | A noun with a @t VarSymbol@ as name(s). -nounOf - :: Locatable arg => Lexicon - -> (SgPl LexicalPhrase -> LexicalPhrase) - -> Prod r Text (Located Token) arg - -> Prod r Text (Located Token) (t VarSymbol) - -> Prod r Text (Located Token) (NounOf arg, t VarSymbol) -nounOf lexicon proj arg vars = - nounOfTrie (nounTrieOf proj (lexiconNouns lexicon)) arg vars - -nounOfTrie - :: Locatable arg => Trie NounStep LexicalItemSgPl - -> Prod r Text (Located Token) arg - -> Prod r Text (Located Token) (t VarSymbol) - -> Prod r Text (Located Token) (NounOf arg, t VarSymbol) -nounOfTrie trie arg vars = - (\(loc, pat, args, xs) -> (Noun loc pat args, xs)) - <$> buildNounTrie arg vars trie - <?> "a noun" - -nounTrieOf - :: (SgPl LexicalPhrase -> LexicalPhrase) - -> [LexicalItemSgPl] - -> Trie NounStep LexicalItemSgPl -nounTrieOf proj pats = trieFromList - [ (nounStepsWithSlot (proj (lexicalItemSgPlPhrase pat)), pat) - | pat <- pats - ] - -structNounOfTrie - :: Locatable arg => Trie NounStep LexicalItemSgPl - -> Prod r Text (Located Token) arg - -> Prod r Text (Located Token) name - -> Prod r Text (Located Token) (StructPhrase, name) -structNounOfTrie trie arg name = - (\(_loc, pat, _args, xs) -> (pat, xs)) - <$> buildNounTrie arg name trie - <?> "a structure noun" - -structNounOf - :: Locatable arg => Lexicon - -> (SgPl LexicalPhrase -> LexicalPhrase) - -> Prod r Text (Located Token) arg - -> Prod r Text (Located Token) name - -> Prod r Text (Located Token) (StructPhrase, name) -structNounOf lexicon proj arg name = - structNounOfTrie (nounTrieOf proj (lexiconStructNouns lexicon)) arg name - --- Trie helpers for lexically-defined phrases. - -data PhraseStep - = PhraseTok Token - | PhraseHole - deriving (Eq, Ord) - -data NounStep - = NounTok Token - | NounHole - | NounVar - deriving (Eq, Ord) - -data Trie k v = Trie - { trieValues :: [v] - , trieEdges :: [(k, Trie k v)] - } - -emptyTrie :: Trie k v -emptyTrie = Trie [] [] - -insertTrie :: Eq k => [k] -> v -> Trie k v -> Trie k v -insertTrie [] v Trie{trieValues = vs, trieEdges = es} = - Trie (vs <> [v]) es -insertTrie (k:ks) v Trie{trieValues = vs, trieEdges = es} = - Trie vs (go es) - where - go = \case - [] -> [(k, insertTrie ks v emptyTrie)] - (k', child) : rest - | k == k' -> (k', insertTrie ks v child) : rest - | otherwise -> (k', child) : go rest - -trieFromList :: Eq k => [([k], v)] -> Trie k v -trieFromList = foldl' (\tr (k, v) -> insertTrie k v tr) emptyTrie - -phraseSteps :: LexicalPhrase -> [PhraseStep] -phraseSteps = map \case - Just tok -> PhraseTok tok - Nothing -> PhraseHole - -nounSteps :: LexicalPhrase -> [NounStep] -nounSteps = map \case - Just tok -> NounTok tok - Nothing -> NounHole - -nounStepsWithSlot :: LexicalPhrase -> [NounStep] -nounStepsWithSlot pat = - let (pat1, pat2) = splitOnVariableSlot pat - in nounSteps pat1 <> [NounVar] <> nounSteps pat2 - -data PhraseAcc a = PhraseAcc - { phraseLoc :: Maybe Location - , phraseArgs :: [a] -> [a] - } - -emptyPhraseAcc :: PhraseAcc a -emptyPhraseAcc = PhraseAcc Nothing id - -setPhraseLoc :: Location -> PhraseAcc a -> PhraseAcc a -setPhraseLoc Nowhere acc = acc -setPhraseLoc _loc acc@PhraseAcc{phraseLoc = Just _} = acc -setPhraseLoc loc PhraseAcc{phraseLoc = Nothing, phraseArgs = args} = - PhraseAcc (Just loc) args - -addPhraseArg :: Locatable a => a -> PhraseAcc a -> PhraseAcc a -addPhraseArg a acc@PhraseAcc{phraseLoc = loc, phraseArgs = args} - | locate a == Nowhere = acc{phraseArgs = args . (a :)} - | otherwise = PhraseAcc (loc <|> Just (locate a)) (args . (a :)) - -finalizePhraseAcc :: PhraseAcc a -> (Location, [a]) -finalizePhraseAcc PhraseAcc{phraseLoc = Just loc, phraseArgs = args} = - (loc, args []) -finalizePhraseAcc PhraseAcc{phraseLoc = Nothing} = - impossible "phraseOf: empty phrase" - -data NounAcc a name = NounAcc - { nounLoc :: Maybe Location - , nounArgs :: [a] -> [a] - , nounName :: Maybe name - } - -emptyNounAcc :: NounAcc a name -emptyNounAcc = NounAcc Nothing id Nothing - -setNounLoc :: Location -> NounAcc a name -> NounAcc a name -setNounLoc Nowhere acc = acc -setNounLoc _loc acc@NounAcc{nounLoc = Just _} = acc -setNounLoc loc NounAcc{nounLoc = Nothing, nounArgs = args, nounName = name} = - NounAcc (Just loc) args name - -addNounArg :: Locatable a => a -> NounAcc a name -> NounAcc a name -addNounArg a acc@NounAcc{nounLoc = loc, nounArgs = args, nounName = name} - | locate a == Nowhere = acc{nounArgs = args . (a :)} - | otherwise = NounAcc (loc <|> Just (locate a)) (args . (a :)) name - -setNounName :: name -> NounAcc a name -> NounAcc a name -setNounName name NounAcc{nounLoc = loc, nounArgs = args, nounName = Nothing} = - NounAcc loc args (Just name) -setNounName _ acc@NounAcc{nounName = Just _} = acc - -finalizeNounAcc :: NounAcc a name -> (Location, [a], name) -finalizeNounAcc NounAcc{nounLoc = Just loc, nounArgs = args, nounName = Just name} = - (loc, args [], name) -finalizeNounAcc NounAcc{nounName = Nothing} = - impossible "nounOf: missing variable slot" -finalizeNounAcc NounAcc{nounLoc = Nothing} = - impossible "nounOf: empty noun phrase" - -buildPhraseTrie - :: Locatable a - => Prod r Text (Located Token) a - -> Trie PhraseStep pat - -> Prod r Text (Located Token) (Location, pat, [a]) -buildPhraseTrie arg trie = - let stepParser = \case - PhraseTok tok -> setPhraseLoc <$> tokenPos tok - PhraseHole -> addPhraseArg <$> arg - finish f = - let (acc, pat) = f emptyPhraseAcc - (loc, args) = finalizePhraseAcc acc - in (loc, pat, args) - in finish <$> buildTrieProd stepParser trie - -buildTrieProd - :: (step -> Prod r Text (Located Token) (acc -> acc)) - -> Trie step pat - -> Prod r Text (Located Token) (acc -> (acc, pat)) -buildTrieProd stepParser = go - where - go Trie{trieValues = pats, trieEdges = edges} = - let leafs = asum [pure (\acc -> (acc, pat)) | pat <- pats] - edgesProds = asum - [ liftA2 (\f g -> g . f) (stepParser step) (go sub) - | (step, sub) <- edges - ] - in leafs <|> edgesProds - -buildNounTrie - :: Locatable a - => Prod r Text (Located Token) a - -> Prod r Text (Located Token) name - -> Trie NounStep pat - -> Prod r Text (Located Token) (Location, pat, [a], name) -buildNounTrie arg vars trie = - let stepParser = \case - NounTok tok -> setNounLoc <$> tokenPos tok - NounHole -> addNounArg <$> arg - NounVar -> setNounName <$> vars - finish f = - let (acc, pat) = f emptyNounAcc - (loc, args, name) = finalizeNounAcc acc - in (loc, pat, args, name) - in finish <$> buildTrieProd stepParser trie - - -symbolicPatternOf - :: forall r. [[MixfixItem]] - -> Prod r Text (Located Token) VarSymbol - -> Grammar r (Prod r Text (Located Token) SymbolPattern) -symbolicPatternOf ops varSymbol = rule $ - (tuplePattern <|> asum - [ go item - | ops' <- ops - , item <- ops' - ]) <?> "a symbolic pattern" - where - tuplePattern = do - token ParenL - first <- varSymbol <* token (Symbol ",") - second <- varSymbol <* token ParenR - pure (SymbolPattern PairSymbol [first, second]) - - go :: MixfixItem -> Prod r Text (Located Token) SymbolPattern - go item = SymbolPattern item <$> parseVars (mixfixPattern item) - - parseVars :: Pattern -> Prod r Text (Located Token) [VarSymbol] - parseVars = \case - End -> pure [] - TokenCons tok pat -> token tok *> parseVars pat - HoleCons pat -> (:) <$> varSymbol <*> parseVars pat - - -makeNounPhrase - :: [AdjL] - -> (Noun, t VarSymbol) - -> [AdjR] - -> Maybe Stmt - -> NounPhrase t -makeNounPhrase ls (n, vs) rs ms = NounPhrase ls n vs rs ms - - - - -begin, end :: Text -> Prod r Text (Located Token) Location -begin kind = tokenPos (BeginEnv kind) <?> ("\"\\begin{" <> kind <> "}\"") -end kind = tokenPos (EndEnv kind) <?> ("\"\\end{" <> kind <> "}\"") - --- | Surround a production rule @body@ with an environment of a certain @kind@ requiring a marker specified in a @\\label@. -envPos :: Text -> Prod r Text (Located Token) a -> Prod r Text (Located Token) (Location, Maybe [Token], Marker, a) -envPos kind body = do - p <- begin kind <?> ("start of a \"" <> kind <> "\" environment") - mt <- optional title - m <- label - a <- body <* end kind - pure (p, mt, m, a) - where - title :: Prod r Text (Located Token) [Token] - title = bracket (many (unLocated <$> satisfy (\ltok -> unLocated ltok /= BracketR))) - --- 'env_' is like 'env', but without allowing titles. --- -envPos_ :: Text -> Prod r Text (Located Token) a -> Prod r Text (Located Token) (Location, a) -envPos_ kind body = (,) <$> begin kind <*> (optional label *> body) <* end kind - -envStartEndLocation :: Text -> Prod r Text (Located Token) a -> Prod r Text (Located Token) (Location, a, Location) -envStartEndLocation kind body = (,,) <$> begin kind <*> (optional label *> body) <*> end kind - -env_ :: Text -> Prod r Text (Located Token) a -> Prod r Text (Located Token) a -env_ kind body = begin kind *> optional label *> body <* end kind - --- | A label specifying a marker for referencing via /@\\label{...}@/. Returns the marker text. -label :: Prod r Text (Located Token) Marker -label = label_ <?> "\"\\label{...}\"" - where - label_ = terminal \ltok -> case unLocated ltok of - Label m -> Just (Marker m) - _tok -> Nothing - --- | A reference via /@\\ref{...}@/. Returns the markers as text. -ref :: Prod r Text (Located Token) (NonEmpty Marker) -ref = terminal \ltok -> case unLocated ltok of - Ref ms -> Just (Marker <$> ms) - _tok -> Nothing - -math :: Prod r Text (Located Token) a -> Prod r Text (Located Token) a -math body = beginMath *> body <* endMath - -mathPos :: Prod r Text (Located Token) a -> Prod r Text (Located Token) (Location, a) -mathPos body = (,) <$> beginMath <*> body <* endMath - -text :: Prod r Text (Located Token) a -> Prod r Text (Located Token) a -text body = begin "text" *> body <* end "text" <?> "\"\\text{...}\"" - -beginMath, endMath :: Prod r Text (Located Token) Location -beginMath = begin "math" <?> "start of a formula, e.g. \"$\"" -endMath = end "math" <?> "end of a formula, e.g. \"$\"" - -paren :: Prod r Text (Located Token) a -> Prod r Text (Located Token) a -paren body = token ParenL *> body <* token ParenR <?> "\"(...)\"" - -bracket :: Prod r Text (Located Token) a -> Prod r Text (Located Token) a -bracket body = token BracketL *> body <* token BracketR <?> "\"[...]\"" - -brace :: Prod r Text (Located Token) a -> Prod r Text (Located Token) a -brace body = token VisibleBraceL *> body <* token VisibleBraceR <?> "\"\\{...\\}\"" - -group :: Prod r Text (Located Token) a -> Prod r Text (Located Token) a -group body = token InvisibleBraceL *> body <* token InvisibleBraceR <?> "\"{...}\"" - -align :: Prod r Text (Located Token) a -> Prod r Text (Located Token) (Location, a) -align body = (,) <$> begin "align*" <*> body <* end "align*" - -cases :: Prod r Text (Located Token) a -> Prod r Text (Located Token) a -cases body = begin "cases" *> body <* end "cases" - - -maybeVarToken :: Located Token -> Maybe VarSymbol -maybeVarToken ltok = case unLocated ltok of - Variable x -> Just (NamedVarAt (startPos ltok) x) - _tok -> Nothing - -maybeWordToken :: Located Token -> Maybe Text -maybeWordToken ltok = case unLocated ltok of - Word n -> Just n - _tok -> Nothing - -maybeIntToken :: Located Token -> Maybe Int -maybeIntToken ltok = case unLocated ltok of - Integer n -> Just n - _tok -> Nothing - -maybeIntTokenWithLoc :: Located Token -> Maybe (Location, Int) -maybeIntTokenWithLoc ltok = case unLocated ltok of - Integer n -> Just (startPos ltok, n) - _tok -> Nothing - -maybeCmdToken :: Located Token -> Maybe Text -maybeCmdToken ltok = case unLocated ltok of - Command n -> Just n - _tok -> Nothing - -structSymbol :: StructSymbol -> Prod r Text (Located Token) StructSymbol -structSymbol s@(StructSymbol c) = terminal \ltok -> case unLocated ltok of - Command c' | c == c' -> Just s - _ -> Nothing - -structSymbolPos :: StructSymbol -> Prod r Text (Located Token) (Location, StructSymbol) -structSymbolPos s@(StructSymbol c) = terminal \ltok -> case unLocated ltok of - Command c' | c == c' -> Just (startPos ltok, s) - _ -> Nothing - --- | Tokens that are allowed to appear in labels of environments. -maybeTagToken :: Located Token -> Maybe Text -maybeTagToken ltok = case unLocated ltok of - Symbol "'" ->Just "'" - Symbol "-" -> Just "" - _ -> maybeWordToken ltok - - -token :: Token -> Prod r Text (Located Token) Token -token tok = terminal maybeToken <?> tokToText tok - where - maybeToken ltok = case unLocated ltok of - tok' | tok == tok' -> Just tok - _ -> Nothing - -tokenLocated :: Token -> Prod r Text (Located Token) (Located Token) -tokenLocated tok = terminal maybeToken <?> tokToText tok - where - maybeToken ltok = case unLocated ltok of - tok' | tok == tok' -> Just ltok - _ -> Nothing - -tokenPos :: Token -> Prod r Text (Located Token) Location -tokenPos tok = terminal maybeToken <?> tokToText tok - where - maybeToken ltok = case unLocated ltok of - tok' | tok == tok' -> Just (startPos ltok) - _ -> Nothing |
