fix: lexer

This commit is contained in:
Daniel Flanagan 2025-02-21 07:51:02 -06:00
parent 56e99a3083
commit 13835d9511
8 changed files with 123 additions and 67 deletions

8
flake.lock generated
View file

@ -61,16 +61,16 @@
}, },
"nixpkgs": { "nixpkgs": {
"locked": { "locked": {
"lastModified": 1739206421, "lastModified": 1740019556,
"narHash": "sha256-PwQASeL2cGVmrtQYlrBur0U20Xy07uSWVnFup2PHnDs=", "narHash": "sha256-vn285HxnnlHLWnv59Og7muqECNMS33mWLM14soFIv2g=",
"owner": "nixos", "owner": "nixos",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "44534bc021b85c8d78e465021e21f33b856e2540", "rev": "dad564433178067be1fbdfcce23b546254b6d641",
"type": "github" "type": "github"
}, },
"original": { "original": {
"owner": "nixos", "owner": "nixos",
"ref": "nixos-24.11", "ref": "nixpkgs-unstable",
"repo": "nixpkgs", "repo": "nixpkgs",
"type": "github" "type": "github"
} }

View file

@ -1,14 +1,17 @@
{ {
inputs.nixpkgs.url = "github:nixos/nixpkgs/nixos-24.11"; inputs.nixpkgs.url = "github:nixos/nixpkgs/nixpkgs-unstable";
inputs.git-hooks.url = "github:cachix/git-hooks.nix"; inputs.git-hooks.url = "github:cachix/git-hooks.nix";
inputs.git-hooks.inputs.nixpkgs.follows = "nixpkgs"; inputs.git-hooks.inputs.nixpkgs.follows = "nixpkgs";
outputs = inputs: let outputs =
inputs:
let
inherit (import nix/boilerplate.nix inputs) call genPkgs; inherit (import nix/boilerplate.nix inputs) call genPkgs;
in { in
{
# overlays = import nix/overlays.nix; # overlays = import nix/overlays.nix;
packages = call (import nix/packages.nix); packages = call (import nix/packages.nix);
checks = call (import nix/checks.nix); checks = call (import nix/checks.nix);
devShells = call (import nix/shells.nix); devShells = call (import nix/shells.nix);
formatter = genPkgs (p: p.alejandra); formatter = genPkgs (p: p.nixfmt-rfc-style);
}; };
} }

View file

@ -1,10 +1,4 @@
use std::{ use std::{iter::Peekable, num::ParseIntError, path::Path, str::Chars, sync::Arc};
iter::{self, from_fn},
num::ParseIntError,
path::Path,
str::Chars,
sync::Arc,
};
// TODO: tree_sitter ? // TODO: tree_sitter ?
@ -24,7 +18,7 @@ enum BareToken {
} }
#[derive(Debug, PartialEq)] #[derive(Debug, PartialEq)]
struct Token { pub struct Token {
location: Option<Location>, // Not all tokens are associated with a location, such as EndOfFile location: Option<Location>, // Not all tokens are associated with a location, such as EndOfFile
token: BareToken, token: BareToken,
} }
@ -52,6 +46,12 @@ enum LexerError {
Unexpected(char), Unexpected(char),
} }
impl From<ParseIntError> for LexerError {
fn from(value: ParseIntError) -> Self {
LexerError::ParseIntError(value)
}
}
#[derive(Debug, PartialEq)] #[derive(Debug, PartialEq)]
pub struct Error { pub struct Error {
pub location: Location, pub location: Location,
@ -62,7 +62,7 @@ pub struct Lexer<'a> {
line: usize, line: usize,
col: usize, col: usize,
source: Source, source: Source,
chars: Chars<'a>, chars: Peekable<Chars<'a>>,
collected: Vec<char>, collected: Vec<char>,
done: bool, done: bool,
@ -70,21 +70,23 @@ pub struct Lexer<'a> {
} }
impl<'a> Lexer<'a> { impl<'a> Lexer<'a> {
fn new(code: &'a str, source: Source) -> Self { pub fn new(code: &'a str, source: Source) -> Self {
let mut lexer = Lexer { let lexer = Lexer {
done: false, done: false,
sent_eof: false, sent_eof: false,
line: 1, line: 1,
col: 0, col: 0,
source: source.clone(), source: source.clone(),
chars: code.chars(), chars: code.chars().peekable(),
collected: vec![], collected: vec![],
}; };
lexer.advance();
lexer lexer
} }
fn advance(&mut self) { fn advance(&mut self) {
if self.done {
return;
}
match self.chars.next() { match self.chars.next() {
Some('\n') => { Some('\n') => {
self.line += 1; self.line += 1;
@ -117,7 +119,7 @@ impl<'a> Lexer<'a> {
t t
} }
fn produce_error(&mut self, error: LexerError) -> Error { fn produce_error(&self, error: LexerError) -> Error {
Error { Error {
location: self.current_location(), location: self.current_location(),
error, error,
@ -131,12 +133,51 @@ impl<'a> Lexer<'a> {
Some(c) => c, Some(c) => c,
}; };
Ok(Some(match current { Ok(Some(match current {
c if c.is_ascii_digit() => self.number()?, c if c.is_digit(10) => self.number()?,
'\n' => self.produce(BareToken::NewLine),
'+' => self.produce(BareToken::Plus),
c if c.is_whitespace() => {
self.whitespace();
return self.token();
}
c => return Err(self.produce_error(LexerError::Unexpected(*c))), c => return Err(self.produce_error(LexerError::Unexpected(*c))),
})) }))
} }
fn number(&mut self) -> Result<Token, Error> {} fn whitespace(&mut self) {
while let Some(c) = self.chars.peek() {
if c.is_whitespace() {
self.advance()
} else {
break;
}
}
self.collected.clear();
}
fn number(&mut self) -> Result<Token, Error> {
while let Some(c) = self.chars.peek() {
if c.is_ascii_digit() {
self.advance()
} else {
break;
}
}
dbg!(&self.collected);
Ok(self.produce(BareToken::Integer(
self.collected
.iter()
.collect::<String>()
.parse()
.map_err(|e: ParseIntError| {
dbg!(&e);
self.produce_error(e.into())
})?,
)))
}
} }
impl<'a> Iterator for Lexer<'a> { impl<'a> Iterator for Lexer<'a> {
@ -153,9 +194,9 @@ impl<'a> Iterator for Lexer<'a> {
})); }));
} }
match self.token() { match self.token() {
Ok(Some(t)) => Some(Ok(t)), Ok(Some(t)) => return Some(Ok(t)),
Ok(None) => None, Ok(None) => return self.next(),
Err(e) => Some(Err(e)), Err(e) => return Some(Err(e)),
} }
} }
} }

View file

@ -28,9 +28,9 @@ impl<'a> From<lexer::Error> for Error {
impl Parser { impl Parser {
pub fn parse_str(&mut self, code: &'static str) -> Result<Expression, Error> { pub fn parse_str(&mut self, code: &'static str) -> Result<Expression, Error> {
let mut lexer = lexer::Lexer::default(); let lexer = lexer::Lexer::new(code, lexer::Source::Unknown);
let tokens = lexer.lex_str(code); let tokens = lexer.collect::<Result<Vec<lexer::Token>, lexer::Error>>()?;
Ok(self.parse(tokens?)?) Ok(self.parse(tokens)?)
} }
pub fn parse(&mut self, tokens: Vec<lexer::Token>) -> Result<Expression, Error> { pub fn parse(&mut self, tokens: Vec<lexer::Token>) -> Result<Expression, Error> {

View file

@ -1,17 +1,25 @@
inputs @ { inputs@{
nixpkgs, nixpkgs,
self, self,
... ...
}: let }:
let
forSelfOverlay = forSelfOverlay =
if builtins.hasAttr "overlays" self && builtins.hasAttr "forSelf" self.overlays if builtins.hasAttr "overlays" self && builtins.hasAttr "forSelf" self.overlays then
then self.overlays.forSelf self.overlays.forSelf
else (_: p: p); else
in rec { (_: p: p);
in
rec {
# TODO: Iterate all Nix's supported systems? # TODO: Iterate all Nix's supported systems?
systems = ["aarch64-linux" "x86_64-linux" "x86_64-darwin" "aarch64-darwin"]; systems = [
"aarch64-linux"
"x86_64-linux"
"x86_64-darwin"
"aarch64-darwin"
];
forSystems = nixpkgs.lib.genAttrs systems; forSystems = nixpkgs.lib.genAttrs systems;
pkgsFor = system: ((import nixpkgs {inherit system;}).extend forSelfOverlay); pkgsFor = system: ((import nixpkgs { inherit system; }).extend forSelfOverlay);
genPkgs = func: (forSystems (system: func (pkgsFor system))); genPkgs = func: (forSystems (system: func (pkgsFor system)));
call = imported: genPkgs (pkgs: imported (inputs // {inherit pkgs;})); call = imported: genPkgs (pkgs: imported (inputs // { inherit pkgs; }));
} }

View file

@ -2,22 +2,24 @@
pkgs, pkgs,
git-hooks, git-hooks,
... ...
}: { }:
let
check-command = command: {
enable = true;
name = command;
entry = command;
pass_filenames = false;
stages = [ "pre-commit" ];
};
in
{
git-hooks = git-hooks.lib.${pkgs.system}.run { git-hooks = git-hooks.lib.${pkgs.system}.run {
src = ./..; src = ./..;
hooks = { hooks = {
alejandra.enable = true; nixfmt-rfc-style.enable = true;
cargo-check.enable = true; cargo-check.enable = true;
convco.enable = true; convco.enable = true;
cargo-test = { cargo-test = check-command "cargo test";
enable = true;
name = "cargo-test";
entry = "cargo test";
# types = ["rust"];
# language = "rust";
pass_filenames = false;
stages = ["pre-commit"];
};
clippy.enable = true; clippy.enable = true;
rustfmt.enable = true; rustfmt.enable = true;
}; };

View file

@ -1,4 +1,5 @@
{pkgs, ...}: let { pkgs, ... }:
let
inherit (builtins) fromTOML readFile; inherit (builtins) fromTOML readFile;
pname = "lyt"; pname = "lyt";
src = ./..; src = ./..;
@ -8,7 +9,8 @@
cargoHash = "sha256-ZrT35F8EoawLgJVcp15kBLGkQZkhi1dxkYEAsV1ZlaU="; cargoHash = "sha256-ZrT35F8EoawLgJVcp15kBLGkQZkhi1dxkYEAsV1ZlaU=";
useFetchCargoVendor = true; useFetchCargoVendor = true;
}; };
in { in
{
${pname} = main-package; ${pname} = main-package;
default = main-package; default = main-package;
} }

View file

@ -2,20 +2,20 @@
self, self,
pkgs, pkgs,
... ...
}: let }:
let
inherit (pkgs) system; inherit (pkgs) system;
in { in
{
default = pkgs.mkShell { default = pkgs.mkShell {
inherit (self.checks.${system}.git-hooks) shellHook; inherit (self.checks.${system}.git-hooks) shellHook;
inputsFrom = [self.packages.${system}.default]; inputsFrom = [ self.packages.${system}.default ];
packages = with pkgs; [ packages = with pkgs; [
convco rustup
rustPackages.clippy gdb
typescript-language-server gdbgui
rust-analyzer
rustfmt
nixd nixd
lldb
]; ];
}; };
} }