summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2014-10-04 08:45:25 -0700
committerKaz Kylheku <kaz@kylheku.com>2014-10-04 08:45:25 -0700
commitb5d39b26caaef4b061530c584aca8cf8a6eea62a (patch)
tree47eea6caf4970cae9ccc3b025983e6915bb6edcc
parenta9d41d03d13b369118a5e12a42898d8af894107f (diff)
downloadtxr-b5d39b26caaef4b061530c584aca8cf8a6eea62a.tar.gz
txr-b5d39b26caaef4b061530c584aca8cf8a6eea62a.tar.bz2
txr-b5d39b26caaef4b061530c584aca8cf8a6eea62a.zip
Printing of regular expression objects implemented.
* regex.c (regex_print): New static function. (regex_obj_ops): Registered regex_print. (print_class_char, paren_print_rec, print_rec): New static functions. * dep.mk: Regenerated.
-rw-r--r--ChangeLog10
-rw-r--r--dep.mk2
-rw-r--r--regex.c152
3 files changed, 162 insertions, 2 deletions
diff --git a/ChangeLog b/ChangeLog
index db72ecee..58ff762f 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,15 @@
2014-10-04 Kaz Kylheku <kaz@kylheku.com>
+ Printing of regular expression objects implemented.
+
+ * regex.c (regex_print): New static function.
+ (regex_obj_ops): Registered regex_print. (print_class_char,
+ paren_print_rec, print_rec): New static functions.
+
+ * dep.mk: Regenerated.
+
+2014-10-04 Kaz Kylheku <kaz@kylheku.com>
+
Keep regex source code in regex objects, in anticipation
of pretty-printing. Fix object construction bugs.
diff --git a/dep.mk b/dep.mk
index 16b1e672..332e9aa2 100644
--- a/dep.mk
+++ b/dep.mk
@@ -3,7 +3,7 @@
./y.tab.o: config.h $(top_srcdir)/./lib.h $(top_srcdir)/./signal.h $(top_srcdir)/./unwind.h $(top_srcdir)/./regex.h $(top_srcdir)/./utf8.h $(top_srcdir)/./match.h $(top_srcdir)/./hash.h $(top_srcdir)/./eval.h $(top_srcdir)/./stream.h $(top_srcdir)/./parser.h
./match.o: config.h $(top_srcdir)/./lib.h $(top_srcdir)/./gc.h $(top_srcdir)/./signal.h $(top_srcdir)/./unwind.h $(top_srcdir)/./regex.h $(top_srcdir)/./stream.h $(top_srcdir)/./parser.h $(top_srcdir)/./txr.h $(top_srcdir)/./utf8.h $(top_srcdir)/./filter.h $(top_srcdir)/./hash.h $(top_srcdir)/./debug.h $(top_srcdir)/./eval.h $(top_srcdir)/./match.h
./lib.o: config.h $(top_srcdir)/./lib.h $(top_srcdir)/./gc.h $(top_srcdir)/./arith.h $(top_srcdir)/./rand.h $(top_srcdir)/./hash.h $(top_srcdir)/./signal.h $(top_srcdir)/./unwind.h $(top_srcdir)/./stream.h $(top_srcdir)/./utf8.h $(top_srcdir)/./filter.h $(top_srcdir)/./eval.h $(top_srcdir)/./regex.h
-./regex.o: config.h $(top_srcdir)/./lib.h $(top_srcdir)/./parser.h $(top_srcdir)/./signal.h $(top_srcdir)/./unwind.h $(top_srcdir)/./gc.h $(top_srcdir)/./regex.h $(top_srcdir)/./txr.h
+./regex.o: config.h $(top_srcdir)/./lib.h $(top_srcdir)/./parser.h $(top_srcdir)/./signal.h $(top_srcdir)/./unwind.h $(top_srcdir)/./stream.h $(top_srcdir)/./gc.h $(top_srcdir)/./regex.h $(top_srcdir)/./txr.h
./gc.o: config.h $(top_srcdir)/./lib.h $(top_srcdir)/./stream.h $(top_srcdir)/./hash.h $(top_srcdir)/./txr.h $(top_srcdir)/./eval.h $(top_srcdir)/./gc.h $(top_srcdir)/./signal.h
./unwind.o: config.h $(top_srcdir)/./lib.h $(top_srcdir)/./gc.h $(top_srcdir)/./stream.h $(top_srcdir)/./txr.h $(top_srcdir)/./signal.h $(top_srcdir)/./eval.h $(top_srcdir)/./parser.h $(top_srcdir)/./unwind.h
./stream.o: config.h $(top_srcdir)/./lib.h $(top_srcdir)/./gc.h $(top_srcdir)/./signal.h $(top_srcdir)/./unwind.h $(top_srcdir)/./stream.h $(top_srcdir)/./utf8.h $(top_srcdir)/./eval.h $(top_srcdir)/./regex.h
diff --git a/regex.c b/regex.c
index df07cf74..b267b52a 100644
--- a/regex.c
+++ b/regex.c
@@ -39,6 +39,7 @@
#include "parser.h"
#include "signal.h"
#include "unwind.h"
+#include "stream.h"
#include "gc.h"
#include "regex.h"
#include "txr.h"
@@ -1305,9 +1306,11 @@ static void regex_mark(val obj)
gc_mark(regex->source);
}
+static void regex_print(val obj, val stream);
+
static struct cobj_ops regex_obj_ops = {
eq,
- cobj_print_op,
+ regex_print,
regex_destroy,
regex_mark,
cobj_hash_op
@@ -1690,6 +1693,153 @@ val regexp(val obj)
return typeof(obj) == regex_s ? t : nil;
}
+static void print_class_char(val ch, val first_p, val stream)
+{
+ wchar_t c = c_chr(ch);
+ switch (c) {
+ case '^':
+ if (!first_p)
+ break;
+ /* fallthrough */
+ case '-':
+ put_char(chr('\\'), stream);
+ break;
+ }
+ put_char(ch, stream);
+}
+
+static void print_rec(val exp, val stream);
+
+static void paren_print_rec(val exp, val stream)
+{
+ put_char(chr('('), stream);
+ print_rec(exp, stream);
+ put_char(chr(')'), stream);
+}
+
+static void print_rec(val exp, val stream)
+{
+ if (exp == space_k) {
+ put_string(lit("\\s"), stream);
+ } else if (exp == digit_k) {
+ put_string(lit("\\d"), stream);
+ } else if (exp == word_char_k) {
+ put_string(lit("\\w"), stream);
+ } else if (exp == cspace_k) {
+ put_string(lit("\\S"), stream);
+ } else if (exp == cdigit_k) {
+ put_string(lit("\\D"), stream);
+ } else if (exp == cword_char_k) {
+ put_string(lit("\\W"), stream);
+ } else if (exp == wild_s) {
+ put_char(chr('.'), stream);
+ } else if (chrp(exp)) {
+ wchar_t ch = c_chr(exp);
+ switch (ch) {
+ case '?': case '.': case '*': case '+':
+ case '(': case ')': case '|': case '~':
+ case '&': case '%': case '/': case '\\':
+ put_char(chr('\\'), stream);
+ break;
+ }
+ put_char(exp, stream);
+ } else if (stringp(exp)) {
+ cnum i;
+ cnum l = c_num(length(exp));
+ for (i = 0; i < l; i++)
+ print_rec(chr_str(exp, num(i)), stream);
+ } else if (consp(exp)) {
+ val sym = first(exp);
+ val args = rest(exp);
+
+ if (sym == set_s || sym == cset_s) {
+ put_char(chr('['), stream);
+ val first_p = t;
+
+ if (sym == cset_s) {
+ put_char(chr('^'), stream);
+ first_p = nil;
+ }
+
+ while (args) {
+ val arg = pop(&args);
+ if (consp(arg)) {
+ print_class_char(car(arg), first_p, stream);
+ put_char(chr('-'), stream);
+ print_class_char(cdr(arg), nil, stream);
+ } else {
+ print_class_char(arg, first_p, stream);
+ }
+ first_p = nil;
+ }
+ put_char(chr(']'), stream);
+ } else if (sym == compound_s) {
+ while (args)
+ print_rec(pop(&args), stream);
+ } else if (sym == zeroplus_s || sym == oneplus_s || sym == optional_s) {
+ val arg = pop(&args);
+ if (consp(arg) && car(arg) != set_s && car(arg) != cset_s)
+ paren_print_rec(arg, stream);
+ else
+ print_rec(arg, stream);
+ if (sym == zeroplus_s)
+ put_char(chr('*'), stream);
+ else if (sym == oneplus_s)
+ put_char(chr('+'), stream);
+ else
+ put_char(chr('?'), stream);
+ } else if (sym == compl_s) {
+ val arg = pop(&args);
+ put_char(chr('~'), stream);
+ if (consp(arg) && (car(arg) == or_s || car(arg) == and_s))
+ paren_print_rec(arg, stream);
+ else
+ print_rec(arg, stream);
+ } else if (sym == and_s) {
+ val arg1 = pop(&args);
+ val arg2 = pop(&args);
+ if (consp(arg1) && car(arg2) == or_s)
+ paren_print_rec(arg1, stream);
+ else
+ print_rec(arg1, stream);
+ put_char(chr('&'), stream);
+ if (consp(arg2) && car(arg2) == or_s)
+ paren_print_rec(arg2, stream);
+ else
+ print_rec(arg2, stream);
+ } else if (sym == or_s) {
+ print_rec(pop(&args), stream);
+ put_char(chr('|'), stream);
+ print_rec(pop(&args), stream);
+ } else if (sym == nongreedy_s) {
+ val arg1 = pop(&args);
+ val arg2 = pop(&args);
+ if (consp(arg1) && car(arg1) != set_s && car(arg1) != cset_s)
+ paren_print_rec(arg1, stream);
+ else
+ print_rec(arg1, stream);
+ put_char(chr('%'), stream);
+ if (consp(arg2) && (car(arg2) == and_s && car(arg2) == or_s))
+ paren_print_rec(arg2, stream);
+ else
+ print_rec(arg2, stream);
+ } else {
+ uw_throwf(error_s, lit("bad operator in regex syntax: ~s"), sym, nao);
+ }
+ } else {
+ uw_throwf(error_s, lit("bad object in regex syntax: ~s"), exp, nao);
+ }
+}
+
+static void regex_print(val obj, val stream)
+{
+ regex_t *regex = (regex_t *) cobj_handle(obj, regex_s);
+
+ put_string(lit("#/"), stream);
+ print_rec(regex->source, stream);
+ put_char(chr('/'), stream);
+}
+
static cnum regex_run(val compiled_regex, const wchar_t *str)
{
regex_t *regex = (regex_t *) cobj_handle(compiled_regex, regex_s);