elipl/test/til/list_parser_test.exs
Kacper Marzecki 748f87636a checkpoint
checkpoint

failing test

after fixing tests

checkpoint

checkpoint

checkpoint

re-work

asd

checkpoint

checkpoint

checkpoint

mix proj

checkpoint mix

first parser impl

checkpoint

fix tests

re-org parser

checkpoint strings

fix multiline strings

tuples

checkpoint maps

checkpoint

checkpoint

checkpoint

checkpoint

fix weird eof expression parse error

checkpoint before typing

checkpoint

checpoint

checkpoint

checkpoint

checkpoint ids in primitive types

checkpoint

checkpoint

fix tests

initial annotation

checkpoint

checkpoint

checkpoint

union subtyping

conventions

refactor - split typer

typing tuples

checkpoint test refactor

checkpoint test refactor

parsing atoms

checkpoint atoms

wip lists

checkpoint typing lists

checkopint

checkpoint

wip fixing

correct list typing

map discussion

checkpoint map basic typing

fix tests checkpoint

checkpoint

checkpoint

checkpoint

fix condition typing

fix literal keys in map types

checkpoint union types

checkpoint union type

checkpoint row types discussion & bidirectional typecheck

checkpoint

basic lambdas

checkpoint lambdas typing application

wip function application

checkpoint

checkpoint

checkpoint cduce

checkpoint

checkpoint

checkpoint

checkpoint

checkpoint

checkpoint

checkpoint
2025-06-13 23:48:07 +02:00

168 lines
6.0 KiB
Elixir

defmodule Til.ListParserTest do
use ExUnit.Case, async: true
alias Til.Parser
import Til.TestHelpers
describe "List Parsing" do
test "parses an empty list []" do
source = "[]"
{:ok, nodes_map} = Parser.parse(source)
file_node = get_file_node_from_map(nodes_map)
list_node_id = hd(file_node.children)
list_node = Map.get(nodes_map, list_node_id)
assert list_node.ast_node_type == :list_expression
assert list_node.raw_string == "[]"
assert list_node.children == []
assert list_node.parsing_error == nil
# Location check
# "[]"
# ^ offset 0, line 1, col 1
# ^ offset 1, line 1, col 2
# ^ offset 2, line 1, col 3 (end position, exclusive for offset, inclusive for col)
assert list_node.location == [0, 1, 1, 2, 1, 3]
# file_node is already fetched and used to get list_node
assert file_node.children == [list_node.id]
end
test "parses a list of integers [1 2 3]" do
source = "[1 2 3]"
{:ok, nodes_map} = Parser.parse(source)
file_node = get_file_node_from_map(nodes_map)
list_node_id = hd(file_node.children)
list_node = Map.get(nodes_map, list_node_id)
assert list_node.ast_node_type == :list_expression
assert list_node.raw_string == "[1 2 3]"
assert list_node.parsing_error == nil
assert length(list_node.children) == 3
# Location check
# "[1 2 3]"
# ^ offset 0, line 1, col 1
# ^ offset 7, line 1, col 8
assert list_node.location == [0, 1, 1, 7, 1, 8]
# Check children
child1_id = Enum.at(list_node.children, 0)
child2_id = Enum.at(list_node.children, 1)
child3_id = Enum.at(list_node.children, 2)
child1 = Map.get(nodes_map, child1_id)
child2 = Map.get(nodes_map, child2_id)
child3 = Map.get(nodes_map, child3_id)
assert child1.ast_node_type == :literal_integer
assert child1.value == 1
assert child1.raw_string == "1"
assert child1.parent_id == list_node.id
# "[1 2 3]"
# ^ offset 1, line 1, col 2
# ^ offset 2, line 1, col 3
assert child1.location == [1, 1, 2, 2, 1, 3]
assert child2.ast_node_type == :literal_integer
assert child2.value == 2
assert child2.raw_string == "2"
assert child2.parent_id == list_node.id
# "[1 2 3]"
# ^ offset 3, line 1, col 4
# ^ offset 4, line 1, col 5
assert child2.location == [3, 1, 4, 4, 1, 5]
assert child3.ast_node_type == :literal_integer
assert child3.value == 3
assert child3.raw_string == "3"
assert child3.parent_id == list_node.id
# "[1 2 3]"
# ^ offset 5, line 1, col 6
# ^ offset 6, line 1, col 7
assert child3.location == [5, 1, 6, 6, 1, 7]
# file_node is already fetched and used to get list_node
assert file_node.children == [list_node.id]
end
test "parses an unclosed list [1 2" do
source = "[1 2"
{:ok, nodes_map} = Parser.parse(source)
file_node = get_file_node_from_map(nodes_map)
list_node_id = hd(file_node.children)
list_node = Map.get(nodes_map, list_node_id)
assert list_node.ast_node_type == :list_expression
assert list_node.raw_string == "[1 2" # Raw string is what was consumed for the list
assert list_node.parsing_error == "Unclosed list"
assert length(list_node.children) == 2 # Children that were successfully parsed
# Location check for the unclosed list node
# "[1 2"
# ^ offset 0, line 1, col 1
# ^ offset 4, line 1, col 5 (end of consumed input for this node)
assert list_node.location == [0, 1, 1, 4, 1, 5]
child1 = get_node_by_id(nodes_map, Enum.at(list_node.children, 0))
child2 = get_node_by_id(nodes_map, Enum.at(list_node.children, 1))
assert child1.value == 1
assert child2.value == 2
# file_node is already fetched and used to get list_node
assert file_node.children == [list_node.id]
end
test "parses an unexpected closing bracket ] at top level" do
source = "]"
{:ok, nodes_map} = Parser.parse(source)
file_node = get_file_node_from_map(nodes_map)
error_node_id = hd(file_node.children)
error_node = Map.get(nodes_map, error_node_id)
assert error_node.ast_node_type == :unknown # Or a more specific error type if desired
assert error_node.raw_string == "]"
assert error_node.parsing_error == "Unexpected ']'"
# Location check
# "]"
# ^ offset 0, line 1, col 1
# ^ offset 1, line 1, col 2
assert error_node.location == [0, 1, 1, 1, 1, 2]
# file_node is already fetched and used to get error_node
assert file_node.children == [error_node.id]
end
test "parses an unexpected closing bracket ] inside S-expression (foo ])" do
source = "(foo ])"
{:ok, nodes_map} = Parser.parse(source)
file_node = get_file_node_from_map(nodes_map)
sexpr_node_id = hd(file_node.children) # S-expression is the top-level
sexpr_node = Map.get(nodes_map, sexpr_node_id)
assert sexpr_node.ast_node_type == :s_expression
assert sexpr_node.raw_string == "(foo ])"
assert sexpr_node.parsing_error == nil # The S-expression itself is not unclosed
assert length(sexpr_node.children) == 2 # 'foo' and the error node for ']'
# First child 'foo'
foo_node = get_node_by_id(nodes_map, Enum.at(sexpr_node.children, 0))
assert foo_node.ast_node_type == :symbol
assert foo_node.name == "foo"
# Second child is the error node for ']'
error_node = get_node_by_id(nodes_map, Enum.at(sexpr_node.children, 1))
assert error_node.ast_node_type == :unknown
assert error_node.raw_string == "]"
assert error_node.parsing_error == "Unexpected ']'"
assert error_node.parent_id == sexpr_node.id
# Location check for ']'
# "(foo ])"
# ^ offset 5, line 1, col 6
# ^ offset 6, line 1, col 7
assert error_node.location == [5, 1, 6, 6, 1, 7]
end
end
end