diff options
| author | LLLL Colonq <llll@colonq> | 2026-06-05 20:32:17 -0400 |
|---|---|---|
| committer | LLLL Colonq <llll@colonq> | 2026-06-05 20:32:17 -0400 |
| commit | b456aa44a172171d4b6120ec566c1499ec25a690 (patch) | |
| tree | 7a835e42351ffd39e5620f5d8e705ef8c69d838e | |
| parent | 48ab2cb8e3de88dbd0722337bd4617ad22de1a12 (diff) | |
Fix integer parsing
| -rw-r--r-- | emacs/pit.el | 56 | ||||
| -rw-r--r-- | src/lexer.c | 37 | ||||
| -rw-r--r-- | src/parser.c | 11 | ||||
| -rw-r--r-- | src/utils.c | 1 | ||||
| -rw-r--r-- | test/int.pit | 1 |
5 files changed, 94 insertions, 12 deletions
diff --git a/emacs/pit.el b/emacs/pit.el index cce2694..9a357a3 100644 --- a/emacs/pit.el +++ b/emacs/pit.el @@ -82,5 +82,61 @@ (setq-local c/contextual-ide 'pit/ide/body)) (add-hook 'pit/mode-hook #'pit/setup) +;;;; nrepl client +;; (require 'nrepl-client) +;; (defun pit/repl/connect (&optional host port) +;; "Connect to pit nREPL server at HOST:PORT." +;; (let ((ret (get-buffer-create (generate-new-buffer-name " *pit-nrepl*") t))) +;; (nrepl-start-client-process (or host "localhost") (or port 7888) nil (lambda (_pl) ret)) +;; ret)) + +(require 'cider) +(defun pit/repl/connect (&optional host port) + "Connect to pit nREPL server at HOST:PORT." + (let ( (dir (if-let* ((p (project-current))) (project-root p) default-directory)) + (cider-repl-init-code nil)) + (cider-nrepl-connect + (print + (thread-first `(:host ,host :port ,port :project-dir ,dir :repl-init-function nil :session-name nil :repl-type pit) + (cider--update-project-dir) + (cider--update-host-port) + (cider--check-existing-session)))))) + +(defun cider-repl-handler (buffer) + "Make an nREPL evaluation handler for the REPL BUFFER." + (message "running cider-repl-handler") + (let ((show-prompt t)) + (nrepl-make-response-handler + buffer + (lambda (buffer value) + (message "value-handler") + (cider-repl-emit-result buffer value t)) + (lambda (buffer out) + (dolist (f cider--repl-stdout-functions) + (funcall f buffer out)) + (cider-repl-emit-stdout buffer out)) + (lambda (buffer err) + (dolist (f cider--repl-stderr-functions) + (funcall f buffer err)) + (cider-repl-emit-stderr buffer err)) + (lambda (buffer) + (message "done-handler: %s" show-prompt) + (when show-prompt + (cider-repl-emit-prompt buffer)) + (when cider-repl-buffer-size-limit + (cider-repl-maybe-trim-buffer buffer)) + (dolist (f cider--repl-done-functions) + (funcall f buffer))) + nrepl-err-handler + (lambda (buffer value content-type) + (if-let* ((content-attrs (cadr content-type)) + (content-type* (car content-type)) + (handler (cdr (assoc content-type* + cider-repl-content-type-handler-alist)))) + (setq show-prompt (funcall handler content-type buffer value nil t)) + (cider-repl-emit-result buffer value t t))) + (lambda (buffer warning) + (cider-repl-emit-stderr buffer warning))))) + (provide 'pit) ;;; pit.el ends here diff --git a/src/lexer.c b/src/lexer.c index adfe8d3..5d9c5e7 100644 --- a/src/lexer.c +++ b/src/lexer.c @@ -1,6 +1,7 @@ #include <lcq/pit/utils.h> #include <lcq/pit/lexer.h> #include <lcq/pit/types.h> +#include <stdio.h> const char *PIT_LEX_TOKEN_NAMES[PIT_LEX_TOKEN__SENTINEL] = { /* [PIT_LEX_TOKEN_EOF] = */ "eof", @@ -92,20 +93,34 @@ restart: } advance(st); return PIT_LEX_TOKEN_STRING_LITERAL; - default: + default: { if (pit_ctype_isspace(c)) goto restart; - if (pit_ctype_isdigit(c)) { - if (c == '0') { - int next = peek(st); - if (next != 'x' && next != 'o' && next != 'b') return PIT_LEX_TOKEN_INTEGER_LITERAL; - advance(st); /* skip base specifier */ - } - while (match(st, is_hexdigit)) {} - return PIT_LEX_TOKEN_INTEGER_LITERAL; + pit_lex_token ret = PIT_LEX_TOKEN_INTEGER_LITERAL; + int num_idx = 0; + bool leading_dash = false; + bool zero_prefix = false; + if (!is_symchar(c)) { + st->error = "unknown character"; + return PIT_LEX_TOKEN_ERROR; } else { - while (match(st, is_symchar)) {} - return PIT_LEX_TOKEN_SYMBOL; + do { + leading_dash = false; + switch (num_idx) { + case 0: + if (c == '0') zero_prefix = true; + else if (c == '-') { leading_dash = true; continue; } + break; + case 1: + if (zero_prefix && (c == 'x' || c == 'o' || c == 'b')) continue; + break; + } + if (!is_hexdigit(c)) ret = PIT_LEX_TOKEN_SYMBOL; + ++num_idx; + } while (c = peek(st), match(st, is_symchar)); } + if (leading_dash) return PIT_LEX_TOKEN_SYMBOL; + return ret; + } } } diff --git a/src/parser.c b/src/parser.c index 5dc57db..77b4172 100644 --- a/src/parser.c +++ b/src/parser.c @@ -129,7 +129,16 @@ pit_value pit_parse(pit_runtime *rt, pit_parser *st, bool *eof) { i64 idx = st->cur.start; i64 base = 10; i64 total = 0; + bool neg = false; char c = st->lexer->input[idx++]; + if (c == '-') { + neg = true; + if (idx < st->cur.end) { + c = st->lexer->input[idx++]; + } else { + pit_error(rt, "malformed negative integer literal"); return PIT_NIL; + } + } if (c == '0' && idx + 1 < st->cur.end) { switch (st->lexer->input[idx++]) { case 'b': base = 2; break; @@ -145,7 +154,7 @@ pit_value pit_parse(pit_runtime *rt, pit_parser *st, bool *eof) { pit_error(rt, "integer literal too large"); return PIT_NIL; } } - return pit_integer_new(rt, total); + return pit_integer_new(rt, neg ? -total : total); } case PIT_LEX_TOKEN_STRING_LITERAL: { char buf[256] = {0}; diff --git a/src/utils.c b/src/utils.c index 7f2831b..53a9ebf 100644 --- a/src/utils.c +++ b/src/utils.c @@ -45,6 +45,7 @@ int pit_string_vsnprintf(char *buf, size_t len, char *format, va_list ap) { if (length_mod == 'l') arg = va_arg(ap, long); else arg = va_arg(ap, int); if (arg == 0) { WRITE('0') } else { + if (arg < 0) { WRITE('-'); arg = -arg; } while (arg != 0) { WRITE_SCRATCH('0' + (char) (arg % 10)); arg /= 10; } while (sidx > 0) { WRITE(scratch[sidx - 1]); sidx -= 1; } } diff --git a/test/int.pit b/test/int.pit new file mode 100644 index 0000000..65646af --- /dev/null +++ b/test/int.pit @@ -0,0 +1 @@ +(print! 0x10) |
