Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for Wren language #2271

Merged
merged 16 commits into from Nov 29, 2022
1 change: 1 addition & 0 deletions pygments/lexers/_mapping.py
Expand Up @@ -528,6 +528,7 @@
'WebIDLLexer': ('pygments.lexers.webidl', 'Web IDL', ('webidl',), ('*.webidl',), ()),
'WhileyLexer': ('pygments.lexers.whiley', 'Whiley', ('whiley',), ('*.whiley',), ('text/x-whiley',)),
'WoWTocLexer': ('pygments.lexers.wowtoc', 'World of Warcraft TOC', ('wowtoc',), ('*.toc',), ()),
'WrenLexer': ('pygments.lexers.wren', 'Wren', ('wren',), ('*.wren',), ()),
'X10Lexer': ('pygments.lexers.x10', 'X10', ('x10', 'xten'), ('*.x10',), ('text/x-x10',)),
'XMLUL4Lexer': ('pygments.lexers.ul4', 'XML+UL4', ('xml+ul4',), ('*.xmlul4',), ()),
'XQueryLexer': ('pygments.lexers.webmisc', 'XQuery', ('xquery', 'xqy', 'xq', 'xql', 'xqm'), ('*.xqy', '*.xquery', '*.xq', '*.xql', '*.xqm'), ('text/xquery', 'application/xquery')),
Expand Down
99 changes: 99 additions & 0 deletions pygments/lexers/wren.py
@@ -0,0 +1,99 @@
"""
pygments.lexers.wren
~~~~~~~~~~~~~~~~~~~~

Lexer for Wren.

:copyright: Copyright 2006-2022 by the Pygments team, see AUTHORS.
:license: BSD, see LICENSE for details.
"""

import re

from pygments.lexer import include, RegexLexer, words
from pygments.token import Whitespace, Punctuation, Keyword, Name, Comment, \
Operator, Number, String, Error

__all__ = ['WrenLexer']

class WrenLexer(RegexLexer):
jeanas marked this conversation as resolved.
Show resolved Hide resolved
"""
For Wren source code, version 0.4.0.

.. versionadded:: 2.14.0
"""
name = 'Wren'
url = 'https://wren.io'
aliases = ['wren']
filenames = ['*.wren']

jeanas marked this conversation as resolved.
Show resolved Hide resolved
flags = re.MULTILINE | re.DOTALL

tokens = {
'root': [
# Whitespace.
(r'\s+', Whitespace),
(r'[,\\\[\]{}]', Punctuation),

# Really 'root', not '#push': in 'interpolation',
# parentheses inside the interpolation expression are
# Punctuation, not String.Interpol.
(r'\(', Punctuation, 'root'),
(r'\)', Punctuation, '#pop'),

# Keywords.
(words((
'as', 'break', 'class', 'construct', 'continue', 'else',
'for', 'foreign', 'if', 'import', 'return', 'static', 'super',
'this', 'var', 'while'), prefix = r'(?<!\.)',
suffix = r'\b'), Keyword),

(words((
'true', 'false', 'null'), prefix = r'(?<!\.)',
suffix = r'\b'), Keyword.Constant),

(words((
'in', 'is'), prefix = r'(?<!\.)',
suffix = r'\b'), Operator.Word),

# Comments.
(r'/\*', Comment.Multiline, 'comment'), # Multiline, can nest.
(r'//.*?$', Comment.Single), # Single line.
(r'#.*?(\(.*?\))?$', Comment.Special), # Attribute or shebang.

# Names and operators.
(r'[!%&*+\-./:<=>?\\^|~]+', Operator),
(r'[a-z][a-zA-Z_0-9]*', Name),
(r'[A-Z][a-zA-Z_0-9]*', Name.Class),
jeanas marked this conversation as resolved.
Show resolved Hide resolved
(r'__[a-zA-Z_0-9]*', Name.Variable.Class),
(r'_[a-zA-Z_0-9]*', Name.Variable.Instance),
jeanas marked this conversation as resolved.
Show resolved Hide resolved

# Numbers.
(r'0x[0-9a-fA-F]+', Number.Hex),
(r'\d+(\.\d+)?([eE][-+]?\d+)?', Number.Float),

# Strings.
(r'""".*?"""', String), # Raw string
(r'"', String, 'string'), # Other string
],
'comment': [
(r'/\*', Comment.Multiline, '#push'),
(r'\*/', Comment.Multiline, '#pop'),
(r'([^*/]|\*(?!/)|/(?!\*))+', Comment.Multiline),
],
'string': [
(r'"', String, '#pop'),
(r'\\[\\%"0abefnrtv]', String.Escape), # Escape.
(r'\\x[a-fA-F0-9]{2}', String.Escape), # Byte escape.
(r'\\u[a-fA-F0-9]{4}', String.Escape), # Unicode escape.
(r'\\U[a-fA-F0-9]{8}', String.Escape), # Long Unicode escape.

(r'%\(', String.Interpol, 'interpolation'),
(r'[^\\"%]+', String), # All remaining characters.
],
'interpolation': [
# redefine closing paren to be String.Interpol
(r'\)', String.Interpol, '#pop'),
include('root'),
],
}
122 changes: 122 additions & 0 deletions tests/examplefiles/wren/example.wren
@@ -0,0 +1,122 @@
#!/bin/wren

/* IMPORTS */
import "random" for Random as Rand

/* COMMENTS */

// single line comment

/*
multiline comment
/*
nested multiline comment
*/
*/

/* CLASSES & ATTRIBUTES */

#!type = "parent"
class Parent {
#method
static setField (field) {
__field = field
}

construct new(parent) {
_parent = parent
return
}

parent { _parent }

foreign method()
}

#!type = "child"
#group(
multiple,
lines = true
)
class Child is Parent {
construct new(parent, child) {
super(parent)
_child = child
}

child { _child }

toString { this.parent }
}

/* VARIABLES & STRINGS */

var rand = Rand.new()
var name = """David"""
var fullName = "%(name) Smith"
var firstChild = Child.new("Philip Smith", fullName)
var age = 21
var weight = 70.25
var male = true
var sex = male ? "M" : "F"
var address = """
"House name" 12 Any Street
Some Town
\t %("Some Country") "
"""

/* LOOPS & CONDITIONALS */
for (i in 1..5) {
if (i == 2) {
continue
} else if (i == 4) {
break
}
System.print(i)
}
var j = 6
while (j <= 1e+1) {
if (j == 8) break
System.print(j)
j = j + 1
}

/* ARITHMETIC OPERATORS */
var a = 1
var b = 2
var c = [-a, a + b, a - b, a * b, a / b, a % b]
var add = c[1]

/* BITWISE OPERATORS */
var d = 3
var e = 4
var f = [~d, d & e, d | e, d ^ e, d << 2, e >> 1]

/* COMPARISON OPERATORS */
var g = 5
var h = 6
var i = [a == b, a != b, a < b, a <= b, a > b, a >= b]
var k = firstChild is Parent

/* FUNCTIONS */
var func = Fn.new { |param|
var z = "this"
System.print(z + " " + param)
}
func.call("function")

/* MISCELLANEOUS */

var hex = 0x12ac
var nul = null
var l = false
var m = true
var n = l && m
var o = l || m
var esc = "\\ \% \" \0 \a \b \t \f \n \r \v \e \x01 \uabcd \Uabcdef01"
var uni = "£ é 😀 ‎🎷"
var map = {"a": 1, "b": 2}
var iex = "%(map["a"] + map[("b")])"
var odd = (1...h).where { |i| i % 2 == 1 }
.toList
var emp = ""