package Ġtex markup Ċ Ċ import Ġjava . io . File Ċ import Ġjava . io . BufferedReader Ċ Ċ enum Ġclass ĠTag Environment Ġ{ ĊĠĠĠ Ġ// ĠA Ġtoken Ġfound Ġimmediately Ġafter Ġthe Ġ< Ġsign ĊĠĠĠ ĠTAG _ NAME , ĊĠĠĠ Ġ// ĠA Ġtoken Ġfound Ġwithin Ġthe Ġbody Ġof Ġa Ġtag Ġdeclaration , Ġeither Ġa Ġflag Ġor Ġa Ġproperty ĊĠĠĠ ĠTAG _ DECL , ĊĠĠĠ Ġ// ĠA Ġtoken Ġfound Ġwithin Ġthe Ġbody Ġof Ġa Ġtag , Ġto Ġbe Ġinterpreted Ġliter ally Ġby Ġthe ĠLaTeX Ġcompiler ĊĠĠĠ ĠL ITERAL , ĊĠĠĠ Ġ// ĠA Ġcomment . ĠShould Ġbe Ġdropped Ġafter Ġthe Ġtoken ization Ġprocess . ĊĠĠĠ ĠCOMMENT Ċ } Ċ Ċ // ĠIf Ġthe Ġend Ġof Ġa Ġline Ġis Ġa Ġback slash Ġcharacter , Ġjoins Ġthis Ġline Ġto Ġthe Ġnext Ċ private Ġfun Ġparse Line Join s ( words : ĠList < String >): ĠList < String > Ġ{ ĊĠĠĠ Ġvar Ġnew Words : ĠMutable List < String > Ġ= Ġmutable ListOf () ĊĠĠĠ Ġvar Ġi Ġ= Ġ 0 ĊĠĠĠ Ġwhile Ġ( i Ġ< Ġwords . size ) Ġ{ ĊĠĠĠĠĠĠĠ Ġvar Ġword Ġ= Ġwords [ i ] ĊĠĠĠĠĠĠĠ Ġif Ġ( word . trim (). endsWith ("\\ ") Ġ&& Ġ! word . trim (). endsWith ("\\ \ \" )) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġtry Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġnew Words . add ( word Ġ+ Ġwords [ i Ġ+ Ġ 1 ]) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġcatch ( e : ĠIndex OutOfBoundsException ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġprintln (" Illegal Ġline Ġjoin Ġcharacter Ġat Ġline Ġ$ i ") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġthrow Ġe ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġnew Words . add ( word ) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġi ++ ĊĠĠĠ Ġ} ĊĠĠĠ Ġreturn Ġnew Words Ċ } Ċ Ċ fun Ġget Words ( file : ĠFile ): ĠList < String > Ġ{ ĊĠĠĠ Ġval Ġbr Ġ= Ġfile . buffered Reader () ĊĠĠĠ Ġvar Ġtext Ġ= Ġbr . read Lines () Ġ// parse Line Join s ( br . read Lines ()) ĊĠĠĠ Ġval ĠTAG _ OPEN Ġ= Ġ'< ' ĊĠĠĠ Ġval ĠTAG _ CLOSE Ġ= Ġ' >' ĊĠĠĠ Ġvar Ġtokens : ĠMutable List < String > Ġ= Ġmutable ListOf () ĊĠĠĠ Ġvar Ġcurr Env : ĠTag Environment Ġ= ĠTag Environment . LITERAL ĊĠĠĠ Ġvar Ġtoken : ĠStringBuilder Ġ= ĠStringBuilder () ĊĠĠĠ Ġvar ĠtagName : ĠStringBuilder Ġ= ĠStringBuilder () ĊĠĠĠ Ġfun Ġadd Token () Ġ{ ĊĠĠĠĠĠĠĠ Ġif Ġ(! token . toString (). isBlank ()) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġtokens . add ( token . toString ()) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġtoken Ġ= ĠStringBuilder () ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĠĠĠ Ġfor Ġ( raw Line Ġin Ġtext ) Ġ{ ĊĠĠĠĠĠĠĠ Ġvar Ġline Ġ= Ġraw Line . trim () ĊĠĠĠĠĠĠĠ Ġreader @ Ġfor Ġ( c Ġin Ġline ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġwhen Ġ( curr Env ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠTag Environment . COMMENT Ġ-> Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġtoken . append ( c ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( c Ġ== ĠTAG _ CLOSE Ġ&& Ġtoken . endsWith ("-- " Ġ+ ĠTAG _ CLOSE )) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġtoken Ġ= ĠStringBuilder () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcurr Env Ġ= ĠTag Environment . LITERAL ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠTag Environment . TAG _ NAME , ĠTag Environment . TAG _ DECL Ġ-> Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġtoken . append ( c ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( token . toString (). trim (). startsWith ( TAG _ OPEN Ġ+ Ġ" !-- ")) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcurr Env Ġ= ĠTag Environment . COMMENT ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcontinue @ reader ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( curr Env Ġ== ĠTag Environment . TAG _ NAME ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠtagName . append ( c ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġwhen Ġ( c ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ' Ġ' Ġ-> Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcurr Env Ġ= ĠTag Environment . TAG _ DECL ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠTAG _ CLOSE Ġ-> Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcurr Env Ġ= ĠTag Environment . LITERAL ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġadd Token () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠtagName Ġ= ĠStringBuilder () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠTAG _ OPEN Ġ-> Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġthrow ĠIllegalArgumentException (" Cannot Ġnest Ġtag Ġdeclarations ") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġelse Ġ-> Ġ{} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġelse Ġ-> Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( c Ġ== ĠTAG _ OPEN ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( token . length Ġ!= Ġ 0 ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġadd Token () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠtagName Ġ= ĠStringBuilder ( TAG _ OPEN . toString ()) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcurr Env Ġ= ĠTag Environment . TAG _ NAME ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġtoken . append ( c ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĠĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġif Ġ( curr Env Ġ== ĠTag Environment . LITERAL Ġ&& Ġ! token . isBlank ()) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġtoken . append ("\ n ") ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġadd Token () ĊĠĠĠ Ġ} ĊĠĠĠ Ġreturn Ġtokens Ċ } Ċ Ċ // ĠTODO Ċ fun Ġcheck Identifier Conflict s () Ġ{ Ċ // Ġuse Ġa Ġset Ċ } Ċ Ċ val ĠTOKEN _ OPEN Ġ= ĠRegex (" (? <= < )[ ^ / ]\\ w *( ?= \\ s ? .* ?> )") Ċ val ĠTOKEN _ FLAG Ġ= ĠRegex (" (? <= Ġ) (? < != )\\ w *( ? =[ Ġ> ]) ") Ġ// Ġnote : Ġdoes Ġnot Ġcheck Ġthat Ġthe Ġstring Ġis Ġwithin Ġan Ġhtml Ġtag Ċ val ĠTOKEN _ PROPERTY _ STR Ġ= ĠRegex (" (? <= Ġ) \\ w + =[ \"\ '][ ^ \"\ '] * [\" \' ]( ?= )") Ġ// Ġsee Ġabove Ċ val ĠTOKEN _ PROPERTY Ġ= ĠRegex (" (? <= Ġ) \\ w * =[ ^\ "] \\ S *( ? =[ Ġ> ]) ") Ċ val ĠTOKEN _ CLOSE Ġ= ĠRegex (" (? <= </ )\\ w *( ?= \\ s ? .* ?> )") Ċ Ċ fun Ġwords To Tokens ( file : ĠFile ): ĠMutable List < Token > Ġ{ ĊĠĠĠ Ġval Ġtokens : ĠMutable List < Token > Ġ= Ġmutable ListOf () ĊĠĠĠ Ġval Ġwords Ġ= Ġget Words ( file ) ĊĠĠĠ Ġ// Ġcreate Ġtokens Ġfrom Ġwords ĊĠĠĠ Ġ// Ġkeeps Ġtrack Ġof Ġwhat Ġtoken Ġrequires Ġclosing , Ġwith Ġmost Ġrecent Ġon Ġthe Ġend ĊĠĠĠ Ġval Ġopen Token Stack : ĠMutable List < String > Ġ= Ġmutable ListOf () ĊĠĠĠ Ġval Ġempty Creator Ġ= Ġ{ -> ĠUnknown Tag . create (" empty ", ĠarrayOf (), Ġhash Map Of ()) } ĊĠĠĠ Ġvar Ġcreator Ġ= Ġempty Creator ĊĠĠĠ Ġvar Ġi Ġ= Ġ 0 ĊĠĠĠ Ġwhile Ġ( i Ġ< Ġwords . size ) Ġ{ ĊĠĠĠĠĠĠĠ Ġvar Ġword Ġ= Ġwords [ i ] ĊĠĠĠĠĠĠĠ Ġif Ġ( TOKEN _ OPEN . contains Match In ( word )) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġtoken Name : ĠString Ġ= ĠTOKEN _ OPEN . find ( word ) !!. value ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġflags : ĠArray < String > Ġ= ĠTOKEN _ FLAG . findAll ( word ). map Ġ{ Ġit . value Ġ}. toList (). to Typed Array () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġproperties : ĠHashMap < String , ĠString > Ġ= Ġget Properties ( word ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġcreator Ġ= Ġwhen Ġ( token Name ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġin Ġheader Tags Ġ-> Ġ{ -> ĠHeader Tag . create ( token Name )} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġin Ġempty Tags Ġ-> Ġ{ -> ĠEmpty Tag . create ( token Name , Ġflags , Ġproperties )} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġin Ġline Tags Ġ-> Ġ{ -> ĠLine Tag . create ( token Name , Ġflags , Ġproperties )} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġin Ġun closed Tags Ġ-> Ġ{ -> Ġun closed Tags [ token Name ] !! ( flags , Ġproperties )} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġin Ġalias Tags Ġ-> Ġ{ -> Ġalias Tags [ token Name ] !! ( flags , Ġproperties )} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġin Ġdefined Tags Ġ-> Ġ{ -> Ġdefined Tags [ token Name ] !! ( flags , Ġproperties )} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġelse Ġ-> Ġ{ -> ĠUnknown Tag . create ( token Name , Ġflags , Ġproperties )} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( token Name Ġ! in Ġun closed Tags ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġopen Token Stack . add ( token Name ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġtokens . add ( creator ()) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġelse Ġif Ġ( TOKEN _ CLOSE . contains Match In ( word )) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġtoken Name Ġ= ĠTOKEN _ CLOSE . find ( word ) !!. value ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ/* if Ġ( token Name Ġ!= Ġopen Token Stack . last ()) Ġ{ Ġ// Ġtoken Ġclosed Ġimpro per ly ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġthrow ĠIllegalArgumentException (" At tempted Ġto Ġclose Ġ${ open Token Stack . last ()} Ġwith Ġ$ token Name Ġon Ġword Ġ#$ i ") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ}*/ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġopen Token Stack . remove At ( open Token Stack . size Ġ- Ġ 1 ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġtokens . add ( Closing Tag ( token Name )) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġcreator Ġ= Ġempty Creator ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġvar Ġliteral : ĠMutable List < String > Ġ= Ġmutable ListOf () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġwhile Ġ( i Ġ< Ġwords . size Ġ&& Ġ! TOKEN _ OPEN . contains Match In ( words [ i ]) Ġ&& Ġ! TOKEN _ CLOSE . contains Match In ( words [ i ])) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġliteral . add ( words [ i ]) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġi ++ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġi -- ĊĠĠĠĠĠĠĠĠĠĠĠ Ġtokens . add ( Literal ( literal )) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġi ++ ĊĠĠĠ Ġ} ĊĠĠĠ Ġif Ġ( open Token Stack . size Ġ!= Ġ 0 ) Ġ{ ĊĠĠĠĠĠĠĠ Ġ// throw ĠIllegalArgumentException (" Un closed Ġtoken ( s ) Ġ${ open Token Stack . toString () }") ĊĠĠĠ Ġ} ĊĠĠĠ Ġreturn Ġtokens Ċ } Ċ Ċ fun Ġget Properties ( word : ĠString ): ĠHashMap < String , ĠString > Ġ{ ĊĠĠĠ Ġval Ġprops Ġ= ĠTOKEN _ PROPERTY . findAll ( word ) ĊĠĠĠ Ġval Ġprops Str Ġ= ĠTOKEN _ PROPERTY _ STR . findAll ( word ) ĊĠĠĠ Ġval Ġmap : ĠMutable Map < String , ĠString > Ġ= Ġmutable Map Of () ĊĠĠĠ Ġfun Ġadd ( item : ĠMatch Result ) Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġsplit Ġ= Ġitem . value . split (" =", Ġlimit = 2 ) ĊĠĠĠĠĠĠĠ Ġif Ġ( split [ 1 ]. length Ġ>= Ġ 2 ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ&& Ġ( split [ 1 ]. startsWith (' \' ') Ġ|| Ġsplit [ 1 ]. startsWith (' \" ')) Ġ&& Ġ( split [ 1 ]. endsWith (' \' ') Ġ|| Ġsplit [ 1 ]. endsWith (' \" '))) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġmap . put ( split [ 0 ], Ġsplit [ 1 ]. substring ( 1 , Ġsplit [ 1 ]. length Ġ- Ġ 1 )) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġmap . put ( split [ 0 ], Ġsplit [ 1 ]) ĊĠĠĠĠĠĠĠ Ġ} Ġ// " Ġthis Ġis Ġto Ġfix Ġsyntax Ġhighlighting ĊĠĠĠ Ġ} ĊĠĠĠ Ġfor Ġ( item Ġin Ġprops ) Ġ{ ĊĠĠĠĠĠĠĠ Ġadd ( item ) ĊĠĠĠ Ġ} ĊĠĠĠ Ġfor Ġ( item Ġin Ġprops Str ) Ġ{ ĊĠĠĠĠĠĠĠ Ġadd ( item ) ĊĠĠĠ Ġ} ĊĠĠĠ Ġreturn ĠHashMap ( map . toMap ()) Ċ } Ċ