Skip to content

Use named capture in error message? #289

@kfsone

Description

@kfsone

Consider the following which declares an enum grammar that wants to enforce a minimum requirement on the number of members. This works,

Enums <- Enum*
%whitespace <- [ \t\r\n]*
%word <- [A-Za-z0-9_.]+

NAME <- < [A-Za-z_][A-Za-z0-9_]* >

Enum <- 'enum' ↑ $name<NAME> '{' ↑ NAME+^enum_count '}'

enum_count <- '' { error_message "enum must contain at least one member" }

but it is inelegant:
image

It would be really nice if we could use the named capture in error_message. Some thoughts:

  • You could change the grammar to make allow error_message BACKREFERENCE (',' BACKREFERENCE) string_literal which would print the backreferences with a ': " after each one.
    meh.

  • You could allow sprintf or std::format formatting, error_message "{}: must have at least one member", $name,

  • You could perhaps provide an automatic "context stack". Consider, to which captures are automatically pushed/popped using '$^' instead of just '$', and $^'...' to push a literal:

TypeDef <- $^type<'type'> ↑ $^name<NAME> Parent? '{' Members '}'
Members <- Member (',' Member)* ','?
Member <- $^'member' $type<NAME> $^field<NAME> MemberDefault
MemberDefault <- '{' '}'  # imagine there's some complex recursion here

Now this has the capability automatically take:

type Connection { Status state {;} }

and report

1:33: type->Connection->member->state: unexpected ';', expecting '}'

Or perhaps rather than the ugly '$^'member' you could allow '^' infront of the production name to indicate it should push its name onto the context stack:

^Type <- 'type' ↑ $^name<NAME> Parent? '{' Members '}'
Members <- Member (',' Member)* ','?
^Member <- $type<NAME> $^field<NAME> DefaultValue
^DefaultValue <- '{' '}'
1:33: Type->Connection->Member->state->DefaultValue: unexpected ';', expecting '}'

If we tighten this down to one $^ per production, you can design the format so that, in rust terms:

match captures {
  Some(production), Some(capture) => { format!("{production} '{capture}': ") },
  Some(production), None => { format!("{production}: ") },
  None, Some(capture) => { format!("'{capture}': ") },
  None, None => { "" }
}
# given: `a b`
^JustType <- 'a' 'b' 'c'  # error: JustType: expecting 'c'
^JustCap <- 'a' $^name<'b'> 'c'  # error: 'b': expecting 'c'
^Both <- 'a' $^name<'b'> 'c'  # error: Both 'b': expecting 'c'
Neither <- 'a' 'b' 'c'  # error: expecting 'c'

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions