Zulip Chat Archive

Stream: lean4

Topic: make syntax cat accept empty string


Alexander Bentkamp (Nov 11 2022 at 14:20):

How can I make a syntax category accept the empty string?

import Lean

open Lean
open Lean.Parser

declare_syntax_cat manyPlus
syntax ("+"*) : manyPlus

#eval ((do logInfo s!"{runParserCategory (← getEnv) `manyPlus "+ +"}") : Elab.TermElabM _)
-- ok: («manyPlus+» ["+" "+"])

#eval ((do logInfo s!"{runParserCategory (← getEnv) `manyPlus "+"}") : Elab.TermElabM _)
-- ok: («manyPlus+» ["+"])

#eval ((do logInfo s!"{runParserCategory (← getEnv) `manyPlus ""}") : Elab.TermElabM _)
-- error: <input>:1:0: unexpected end of input

Sebastian Ullrich (Nov 11 2022 at 14:21):

:astonished:

Sebastian Ullrich (Nov 11 2022 at 14:23):

Is using a wrapper syntax foo := (manyPlus)? not an option?

Alexander Bentkamp (Nov 11 2022 at 15:37):

I am using runParserCategory, so I think it has to be a syntax category. Or is there a similar function for syntax that does not have its own category? Of course, I can work around the whole issue by checking whether what I am parsing is only whitespace. I just wanted to make sure I am not missing a better solution here.

Mario Carneiro (Nov 11 2022 at 15:42):

you can just run Parser.optional (runParserCategory ...) in that case, I think?

Sebastian Ullrich (Nov 11 2022 at 15:43):

Not quite, you'd have to copy its implementation and change the invoked parser p

Mario Carneiro (Nov 11 2022 at 15:44):

hm, there should be a Parser.run frontend that just takes a string and a Parser

François G. Dorais (Nov 12 2022 at 22:47):

I'm running into a related issue and, before I try to work on a workaround, what is the issue behind having a Parser.run frontend as @Mario Carneiro just described?

Mario Carneiro (Nov 12 2022 at 22:48):

it's not difficult to write, you can just adapt runParserCategory

Mario Carneiro (Nov 12 2022 at 22:50):

import Lean
open Lean Parser

/-- convenience function for testing -/
def Parser.run (env : Environment) (p : Parser) (input : String) (fileName := "<input>") : Except String Syntax :=
  let c := mkParserContext (mkInputContext input fileName) { env := env, options := {} }
  let s := mkParserState input
  let s := whitespace c s
  let s := p.fn c s
  if s.hasError then
    Except.error (s.toErrorMsg c)
  else if input.atEnd s.pos then
    Except.ok s.stxStack.back
  else
    Except.error ((s.mkError "end of input").toErrorMsg c)

François G. Dorais (Nov 12 2022 at 23:12):

Can I drop env if I don't need fileName? (I'm only parsing strings in my use case.)

François G. Dorais (Nov 12 2022 at 23:14):

Seems like mkParserState might use the environment.

Mario Carneiro (Nov 12 2022 at 23:24):

no, parsers need the environment because a parser might call a category parser which needs everything in the parser extension

Mario Carneiro (Nov 12 2022 at 23:24):

fileName is only used in error messages AFAIK

François G. Dorais (Nov 12 2022 at 23:39):

Right. That makes sense. Thanks!

Sebastian Ullrich (Nov 13 2022 at 08:30):

You can keep the environment empty if all your parsers are builtin, though that is not currently possible with syntax


Last updated: Dec 20 2023 at 11:08 UTC