diff --git a/tests/objects/regex.vala b/tests/objects/regex.vala
new file mode 100644
index 0000000..63d5df6
--- /dev/null
+++ b/tests/objects/regex.vala
@@ -0,0 +1,109 @@
+using GLib;
+
+
+static Regex get_from_array (int index)
+{
+	Regex[] arr = {
+		/(\d+\.\d+\.\d+)/,
+		/(\d+)\.\d+\.\d+/,
+		/\d+\.(\d+)\.\d+/,
+		/(\d+)\.\d+\.(\d+)/
+	};
+
+	assert (0 <= index <= 3);
+	return arr[index];
+}
+
+static Regex get_fixed ()
+{
+	return /(is.*ip)/;
+}
+
+class Test : Object {
+	public signal void regexTest (string str);
+	public void run (string s)
+	{
+		regexTest (s);
+	}
+}
+
+static int main (string[] args)
+{
+	MatchInfo info;
+
+	// Simple greedy regular expression matching, regex received as a function return value.
+	var str1 = "mississippi";
+	if (get_fixed ().match (str1, 0, out info)) {
+		stdout.printf ("Part of %s is '%s'...\n", str1, info.fetch (1));
+	} else {
+		stdout.printf ("Did not match at all.\n");
+	}
+
+	// Match caseless.
+	var str2 = "demonStration";
+	if (/mon(str.*o)n/i.match (str2, 0, out info)) {
+		stdout.printf ("Part of %s is '%s'...\n", str2, info.fetch (1));
+	} else {
+		stdout.printf ("%s did not match at all.\n", str2);
+	}
+
+	// Match and pick substrings.
+	var ts   = "Time: 10:42:12";
+	if (/Time: (..):(..):(..)/.match (ts, 0, out info)) {
+		stdout.printf ("%s\n\thours = %s\n\tminutes = %s\n\tseconds = %s\n\n", ts, info.fetch (1), info.fetch (2), info.fetch (3));
+	}
+
+	// Replace demo: word swapping
+	try {
+		var str = "apple grape";
+		stdout.printf ("'%s' becomes '%s'\n", str, /^([^ ]*) *([^ ]*)/.replace (str, -1, 0, """\2 \1"""));
+	} catch (RegexError err) {
+		// Replacing still needs exception catching
+		message (err.message);
+	}
+
+	// Regex literals in an array
+	for (int i=0; i<4; i++) {
+		if (get_from_array (i).match ("23.3.2010", 0, out info)) {
+			stdout.printf ("Round %d: %s\n", i, info.fetch (1));
+		}
+	}
+
+	// ??-operator
+	Regex? r = null;
+	Regex? r1 = null;
+	Regex? r2 = null;
+
+	r = r1 ?? r2 ?? /match (this)/i;
+	if (r.match ("match THIS", 0, out info)) {
+		stdout.printf ("Match: %s\n", info.fetch (1));
+	}
+
+	// Escape sequences
+	if (/\.\+\(\)\-\?\/\"\$\[\]\*\^/.match (".+()-?/\"$[]*^")) {
+		stdout.printf ("Matches\n");
+	} else {
+		stdout.printf ("Does not match.\n");
+	}
+
+	// Lambda and closure test
+	Regex? rc = /foo(bar)/i;
+	var test = new Test ();
+	test.regexTest.connect ((s) => {
+		if (rc.match (s, 0, out info)) {
+			stdout.printf ("Lambda (closure var.): %s -> %s\n", s, info.fetch (1));
+		} else {
+			stdout.printf ("Does not match.\n");
+		}
+		if (/foo(bar)/i.match (s, 0, out info)) {
+			stdout.printf ("Lambda (lit.): %s -> %s\n", s, info.fetch (1));
+		} else {
+			stdout.printf ("Does not match.\n");
+		}
+	});
+	test.run ("fooBar");
+	test.run ("foobAr");
+
+	return 0;
+}
+
diff --git a/vala/valaregexliteral.vala b/vala/valaregexliteral.vala
new file mode 100644
index 0000000..e4472a1
--- /dev/null
+++ b/vala/valaregexliteral.vala
@@ -0,0 +1,93 @@
+/* valaregexliteral.vala
+ *
+ * Copyright (C) 2010  Jukka-Pekka Iivonen
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
+ *
+ * Author:
+ * 	Jukka-Pekka Iivonen <jp0409@jippii.fi>
+ */
+
+using GLib;
+
+/**
+ * Represents a regular expression literal in the source code.
+ */
+public class Vala.RegexLiteral : Literal {
+	/**
+	 * The literal value.
+	 */
+	public string value { get; set; }
+
+	/**
+	 * Creates a new regular expression literal.
+	 *
+	 * @param s      the literal value
+	 * @param source reference to source code
+	 * @return       newly created string literal
+	 */
+	public RegexLiteral (string value, SourceReference? source_reference = null) {
+		this.value = value;
+		this.source_reference = source_reference;
+	}
+
+	/**
+	 * Evaluates the literal string value.
+	 *
+	 * @return the unescaped string
+	 */	
+	public string? eval () {
+		if (value == null) {
+			return null;
+		}
+		
+		/* remove quotes */
+		var noquotes = value.substring (1, (uint) (value.len () - 2));
+		/* unescape string */
+		return noquotes.compress ();
+	}
+	
+	public override void accept (CodeVisitor visitor) {
+		visitor.visit_regex_literal (this);
+
+		visitor.visit_expression (this);
+	}
+
+	public override bool is_pure () {
+		return true;
+	}
+
+	public override bool is_non_null () {
+		return true;
+	}
+
+	public override string to_string () {
+		return value;
+	}
+
+	public override bool check (SemanticAnalyzer analyzer) {
+		if (checked) {
+			return !error;
+		}
+
+		checked = true;
+
+		analyzer.visit_regex_literal (this);
+		value_type = analyzer.regex_type.copy ();
+
+		return !error;
+	}
+}
+
