1. package lexers
    
  2. 
    
  3. import (
    
  4. 	"strings"
    
  5. 
    
  6. 	. "github.com/alecthomas/chroma/v2" // nolint
    
  7. )
    
  8. 
    
  9. // Restructuredtext lexer.
    
  10. var Restructuredtext = Register(MustNewLexer(
    
  11. 	&Config{
    
  12. 		Name:      "reStructuredText",
    
  13. 		Aliases:   []string{"rst", "rest", "restructuredtext"},
    
  14. 		Filenames: []string{"*.rst", "*.rest"},
    
  15. 		MimeTypes: []string{"text/x-rst", "text/prs.fallenstein.rst"},
    
  16. 	},
    
  17. 	restructuredtextRules,
    
  18. ))
    
  19. 
    
  20. func restructuredtextRules() Rules {
    
  21. 	return Rules{
    
  22. 		"root": {
    
  23. 			{"^(=+|-+|`+|:+|\\.+|\\'+|\"+|~+|\\^+|_+|\\*+|\\++|#+)([ \\t]*\\n)(.+)(\\n)(\\1)(\\n)", ByGroups(GenericHeading, Text, GenericHeading, Text, GenericHeading, Text), nil},
    
  24. 			{"^(\\S.*)(\\n)(={3,}|-{3,}|`{3,}|:{3,}|\\.{3,}|\\'{3,}|\"{3,}|~{3,}|\\^{3,}|_{3,}|\\*{3,}|\\+{3,}|#{3,})(\\n)", ByGroups(GenericHeading, Text, GenericHeading, Text), nil},
    
  25. 			{`^(\s*)([-*+])( .+\n(?:\1  .+\n)*)`, ByGroups(Text, LiteralNumber, UsingSelf("inline")), nil},
    
  26. 			{`^(\s*)([0-9#ivxlcmIVXLCM]+\.)( .+\n(?:\1  .+\n)*)`, ByGroups(Text, LiteralNumber, UsingSelf("inline")), nil},
    
  27. 			{`^(\s*)(\(?[0-9#ivxlcmIVXLCM]+\))( .+\n(?:\1  .+\n)*)`, ByGroups(Text, LiteralNumber, UsingSelf("inline")), nil},
    
  28. 			{`^(\s*)([A-Z]+\.)( .+\n(?:\1  .+\n)+)`, ByGroups(Text, LiteralNumber, UsingSelf("inline")), nil},
    
  29. 			{`^(\s*)(\(?[A-Za-z]+\))( .+\n(?:\1  .+\n)+)`, ByGroups(Text, LiteralNumber, UsingSelf("inline")), nil},
    
  30. 			{`^(\s*)(\|)( .+\n(?:\|  .+\n)*)`, ByGroups(Text, Operator, UsingSelf("inline")), nil},
    
  31. 			{`^( *\.\.)(\s*)((?:source)?code(?:-block)?)(::)([ \t]*)([^\n]+)(\n[ \t]*\n)([ \t]+)(.*)(\n)((?:(?:\8.*|)\n)+)`, EmitterFunc(rstCodeBlock), nil},
    
  32. 			{`^( *\.\.)(\s*)([\w:-]+?)(::)(?:([ \t]*)(.*))`, ByGroups(Punctuation, Text, OperatorWord, Punctuation, Text, UsingSelf("inline")), nil},
    
  33. 			{`^( *\.\.)(\s*)(_(?:[^:\\]|\\.)+:)(.*?)$`, ByGroups(Punctuation, Text, NameTag, UsingSelf("inline")), nil},
    
  34. 			{`^( *\.\.)(\s*)(\[.+\])(.*?)$`, ByGroups(Punctuation, Text, NameTag, UsingSelf("inline")), nil},
    
  35. 			{`^( *\.\.)(\s*)(\|.+\|)(\s*)([\w:-]+?)(::)(?:([ \t]*)(.*))`, ByGroups(Punctuation, Text, NameTag, Text, OperatorWord, Punctuation, Text, UsingSelf("inline")), nil},
    
  36. 			{`^ *\.\..*(\n( +.*\n|\n)+)?`, CommentPreproc, nil},
    
  37. 			{`^( *)(:[a-zA-Z-]+:)(\s*)$`, ByGroups(Text, NameClass, Text), nil},
    
  38. 			{`^( *)(:.*?:)([ \t]+)(.*?)$`, ByGroups(Text, NameClass, Text, NameFunction), nil},
    
  39. 			{`^(\S.*(?<!::)\n)((?:(?: +.*)\n)+)`, ByGroups(UsingSelf("inline"), UsingSelf("inline")), nil},
    
  40. 			{`(::)(\n[ \t]*\n)([ \t]+)(.*)(\n)((?:(?:\3.*|)\n)+)`, ByGroups(LiteralStringEscape, Text, LiteralString, LiteralString, Text, LiteralString), nil},
    
  41. 			Include("inline"),
    
  42. 		},
    
  43. 		"inline": {
    
  44. 			{`\\.`, Text, nil},
    
  45. 			{"``", LiteralString, Push("literal")},
    
  46. 			{"(`.+?)(<.+?>)(`__?)", ByGroups(LiteralString, LiteralStringInterpol, LiteralString), nil},
    
  47. 			{"`.+?`__?", LiteralString, nil},
    
  48. 			{"(`.+?`)(:[a-zA-Z0-9:-]+?:)?", ByGroups(NameVariable, NameAttribute), nil},
    
  49. 			{"(:[a-zA-Z0-9:-]+?:)(`.+?`)", ByGroups(NameAttribute, NameVariable), nil},
    
  50. 			{`\*\*.+?\*\*`, GenericStrong, nil},
    
  51. 			{`\*.+?\*`, GenericEmph, nil},
    
  52. 			{`\[.*?\]_`, LiteralString, nil},
    
  53. 			{`<.+?>`, NameTag, nil},
    
  54. 			{"[^\\\\\\n\\[*`:]+", Text, nil},
    
  55. 			{`.`, Text, nil},
    
  56. 		},
    
  57. 		"literal": {
    
  58. 			{"[^`]+", LiteralString, nil},
    
  59. 			{"``((?=$)|(?=[-/:.,; \\n\\x00\\\u2010\\\u2011\\\u2012\\\u2013\\\u2014\\\u00a0\\'\\\"\\)\\]\\}\\>\\\u2019\\\u201d\\\u00bb\\!\\?]))", LiteralString, Pop(1)},
    
  60. 			{"`", LiteralString, nil},
    
  61. 		},
    
  62. 	}
    
  63. }
    
  64. 
    
  65. func rstCodeBlock(groups []string, state *LexerState) Iterator {
    
  66. 	iterators := []Iterator{}
    
  67. 	tokens := []Token{
    
  68. 		{Punctuation, groups[1]},
    
  69. 		{Text, groups[2]},
    
  70. 		{OperatorWord, groups[3]},
    
  71. 		{Punctuation, groups[4]},
    
  72. 		{Text, groups[5]},
    
  73. 		{Keyword, groups[6]},
    
  74. 		{Text, groups[7]},
    
  75. 	}
    
  76. 	code := strings.Join(groups[8:], "")
    
  77. 	lexer := Get(groups[6])
    
  78. 	if lexer == nil {
    
  79. 		tokens = append(tokens, Token{String, code})
    
  80. 		iterators = append(iterators, Literator(tokens...))
    
  81. 	} else {
    
  82. 		sub, err := lexer.Tokenise(nil, code)
    
  83. 		if err != nil {
    
  84. 			panic(err)
    
  85. 		}
    
  86. 		iterators = append(iterators, Literator(tokens...), sub)
    
  87. 	}
    
  88. 	return Concaterator(iterators...)
    
  89. }