Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Very weird bug using otherwise OK parsers in Union #389

Closed
oguimbal opened this issue Feb 20, 2024 · 5 comments
Closed

Very weird bug using otherwise OK parsers in Union #389

oguimbal opened this issue Feb 20, 2024 · 5 comments

Comments

@oguimbal
Copy link

oguimbal commented Feb 20, 2024

Hi !

I'm a bit new to Participle, but I've been writting parsers for a while, and I'm falling a bit short on why the last test fails to parse

func TestBrokenUnion(t *testing.T) {

	// ==========================================
	// ==== check that "named" parser works =====
	// ==========================================

	type Named struct {
		Name string `@(Ident ('.' Ident)?)`
	}

	namedParser := participle.MustBuild[Named]()

	// parses a named type with dot ✅
	named, err := namedParser.ParseString("", "Abc.def")
	require.NoError(t, err)
	require.Equal(t, &Named{Name: "Abc.def"}, named)

	// parses a named type without dot ✅
	named, err = namedParser.ParseString("", "Abc")
	require.NoError(t, err)
	require.Equal(t, &Named{Name: "Abc"}, named)

	// ===========================================
	// ==== use this type parser in an union =====
	// ===========================================

	type AnyType interface{}
	type ArrayOf struct {
		Of *Named `@@ '[' ']'`
	}
	typeParser := participle.MustBuild[AnyType](
		// union includes the "named" parser, which works
		participle.Union[AnyType](&ArrayOf{}, &Named{}),
	)

	// parses an array type without dot ✅
	typ, err := typeParser.ParseString("", "Abc[]")
	require.NoError(t, err)
	require.Equal(t, &ArrayOf{Of: &Named{Name: "Abc"}}, *typ)

	// parses an array type with dot ✅
	typ, err = typeParser.ParseString("", "Abc.def[]")
	require.NoError(t, err)
	require.Equal(t, &ArrayOf{Of: &Named{Name: "Abc.def"}}, *typ)

	// parses non array type without dot ✅
	typ, err = typeParser.ParseString("", "Abc")
	require.NoError(t, err)
	require.Equal(t, &Named{Name: "Abc"}, *typ)

	// parses non array type with dot
	//   ❌  unexpected token "<EOF>" (expected "[" "]")
	//   👉  why hasnt it fallback on "named" parser, as the array did not match ?
	//    (like it did on the test above)
	typ, err = typeParser.ParseString("", "Abc.def")
	require.NoError(t, err)
	require.Equal(t, &Named{Name: "Abc.def"}, *typ)
}

Any idea ?

Thanks

@alecthomas
Copy link
Owner

I can't really parse this as-is. Can you paste a link to a failing example on https://play.golang.org that illustrates the issue?

@oguimbal
Copy link
Author

sure, here it is https://go.dev/play/p/tais4cSPVOz

@oguimbal
Copy link
Author

oguimbal commented Mar 5, 2024

Hi @alecthomas, any way I can help ? If you point me in the right direction I might try a PR

@alecthomas
Copy link
Owner

You need to configure Participle to use enough lookahead that it will be able to backtrack if a branch fails. In this case participle.UseLookahead(4) seems to work.

@oguimbal
Copy link
Author

oguimbal commented Mar 6, 2024

Oh thanks !

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants