// 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, 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, CenteringCtrlSeq, BibliographyCtrlSeq, BibliographyStyleCtrlSeq, AuthorCtrlSeq, MaketitleCtrlSeq } @external specialize {EnvName} specializeEnvName from "./tokens.mjs" { DocumentEnvName, TabularEnvName, EquationEnvName, EquationArrayEnvName, VerbatimEnvName, TikzPictureEnvName, FigureEnvName, ListEnvName } @external specialize {CtrlSym} specializeCtrlSym from "./tokens.mjs" { OpenParenCtrlSym, CloseParenCtrlSym, OpenBracketCtrlSym, CloseBracketCtrlSym } @tokens { CtrlSeq { "\\" $[a-zA-Z]+ } CtrlSym { "\\" ![a-zA-Z] } // tokens for paragraphs Whitespace { $[ \t]+ } NewLine { "\n" } BlankLine { "\n" "\n"+ } Normal { ![\\{}\[\]$&#^_% \t\n] ![\\{}\[\]$&#^_%\t\n]* } // allow ~ space in normal text @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 { "&" } 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 } 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") } // 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 } | DocumentClass { DocumentClassCtrlSeq optionalWhitespace? OptionalArgument? DocumentClassArgument { ShortTextArgument } } | BibliographyCommand { BibliographyCtrlSeq optionalWhitespace? BibliographyArgument { ShortTextArgument } } | BibliographyStyleCommand { BibliographyStyleCtrlSeq optionalWhitespace? BibliographyStyleArgument { ShortTextArgument } } | UsePackage { UsePackageCtrlSeq optionalWhitespace? OptionalArgument? PackageArgument } | HrefCommand { HrefCtrlSeq optionalWhitespace? UrlArgument ShortTextArgument } | 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 (Csname | CtrlSym) optionalWhitespace? MacroParameter* 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 optionalWhitespace? } | Maketitle { MaketitleCtrlSeq optionalWhitespace? } } UnknownCommand { (CtrlSeq !argument Whitespace (OptionalArgument | TextArgument)+) | ((CtrlSeq | MathTextCtrlSeq) (OptionalArgument | TextArgument)+) | CtrlSeq Whitespace? | CtrlSym } Command { KnownCommand | UnknownCommand } textBase { ( Command | DollarMath | BracketMath | ParenMath | NewLine | Normal | Whitespace | Ampersand ) } 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 )* } 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 | BlankLine | NewLine | Normal | Whitespace | OpenBracket | CloseBracket | "#" // macro character | Ampersand // for tables | "_" | "^" // other math chars | SectioningCommand< BookCtrlSeq | PartCtrlSeq | ChapterCtrlSeq | SectionCtrlSeq | SubSectionCtrlSeq | SubSubSectionCtrlSeq | ParagraphCtrlSeq | SubParagraphCtrlSeq > )* } KnownEnvironment { ( DocumentEnvironment | TabularEnvironment | EquationEnvironment | EquationArrayEnvironment | VerbatimEnvironment | TikzPictureEnvironment | FigureEnvironment | ListEnvironment ) } BeginEnv { Begin EnvNameGroup OptionalArgument? (!argument TextArgument)* } EndEnv { End EnvNameGroup } DocumentEnvironment[@isGroup="$Environment"] { BeginEnv Content EndEnv (TrailingWhitespaceOnly | TrailingContent)? } TabularEnvironment[@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 | Label { LabelCtrlSeq optionalWhitespace? OptionalArgument? LabelArgument } )+ } MathTextCommand { (MathTextCtrlSeq | HboxCtrlSeq) optionalWhitespace? "*"? TextArgument } MathCommand { CtrlSeq } MathCtrlSym { CtrlSym } 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 }