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
102 changes: 102 additions & 0 deletions pygments/lexers/wren.py
@@ -0,0 +1,102 @@
"""
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 RegexLexer, words
from pygments.token import Whitespace, Punctuation, Keyword, Name, Comment, \
Operator, Number, String

__all__ = ['WrenLexer']

class WrenLexer(RegexLexer):
jeanas marked this conversation as resolved.
Show resolved Hide resolved
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),

# Push a parenthesized state so that we know the corresponding ')'
# is for a parenthesized expression and not interpolation.
(r'\(', Punctuation, ('parenthesized', 'root')),

# In this state, we don't know whether a closing ')' is for a
# parenthesized expression or the end of an interpolation. So, do
# a non-consuming match and let the parent state (either
# 'parenthesized' or 'interpolation') decide.
(r'(?=\))', Punctuation, '#pop'),

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

(words((
'this'), prefix = r'(?<!\.)',
suffix = r'\b'), Name.Builtin),

(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, '#pop'),
(r'[^*]+', Comment.Multiline),
(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', 'root')),
(r'[^\\"%]*', String), # All remaining characters.
jeanas marked this conversation as resolved.
Show resolved Hide resolved
],
'parenthesized': [
# We only get to this state when we're at a ')'.
(r'\)', Punctuation, '#pop'),
],
'interpolation': [
# We only get to this state when we're at a ')'.
(r'\)', String.Interpol, '#pop'),
],
}
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 = ""