Current section
Files
Jump to
Current section
Files
src/eyg/parser.gleam
import eyg/ir/tree as ir
import eyg/parser/debug
import eyg/parser/lexer
import eyg/parser/location
import eyg/parser/parser
import eyg/parser/token
import gleam/list
import gleam/option.{None, Some}
import gleam/result
import gleam/string
pub fn from_string(src) {
src
|> lexer.lex()
|> token.drop_whitespace()
|> token.drop_comments()
|> parser.expression()
}
pub fn all_from_string(src) {
use #(source, remaining) <- result.try(from_string(src))
case remaining {
[] -> Ok(source)
[#(tok, at), ..] -> Error(parser.TrailingTokens(tok, at))
}
}
pub fn block_from_string(src) {
let parsed =
src
|> lexer.lex()
|> token.drop_whitespace()
|> token.drop_comments()
|> parser.block()
case parsed {
Ok(#(exp, left)) -> Ok(#(do_gather(exp, []), left))
Error(reason) -> Error(reason)
}
}
fn do_gather(exp, acc) {
let #(exp, span) = exp
case exp {
ir.Let(label, value, then) ->
do_gather(then, [#(label, value, span), ..acc])
ir.Vacant -> #(acc, None)
_ -> #(acc, Some(#(exp, span)))
}
}
/// Format a parse error as a human-readable string, showing the relevant
/// source line with a pointer to the error location.
pub fn format_error(reason: parser.Reason, source: String) -> String {
let description = debug.describe(reason)
let hint = debug.hint(reason)
let span = case reason_position(reason) {
Some(start) -> #(start, start)
None -> #(0, 0)
}
render_error(description, hint, source, span)
}
pub fn render_error(description, hint, code, span) {
let lines = ["error: " <> description, "hint: " <> hint]
let context = case span {
#(0, 0) -> []
_ -> ["", ..location.source_context(code, span)]
}
string.join(list.append(lines, context), "\n")
}
fn reason_position(reason: parser.Reason) -> option.Option(Int) {
case reason {
parser.UnexpectedToken(_, pos) -> Some(pos)
parser.UnexpectEnd -> None
parser.MissingEquals(pos) -> Some(pos)
parser.MissingArrow(pos) -> Some(pos)
parser.UnclosedFunctionBody(open_at) -> Some(open_at)
parser.ExpectedEffectName(_, pos) -> Some(pos)
parser.ExpectedBuiltinName(pos) -> Some(pos)
parser.InvalidCidReference(pos) -> Some(pos)
parser.InvalidReleaseVersion(pos) -> Some(pos)
parser.InvalidImportPath(pos) -> Some(pos)
parser.TrailingTokens(_, pos) -> Some(pos)
parser.InvalidCharacter(_, pos) -> Some(pos)
parser.UnterminatedStringLiteral(pos) -> Some(pos)
parser.InvalidEscapeSequence(_, pos) -> Some(pos)
parser.IntegerLiteralOutOfRange(_, pos) -> Some(pos)
}
}