61 lines
1.5 KiB
JavaScript
61 lines
1.5 KiB
JavaScript
{{
|
|
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
|
|
|