Zulip Chat Archive
Stream: new members
Topic: How to write a Parser for lean
kishou yusa (Jun 15 2024 at 07:45):
How can I create a new Parser to parse a comment likehere: https://github.com/leanprover/lean4/blob/fe0cb97c5d4d43393728ddd885415bc5bfb4b929/src/Lean/Parser/Term.lean#L14C5-L14C17.
I tried with my code here
declare_syntax_cat comment
declare_syntax_cat project_term
set_option trace.Elab.info true
partial def getCommentUntilTheEnd : ParserFn := fun c s =>
let input := c.input
let pos := s.pos
if h : input.atEnd pos then s else
let curr := input.get pos
if curr == '\n' then s.next' input pos h else
getCommentUntilTheEnd c (s.next' input pos h)
def commentBody : Parser := {
fn := getCommentUntilTheEnd
info := epsilonInfo
}
elab "begin_test" s:project_term* "end_test": command => pure ()
syntax comment_wrap := "/*" rawIdent "*/"
syntax comment_line := "//" commentBody
syntax comment_wrap : comment
syntax comment_line : comment
syntax comment : project_term
syntax basic_type := "int*" <|> "uint*" <|> "address" <|> "bool" <|> "string" <|> "bytes" <|> rawIdent "." rawIdent
begin_test
/* hello */
/* hello1 */
// fsadfsdaf
end_test
but for the line syntax comment_line : comment
it give error that don't know how to generate formatter for non-definition '{ info := epsilonInfo, fn := getCommentUntilTheEnd }'
Alex J. Best (Jun 16 2024 at 15:11):
I get loads of errors if I try and run your code in the web editor. Can you make a #mwe that works there with only one error (the one you want help with) to make it easier for others to answer your question
kishou yusa (Jun 16 2024 at 16:47):
Here is mwe
import Lean
import Lean.Parser.Term
import Lean.Parser.Attr
import Lean.Parser.Level
open Lean
open Lean.Parser
open Lean.Parser.Term
declare_syntax_cat comment
declare_syntax_cat project_term
set_option trace.Elab.info true
partial def getCommentUntilTheEnd : ParserFn := fun c s =>
let input := c.input
let pos := s.pos
if h : input.atEnd pos then s else
let curr := input.get pos
if curr == '\n' then s.next' input pos h else
getCommentUntilTheEnd c (s.next' input pos h)
def commentBody : Parser := {
fn := getCommentUntilTheEnd
info := epsilonInfo
}
elab "begin_test" s:project_term* "end_test": command => pure ()
syntax comment_wrap := "/*" rawIdent "*/"
syntax comment_line := "//" commentBody
syntax comment_wrap : comment
syntax comment_line : comment
syntax comment : project_term
syntax basic_type := "int*" <|> "uint*" <|> "address" <|> "bool" <|> "string" <|> "bytes" <|> rawIdent "." rawIdent
kishou yusa (Jun 17 2024 at 15:28):
ok I manage to solve the problem by adding formatter and parenthesizer, here is the final code:
partial def getCommentUntilTheEnd : ParserFn := fun c s =>
let input := c.input
let pos := s.pos
if h : input.atEnd pos then s else
let curr := input.get pos
if curr == '\n' then s.next' input pos h else
getCommentUntilTheEnd c (s.next' input pos h)
def commentBody : Parser := {
fn := getCommentUntilTheEnd
info := mkAtomicInfo "comment"
}
@[combinator_parenthesizer commentBody]
def commentBody.parenthesizer := PrettyPrinter.Parenthesizer.visitToken
@[combinator_formatter commentBody]
def commentBody.formatter := PrettyPrinter.Formatter.visitAtom Name.anonymous
elab "begin_test" s:project_term* "end_test": command => pure ()
syntax comment_wrap := "/*" rawIdent "*/"
syntax comment_line := "//" commentBody
syntax comment_wrap : comment
syntax comment_line : comment
syntax comment : project_term
syntax basic_type := "int*" <|> "uint*" <|> "address" <|> "bool" <|> "string" <|> "bytes" <|> rawIdent "." rawIdent
but I don't understand why do I need to add those, I just take it from the commentBody of lean4
Last updated: May 02 2025 at 03:31 UTC