Syntax and Semantics

Introduction to expressions types and (^)

The full explanation of the what and why of types is available in the section The Story of Oak. A goal of this library is to give a type to any expression grammar. This permits to call a semantic action without naming expressions. In some cases, for example with the spacing rule spacing = [" \n\t"]*, the grammar compiler will not generate the expected type, here the rule spacing has type Vec<char> instead of () — we usually do not care about spaces. Therefore, users must annotate expressions with e -> () to force their types to be (). It works and is enough for most cases. However, we sometimes want to propagate unit type up in the expression tree because these expressions are only of syntactic interest. The fact is that e? has type Option<T> even if T = (). It is expected since Option<()> carries a boolean information about the presence of something. If we do not care, we can annotate e with (^) and the unit type will automatically be propagated, and even e1? e2* will have type (^) if e1 and e2 have type (^). In the end, the goal is really to give an expression the type that you expect it to have!