Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Tree-sitter grammar: support Records #5348

Merged
merged 7 commits into from
Apr 17, 2024
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
Tree-sitter grammar: support Records
OceanOak committed Apr 17, 2024
commit 2317b9372f757b942fb1c7114d53bca03f43b466
38 changes: 35 additions & 3 deletions backend/testfiles/execution/stdlib/parser.dark
Original file line number Diff line number Diff line change
@@ -63,16 +63,28 @@ module ParseToSimplifiedTree =

ParsedNode
{ fieldName = Stdlib.Option.Option.Some "typ"
typ = "type_reference"
typ = "type_decl_def"
text = "Int64"
sourceRange = range (0L, 10L) (0L, 15L)
children =
[ ParsedNode
{ fieldName = Stdlib.Option.Option.None
typ = "builtin_type"
typ = "type_decl_def_alias"
text = "Int64"
sourceRange = range (0L, 10L) (0L, 15L)
children = [] } ] } ] } ] }
children =
[ ParsedNode
{ fieldName = Stdlib.Option.Option.None
typ = "type_reference"
text = "Int64"
sourceRange = range (0L, 10L) (0L, 15L)
children =
[ ParsedNode
{ fieldName = Stdlib.Option.Option.None
typ = "builtin_type"
text = "Int64"
sourceRange = range (0L, 10L) (0L, 15L)
children = [] } ] } ] } ] } ] } ] }


("" |> Builtin.parserParseToSimplifiedTree) = ParsedNode
@@ -232,6 +244,18 @@ module TextToTextRoundtripping =
module TypeDeclaration =
("type SimpleAlias = Unit" |> roundtripCliScript) = "type SimpleAlias =\n Unit"

// record type
("type Person = {name: String}" |> roundtripCliScript) = "type Person =\n { name: String }"

("type Person = {name: String; age: Int64}" |> roundtripCliScript) = "type Person =\n { name: String\n age: Int64 }"
("type Person = {name: String; age: Int64; hasPet: Bool}" |> roundtripCliScript) = "type Person =\n { name: String\n age: Int64\n hasPet: Bool }"

("type Person = {name: String; age: Int64; hasPet: Bool; pet: Pet}"
|> roundtripCliScript) = """type Person =
{ name: String
age: Int64
hasPet: Bool
pet: Pet }"""

module Expr =
// units
@@ -298,6 +322,14 @@ module TextToTextRoundtripping =
("(1L, \"hello\", 2L, true)" |> roundtripCliScript) = "(1L, \"hello\", 2L, true)"
("(1L, 2L + 3L, 4L)" |> roundtripCliScript) = "(1L, (2L) + (3L), 4L)"

// record literal
("Person {name =\"John\"} " |> roundtripCliScript) = "Person { name = \"John\" }"
("Person {name =\"John\"; age = 30L} " |> roundtripCliScript) = "Person { name = \"John\"; age = 30L }"
("Person {name =\"John\"; age = 30L; hasPet = true} " |> roundtripCliScript) = "Person { name = \"John\"; age = 30L; hasPet = true }"

("Person {name =\"John\"; age = 30L; hasPet = true; pet = Pet {name = \"Luna\"}} "
|> roundtripCliScript) = "Person { name = \"John\"; age = 30L; hasPet = true; pet = Pet { name = \"Luna\" } }"

// variables and let bindings
("assumedlyAVariableName" |> roundtripCliScript) = "assumedlyAVariableName"
// TODO: this is ugly
8 changes: 4 additions & 4 deletions packages/darklang/languageTools/nameResolver.dark
Original file line number Diff line number Diff line change
@@ -121,11 +121,11 @@ module Darklang =
(packageThingExists: String -> Bool)
(allowError: Bool)
(currentModule: List<String>)
(name: LanguageTools.WrittenTypesToProgramTypes.Name)
(name: LanguageTools.WrittenTypes.Name)
: LanguageTools.ProgramTypes.NameResolution<LanguageTools.ProgramTypes.FQTypeName.FQTypeName> =

match name with
| Unresolved given ->
| Unresolved(_, given) ->
let result =
Stdlib.List.fold
(NameResolver.namesToTry given currentModule)
@@ -172,7 +172,7 @@ module Darklang =
let maybeResolve
(resolver: NameResolver.NameResolutionSettings)
(currentModule: List<String>)
(name: LanguageTools.WrittenTypesToProgramTypes.Name)
(name: LanguageTools.WrittenTypes.Name)
: LanguageTools.ProgramTypes.NameResolution<LanguageTools.ProgramTypes.FQTypeName.FQTypeName> =

resolveTypeName
@@ -186,7 +186,7 @@ module Darklang =
let resolve
(resolver: NameResolver.NameResolutionSettings)
(currentModule: List<String>)
(name: LanguageTools.WrittenTypesToProgramTypes.Name)
(name: LanguageTools.WrittenTypes.Name)
: LanguageTools.ProgramTypes.NameResolution<LanguageTools.ProgramTypes.FQTypeName.FQTypeName> =
resolveTypeName
LanguageTools.Parser.parseName
226 changes: 220 additions & 6 deletions packages/darklang/languageTools/parser.dark
Original file line number Diff line number Diff line change
@@ -388,6 +388,26 @@ module Darklang =


let parse
(node: ParsedNode)
: Stdlib.Result.Result<WrittenTypes.TypeReference.TypeReference, WrittenTypes.Unparseable> =
if node.typ == "type_decl_def_alias" then
match node.children with
| [ single ] when single.typ == "type_reference" ->
parseTypeReference single

| _ ->
(WrittenTypes.Unparseable { source = node })
|> Stdlib.Result.Result.Error

elif node.typ == "type_reference" then
parseTypeReference node

else
(WrittenTypes.Unparseable { source = node })
|> Stdlib.Result.Result.Error


let parseTypeReference
(node: ParsedNode)
: Stdlib.Result.Result<WrittenTypes.TypeReference.TypeReference, WrittenTypes.Unparseable> =
if node.typ == "type_reference" then
@@ -428,13 +448,82 @@ module Darklang =
let parseDefinition
(node: ParsedNode)
: Stdlib.Result.Result<WrittenTypes.TypeDeclaration.Definition, WrittenTypes.Unparseable> =
if node.typ == "type_reference" then
match TypeReference.parse node with
| Ok typeRef ->
(WrittenTypes.TypeDeclaration.Definition.Alias typeRef)
|> Stdlib.Result.Result.Ok
if node.typ == "type_decl_def" then
match node.children with
| [ child ] when child.typ == "type_decl_def_alias" ->

| Error _ ->
match TypeReference.parse child with
| Ok typeRef ->
(WrittenTypes.TypeDeclaration.Definition.Alias typeRef)
|> Stdlib.Result.Result.Ok
| Error _ ->
(WrittenTypes.Unparseable { source = node })
|> Stdlib.Result.Result.Error

| [ child ] when child.typ == "type_decl_def_record" ->
let openBraceNode =
(findNodeByFieldName child "symbol_open_brace")
|> Stdlib.Option.toResult
"No symbol_open_brace node found in type_decl_def_record"

let recordFields =
match (findNodeByFieldName child "content") with
| Some contentNode ->
contentNode.children
|> Stdlib.List.filter (fun c ->
c.typ == "type_decl_def_record_field")
|> Stdlib.List.map (fun fieldNode ->
let fieldNameNode =
(findNodeByFieldName fieldNode "field")
|> Stdlib.Option.toResult
"No field_name node found in type_decl_def_record"

let symbolColonNode =
(findNodeByFieldName fieldNode "symbol_colon")
|> Stdlib.Option.toResult
"No symbol_colon node found in type_decl_def_record"

let fieldTypeNode =
(findNodeByFieldName fieldNode "type")
|> Stdlib.Option.toResult
"No field_type node found in type_decl_def_record"

match fieldNameNode, symbolColonNode, fieldTypeNode with
| Ok fieldNameNode, Ok symbolColonNode, Ok fieldTypeNode ->
let fieldName = fieldNameNode.text
let fieldType = TypeReference.parse fieldTypeNode

match fieldType with
| Ok fieldType ->
(WrittenTypes.TypeDeclaration.RecordField
{ range = fieldNode.sourceRange
name = fieldName
typ = fieldType
description = ""
symbolColon = symbolColonNode.sourceRange })
|> Stdlib.Result.Result.Ok

| Error _ ->
(WrittenTypes.Unparseable { source = fieldTypeNode })
|> Stdlib.Result.Result.Error
| _ ->
(WrittenTypes.Unparseable { source = fieldNode })
|> Stdlib.Result.Result.Error)
| None -> [] |> Stdlib.Result.Result.Ok

let recordFields = recordFields |> Stdlib.Result.values

let closeBraceNode =
(findNodeByFieldName child "symbol_close_brace")
|> Stdlib.Option.toResult
"No symbol_close_brace node found in type_decl_def_record"

match openBraceNode, recordFields, closeBraceNode with
| Ok openBraceNode, Ok recordFields, Ok closeBraceNode ->
(WrittenTypes.TypeDeclaration.Definition.Record recordFields)
|> Stdlib.Result.Result.Ok

| _ ->
(WrittenTypes.Unparseable { source = node })
|> Stdlib.Result.Result.Error

@@ -1017,6 +1106,129 @@ module Darklang =
|> Stdlib.Result.Result.Error


let parseRecordLiteral
(node: ParsedNode)
: Stdlib.Result.Result<WrittenTypes.Expr, WrittenTypes.Unparseable> =
if node.typ == "record_literal" then
let typeNameNode =
(findNodeByFieldName node "type_name")
|> Stdlib.Option.toResult "No type_name node found in record_literal"

let openBraceNode =
(findNodeByFieldName node "symbol_open_brace")
|> Stdlib.Option.toResult
"No symbol_open_brace node found in record_literal"

let contents =
node
|> findNodeByFieldName "content"
|> Stdlib.Option.map (fun contentsNode ->
contentsNode.children
|> Stdlib.List.chunkBySize 2L
|> Builtin.unwrap
|> Stdlib.List.map (fun chunk ->
match chunk with
| [ recordPairNode; _separator ] ->
let fieldNode =
(findNodeByFieldName recordPairNode "field")
|> Stdlib.Option.toResult
"No field node found in record_pair"

let symbolEqualsNode =
(findNodeByFieldName recordPairNode "symbol_equals")
|> Stdlib.Option.toResult
"No symbol_equals node found in record_pair"

let valueNode =
(findNodeByFieldName recordPairNode "value")
|> Stdlib.Option.toResult
"No value node found in record_pair"

match fieldNode, symbolEqualsNode, valueNode with
| Ok fieldNode, Ok symbolEqualsNode, Ok valueNode ->
let field = fieldNode.text
let value = Expr.parse valueNode

match value with
| Ok value -> (symbolEqualsNode, field, value)
| _ ->
Stdlib.Result.Result.Error(
WrittenTypes.Unparseable { source = recordPairNode }
)
| _ ->
Stdlib.Result.Result.Error(
WrittenTypes.Unparseable { source = chunk }
)

| [ recordPairNode ] ->
let fieldNode =
(findNodeByFieldName recordPairNode "field")
|> Stdlib.Option.toResult
"No field node found in record_pair"

let symbolEqualsNode =
(findNodeByFieldName recordPairNode "symbol_equals")
|> Stdlib.Option.toResult
"No symbol_equals node found in record_pair"

let valueNode =
(findNodeByFieldName recordPairNode "value")
|> Stdlib.Option.toResult
"No value node found in record_pair"

match fieldNode, symbolEqualsNode, valueNode with
| Ok fieldNode, Ok symbolEqualsNode, Ok valueNode ->
let field = fieldNode.text
let value = Expr.parse valueNode

match value with
| Ok value -> (symbolEqualsNode, field, value)
| _ ->
Stdlib.Result.Result.Error(
WrittenTypes.Unparseable { source = recordPairNode }
)
| _ ->
Stdlib.Result.Result.Error(
WrittenTypes.Unparseable { source = chunk }
)
| _ ->
Stdlib.Result.Result.Error(
WrittenTypes.Unparseable { source = chunk }
)))
|> Stdlib.Option.withDefault []

let closeBraceNode =
(findNodeByFieldName node "symbol_close_brace")
|> Stdlib.Option.toResult
"No symbol_close_brace node found in record_literal"

match typeNameNode, openBraceNode, closeBraceNode with
| Ok typeNameNode, Ok openBraceNode, Ok closeBraceNode ->
let typeNameNode =
Darklang.LanguageTools.WrittenTypes.Name.Unresolved(
typeNameNode.sourceRange,
[ typeNameNode.text ]
)

(WrittenTypes.Expr.ERecord(
node.sourceRange,
typeNameNode,
contents,
openBraceNode.sourceRange,
closeBraceNode.sourceRange
))
|> Stdlib.Result.Result.Ok

| _ ->
(WrittenTypes.Unparseable { source = node })
|> Stdlib.Result.Result.Error

else
(WrittenTypes.Unparseable { source = node })
|> Stdlib.Result.Result.Error



let parseLetExpr
(node: ParsedNode)
: Stdlib.Result.Result<WrittenTypes.Expr, WrittenTypes.Unparseable> =
@@ -1302,6 +1514,8 @@ module Darklang =
| "dict_literal" -> parseDictLiteral node
| "tuple_literal" -> parseTupleLiteral node

| "record_literal" -> parseRecordLiteral node

// assigning and accessing variables
| "let_expression" -> parseLetExpr node
| "variable_identifier" ->
17 changes: 17 additions & 0 deletions packages/darklang/languageTools/semanticTokens.dark
Original file line number Diff line number Diff line change
@@ -340,6 +340,23 @@ module Darklang =
[ makeToken symbolCloseParen TokenType.Symbol ] ]
|> Stdlib.List.flatten

// Person { name = "Alice" }
| ERecord(range, name, fields, symbolOpenBrace, symbolCloseBrace) ->
let fields =
fields
|> Stdlib.List.map (fun (_, fieldName, value) -> Expr.tokenize value)
|> Stdlib.List.flatten

[ // Person
QualifiedTypeIdentifier.tokenize name
// {
[ makeToken symbolOpenBrace TokenType.Symbol ]
// name = "Alice"
fields
// }
[ makeToken symbolCloseBrace TokenType.Symbol ] ]
|> Stdlib.List.flatten

// let x = 2
// x + 1
| ELet(range, lp, expr, body, keywordLet, symbolEquals) ->
19 changes: 18 additions & 1 deletion packages/darklang/languageTools/writtenTypes.dark
Original file line number Diff line number Diff line change
@@ -31,6 +31,7 @@ module Darklang =
fn: FnIdentifier
}

type Name = Unresolved of SourceRange * List<String>

// Types
module TypeReference =
@@ -86,7 +87,16 @@ module Darklang =


module TypeDeclaration =
type Definition = Alias of TypeReference.TypeReference
type RecordField =
{ range: SourceRange
name: String
typ: TypeReference.TypeReference
description: String
symbolColon: SourceRange }

type Definition =
| Alias of TypeReference.TypeReference
| Record of List<RecordField>

type TypeDeclaration =
{ range: SourceRange
@@ -200,6 +210,13 @@ module Darklang =
symbolOpenParen: SourceRange *
symbolCloseParen: SourceRange

| ERecord of
SourceRange *
typeName: Name *
fields: List<SourceRange * String * Expr> *
symbolOpenBrace: SourceRange *
symbolCloseBrace: SourceRange

| ELet of
SourceRange *
LetPattern *
27 changes: 26 additions & 1 deletion packages/darklang/languageTools/writtenTypesToProgramTypes.dark
Original file line number Diff line number Diff line change
@@ -26,7 +26,7 @@ module Darklang =
NameResolver.TypeName.resolve
resolver
currentModule
(WrittenTypesToProgramTypes.Name.Unresolved nametoResolve)
(WrittenTypes.Name.Unresolved(i.range, nametoResolve))

match resolvedName with
| Ok n -> n
@@ -117,6 +117,17 @@ module Darklang =


module TypeDeclaration =
module RecordField =
let toPT
(resolver: NameResolver.NameResolutionSettings)
(f: WrittenTypes.TypeDeclaration.RecordField)
: ProgramTypes.TypeDeclaration.RecordField =

ProgramTypes.TypeDeclaration.RecordField
{ name = f.name
typ = TypeReference.toPT resolver f.typ
description = "" }

module Definition =
let toPT
(resolver: NameResolver.NameResolutionSettings)
@@ -129,6 +140,12 @@ module Darklang =

ProgramTypes.TypeDeclaration.Definition.Alias typ

| Record fields ->
let fields =
Stdlib.List.map fields (fun f -> RecordField.toPT resolver f)

ProgramTypes.TypeDeclaration.Definition.Record fields

let toPT
(resolver: NameResolver.NameResolutionSettings)
(d: WrittenTypes.TypeDeclaration.TypeDeclaration)
@@ -249,6 +266,14 @@ module Darklang =

ProgramTypes.Expr.ETuple(gid (), first, second, rest)

| ERecord(_, name, fields, _, _) ->
let name = NameResolver.TypeName.resolve resolver [] name

let fields =
Stdlib.List.map fields (fun (_, k, v) -> (k, toPT resolver v))

ProgramTypes.Expr.ERecord(gid (), name, fields)

// declaring and accessing variables
| ELet(_, pat, rhs, body, _, _) ->
ProgramTypes.Expr.ELet(
9 changes: 4 additions & 5 deletions packages/darklang/prettyPrinter/programTypes.dark
Original file line number Diff line number Diff line change
@@ -701,9 +701,8 @@ module Darklang =
$"{name} = {PrettyPrinter.ProgramTypes.expr expr}")
|> Stdlib.String.join "; "
|> fun parts -> "{ " ++ parts ++ " }"
|> PrettyPrinter.indent

$"{typeNamePart}\n{fieldPart}"
$"{typeNamePart} {fieldPart}"

| EEnum(_id, typeName, caseName, fields) ->
let typeNamePart =
@@ -901,7 +900,7 @@ module Darklang =
(d: LanguageTools.ProgramTypes.TypeDeclaration.RecordField)
: String =
// TODO: /// for description
$"{d.name} : {PrettyPrinter.ProgramTypes.typeReference d.typ}"
$"{d.name}: {PrettyPrinter.ProgramTypes.typeReference d.typ}"

let enumField
(d: LanguageTools.ProgramTypes.TypeDeclaration.EnumField)
@@ -937,9 +936,9 @@ module Darklang =
fields
|> Stdlib.List.map (fun field ->
PrettyPrinter.ProgramTypes.TypeDeclaration.recordField field)
|> Stdlib.String.join "\n"
|> Stdlib.String.join "\n "

"{\n" ++ (PrettyPrinter.indent fieldsPart) ++ "\n}"
"{ " ++ (fieldsPart) ++ " }"

| Enum cases ->
cases
59 changes: 58 additions & 1 deletion tree-sitter-darklang/grammar.js
Original file line number Diff line number Diff line change
@@ -62,7 +62,37 @@ module.exports = grammar({
field("keyword_type", alias("type", $.keyword)),
field("name", $.type_identifier),
field("symbol_equals", alias("=", $.symbol)),
field("typ", $.type_reference),
field("typ", $.type_decl_def),
),

type_decl_def: $ => choice($.type_decl_def_alias, $.type_decl_def_record),

type_decl_def_alias: $ => $.type_reference,

// e.g. `type Person = { name: String; age: Int }`
type_decl_def_record: $ =>
seq(
field("symbol_open_brace", alias("{", $.symbol)),
field("content", optional($.type_decl_def_record_content)),
field("symbol_close_brace", alias("}", $.symbol)),
),

type_decl_def_record_content: $ =>
seq(
$.type_decl_def_record_field,
repeat(
seq(
field("record_separator", alias(";", $.symbol)),
$.type_decl_def_record_field,
),
),
),

type_decl_def_record_field: $ =>
seq(
field("field", $.variable_identifier),
field("symbol_colon", alias(":", $.symbol)),
field("type", $.type_reference),
),

//
@@ -88,6 +118,7 @@ module.exports = grammar({
$.list_literal,
$.tuple_literal,
$.dict_literal,
$.record_literal,
$.if_expression,
$.let_expression,
$.variable_identifier,
@@ -357,6 +388,32 @@ module.exports = grammar({
),
),

//
// Record
// // TODO: allow multi-line records where a newline is 'interpreted' as a record delimiter (i.e. no ; needed)
record_literal: $ =>
seq(
field("type_name", $.qualified_type_name),
field("symbol_open_brace", alias("{", $.symbol)),
field("content", optional($.record_content)),
field("symbol_close_brace", alias("}", $.symbol)),
),
record_content: $ =>
seq(
$.record_pair,
repeat(
seq(field("record_separator", alias(";", $.symbol)), $.record_pair),
),
),
record_pair: $ =>
seq(
field("field", $.variable_identifier),
field("symbol_equals", alias("=", $.symbol)),
field("value", $.expression),
),

//
// If expressions
if_expression: $ =>
prec.right(
seq(
259 changes: 259 additions & 0 deletions tree-sitter-darklang/src/grammar.json
Original file line number Diff line number Diff line change
@@ -221,6 +221,138 @@
{
"type": "FIELD",
"name": "typ",
"content": {
"type": "SYMBOL",
"name": "type_decl_def"
}
}
]
},
"type_decl_def": {
"type": "CHOICE",
"members": [
{
"type": "SYMBOL",
"name": "type_decl_def_alias"
},
{
"type": "SYMBOL",
"name": "type_decl_def_record"
}
]
},
"type_decl_def_alias": {
"type": "SYMBOL",
"name": "type_reference"
},
"type_decl_def_record": {
"type": "SEQ",
"members": [
{
"type": "FIELD",
"name": "symbol_open_brace",
"content": {
"type": "ALIAS",
"content": {
"type": "STRING",
"value": "{"
},
"named": true,
"value": "symbol"
}
},
{
"type": "FIELD",
"name": "content",
"content": {
"type": "CHOICE",
"members": [
{
"type": "SYMBOL",
"name": "type_decl_def_record_content"
},
{
"type": "BLANK"
}
]
}
},
{
"type": "FIELD",
"name": "symbol_close_brace",
"content": {
"type": "ALIAS",
"content": {
"type": "STRING",
"value": "}"
},
"named": true,
"value": "symbol"
}
}
]
},
"type_decl_def_record_content": {
"type": "SEQ",
"members": [
{
"type": "SYMBOL",
"name": "type_decl_def_record_field"
},
{
"type": "REPEAT",
"content": {
"type": "SEQ",
"members": [
{
"type": "FIELD",
"name": "record_separator",
"content": {
"type": "ALIAS",
"content": {
"type": "STRING",
"value": ";"
},
"named": true,
"value": "symbol"
}
},
{
"type": "SYMBOL",
"name": "type_decl_def_record_field"
}
]
}
}
]
},
"type_decl_def_record_field": {
"type": "SEQ",
"members": [
{
"type": "FIELD",
"name": "field",
"content": {
"type": "SYMBOL",
"name": "variable_identifier"
}
},
{
"type": "FIELD",
"name": "symbol_colon",
"content": {
"type": "ALIAS",
"content": {
"type": "STRING",
"value": ":"
},
"named": true,
"value": "symbol"
}
},
{
"type": "FIELD",
"name": "type",
"content": {
"type": "SYMBOL",
"name": "type_reference"
@@ -307,6 +439,10 @@
"type": "SYMBOL",
"name": "dict_literal"
},
{
"type": "SYMBOL",
"name": "record_literal"
},
{
"type": "SYMBOL",
"name": "if_expression"
@@ -1577,6 +1713,129 @@
]
}
},
"record_literal": {
"type": "SEQ",
"members": [
{
"type": "FIELD",
"name": "type_name",
"content": {
"type": "SYMBOL",
"name": "qualified_type_name"
}
},
{
"type": "FIELD",
"name": "symbol_open_brace",
"content": {
"type": "ALIAS",
"content": {
"type": "STRING",
"value": "{"
},
"named": true,
"value": "symbol"
}
},
{
"type": "FIELD",
"name": "content",
"content": {
"type": "CHOICE",
"members": [
{
"type": "SYMBOL",
"name": "record_content"
},
{
"type": "BLANK"
}
]
}
},
{
"type": "FIELD",
"name": "symbol_close_brace",
"content": {
"type": "ALIAS",
"content": {
"type": "STRING",
"value": "}"
},
"named": true,
"value": "symbol"
}
}
]
},
"record_content": {
"type": "SEQ",
"members": [
{
"type": "SYMBOL",
"name": "record_pair"
},
{
"type": "REPEAT",
"content": {
"type": "SEQ",
"members": [
{
"type": "FIELD",
"name": "record_separator",
"content": {
"type": "ALIAS",
"content": {
"type": "STRING",
"value": ";"
},
"named": true,
"value": "symbol"
}
},
{
"type": "SYMBOL",
"name": "record_pair"
}
]
}
}
]
},
"record_pair": {
"type": "SEQ",
"members": [
{
"type": "FIELD",
"name": "field",
"content": {
"type": "SYMBOL",
"name": "variable_identifier"
}
},
{
"type": "FIELD",
"name": "symbol_equals",
"content": {
"type": "ALIAS",
"content": {
"type": "STRING",
"value": "="
},
"named": true,
"value": "symbol"
}
},
{
"type": "FIELD",
"name": "value",
"content": {
"type": "SYMBOL",
"name": "expression"
}
}
]
},
"if_expression": {
"type": "PREC_RIGHT",
"value": 0,
244 changes: 244 additions & 0 deletions tree-sitter-darklang/src/node-types.json
Original file line number Diff line number Diff line change
@@ -319,6 +319,10 @@
"type": "paren_expression",
"named": true
},
{
"type": "record_literal",
"named": true
},
{
"type": "string_literal",
"named": true
@@ -1061,6 +1065,114 @@
]
}
},
{
"type": "record_content",
"named": true,
"fields": {
"record_separator": {
"multiple": true,
"required": false,
"types": [
{
"type": "symbol",
"named": true
}
]
}
},
"children": {
"multiple": true,
"required": true,
"types": [
{
"type": "record_pair",
"named": true
}
]
}
},
{
"type": "record_literal",
"named": true,
"fields": {
"content": {
"multiple": false,
"required": false,
"types": [
{
"type": "record_content",
"named": true
}
]
},
"symbol_close_brace": {
"multiple": false,
"required": true,
"types": [
{
"type": "symbol",
"named": true
}
]
},
"symbol_open_brace": {
"multiple": false,
"required": true,
"types": [
{
"type": "symbol",
"named": true
}
]
},
"type_name": {
"multiple": false,
"required": true,
"types": [
{
"type": "qualified_type_name",
"named": true
}
]
}
}
},
{
"type": "record_pair",
"named": true,
"fields": {
"field": {
"multiple": false,
"required": true,
"types": [
{
"type": "variable_identifier",
"named": true
}
]
},
"symbol_equals": {
"multiple": false,
"required": true,
"types": [
{
"type": "symbol",
"named": true
}
]
},
"value": {
"multiple": false,
"required": true,
"types": [
{
"type": "expression",
"named": true
}
]
}
}
},
{
"type": "source_file",
"named": true,
@@ -1328,6 +1440,138 @@
]
},
"typ": {
"multiple": false,
"required": true,
"types": [
{
"type": "type_decl_def",
"named": true
}
]
}
}
},
{
"type": "type_decl_def",
"named": true,
"fields": {},
"children": {
"multiple": false,
"required": true,
"types": [
{
"type": "type_decl_def_alias",
"named": true
},
{
"type": "type_decl_def_record",
"named": true
}
]
}
},
{
"type": "type_decl_def_alias",
"named": true,
"fields": {},
"children": {
"multiple": false,
"required": true,
"types": [
{
"type": "type_reference",
"named": true
}
]
}
},
{
"type": "type_decl_def_record",
"named": true,
"fields": {
"content": {
"multiple": false,
"required": false,
"types": [
{
"type": "type_decl_def_record_content",
"named": true
}
]
},
"symbol_close_brace": {
"multiple": false,
"required": true,
"types": [
{
"type": "symbol",
"named": true
}
]
},
"symbol_open_brace": {
"multiple": false,
"required": true,
"types": [
{
"type": "symbol",
"named": true
}
]
}
}
},
{
"type": "type_decl_def_record_content",
"named": true,
"fields": {
"record_separator": {
"multiple": true,
"required": false,
"types": [
{
"type": "symbol",
"named": true
}
]
}
},
"children": {
"multiple": true,
"required": true,
"types": [
{
"type": "type_decl_def_record_field",
"named": true
}
]
}
},
{
"type": "type_decl_def_record_field",
"named": true,
"fields": {
"field": {
"multiple": false,
"required": true,
"types": [
{
"type": "variable_identifier",
"named": true
}
]
},
"symbol_colon": {
"multiple": false,
"required": true,
"types": [
{
"type": "symbol",
"named": true
}
]
},
"type": {
"multiple": false,
"required": true,
"types": [
39,610 changes: 39,610 additions & 0 deletions tree-sitter-darklang/src/parser.c

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -16,7 +16,7 @@ let x = 1L + 2L
---

(source_file
(type_decl (keyword) (type_identifier) (symbol) (type_reference (builtin_type)))
(type_decl (keyword) (type_identifier) (symbol) (type_decl_def (type_decl_def_alias (type_reference (builtin_type)))))
(fn_decl
(keyword)
(fn_identifier)
116 changes: 116 additions & 0 deletions tree-sitter-darklang/test/corpus/exhaustive/exprs/Record.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
==================
Record -one field
==================

Person {name = "John"}

---

(source_file
(expression
(record_literal
(qualified_type_name (type_identifier))
(symbol)
(record_content
(record_pair (variable_identifier) (symbol) (expression (string_literal (symbol) (string_content) (symbol))))
)
(symbol)
)
)
)


==================
Record -two fields
==================

Person {name = "John"; age = 30L}

---

(source_file
(expression
(record_literal
(qualified_type_name (type_identifier))
(symbol)
(record_content
(record_pair (variable_identifier) (symbol) (expression (string_literal (symbol) (string_content) (symbol))))
(symbol)
(record_pair (variable_identifier) (symbol) (expression (int64_literal (digits (positive_digits)) (symbol))))
)
(symbol)
)
)
)


==================
Record -multiple fields
==================

Person {name = "John"; age = 30L; hobbies = ["reading"; "swimming"]}

---

(source_file
(expression
(record_literal
(qualified_type_name (type_identifier))
(symbol)
(record_content
(record_pair (variable_identifier) (symbol) (expression (string_literal (symbol) (string_content) (symbol))))
(symbol)
(record_pair (variable_identifier) (symbol) (expression (int64_literal (digits (positive_digits)) (symbol))))
(symbol)
(record_pair (variable_identifier) (symbol)
(expression (list_literal
(symbol)
(list_content
(expression (string_literal (symbol) (string_content) (symbol)))
(symbol)
(expression (string_literal (symbol) (string_content) (symbol)))
)
(symbol))
)
)
)
(symbol)
)
)
)


==================
Record -nested Record
==================

Person {name = "John"; address = Address {city = "New York"; street = "5th Avenue"}}

---

(source_file
(expression
(record_literal
(qualified_type_name (type_identifier)) (symbol)
(record_content
(record_pair (variable_identifier) (symbol) (expression (string_literal (symbol) (string_content) (symbol))))
(symbol)
(record_pair (variable_identifier) (symbol)
(expression
(record_literal (qualified_type_name (type_identifier)) (symbol)
(record_content
(record_pair (variable_identifier) (symbol) (expression (string_literal (symbol) (string_content) (symbol))))
(symbol)
(record_pair (variable_identifier) (symbol) (expression (string_literal (symbol) (string_content) (symbol))))
)
(symbol)
)
)
)
)
(symbol)
)
)
)


21 changes: 13 additions & 8 deletions tree-sitter-darklang/test/corpus/exhaustive/exprs/bools.txt
Original file line number Diff line number Diff line change
@@ -29,8 +29,9 @@ TRUE
---

(source_file
(ERROR)
)
(ERROR
(qualified_type_name
(type_identifier))))


==================
@@ -42,8 +43,10 @@ FALSE
---

(source_file
(ERROR)
)
(ERROR
(qualified_type_name
(type_identifier))))



==================
@@ -55,8 +58,9 @@ True
---

(source_file
(ERROR)
)
(ERROR
(qualified_type_name
(type_identifier))))

==================
False (error)
@@ -67,5 +71,6 @@ False
---

(source_file
(ERROR)
)
(ERROR
(qualified_type_name
(type_identifier))))
13 changes: 8 additions & 5 deletions tree-sitter-darklang/test/corpus/exhaustive/exprs/fn_calls.txt
Original file line number Diff line number Diff line change
@@ -258,8 +258,11 @@ Bool.and true false

(source_file
(ERROR
(symbol)
(UNEXPECTED 'a'))
(expression (bool_literal))
(expression (bool_literal))
)
(module_identifier)
(symbol))
(expression
(variable_identifier))
(expression
(bool_literal))
(expression
(bool_literal)))
64 changes: 50 additions & 14 deletions tree-sitter-darklang/test/corpus/exhaustive/type_decls.txt
Original file line number Diff line number Diff line change
@@ -11,8 +11,11 @@ type ID = Int64
(keyword)
(type_identifier)
(symbol)
(type_reference
(builtin_type))))
(type_decl_def
(type_decl_def_alias (type_reference (builtin_type)))
)
)
)


==================
@@ -28,15 +31,19 @@ type MyID = PACKAGE.Darklang.LanguageTools.Test
(keyword)
(type_identifier)
(symbol)
(type_reference
(qualified_type_name
(module_identifier)
(symbol)
(module_identifier)
(symbol)
(module_identifier)
(symbol)
(type_identifier)
(type_decl_def
(type_decl_def_alias
(type_reference
(qualified_type_name
(module_identifier)
(symbol)
(module_identifier)
(symbol)
(module_identifier)
(symbol)
(type_identifier)
)
)
)
)
)
@@ -55,9 +62,38 @@ type MyID = Test
keyword_type: (keyword)
name: (type_identifier)
symbol_equals: (symbol)
typ: (type_reference
(qualified_type_name
(type_identifier)
typ: (type_decl_def
(type_decl_def_alias
(type_reference (qualified_type_name (type_identifier)))
)
)
)
)


==================
type def Record
==================

type Cols2 = { col1: Int64; col2: Int64 }

---

(source_file
(type_decl (keyword) (type_identifier) (symbol)
(type_decl_def
(type_decl_def_record
(symbol)
(type_decl_def_record_content
(type_decl_def_record_field
(variable_identifier) (symbol) (type_reference (builtin_type))
)
(symbol)
(type_decl_def_record_field
(variable_identifier) (symbol) (type_reference (builtin_type))
)
)
(symbol)
)
)
)
165 changes: 89 additions & 76 deletions tree-sitter-darklang/test/corpus/exhaustive/type_refs.txt
Original file line number Diff line number Diff line change
@@ -26,82 +26,88 @@ type MyDict = Dict<Int64>
---

(source_file
(type_decl (keyword) (type_identifier) (symbol) (type_reference (builtin_type)))
(type_decl (keyword) (type_identifier) (symbol) (type_reference (builtin_type)))
(type_decl (keyword) (type_identifier) (symbol) (type_reference (builtin_type)))
(type_decl (keyword) (type_identifier) (symbol) (type_reference (builtin_type)))
(type_decl (keyword) (type_identifier) (symbol) (type_reference (builtin_type)))
(type_decl (keyword) (type_identifier) (symbol) (type_reference (builtin_type)))
(type_decl (keyword) (type_identifier) (symbol) (type_reference (builtin_type)))
(type_decl (keyword) (type_identifier) (symbol) (type_reference (builtin_type)))
(type_decl (keyword) (type_identifier) (symbol) (type_reference (builtin_type)))
(type_decl (keyword) (type_identifier) (symbol) (type_reference (builtin_type)))
(type_decl (keyword) (type_identifier) (symbol) (type_reference (builtin_type)))
(type_decl (keyword) (type_identifier) (symbol) (type_reference (builtin_type)))
(type_decl (keyword) (type_identifier) (symbol) (type_reference (builtin_type)))
(type_decl (keyword) (type_identifier) (symbol) (type_reference (builtin_type)))
(type_decl (keyword) (type_identifier) (symbol) (type_reference (builtin_type)))
(type_decl (keyword) (type_identifier) (symbol) (type_reference (builtin_type (list_type_reference (keyword) (symbol) (type_reference (builtin_type)) (symbol)))))
(type_decl (keyword) (type_identifier) (symbol) (type_decl_def (type_decl_def_alias (type_reference (builtin_type)))))
(type_decl (keyword) (type_identifier) (symbol) (type_decl_def (type_decl_def_alias (type_reference (builtin_type)))))
(type_decl (keyword) (type_identifier) (symbol) (type_decl_def (type_decl_def_alias (type_reference (builtin_type)))))
(type_decl (keyword) (type_identifier) (symbol) (type_decl_def (type_decl_def_alias (type_reference (builtin_type)))))
(type_decl (keyword) (type_identifier) (symbol) (type_decl_def (type_decl_def_alias (type_reference (builtin_type)))))
(type_decl (keyword) (type_identifier) (symbol) (type_decl_def (type_decl_def_alias (type_reference (builtin_type)))))
(type_decl (keyword) (type_identifier) (symbol) (type_decl_def (type_decl_def_alias (type_reference (builtin_type)))))
(type_decl (keyword) (type_identifier) (symbol) (type_decl_def (type_decl_def_alias (type_reference (builtin_type)))))
(type_decl (keyword) (type_identifier) (symbol) (type_decl_def (type_decl_def_alias (type_reference (builtin_type)))))
(type_decl (keyword) (type_identifier) (symbol) (type_decl_def (type_decl_def_alias (type_reference (builtin_type)))))
(type_decl (keyword) (type_identifier) (symbol) (type_decl_def (type_decl_def_alias (type_reference (builtin_type)))))
(type_decl (keyword) (type_identifier) (symbol) (type_decl_def (type_decl_def_alias (type_reference (builtin_type)))))
(type_decl (keyword) (type_identifier) (symbol) (type_decl_def (type_decl_def_alias (type_reference (builtin_type)))))
(type_decl (keyword) (type_identifier) (symbol) (type_decl_def (type_decl_def_alias (type_reference (builtin_type)))))
(type_decl (keyword) (type_identifier) (symbol) (type_decl_def (type_decl_def_alias (type_reference (builtin_type)))))
(type_decl (keyword) (type_identifier) (symbol) (type_decl_def (type_decl_def_alias (type_reference (builtin_type (list_type_reference (keyword) (symbol) (type_reference (builtin_type)) (symbol)))))))
(type_decl
(keyword)
(type_identifier)
(symbol)
(type_reference
(builtin_type
(tuple_type_reference
(symbol)
(type_reference
(builtin_type))
(symbol)
(type_reference
(builtin_type))
(symbol)))))
(type_decl_def
(type_decl_def_alias
(type_reference
(builtin_type
(tuple_type_reference
(symbol)
(type_reference
(builtin_type))
(symbol)
(type_reference
(builtin_type))
(symbol)))))))
(type_decl
(keyword)
(type_identifier)
(symbol)
(type_reference
(builtin_type
(tuple_type_reference
(symbol)
(type_reference
(builtin_type))
(symbol)
(type_reference
(builtin_type))
(type_reference_tuple_the_rest
(symbol)
(type_reference
(builtin_type)))
(symbol)))))
(type_decl_def
(type_decl_def_alias
(type_reference
(builtin_type
(tuple_type_reference
(symbol)
(type_reference
(builtin_type))
(symbol)
(type_reference
(builtin_type))
(type_reference_tuple_the_rest
(symbol)
(type_reference
(builtin_type)))
(symbol)))))))
(type_decl
(keyword)
(type_identifier)
(symbol)
(type_reference
(builtin_type
(tuple_type_reference
(symbol)
(type_reference
(builtin_type))
(symbol)
(type_reference
(builtin_type))
(type_reference_tuple_the_rest
(symbol)
(type_reference
(builtin_type))
(symbol)
(type_reference
(builtin_type))
(symbol)
(type_reference
(builtin_type))
(symbol)
(type_reference
(builtin_type)))
(symbol)))))
(type_decl (keyword) (type_identifier) (symbol) (type_reference (builtin_type (dict_type_reference (keyword) (symbol) (type_reference (builtin_type)) (symbol)))))
(type_decl_def
(type_decl_def_alias
(type_reference
(builtin_type
(tuple_type_reference
(symbol)
(type_reference
(builtin_type))
(symbol)
(type_reference
(builtin_type))
(type_reference_tuple_the_rest
(symbol)
(type_reference
(builtin_type))
(symbol)
(type_reference
(builtin_type))
(symbol)
(type_reference
(builtin_type))
(symbol)
(type_reference
(builtin_type)))
(symbol)))))))
(type_decl (keyword) (type_identifier) (symbol) (type_decl_def (type_decl_def_alias (type_reference (builtin_type (dict_type_reference (keyword) (symbol) (type_reference (builtin_type)) (symbol)))))))
)


@@ -118,10 +124,13 @@ type ID = Test
(keyword)
(type_identifier)
(symbol)
(type_reference (qualified_type_name (type_identifier)))
(type_decl_def
(type_decl_def_alias (type_reference (qualified_type_name (type_identifier))))
)
)
)


==================
multi-part qualified type identifier
==================
@@ -135,17 +144,21 @@ type ID = PACKAGE.Darklang.Stdlib.Option.Option
(keyword)
(type_identifier)
(symbol)
(type_reference
(qualified_type_name
(module_identifier)
(symbol)
(module_identifier)
(symbol)
(module_identifier)
(symbol)
(module_identifier)
(symbol)
(type_identifier)
(type_decl_def
(type_decl_def_alias
(type_reference
(qualified_type_name
(module_identifier)
(symbol)
(module_identifier)
(symbol)
(module_identifier)
(symbol)
(module_identifier)
(symbol)
(type_identifier)
)
)
)
)
)