ul4.py 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267
  1. """
  2. pygments.lexers.ul4
  3. ~~~~~~~~~~~~~~~~~~~
  4. Lexer for the UL4 templating language.
  5. More information: https://python.livinglogic.de/UL4.html
  6. :copyright: Copyright 2006-2023 by the Pygments team, see AUTHORS.
  7. :license: BSD, see LICENSE for details.
  8. """
  9. import re
  10. from pygments.lexer import RegexLexer, DelegatingLexer, bygroups, words, include
  11. from pygments.token import Comment, Text, Keyword, String, Number, Literal, \
  12. Name, Other, Operator
  13. from pygments.lexers.web import HtmlLexer, XmlLexer, CssLexer, JavascriptLexer
  14. from pygments.lexers.python import PythonLexer
  15. __all__ = ['UL4Lexer', 'HTMLUL4Lexer', 'XMLUL4Lexer', 'CSSUL4Lexer',
  16. 'JavascriptUL4Lexer', 'PythonUL4Lexer']
  17. class UL4Lexer(RegexLexer):
  18. """
  19. Generic lexer for UL4.
  20. .. versionadded:: 2.12
  21. """
  22. flags = re.MULTILINE | re.DOTALL
  23. name = 'UL4'
  24. aliases = ['ul4']
  25. filenames = ['*.ul4']
  26. tokens = {
  27. "root": [
  28. (
  29. # Template header without name:
  30. # ``<?ul4?>``
  31. r"(<\?)(\s*)(ul4)(\s*)(\?>)",
  32. bygroups(Comment.Preproc, Text.Whitespace, Keyword,
  33. Text.Whitespace, Comment.Preproc),
  34. ),
  35. (
  36. # Template header with name (potentially followed by the signature):
  37. # ``<?ul4 foo(bar=42)?>``
  38. r"(<\?)(\s*)(ul4)(\s*)([a-zA-Z_][a-zA-Z_0-9]*)?",
  39. bygroups(Comment.Preproc, Text.Whitespace, Keyword,
  40. Text.Whitespace, Name.Function),
  41. "ul4", # Switch to "expression" mode
  42. ),
  43. (
  44. # Comment:
  45. # ``<?note foobar?>``
  46. r"<\?\s*note\s.*?\?>",
  47. Comment,
  48. ),
  49. (
  50. # Template documentation:
  51. # ``<?doc foobar?>``
  52. r"<\?\s*doc\s.*?\?>",
  53. String.Doc,
  54. ),
  55. (
  56. # ``<?ignore?>`` tag for commenting out code:
  57. # ``<?ignore?>...<?end ignore?>``
  58. r"<\?\s*ignore\s*\?>",
  59. Comment,
  60. "ignore", # Switch to "ignore" mode
  61. ),
  62. (
  63. # ``<?def?>`` tag for defining local templates
  64. # ``<?def foo(bar=42)?>...<?end def?>``
  65. r"(<\?)(\s*)(def)(\s*)([a-zA-Z_][a-zA-Z_0-9]*)?",
  66. bygroups(Comment.Preproc, Text.Whitespace, Keyword,
  67. Text.Whitespace, Name.Function),
  68. "ul4", # Switch to "expression" mode
  69. ),
  70. (
  71. # The rest of the supported tags
  72. r"(<\?)(\s*)(printx|print|for|if|elif|else|while|code|renderblocks?|render)\b",
  73. bygroups(Comment.Preproc, Text.Whitespace, Keyword),
  74. "ul4", # Switch to "expression" mode
  75. ),
  76. (
  77. # ``<?end?>`` tag for ending ``<?def?>``, ``<?for?>``,
  78. # ``<?if?>``, ``<?while?>``, ``<?renderblock?>`` and
  79. # ``<?renderblocks?>`` blocks.
  80. r"(<\?)(\s*)(end)\b",
  81. bygroups(Comment.Preproc, Text.Whitespace, Keyword),
  82. "end", # Switch to "end tag" mode
  83. ),
  84. (
  85. # ``<?whitespace?>`` tag for configuring whitespace handlng
  86. r"(<\?)(\s*)(whitespace)\b",
  87. bygroups(Comment.Preproc, Text.Whitespace, Keyword),
  88. "whitespace", # Switch to "whitespace" mode
  89. ),
  90. # Plain text
  91. (r"[^<]+", Other),
  92. (r"<", Other),
  93. ],
  94. # Ignore mode ignores everything upto the matching ``<?end ignore?>`` tag
  95. "ignore": [
  96. # Nested ``<?ignore?>`` tag
  97. (r"<\?\s*ignore\s*\?>", Comment, "#push"),
  98. # ``<?end ignore?>`` tag
  99. (r"<\?\s*end\s+ignore\s*\?>", Comment, "#pop"),
  100. # Everything else
  101. (r"[^<]+", Comment),
  102. (r".", Comment),
  103. ],
  104. # UL4 expressions
  105. "ul4": [
  106. # End the tag
  107. (r"\?>", Comment.Preproc, "#pop"),
  108. # Start triple quoted string constant
  109. ("'''", String, "string13"),
  110. ('"""', String, "string23"),
  111. # Start single quoted string constant
  112. ("'", String, "string1"),
  113. ('"', String, "string2"),
  114. # Floating point number
  115. (r"\d+\.\d*([eE][+-]?\d+)?", Number.Float),
  116. (r"\.\d+([eE][+-]?\d+)?", Number.Float),
  117. (r"\d+[eE][+-]?\d+", Number.Float),
  118. # Binary integer: ``0b101010``
  119. (r"0[bB][01]+", Number.Bin),
  120. # Octal integer: ``0o52``
  121. (r"0[oO][0-7]+", Number.Oct),
  122. # Hexadecimal integer: ``0x2a``
  123. (r"0[xX][0-9a-fA-F]+", Number.Hex),
  124. # Date or datetime: ``@(2000-02-29)``/``@(2000-02-29T12:34:56.987654)``
  125. (r"@\(\d\d\d\d-\d\d-\d\d(T(\d\d:\d\d(:\d\d(\.\d{6})?)?)?)?\)", Literal.Date),
  126. # Color: ``#fff``, ``#fff8f0`` etc.
  127. (r"#[0-9a-fA-F]{8}", Literal.Color),
  128. (r"#[0-9a-fA-F]{6}", Literal.Color),
  129. (r"#[0-9a-fA-F]{3,4}", Literal.Color),
  130. # Decimal integer: ``42``
  131. (r"\d+", Number.Integer),
  132. # Operators
  133. (r"//|==|!=|>=|<=|<<|>>|\+=|-=|\*=|/=|//=|<<=|>>=|&=|\|=|^=|=|[\[\]{},:*/().~%&|<>^+-]", Operator),
  134. # Keywords
  135. (words(("for", "in", "if", "else", "not", "is", "and", "or"), suffix=r"\b"), Keyword),
  136. # Builtin constants
  137. (words(("None", "False", "True"), suffix=r"\b"), Keyword.Constant),
  138. # Variable names
  139. (r"[a-zA-Z_][a-zA-Z0-9_]*", Name),
  140. # Whitespace
  141. (r"\s+", Text.Whitespace),
  142. ],
  143. # ``<?end ...?>`` tag for closing the last open block
  144. "end": [
  145. (r"\?>", Comment.Preproc, "#pop"),
  146. (words(("for", "if", "def", "while", "renderblock", "renderblocks"), suffix=r"\b"), Keyword),
  147. (r"\s+", Text),
  148. ],
  149. # Content of the ``<?whitespace ...?>`` tag:
  150. # ``keep``, ``strip`` or ``smart``
  151. "whitespace": [
  152. (r"\?>", Comment.Preproc, "#pop"),
  153. (words(("keep", "strip", "smart"), suffix=r"\b"), Comment.Preproc),
  154. (r"\s+", Text.Whitespace),
  155. ],
  156. # Inside a string constant
  157. "stringescapes": [
  158. (r"""\\[\\'"abtnfr]""", String.Escape),
  159. (r"\\x[0-9a-fA-F]{2}", String.Escape),
  160. (r"\\u[0-9a-fA-F]{4}", String.Escape),
  161. (r"\\U[0-9a-fA-F]{8}", String.Escape),
  162. ],
  163. # Inside a triple quoted string started with ``'''``
  164. "string13": [
  165. (r"'''", String, "#pop"),
  166. include("stringescapes"),
  167. (r"[^\\']+", String),
  168. (r'.', String),
  169. ],
  170. # Inside a triple quoted string started with ``"""``
  171. "string23": [
  172. (r'"""', String, "#pop"),
  173. include("stringescapes"),
  174. (r'[^\\"]+', String),
  175. (r'.', String),
  176. ],
  177. # Inside a single quoted string started with ``'``
  178. "string1": [
  179. (r"'", String, "#pop"),
  180. include("stringescapes"),
  181. (r"[^\\']+", String),
  182. (r'.', String),
  183. ],
  184. # Inside a single quoted string started with ``"``
  185. "string2": [
  186. (r'"', String, "#pop"),
  187. include("stringescapes"),
  188. (r'[^\\"]+', String),
  189. (r'.', String),
  190. ],
  191. }
  192. class HTMLUL4Lexer(DelegatingLexer):
  193. """
  194. Lexer for UL4 embedded in HTML.
  195. """
  196. name = 'HTML+UL4'
  197. aliases = ['html+ul4']
  198. filenames = ['*.htmlul4']
  199. def __init__(self, **options):
  200. super().__init__(HtmlLexer, UL4Lexer, **options)
  201. class XMLUL4Lexer(DelegatingLexer):
  202. """
  203. Lexer for UL4 embedded in XML.
  204. """
  205. name = 'XML+UL4'
  206. aliases = ['xml+ul4']
  207. filenames = ['*.xmlul4']
  208. def __init__(self, **options):
  209. super().__init__(XmlLexer, UL4Lexer, **options)
  210. class CSSUL4Lexer(DelegatingLexer):
  211. """
  212. Lexer for UL4 embedded in CSS.
  213. """
  214. name = 'CSS+UL4'
  215. aliases = ['css+ul4']
  216. filenames = ['*.cssul4']
  217. def __init__(self, **options):
  218. super().__init__(CssLexer, UL4Lexer, **options)
  219. class JavascriptUL4Lexer(DelegatingLexer):
  220. """
  221. Lexer for UL4 embedded in Javascript.
  222. """
  223. name = 'Javascript+UL4'
  224. aliases = ['js+ul4']
  225. filenames = ['*.jsul4']
  226. def __init__(self, **options):
  227. super().__init__(JavascriptLexer, UL4Lexer, **options)
  228. class PythonUL4Lexer(DelegatingLexer):
  229. """
  230. Lexer for UL4 embedded in Python.
  231. """
  232. name = 'Python+UL4'
  233. aliases = ['py+ul4']
  234. filenames = ['*.pyul4']
  235. def __init__(self, **options):
  236. super().__init__(PythonLexer, UL4Lexer, **options)