Zulip Chat Archive

Stream: new members

Topic: Matching if Statements of Another Syntax


Jack Hackshaw (Sep 07 2025 at 15:10):

I'm trying to embed a language in Lean. It seems like there is a conflict between lean's syntax and my language. The if syntax for the language looks like this:

if x > 0 {
    return 1;
} else {
    return 0;
}

I've defined it like this:

declare_syntax_cat if_else
syntax "if" term "{" doSeq "}" "else" "{" doSeq "}" : if_else

And I try to translate it to Lean with the following macro rule:

macro_rules
 | `(if_else| if $cond {$a}{$if_body} else {$else_body}) =>
   `(if $cond then do $if_body else do $else_body)

Notice the {$a}. If I don't include it I get an error.a has the type TSyntax Lean.Parser.Term.structInstField`

Regardless, if I write an if statement in my language Lean complains about a missing then so obviously, the macro rule is not being applied.

Jakub Nowak (Sep 07 2025 at 16:20):

It seems like you're trying to parse your if in the context where lean expects term. You declared your if to belong to if_else category, which is not term.

Jakub Nowak (Sep 07 2025 at 16:28):

You might be interested in reading https://leanprover-community.github.io/lean4-metaprogramming-book/main/08_dsls.html.

Kyle Miller (Sep 07 2025 at 17:19):

A significant issue with this syntax is that terms can be followed by curly braces; for example f { return 2 } is valid as a term, because return 2 is a term and { ... } is a term (singleton set). It goes for the longest valid parse.

What MrQubo points out should not be a problem for the macro rule, just as long as you are aware this is in the if_else category, and that you might need to make an if_else macro expander (macros are not expanded automatically, each category writes its own hook for that), and that you'll definitely need to use the if_else category in some syntax available to terms/doElems/etc.

It's possible set forbidden tokens to get this to parse, though withForbidden doesn't appear to be available in syntax, only lower-level parsers. Another option might be to adjust the precedence, but it's not possible to disambiguate x > 0 { return 1 } that way. Easiest is to change your DSL to use C syntax, if (x > 0) { ... } else { ... }. Harder is to make your own term category from scratch with exactly the term syntaxes you want.

Jack Hackshaw (Sep 08 2025 at 00:10):

Unfortunately, changing the DSL is not an option.

I am not wedded to using syntax, if I can get the desired result with a lower level parser that allows withForbidden then that is an option. Otherwise I guess I will have to do it the hard way and implement my own term category.

Do you have a recommendation on where I might look to get started?


Last updated: Dec 20 2025 at 21:32 UTC