aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README.md3
-rw-r--r--bp.111
-rw-r--r--bp.c41
-rw-r--r--compiler.c21
-rw-r--r--compiler.h4
5 files changed, 43 insertions, 37 deletions
diff --git a/README.md b/README.md
index f90b62d..650fb53 100644
--- a/README.md
+++ b/README.md
@@ -14,8 +14,6 @@ It's written in pure C with no dependencies.
* `-e` `--explain` print an explanation of the matches
* `-j` `--json` print matches as JSON objects
* `-l` `--list-files` print only filenames containing matches
-* `-d` `--define <name>:<def>` define a grammar rule
-* `-D` `--define-string <name>:<def>` define a grammar rule (string-pattern)
* `-p` `--pattern <pat>` provide a pattern (equivalent to `bp '\(<pat>)'`)
* `-P` `--pattern-string <pat>` provide a string pattern (equivalent to `bp '<pat>'`, but may be useful if `'<pat>'` begins with a '-')
* `-r` `--replace <replacement>` replace the input pattern with the given replacement
@@ -63,6 +61,7 @@ Pattern | Meaning
`(pat1 @keep=pat2) => "@keep"` | Match `pat1` followed by `pat2` and replace it with the text of `pat2`
`pat1==pat2` | `pat1`, assuming `pat2` also matches with the same length
`pat1!=pat2` | `pat1`, unless `pat2` also matches with the same length
+`name:pat2` | `name` is defined to mean `pat`
`#( block comment )#` | A block comment
`# line comment` | A line comment
diff --git a/bp.1 b/bp.1
index 2c48799..5b220ad 100644
--- a/bp.1
+++ b/bp.1
@@ -14,8 +14,6 @@ bp \- Bruce's Parsing Expression Grammar tool
[\fI-I\fR|\fI--inplace\fR]
[\fI-p\fR|\fI--pattern\fR \fI<pattern>\fR]
[\fI-P\fR|\fI--pattern-string\fR \fI<string-pattern>\fR]
-[\fI-d\fR|\fI--define\fR \fI<name>\fR:\fI<pattern>\fR]
-[\fI-D\fR|\fI--define-string\fR \fI<name>\fR:\fI<string-pattern>\fR]
[\fI-r\fR|\fI--replace\fR \fI<replacement>\fR]
[\fI-g\fR|\fI--grammar\fR \fI<grammar file>\fR]
[\fI-c\fR|\fI--conntext\fR \fI<N>\fR]
@@ -42,12 +40,6 @@ Perform pattern matching case-insensitively.
.B \-I\fR, \fB--inplace
Perform filtering or replacement in-place (i.e. overwrite files with new content).
-.B \-d\fR, \fB--define \fI<name>\fR:\fI<pattern>\fR
-Define a grammar rule using a bp pattern.
-
-.B \-D\fR, \fB--define-string \fI<name>\fR:\fI<string-pattern>\fR
-Define a grammar rule using a bp string pattern.
-
.B \-r\fR, \fB--replace \fI<replacement>\fR
Replace all occurrences of the main pattern with the given string.
@@ -188,6 +180,9 @@ Will match only if \fI<pat1>\fR matches and \fI<pat2>\fR doesn't match the text
Will match only if \fI<pat1>\fR and \fI<pat2>\fR don't both match and have the
exact same length. Pronounced \fI<pat1>\fB-assuming-it-doesn't-equal-\fI<pat2>\fR
+.B \fI<name>\fB:\fI<pat>\fR
+\fBDefine-\fI<name>\fB-to-mean-\fI<pat>\fR (pattern definition)
+
.B |
This pattern matches the indentation at the beginning of a line that has the
same indentation as the line before (or zero indentation on the first line).
diff --git a/bp.c b/bp.c
index 5f5158c..0b0590f 100644
--- a/bp.c
+++ b/bp.c
@@ -31,8 +31,6 @@ static const char *usage = (
" -I --inplace modify a file in-place\n"
" -i --ignore-case preform matching case-insensitively\n"
" -l --list-files list filenames only\n"
- " -d --define <name>:<def> define a grammar rule\n"
- " -D --define-string <name>:<def> define a grammar rule (string-pattern)\n"
" -p --pattern <pat> provide a pattern (equivalent to bp '\\(<pat>)')\n"
" -P --pattern-string <pat> provide a string pattern (may be useful if '<pat>' begins with a '-')\n"
" -r --replace <replacement> replace the input pattern with the given replacement\n"
@@ -311,33 +309,24 @@ int main(int argc, char *argv[])
f = load_file(&loaded_files, "/etc/xdg/bp/%s.bp", flag);
check(f != NULL, "Couldn't find grammar: %s", flag);
defs = load_grammar(defs, f); // Keep in memory for debug output
- } else if (FLAG("--define") || FLAG("-d")) {
- char *def = flag;
- char *eq = strchr(def, ':');
- check(eq, "Rule definitions must include an ':'\n\n%s", usage);
- *eq = '\0';
- char *src = ++eq;
- file_t *def_file = spoof_file(&loaded_files, def, src);
- vm_op_t *pat = bp_pattern(def_file, def_file->contents);
- check(pat, "Failed to compile pattern: %s", flag);
- defs = with_def(defs, def_file, strlen(def), def, pat);
- } else if (FLAG("--define-string") || FLAG("-D")) {
- char *def = flag;
- char *eq = strchr(def, ':');
- check(eq, "Rule definitions must include an ':'\n\n%s", usage);
- *eq = '\0';
- char *src = ++eq;
- file_t *def_file = spoof_file(&loaded_files, def, src);
- vm_op_t *pat = bp_stringpattern(def_file, def_file->contents);
- check(pat, "Failed to compile pattern: %s", src);
- defs = with_def(defs, def_file, strlen(def), def, pat);
} else if (FLAG("--pattern") || FLAG("-p")) {
check(npatterns == 0, "Cannot define multiple patterns");
file_t *arg_file = spoof_file(&loaded_files, "<pattern argument>", flag);
- vm_op_t *p = bp_pattern(arg_file, arg_file->contents);
- check(p, "Pattern failed to compile: %s", flag);
- defs = with_def(defs, arg_file, strlen("pattern"), "pattern", p);
- ++npatterns;
+ for (const char *str = arg_file->contents; str < arg_file->end; ) {
+ def_t *d = bp_definition(arg_file, str);
+ if (d) {
+ d->next = defs;
+ defs = d;
+ str = d->op->end;
+ } else {
+ vm_op_t *p = bp_pattern(arg_file, str);
+ check(p, "Pattern failed to compile: %s", flag);
+ defs = with_def(defs, arg_file, strlen("pattern"), "pattern", p);
+ ++npatterns;
+ str = p->end;
+ }
+ str = strchr(str, ';') ? strchr(str, ';') + 1 : str;
+ }
} else if (FLAG("--pattern-string") || FLAG("-P")) {
file_t *arg_file = spoof_file(&loaded_files, "<pattern argument>", flag);
vm_op_t *p = bp_stringpattern(arg_file, arg_file->contents);
diff --git a/compiler.c b/compiler.c
index 951462a..8e782cc 100644
--- a/compiler.c
+++ b/compiler.c
@@ -593,4 +593,25 @@ vm_op_t *bp_pattern(file_t *f, const char *str)
return op;
}
+//
+// Match a definition (id__`:__pattern)
+//
+def_t *bp_definition(file_t *f, const char *str)
+{
+ const char *name = after_spaces(str);
+ str = after_name(name);
+ if (!str) return NULL;
+ size_t namelen = (size_t)(str - name);
+ if (!matchchar(&str, ':')) return NULL;
+ vm_op_t *pat = bp_pattern(f, str);
+ if (!pat) return NULL;
+ matchchar(&pat->end, ';'); // TODO: verify this is safe to mutate
+ def_t *def = new(def_t);
+ def->file = f;
+ def->namelen = namelen;
+ def->name = name;
+ def->op = pat;
+ return def;
+}
+
// vim: ts=4 sw=0 et cino=L2,l1,(0,W4,m1
diff --git a/compiler.h b/compiler.h
index 3b61c17..76e7734 100644
--- a/compiler.h
+++ b/compiler.h
@@ -15,8 +15,10 @@ __attribute__((nonnull(1,2)))
vm_op_t *bp_stringpattern(file_t *f, const char *str);
__attribute__((nonnull(1,2)))
vm_op_t *bp_replacement(file_t *f, vm_op_t *pat, const char *replacement);
-__attribute__((nonnull(1,2)))
+__attribute__((nonnull))
vm_op_t *bp_pattern(file_t *f, const char *str);
+__attribute__((nonnull))
+def_t *bp_definition(file_t *f, const char *str);
#endif
// vim: ts=4 sw=0 et cino=L2,l1,(0,W4,m1