diff --git a/lib/datalog/parser.sx b/lib/datalog/parser.sx index 66ff43dd..16701597 100644 --- a/lib/datalog/parser.sx +++ b/lib/datalog/parser.sx @@ -91,6 +91,16 @@ ((= ty "number") (do (dl-pp-advance! st) vv)) ((= ty "string") (do (dl-pp-advance! st) vv)) ((= ty "var") (do (dl-pp-advance! st) (string->symbol vv))) + ;; Negative numeric literal: `-` op directly followed by a + ;; number (no `(`) is parsed as a single negative number. + ;; This keeps `(-X Y)` (compound) and `-N` (literal) distinct. + ((and (= ty "op") (= vv "-") + (= (get (dl-pp-peek2 st) :type) "number")) + (do + (dl-pp-advance! st) + (let + ((n (get (dl-pp-peek st) :value))) + (do (dl-pp-advance! st) (- 0 n))))) ((or (= ty "atom") (= ty "op")) (do (dl-pp-advance! st) diff --git a/lib/datalog/scoreboard.json b/lib/datalog/scoreboard.json index b67356f8..36aea08c 100644 --- a/lib/datalog/scoreboard.json +++ b/lib/datalog/scoreboard.json @@ -1,11 +1,11 @@ { "lang": "datalog", - "total_passed": 246, + "total_passed": 248, "total_failed": 0, - "total": 246, + "total": 248, "suites": [ {"name":"tokenize","passed":26,"failed":0,"total":26}, - {"name":"parse","passed":20,"failed":0,"total":20}, + {"name":"parse","passed":22,"failed":0,"total":22}, {"name":"unify","passed":28,"failed":0,"total":28}, {"name":"eval","passed":36,"failed":0,"total":36}, {"name":"builtins","passed":23,"failed":0,"total":23}, @@ -16,5 +16,5 @@ {"name":"magic","passed":34,"failed":0,"total":34}, {"name":"demo","passed":21,"failed":0,"total":21} ], - "generated": "2026-05-10T20:51:33+00:00" + "generated": "2026-05-10T20:55:23+00:00" } diff --git a/lib/datalog/scoreboard.md b/lib/datalog/scoreboard.md index 7c5196ef..53252867 100644 --- a/lib/datalog/scoreboard.md +++ b/lib/datalog/scoreboard.md @@ -1,11 +1,11 @@ # datalog scoreboard -**246 / 246 passing** (0 failure(s)). +**248 / 248 passing** (0 failure(s)). | Suite | Passed | Total | Status | |-------|--------|-------|--------| | tokenize | 26 | 26 | ok | -| parse | 20 | 20 | ok | +| parse | 22 | 22 | ok | | unify | 28 | 28 | ok | | eval | 36 | 36 | ok | | builtins | 23 | 23 | ok | diff --git a/lib/datalog/tests/parse.sx b/lib/datalog/tests/parse.sx index 2080e77c..9d0f7201 100644 --- a/lib/datalog/tests/parse.sx +++ b/lib/datalog/tests/parse.sx @@ -126,6 +126,21 @@ "underscore var" (dl-parse "p(X) :- q(X, _).") (list {:body (list (list (quote q) (quote X) (quote _))) :head (list (quote p) (quote X))})) + ;; Negative number literals parse as one negative number, + ;; while subtraction (`-(X, Y)`) compound is preserved. + (dl-pt-test! + "negative integer literal" + (dl-parse "n(-3).") + (list {:head (list (quote n) -3) :body (list)})) + + (dl-pt-test! + "subtraction compound preserved" + (dl-parse "r(X) :- is(X, -(10, 3)).") + (list + {:head (list (quote r) (quote X)) + :body (list (list (quote is) (quote X) + (list (string->symbol "-") 10 3)))})) + (dl-pt-test! "number as relation name raises" (dl-pt-throws? (fn () (dl-parse "1(X) :- p(X).")))