// Track environments @context elementContext from "./tokens.mjs" // External tokens must be defined before normal @tokens to take precedence // over them. @external tokens verbTokenizer from "./tokens.mjs" { VerbContent } @external tokens lstinlineTokenizer from "./tokens.mjs" { LstInlineContent } @external tokens literalArgTokenizer from "./tokens.mjs" { LiteralArgContent } @external tokens spaceDelimitedLiteralArgTokenizer from "./tokens.mjs" { SpaceDelimitedLiteralArgContent } @external tokens verbatimTokenizer from "./tokens.mjs" { VerbatimContent } @external tokens mathDelimiterTokenizer from "./tokens.mjs" { MathDelimiter } // external tokenizer to read control sequence names including @ signs // (which are often used in TeX definitions). @external tokens csnameTokenizer from "./tokens.mjs" { Csname } @external tokens trailingContentTokenizer from "./tokens.mjs" { TrailingWhitespaceOnly, TrailingContent } // It doesn't seem to be possible to access specialized tokens in the context tracker. // They have id's which are not exported in the latex.terms.js file. // This is a workaround: use an external specializer to explicitly choose the terms // to use for the specialized tokens. @external specialize {CtrlSeq} specializeCtrlSeq from "./tokens.mjs" { Begin, End, RefCtrlSeq, RefStarrableCtrlSeq, CiteCtrlSeq, CiteStarrableCtrlSeq, LabelCtrlSeq, MathTextCtrlSeq, HboxCtrlSeq, TitleCtrlSeq, DocumentClassCtrlSeq, UsePackageCtrlSeq, HrefCtrlSeq, UrlCtrlSeq, VerbCtrlSeq, LstInlineCtrlSeq, IncludeGraphicsCtrlSeq, CaptionCtrlSeq, DefCtrlSeq, LeftCtrlSeq, RightCtrlSeq, NewCommandCtrlSeq, RenewCommandCtrlSeq, NewEnvironmentCtrlSeq, RenewEnvironmentCtrlSeq, // services/web/frontend/js/features/outline/outline-parser.js BookCtrlSeq, PartCtrlSeq, ChapterCtrlSeq, SectionCtrlSeq, SubSectionCtrlSeq, SubSubSectionCtrlSeq, ParagraphCtrlSeq, SubParagraphCtrlSeq, InputCtrlSeq, IncludeCtrlSeq, ItemCtrlSeq, NewTheoremCtrlSeq, TheoremStyleCtrlSeq, CenteringCtrlSeq, BibliographyCtrlSeq, BibliographyStyleCtrlSeq, AuthorCtrlSeq, AffilCtrlSeq, AffiliationCtrlSeq, MaketitleCtrlSeq, TextColorCtrlSeq, ColorBoxCtrlSeq, HLineCtrlSeq, TopRuleCtrlSeq, MidRuleCtrlSeq, BottomRuleCtrlSeq, MultiColumnCtrlSeq } @external specialize {EnvName} specializeEnvName from "./tokens.mjs" { DocumentEnvName, TabularEnvName, EquationEnvName, EquationArrayEnvName, VerbatimEnvName, TikzPictureEnvName, FigureEnvName, ListEnvName, TableEnvName } @external specialize {CtrlSym} specializeCtrlSym from "./tokens.mjs" { OpenParenCtrlSym, CloseParenCtrlSym, OpenBracketCtrlSym, CloseBracketCtrlSym, LineBreakCtrlSym } @tokens { CtrlSeq { "\\" $[a-zA-Z]+ } CtrlSym { "\\" ![a-zA-Z] } // tokens for paragraphs Whitespace { $[ \t]+ } NewLine { "\n" } BlankLine { "\n" "\n"+ } Normal { ![\\{}\[\]$&~#^_% \t\n] ![\\{}\[\]$&~#^_%\t\n]* } // everything is normal text, except these characters @precedence { CtrlSeq, CtrlSym, BlankLine, NewLine, Whitespace, Normal } OpenBrace[closedBy=CloseBrace] { "{" } CloseBrace[openedBy=OpenBrace] { "}" } OpenBracket[closedBy=CloseBracket] { "[" } CloseBracket[openedBy=OpenBracket] { "]" } Comment { "%" ![\n]* "\n"? } Dollar { "$" } Number { $[0-9]+ ("." $[0-9]*)? } MathSpecialChar { $[^_=<>()\-+/*]+ } // FIXME not all of these are special MathChar { ![0-9^_=<>()\-+/*\\{}\[\]\n$%&~]+ } @precedence { Number, MathSpecialChar, MathChar } Ampersand { "&" } Tilde { "~" } EnvName { $[a-zA-Z]+ $[*]? } } @top LaTeX { Text } @skip { Comment } // TEXT MODE optionalWhitespace { !argument Whitespace } OptionalArgument { !argument OpenBracket ShortOptionalArg CloseBracket } TextArgument { !argument OpenBrace LongArg CloseBrace } SectioningArgument { !argument OpenBrace LongArg CloseBrace } LabelArgument { !argument ShortTextArgument } RefArgument { !argument ShortTextArgument } BibKeyArgument { !argument ShortTextArgument } PackageArgument { !argument ShortTextArgument } TabularArgument { !argument OpenBrace TabularContent CloseBrace } UrlArgument { OpenBrace LiteralArgContent CloseBrace } FilePathArgument { OpenBrace LiteralArgContent CloseBrace } BareFilePathArgument { Whitespace SpaceDelimitedLiteralArgContent } DefinitionArgument { !argument NewLine? Whitespace* OpenBrace DefinitionFragment CloseBrace } argument[@isGroup="$Argument"] { TextArgument | SectioningArgument | LabelArgument | RefArgument | BibKeyArgument | PackageArgument | UrlArgument | FilePathArgument | BareFilePathArgument | DefinitionArgument } MacroParameter { "#" ("1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9") } OptionalMacroParameter { OpenBracket MacroParameter CloseBracket } // The autocompletion code in services/web/frontend/js/features/source-editor/utils/tree-operations/commands.ts // depends on following the `KnownCommand { Command { CommandCtrlSeq [args] } }` // structure KnownCommand { Title { TitleCtrlSeq optionalWhitespace? OptionalArgument? TextArgument } | Author { AuthorCtrlSeq optionalWhitespace? OptionalArgument? optionalWhitespace? TextArgument } | Affil { AffilCtrlSeq optionalWhitespace? OptionalArgument? optionalWhitespace? TextArgument } | Affiliation { AffiliationCtrlSeq optionalWhitespace? OptionalArgument? optionalWhitespace? TextArgument } | DocumentClass { DocumentClassCtrlSeq optionalWhitespace? OptionalArgument? DocumentClassArgument { ShortTextArgument } } | BibliographyCommand { BibliographyCtrlSeq optionalWhitespace? BibliographyArgument { ShortTextArgument } } | BibliographyStyleCommand { BibliographyStyleCtrlSeq optionalWhitespace? BibliographyStyleArgument { ShortTextArgument } } | UsePackage { UsePackageCtrlSeq optionalWhitespace? OptionalArgument? PackageArgument } | TextColorCommand { TextColorCtrlSeq optionalWhitespace? ShortTextArgument optionalWhitespace? TextArgument } | ColorBoxCommand { ColorBoxCtrlSeq optionalWhitespace? ShortTextArgument optionalWhitespace? TextArgument } | HrefCommand { HrefCtrlSeq optionalWhitespace? UrlArgument ShortTextArgument } | NewTheoremCommand { NewTheoremCtrlSeq "*"? optionalWhitespace? ShortTextArgument ((OptionalArgument? TextArgument) | (TextArgument OptionalArgument)) } | TheoremStyleCommand { TheoremStyleCtrlSeq optionalWhitespace? ShortTextArgument } | UrlCommand { UrlCtrlSeq optionalWhitespace? UrlArgument } | VerbCommand { VerbCtrlSeq VerbContent } | LstInlineCommand { LstInlineCtrlSeq optionalWhitespace? OptionalArgument? LstInlineContent } | IncludeGraphics { IncludeGraphicsCtrlSeq optionalWhitespace? OptionalArgument? IncludeGraphicsArgument { FilePathArgument } } | Caption { CaptionCtrlSeq "*"? optionalWhitespace? OptionalArgument? TextArgument } | Label { LabelCtrlSeq optionalWhitespace? LabelArgument } | Ref { (RefCtrlSeq | RefStarrableCtrlSeq "*"?) optionalWhitespace? OptionalArgument? optionalWhitespace? OptionalArgument? optionalWhitespace? RefArgument } | Cite { (CiteCtrlSeq | CiteStarrableCtrlSeq "*"?) optionalWhitespace? OptionalArgument? optionalWhitespace? OptionalArgument? optionalWhitespace? BibKeyArgument } | Def { // allow more general Csname argument to \def commands, since other symbols such as '@' are often used in definitions DefCtrlSeq optionalWhitespace? (Csname | CtrlSym) optionalWhitespace? (MacroParameter | OptionalMacroParameter)* optionalWhitespace? DefinitionArgument } | Hbox { HboxCtrlSeq optionalWhitespace? TextArgument } | Left { LeftCtrlSeq optionalWhitespace? } | Right { RightCtrlSeq optionalWhitespace? } | NewCommand { NewCommandCtrlSeq optionalWhitespace? (Csname | OpenBrace LiteralArgContent CloseBrace) (OptionalArgument)* DefinitionArgument } | RenewCommand { RenewCommandCtrlSeq optionalWhitespace? (Csname | OpenBrace LiteralArgContent CloseBrace) (OptionalArgument)* DefinitionArgument } | NewEnvironment { NewEnvironmentCtrlSeq optionalWhitespace? (OpenBrace LiteralArgContent CloseBrace) (OptionalArgument)* DefinitionArgument DefinitionArgument } | RenewEnvironment { RenewEnvironmentCtrlSeq optionalWhitespace? (Csname | OpenBrace LiteralArgContent CloseBrace) (OptionalArgument)* DefinitionArgument DefinitionArgument } | Input { InputCtrlSeq InputArgument { ( FilePathArgument | BareFilePathArgument ) } } | Include { IncludeCtrlSeq IncludeArgument { FilePathArgument } } | Centering { CenteringCtrlSeq } | Item { ItemCtrlSeq OptionalArgument? optionalWhitespace? } | Maketitle { MaketitleCtrlSeq optionalWhitespace? } | HorizontalLine { (HLineCtrlSeq | TopRuleCtrlSeq | MidRuleCtrlSeq | BottomRuleCtrlSeq) optionalWhitespace? } | MultiColumn { MultiColumnCtrlSeq optionalWhitespace? SpanArgument { ShortTextArgument } optionalWhitespace? ColumnArgument { ShortTextArgument } optionalWhitespace? TabularArgument } } UnknownCommand { (CtrlSeq !argument Whitespace (OptionalArgument | TextArgument)+) | ((CtrlSeq | MathTextCtrlSeq) (OptionalArgument | TextArgument)+) | CtrlSeq Whitespace? | CtrlSym } Command { KnownCommand | UnknownCommand | KnownCtrlSym } KnownCtrlSym { LineBreak { LineBreakCtrlSym OptionalArgument? } } textBase { ( Command | DollarMath | BracketMath | ParenMath | NewLine | Normal | Whitespace | Ampersand | Tilde ) } textWithBrackets { ( textBase | OpenBracket | CloseBracket ) } textWithEnvironmentsAndBlankLines { ( BlankLine | KnownEnvironment | Environment | textWithBrackets ) } textWithGroupsEnvironmentsAndBlankLines { textWithEnvironmentsAndBlankLines | Group } Content { Element } SectioningCommand { Command optionalWhitespace? "*"? optionalWhitespace? OptionalArgument? optionalWhitespace? SectioningArgument } documentSection { SectioningCommand Content<(sectionText | !section Next)*> } Book[@isGroup="$SectioningCommand"] { documentSection } Part[@isGroup="$SectioningCommand"] { documentSection } Chapter[@isGroup="$SectioningCommand"] { documentSection } Section[@isGroup="$SectioningCommand"] { documentSection } SubSection[@isGroup="$SectioningCommand"] { documentSection } SubSubSection[@isGroup="$SectioningCommand"] { documentSection } Paragraph[@isGroup="$SectioningCommand"] { documentSection } SubParagraph[@isGroup="$SectioningCommand"] { SectioningCommand Content } sectioningCommand { Book | Part | Chapter | Section | SubSection | SubSubSection | Paragraph | SubParagraph } sectionText { !section ( textWithGroupsEnvironmentsAndBlankLines )+ } Text { ( sectionText | sectioningCommand)+ } LongArg { ( textWithBrackets | NonEmptyGroup | KnownEnvironment | Environment | BlankLine | "#" // macro character | "_" | "^" // other math chars )* } ShortTextArgument { OpenBrace ShortArg CloseBrace } ShortArg { ( textWithBrackets | NonEmptyGroup | "#" // macro character | "_" | "^" // other math chars )* } ShortOptionalArg { ( textBase | NonEmptyGroup | "#" // macro character | "_" // underscore is used in some parameter names )* } TikzPictureContent { /// same as Text but with added allowed characters ( textWithEnvironmentsAndBlankLines | NonEmptyGroup | "#" // macro character | "_" | "^" // other math chars )+ } DefinitionFragment { ( KnownCommand | CtrlSeq optionalWhitespace? | CtrlSym | Begin | End | NonEmptyGroup | Dollar | OpenParenCtrlSym | CloseParenCtrlSym | OpenBracketCtrlSym | CloseBracketCtrlSym | KnownCtrlSym | BlankLine | NewLine | Normal | Whitespace | OpenBracket | CloseBracket | "#" // macro character | Ampersand // for tables | Tilde // unbreakable space | "_" | "^" // other math chars | SectioningCommand< BookCtrlSeq | PartCtrlSeq | ChapterCtrlSeq | SectionCtrlSeq | SubSectionCtrlSeq | SubSubSectionCtrlSeq | ParagraphCtrlSeq | SubParagraphCtrlSeq > )* } KnownEnvironment { ( DocumentEnvironment | TabularEnvironment | EquationEnvironment | EquationArrayEnvironment | VerbatimEnvironment | TikzPictureEnvironment | FigureEnvironment | ListEnvironment | TableEnvironment ) } BeginEnv { Begin EnvNameGroup OptionalArgument? (!argument TextArgument)* } EndEnv { End EnvNameGroup } DocumentEnvironment[@isGroup="$Environment"] { BeginEnv Content EndEnv (TrailingWhitespaceOnly | TrailingContent)? } TabularContent { (textWithGroupsEnvironmentsAndBlankLines)* } TabularEnvironment[@isGroup="$Environment"] { BeginEnv Content EndEnv } TableEnvironment[@isGroup="$Environment"] { BeginEnv Content EndEnv } EquationEnvironment[@isGroup="$Environment"] { BeginEnv Content EndEnv } EquationArrayEnvironment[@isGroup="$Environment"] { BeginEnv Content EndEnv } VerbatimEnvironment[@isGroup="$Environment"] { BeginEnv Content EndEnv } TikzPictureEnvironment[@isGroup="$Environment"] { BeginEnv Content EndEnv } FigureEnvironment[@isGroup="$Environment"] { BeginEnv Content EndEnv } ListEnvironment[@isGroup="$Environment"] { BeginEnv Content EndEnv } EnvNameGroup { OpenBrace name CloseBrace } Environment[@isGroup="$Environment"] { BeginEnv Content EndEnv } Group { OpenBrace GroupContent? CloseBrace } NonEmptyGroup { OpenBrace GroupContent CloseBrace } /// MATH MODE DollarMath { Dollar (InlineMath | DisplayMath) Dollar } InlineMath { Math } DisplayMath { Dollar Math? Dollar } OpenParenMath[closedBy=CloseParenMath] { OpenParenCtrlSym } CloseParenMath[openedBy=OpenParenMath] { CloseParenCtrlSym } // alternative syntax \( math \) for inline math, it is the same as $ math $ ParenMath { OpenParenMath Math? CloseParenMath } OpenBracketMath[closedBy=CloseBracketMath] { OpenBracketCtrlSym } CloseBracketMath[openedBy=OpenBracketMath] { CloseBracketCtrlSym } // alternative syntax \[ math \] for display math, it is the same as $$ math $$ BracketMath { OpenBracketMath Math? CloseBracketMath } // FIXME: we should have separate math modes for inline and display math, // because display math can contain blank lines while inline math cannot. Math { ( MathTextCommand | MathCommand | MathCtrlSym | MathGroup | MathDelimitedGroup | MathSpecialChar | Number | NewLine | KnownEnvironment | Environment | MathChar | OpenBracket | CloseBracket | Ampersand | Tilde | Label { LabelCtrlSeq optionalWhitespace? OptionalArgument? LabelArgument } | Ref { (RefCtrlSeq | RefStarrableCtrlSeq "*"?) optionalWhitespace? OptionalArgument? optionalWhitespace? OptionalArgument? optionalWhitespace? RefArgument } )+ } MathTextCommand { (MathTextCtrlSeq | HboxCtrlSeq) optionalWhitespace? "*"? TextArgument } MathCommand { CtrlSeq } MathCtrlSym { CtrlSym | KnownCtrlSym } MathGroup { OpenBrace Math? CloseBrace } MathDelimitedGroup { MathOpening Math? MathClosing } // FIXME: we have the same problem with specialize on \left,\right as the delimiters MathOpening { LeftCtrlSeq optionalWhitespace? MathDelimiter } MathClosing { RightCtrlSeq optionalWhitespace? MathDelimiter } // NOTE: precedence works differently for rules and token, in the rule // you have to give a specifier !foo which is defined in the @precedence // block here. @precedence { section @left, argument @left // make CtrlSeq arguments left associative }