aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBruce Hill <bruce@bruce-hill.com>2021-01-05 19:31:50 -0800
committerBruce Hill <bruce@bruce-hill.com>2021-01-05 19:31:50 -0800
commitd8d2a5a66e9530387a5a1380219aedc833379b23 (patch)
tree9539a7c8751257340e7c7ff309236a683a2d3b9e
parent00226cb76314ed69869c951b3cdb589393c3ca52 (diff)
Changed precedence of =>
-rw-r--r--compiler.c73
-rw-r--r--grammars/bpeg.bp2
2 files changed, 38 insertions, 37 deletions
diff --git a/compiler.c b/compiler.c
index 69b2f10..982a4cf 100644
--- a/compiler.c
+++ b/compiler.c
@@ -56,14 +56,47 @@ static vm_op_t *expand_chain(file_t *f, vm_op_t *first)
}
/*
- * Take an opcode and expand it into a chain of choices if it's
- * followed by any "/"-separated patterns (e.g. "`x/`y"), otherwise
- * return the original input.
+ * Take an opcode and parse any "=>" replacements and then expand it into a
+ * chain of choices if it's followed by any "/"-separated patterns (e.g.
+ * "`x/`y"), otherwise return the original input.
*/
static vm_op_t *expand_choices(file_t *f, vm_op_t *first)
{
first = expand_chain(f, first);
const char *str = first->end;
+
+ while (str+2 < f->end && matchstr(&str, "=>")) { // Replacement <pat> => <pat>
+ str = after_spaces(str);
+ char quote = *str;
+ if (!(matchchar(&str, '"') || matchchar(&str, '\'')))
+ file_err(f, str, str, "There should be a string literal as a replacement here.");
+ const char *repstr = str;
+ for (; *str && *str != quote; str++) {
+ if (*str == '\\') {
+ if (!str[1] || str[1] == '\n')
+ file_err(f, str, str+1,
+ "There should be an escape sequence after this backslash.");
+ ++str;
+ }
+ }
+ if (!matchchar(&str, quote))
+ file_err(f, &repstr[-1], str, "This string doesn't have a closing quote.");
+
+ size_t replace_len = (size_t)(str-repstr-1);
+ const char *replacement = xcalloc(sizeof(char), replace_len+1);
+ memcpy((void*)replacement, repstr, replace_len);
+
+ vm_op_t *pat = first;
+ first = new(vm_op_t);
+ first->op = VM_REPLACE;
+ first->args.replace.pat = pat;
+ first->args.replace.text = replacement;
+ first->args.replace.len = replace_len;
+ first->len = pat->len;
+ first->start = pat->start;
+ first->end = str;
+ }
+
if (!matchchar(&str, '/')) return first;
vm_op_t *second = bp_simplepattern(f, str);
if (!second)
@@ -430,39 +463,7 @@ vm_op_t *bp_simplepattern(file_t *f, const char *str)
// Postfix operators:
postfix:
str = after_spaces(str);
- if (str+2 < f->end && matchstr(&str, "=>")) { // Replacement <pat> => <pat>
- str = after_spaces(str);
- char quote = *str;
- if (!(matchchar(&str, '"') || matchchar(&str, '\'')))
- file_err(f, str, str, "There should be a string literal as a replacement here.");
- const char *repstr = str;
- for (; *str && *str != quote; str++) {
- if (*str == '\\') {
- if (!str[1] || str[1] == '\n')
- file_err(f, str, str+1,
- "There should be an escape sequence after this backslash.");
- ++str;
- }
- }
- if (!matchchar(&str, quote))
- file_err(f, &repstr[-1], str, "This string doesn't have a closing quote.");
-
- size_t replace_len = (size_t)(str-repstr-1);
- const char *replacement = xcalloc(sizeof(char), replace_len+1);
- memcpy((void*)replacement, repstr, replace_len);
-
- vm_op_t *pat = op;
- op = new(vm_op_t);
- op->op = VM_REPLACE;
- op->args.replace.pat = pat;
- op->args.replace.text = replacement;
- op->args.replace.len = replace_len;
- op->len = pat->len;
- op->start = pat->start;
- op->end = str;
- goto postfix;
-
- } else if (str+2 < f->end && (matchstr(&str, "!=") || matchstr(&str, "=="))) { // Equality <pat1>==<pat2> and inequality <pat1>!=<pat2>
+ if (str+2 < f->end && (matchstr(&str, "!=") || matchstr(&str, "=="))) { // Equality <pat1>==<pat2> and inequality <pat1>!=<pat2>
int equal = str[-2] == '=';
vm_op_t *first = op;
vm_op_t *second = bp_simplepattern(f, str);
diff --git a/grammars/bpeg.bp b/grammars/bpeg.bp
index 8a223b2..4855255 100644
--- a/grammars/bpeg.bp
+++ b/grammars/bpeg.bp
@@ -34,7 +34,7 @@ Char: (@s=. / @!=(''=> "Expected a character following the '`'"))
Escape-range: `\ @low=escape-sequence `- @high=escape-sequence
Escape: `\ (@s=escape-sequence
/ $ @!=(''=>"Backslashes are used for escape sequences, not splitting lines")
- / @!=((. *(Abc/`0-9)) => "Invalid escape sequence: '@0'")
+ / @!=(. *(Abc/`0-9) => "Invalid escape sequence: '@0'")
)
escape-sequence: (
`n,t,r,e,b,a,v