# Need a bit of help with an instaparse grammar

**URL:** https://clojureverse.org/t/need-a-bit-of-help-with-an-instaparse-grammar/965
**Category:** How to?
**Created:** [November 23, 2017, 8:26pm UTC](https://clojureverse.org/t/need-a-bit-of-help-with-an-instaparse-grammar/965 "2017-11-23T20:26:01Z")
**Posts on this page:** 5
**Page:** 1

<div class="post-metadata">

### Author: ![JeremS](https://clojureverse.org/user_avatar/clojureverse.org/jerems/32/3646_2.png) [@JeremS](https://clojureverse.org/u/JeremS)
#### Post date: [November 23, 2017, 8:26pm UTC](https://clojureverse.org/t/need-a-bit-of-help-with-an-instaparse-grammar/965/1 "2017-11-23T20:26:01Z")

</div>

Hey guys,

I am playing with instaparse and I have a problem contructucting a grammar.

Here is what I am going for

```clojure
(insta/defparser ex7
  "
  doc = (text | tag)*
  text = #'[^@]*'
  tag = '@' #'[a-z]*' inner-text*
  inner-text = '{' #'[^}]*' '}'
  ")

(ex7 "some text @toto{inner text}")

```

The problem is the parser when parsing a `tag` rule won’t consider the `inner-text` rule giving me the parse

```auto
[:doc [:text "some text "] [:tag "@" "toto"] [:text "{inner text}"]]

```

instead of the desired :

```auto
[:doc [:text "some text "] [:tag "@" "toto" [:inner-text "{" "inner text" "}"]]]

```

Any idea how I can modify the grammar so that the parser would consider the `inner-text rule` before going back to the `text` one ?

---

<div class="post-metadata">

### Author: ![floop](https://clojureverse.org/user_avatar/clojureverse.org/floop/32/472_2.png) [@floop](https://clojureverse.org/u/floop)
#### Post date: [November 23, 2017, 11:29pm UTC](https://clojureverse.org/t/need-a-bit-of-help-with-an-instaparse-grammar/965/2 "2017-11-23T23:29:40Z")

</div>

**ordered choice operator**

Instead of alternation `|`:

```auto
  doc = (text | tag)*

```

try the [ordered choice](https://github.com/Engelberg/instaparse#ordered-choice) operator `/`:

```auto
  doc = (tag / text)*

```

**debugging**

As you may know, `insta/parses` helps debug ambiguous grammars, by showing all parses.

```clojure
(->> (insta/parses ex7 "some text @toto{inner text}")
     clojure.pprint/pprint)

```

**ensuring tags, even if empty**

I’d tend to ensure an `:inner-text`, even if empty, just to keep things regular:

```clojure
  tag = '@' #'[a-z]*' inner-text
  inner-text = ( '{' #'[^}]*' '}' )*

```

---

<div class="post-metadata">

### Author: ![plexus](https://clojureverse.org/user_avatar/clojureverse.org/plexus/32/6_2.png) [@plexus](https://clojureverse.org/u/plexus)
#### Post date: [November 24, 2017, 11:13am UTC](https://clojureverse.org/t/need-a-bit-of-help-with-an-instaparse-grammar/965/3 "2017-11-24T11:13:52Z")

</div>

Hi @JeremS, if this answer solved your problem then you can mark it as “resolved” by checking the little checkmark underneath @floop’s post! That way others know that your question has been answered and you don’t need more help right now.

---

<div class="post-metadata">

### Author: ![JeremS](https://clojureverse.org/user_avatar/clojureverse.org/jerems/32/3646_2.png) [@JeremS](https://clojureverse.org/u/JeremS)
#### Post date: [November 24, 2017, 12:49pm UTC](https://clojureverse.org/t/need-a-bit-of-help-with-an-instaparse-grammar/965/4 "2017-11-24T12:49:13Z")

</div>

Hey guys thank you for the reply. The ordered choice operator works !

As a conclusion to this thread, here is some code using @floop solution and another suggested to me by Alex Engelberg on the instaparse channel of the clojure slack.

Here is @floop’s solution using PEG’s ordered choice operator in the `doc` rule:

```auto
(insta/defparser ex-with-choice
  "
  doc = (tag / text)*
  text = #'[^@]*'
  tag = <'@'> #'[a-z]\\w*' text-block*
  text-block = <'{'> inner-text <'}'>
  <inner-text> = #'[^}]*'
  ")

```

Alex’s solution uses PEG’s negative lookahead operator:

```auto
(insta/defparser ex-with-lookahead
  "
  doc = (text | tag)*
  text = #'[^@]*'
  tag = <'@'> #'[a-z]\\w*' text-block* !text-block
  text-block = <'{'> inner-text <'}'>
  <inner-text> = #'[^}]*'
  ")

```

The solutions seem to yield the same results

```auto

(= (ex-with-choice "some text @tag1{inner text}{inner text 2} some text 2 @tag2 other text")
   (ex-with-lookahead "some text @tag1{inner text}{inner text 2} some text 2 @tag2 other text"))
;=> true

```

Which is:

```auto
(ex-with-choice "some text @tag1{inner text}{inner text 2} some text 2 @tag2 other text")

;=>
[:doc
 [:text "some text "]
 [:tag "tag1" [:text-block "inner text"] [:text-block "inner text 2"]]
 [:text " some text 2 "]
 [:tag "tag2"]
 [:text " other text"]]

```

The PEG extensions in instaparse are very useful indeed.

Thx again. Cheers,

---

<div class="post-metadata">

### Author: ![system](https://clojureverse.org/uploads/default/original/2X/5/51079bf9e4b7d9466242c06cf1e43b9f8bd6da14.png) [@system](https://clojureverse.org/u/system)
#### Post date: [October 5, 2018, 12:50pm UTC](https://clojureverse.org/t/need-a-bit-of-help-with-an-instaparse-grammar/965/5 "2018-10-05T12:50:41Z")

</div>


