Last active
February 14, 2020 18:59
-
-
Save Gerrit0/bd8607759adcc2fdd9a5feba5c14e4e8 to your computer and use it in GitHub Desktop.
TypeScript type grammar - paste this into https://omrelli.ug/nearley-playground/
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@{% | |
const nth = n => d => d[n] | |
const intrinsic = d => ({ type: 'intrinsic', value: d[0] }) | |
%} | |
# I skipped function types and object types, running low on time. | |
Main -> _ Type0 _ {% d => JSON.stringify(d[1]) %} | |
# Handle precedence, lowest first | |
Type0 -> ConditionalType {% id %} | |
| UnionType {% id %} | |
| Type1 {% id %} | |
Type1 -> IntersectionType {% id %} | |
| Type2 {% id %} | |
Type2 -> | |
ArrayType {% id %} | |
| IndexedAccessType {% id %} | |
| InferredType {% id %} | |
| IntrinsicType {% id %} | |
| MappedType {% id %} | |
| ReferenceType {% id %} | |
| TupleType {% id %} | |
| TypeOperatorType {% id %} | |
| TypeQueryType {% id %} | |
| "(" _ Type0 _ ")" {% nth(2) %} | |
TypeList -> Type0 | |
| Type0 _ "," _ TypeList {% d => [d[0]].concat(d[4]) %} | |
ArrayType -> Type1 _ "[" _ "]" {% d => ({ type: 'array', valueType: d[0] }) %} | |
ConditionalType -> Type1 SP "extends" SP Type0 _ "?" _ Type0 _ ":" _ Type0 {% d => ({ | |
type: 'conditional', checkType: d[0], extendsType: d[4], trueType: d[8], falseType: d[12] | |
}) %} | |
IndexedAccessType -> Type1 _ "[" Type0 _ "]" {% d => ({ type: 'indexed-access', objectType: d[0], accessType: d[3] }) %} | |
InferredType -> "infer" SP TypeName {% d => ({ type: 'infer', name: d[2] }) %} | |
IntersectionType -> Type1 _ "&" _ Type2 {% d => ({ type: 'intersection', left: d[0], right: d[4] }) %} | |
IntrinsicType -> "any" {% intrinsic %} | |
| "unknown" {% intrinsic %} | |
| "never" {% intrinsic %} | |
| "number" {% intrinsic %} | |
| "boolean" {% intrinsic %} | |
| "true" {% intrinsic %} | |
| "false" {% intrinsic %} | |
| "bigint" {% intrinsic %} | |
| "symbol" {% intrinsic %} | |
MappedType -> "{" (_ ReadonlyModifier):? _ "[" _ TypeName _ "in" _ Type0 _ "]" (_ QuestionModifier):? _ ":" _ Type0 _ "}" | |
{% d => ({ | |
type: 'mapped', | |
readonlyModifier: d[1] ? d[1][1] : null, | |
questionModifier: d[12] ? d[12][1] : null, | |
keyName: d[5], | |
keyType: d[9], | |
valueType: d[16] | |
})%} | |
ReferenceType -> | |
TypeName {% d => ({ type: 'reference', target: d[0] }) %} | |
| TypeName _ "<" TypeList _ ">" {% d => ({ type: 'reference', target: d[0], args: d[3] }) %} | |
TupleType -> "[" _ TypeList _ "]" {% d => ({ type: 'tuple', items: d[2] }) %} | |
TypeOperatorType -> ("readonly" | "keyof") SP Type1 {% d => ({ type: 'operator', operator: d[0][0], type: d[2] }) %} | |
TypeQueryType -> "typeof" SP Identifier {% d => ({ type: 'query', name: d[2] }) %} | |
UnionType -> Type0 _ "|" _ Type1 {% d => ({ type: 'union', left: d[0], right: d[4] }) %} | |
ReadonlyModifier -> [+-]:? _ "readonly" {% d => d[0] != "-" %} | |
QuestionModifier -> [+-]:? _ "?" {% d => d[0] != "-" %} | |
TypeName -> Identifier {% id %} | |
# This is wrong, identifiers can start with lower case... but because | |
# I don't have a scanner here, avoid the ambiguity with IntrinsicType by pretending | |
# they all start with an uppercase letter. | |
Identifier -> [A-Z] [A-Za-z0-9]:* {% d => d[0] + d[1].join('') %} | |
SP -> [\s]:+ {% () => null %} | |
_ -> [\s]:* {% () => null %} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment