structemit/parser.pegjs
2025-03-18 02:10:45 +01:00

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