diff --git a/doc/Peg.md b/doc/Peg.md index c57a3dda..93a04489 100644 --- a/doc/Peg.md +++ b/doc/Peg.md @@ -109,6 +109,8 @@ can be thought of as the looping and branching forms in a traditional language | `(! patt)` | Alias for `(not patt)` | | `(look offset patt)` | Matches only if patt matches at a fixed offset. offset can be any integer. patt will not produce captures and the peg will not advance any characters. | | `(> offset patt)` | Alias for `(look offset patt)` | +| `(opt patt)` | Alias for `(between 0 1 patt)` | +| `(? patt)` | Alias for `(between 0 1 patt)` | PEGs try to match an input text with a pattern in a greedy manner. This means that if a rule fails to match, that rule will fail and not try again. The only diff --git a/src/core/peg.c b/src/core/peg.c index ca1ce448..551a2452 100644 --- a/src/core/peg.c +++ b/src/core/peg.c @@ -713,7 +713,6 @@ static void spec_replace(Builder *b, int32_t argc, const Janet *argv) { emit_2(r, RULE_REPLACE, subrule, constant); } -/* For some and any, really just short-hand for (^ rule n) */ static void spec_repeater(Builder *b, int32_t argc, const Janet *argv, int32_t min) { peg_fixarity(b, argc, 1); Reserve r = reserve(b, 4); @@ -744,6 +743,13 @@ static void spec_atmost(Builder *b, int32_t argc, const Janet *argv) { emit_3(r, RULE_BETWEEN, 0, n, subrule); } +static void spec_opt(Builder *b, int32_t argc, const Janet *argv) { + peg_fixarity(b, argc, 1); + Reserve r = reserve(b, 4); + uint32_t subrule = compile1(b, argv[0]); + emit_3(r, RULE_BETWEEN, 0, 1, subrule); +} + static void spec_matchtime(Builder *b, int32_t argc, const Janet *argv) { peg_fixarity(b, argc, 2); Reserve r = reserve(b, 3); @@ -773,6 +779,7 @@ static const SpecialPair specials[] = { {"/", spec_replace}, {"<-", spec_capture}, {">", spec_look}, + {"?", spec_opt}, {"any", spec_any}, {"argument", spec_argument}, {"at-least", spec_atleast}, @@ -788,6 +795,7 @@ static const SpecialPair specials[] = { {"if-not", spec_ifnot}, {"look", spec_look}, {"not", spec_not}, + {"opt", spec_opt}, {"position", spec_position}, {"range", spec_range}, {"replace", spec_replace}, diff --git a/test/suite3.janet b/test/suite3.janet index 4c98385a..acf002be 100644 --- a/test/suite3.janet +++ b/test/suite3.janet @@ -319,4 +319,13 @@ (check-match janet-longstring "``` `` ```" true) (check-match janet-longstring "`` ```" false) +# Optional + +(check-match '(* (opt "hi") -1) "" true) +(check-match '(* (opt "hi") -1) "hi" true) +(check-match '(* (opt "hi") -1) "no" false) +(check-match '(* (? "hi") -1) "" true) +(check-match '(* (? "hi") -1) "hi" true) +(check-match '(* (? "hi") -1) "no" false) + (end-suite)