{{ let defIds = 0; let tyIds = 0; const Ty = (kind, loc) => ({ id: tyIds++, loc, kind }); }} Defs = _ defs:StructDef|.., _ | _ { return defs; } StructDef = "struct" _ ident:Ident _ generics:Generics? _ "{" fields:Fields "}" { return { id: defIds++, ident, loc: location(), generics, fields } } Fields = _ fields:FieldDef|.., _ "," _| _ ","? _ { return fields; } Generics = "<" _ params:Ident|.., _ "," _| _ ","? _ ">" { return { params }; } FieldDef = ident:Ident _ ":" _ ty:Ty { return { ident, loc: location(), ty }; } Ty = ty:Ty4 { return ty; } Ty4 = ty:Ty3 pairs:(_ "[" _ len:Ty? _ "]" { return { length: len, loc: location() }; })* { return pairs .reduce((inner, {length, loc: {end}}) => Ty({ tag: "array", length, ty: inner }, {...inner.loc, end}), ty); } / Ty3 Ty3 = ident:Ident _ "<" _ args:Ty|.., _ ", " _| _ ","? _ ">" { return Ty({ tag: "generic", ident, args }, location); } / Ty2 Ty2 = "{" fields:Fields "}" { return Ty({ tag: "struct_literal", fields }, location()); } / Ty1 Ty1 "type" = ident:Ident { return Ty({ tag: "ident", ident }, location()) } / value:Int { return Ty({ tag: "int", value }, location); } Ident "identifier" = [a-zA-Z_][a-zA-Z0-9_]* { return text(); } Int "integer" = ("0" / [1-9][0-9]*) { return parseInt(text()); } _ "whitespace" = (WhiteSpaceChars / SingleLineComment)* WhiteSpaceChars = [ \t\n\r] SingleLineComment = "//" (!"\n" .)* // vim: syntax=typescript commentstring=//\ %s