From c859d9d2120ec47dca11cb917b533b720c34a7f8 Mon Sep 17 00:00:00 2001 From: BENJAMIN PEINHARDT Date: Tue, 27 Aug 2024 00:13:10 -0500 Subject: [PATCH] scanner work --- priv/static/squared_away.mjs | 105 +++++++++++++++------------- src/squared_away/lang/scanner.gleam | 55 ++++++--------- test/squared_away_test.gleam | 1 - 3 files changed, 80 insertions(+), 81 deletions(-) diff --git a/priv/static/squared_away.mjs b/priv/static/squared_away.mjs index 274a534..aeb0345 100644 --- a/priv/static/squared_away.mjs +++ b/priv/static/squared_away.mjs @@ -2561,7 +2561,7 @@ var StringLiteral = class extends CustomType { }; var ScanError = class extends CustomType { }; -function maybe_parse_integer(loop$src, loop$acc) { +function parse_integer(loop$src, loop$acc) { while (true) { let src = loop$src; let acc = loop$acc; @@ -2616,17 +2616,14 @@ function maybe_parse_integer(loop$src, loop$acc) { loop$src = rest; loop$acc = acc + x; } else { - let $ = parse2(acc); - if ($.isOk()) { - let x = $[0]; - return new Some([x, src]); - } else { - return new None(); - } + let _pipe = parse2(acc); + return map2(_pipe, (n) => { + return [n, src]; + }); } } } -function maybe_parse_cell_ref(loop$src, loop$acc) { +function parse_cell_ref(loop$src, loop$acc) { while (true) { let src = loop$src; let acc = loop$acc; @@ -2762,16 +2759,16 @@ function maybe_parse_cell_ref(loop$src, loop$acc) { loop$acc = acc + l; } else { if (acc === "") { - return new None(); + return new Error(void 0); } else { - let $ = maybe_parse_integer(src, ""); - if ($ instanceof Some) { - let n = $[0][0]; - let rest = $[0][1]; - return new Some([acc + to_string2(n), rest]); - } else { - return new None(); - } + return try$( + parse_integer(src, ""), + (_use0) => { + let n = _use0[0]; + let rest = _use0[1]; + return new Ok([acc + to_string2(n), rest]); + } + ); } } } @@ -2864,47 +2861,59 @@ function do_scan(loop$src, loop$acc) { loop$src = trim_left2(rest); loop$acc = prepend(new RParen(), acc); } else { - let $ = maybe_parse_integer(src, ""); - if ($ instanceof Some) { + let $ = parse_integer(src, ""); + if ($.isOk()) { let n = $[0][0]; let rest = $[0][1]; if (rest.startsWith(".")) { let rest$1 = rest.slice(1); - let $1 = maybe_parse_integer(rest$1, ""); - if ($1 instanceof Some) { - let m = $1[0][0]; - let rest$2 = $1[0][1]; - let $2 = parse(to_string2(n) + "." + to_string2(m)); - if (!$2.isOk()) { - throw makeError( - "assignment_no_match", - "squared_away/lang/scanner", - 98, - "do_scan", - "Assignment pattern did not match", - { value: $2 } + return try$( + (() => { + let _pipe = parse_integer(rest$1, ""); + return replace_error(_pipe, new ScanError()); + })(), + (_use0) => { + let m = _use0[0]; + let rest$2 = _use0[1]; + let $1 = parse( + to_string2(n) + "." + to_string2(m) + ); + if (!$1.isOk()) { + throw makeError( + "assignment_no_match", + "squared_away/lang/scanner", + 99, + "", + "Assignment pattern did not match", + { value: $1 } + ); + } + let f = $1[0]; + return do_scan( + trim_left2(rest$2), + prepend(new FloatLiteral(f), acc) ); } - let f = $2[0]; - loop$src = trim_left2(rest$2); - loop$acc = prepend(new FloatLiteral(f), acc); - } else { - return new Error(new ScanError()); - } + ); } else { loop$src = trim_left2(rest); loop$acc = prepend(new IntegerLiteral(n), acc); } } else { - let $1 = maybe_parse_cell_ref(src, ""); - if ($1 instanceof Some) { - let cell_ref = $1[0][0]; - let rest = $1[0][1]; - loop$src = trim_left2(rest); - loop$acc = prepend(new CellReference(cell_ref), acc); - } else { - return new Error(new ScanError()); - } + return try$( + (() => { + let _pipe = parse_cell_ref(src, ""); + return replace_error(_pipe, new ScanError()); + })(), + (_use0) => { + let cell_ref = _use0[0]; + let rest = _use0[1]; + return do_scan( + trim_left2(rest), + prepend(new CellReference(cell_ref), acc) + ); + } + ); } } } diff --git a/src/squared_away/lang/scanner.gleam b/src/squared_away/lang/scanner.gleam index 4b900fb..1883da4 100644 --- a/src/squared_away/lang/scanner.gleam +++ b/src/squared_away/lang/scanner.gleam @@ -1,7 +1,7 @@ import gleam/float import gleam/int import gleam/list -import gleam/option.{type Option, None, Some} +import gleam/result import gleam/string pub type Token { @@ -88,36 +88,34 @@ fn do_scan(src: String, acc: List(Token)) -> Result(List(Token), ScanError) { "(" <> rest -> do_scan(string.trim_left(rest), [LParen, ..acc]) ")" <> rest -> do_scan(string.trim_left(rest), [RParen, ..acc]) _ -> { - case maybe_parse_integer(src, "") { - Some(#(n, rest)) -> { + case parse_integer(src, "") { + Ok(#(n, rest)) -> { // Might be a float case rest { "." <> rest -> { - case maybe_parse_integer(rest, "") { - Some(#(m, rest)) -> { - let assert Ok(f) = - float.parse(int.to_string(n) <> "." <> int.to_string(m)) - do_scan(string.trim_left(rest), [FloatLiteral(f), ..acc]) - } - None -> Error(ScanError) - } + use #(m, rest) <- result.try( + parse_integer(rest, "") |> result.replace_error(ScanError), + ) + let assert Ok(f) = + float.parse(int.to_string(n) <> "." <> int.to_string(m)) + do_scan(string.trim_left(rest), [FloatLiteral(f), ..acc]) } _ -> do_scan(string.trim_left(rest), [IntegerLiteral(n), ..acc]) } } - None -> - case maybe_parse_cell_ref(src, "") { - Some(#(cell_ref, rest)) -> - do_scan(string.trim_left(rest), [CellReference(cell_ref), ..acc]) - None -> Error(ScanError) - } + Error(_) -> { + use #(cell_ref, rest) <- result.try( + parse_cell_ref(src, "") |> result.replace_error(ScanError), + ) + do_scan(string.trim_left(rest), [CellReference(cell_ref), ..acc]) + } } } } } -fn maybe_parse_cell_ref(src: String, acc: String) -> Option(#(String, String)) { +fn parse_cell_ref(src: String, acc: String) -> Result(#(String, String), Nil) { // A cell reference is a string of characters followed by a string of numbers (aka an int), // so we can reuse the integer parsing at a slight runtime cost for now case src { @@ -146,23 +144,21 @@ fn maybe_parse_cell_ref(src: String, acc: String) -> Option(#(String, String)) { | "W" as l <> rest | "X" as l <> rest | "Y" as l <> rest - | "Z" as l <> rest -> maybe_parse_cell_ref(rest, acc <> l) + | "Z" as l <> rest -> parse_cell_ref(rest, acc <> l) _ -> { case acc { // Meaning we called this on something that didnt start with a capital letter - "" -> None + "" -> Error(Nil) _ -> { - case maybe_parse_integer(src, "") { - Some(#(n, rest)) -> Some(#(acc <> int.to_string(n), rest)) - None -> None - } + use #(n, rest) <- result.try(parse_integer(src, "")) + Ok(#(acc <> int.to_string(n), rest)) } } } } } -fn maybe_parse_integer(src: String, acc: String) -> Option(#(Int, String)) { +fn parse_integer(src: String, acc: String) -> Result(#(Int, String), Nil) { case src { "1" as x <> rest | "2" as x <> rest @@ -173,12 +169,7 @@ fn maybe_parse_integer(src: String, acc: String) -> Option(#(Int, String)) { | "7" as x <> rest | "8" as x <> rest | "9" as x <> rest - | "0" as x <> rest -> maybe_parse_integer(rest, acc <> x) - _ -> { - case int.parse(acc) { - Ok(x) -> Some(#(x, src)) - _ -> None - } - } + | "0" as x <> rest -> parse_integer(rest, acc <> x) + _ -> int.parse(acc) |> result.map(fn(n) { #(n, src) }) } } diff --git a/test/squared_away_test.gleam b/test/squared_away_test.gleam index d617b4c..169aee2 100644 --- a/test/squared_away_test.gleam +++ b/test/squared_away_test.gleam @@ -2,7 +2,6 @@ import gleam/dict import gleam/list import gleeunit import gleeunit/should -import squared_away/lang import squared_away/lang/interpreter import squared_away/lang/parser import squared_away/lang/scanner