diff --git a/collects/datalog/parse.rkt b/collects/datalog/parse.rkt index f846055db0..83e524991d 100644 --- a/collects/datalog/parse.rkt +++ b/collects/datalog/parse.rkt @@ -4,36 +4,6 @@ "private/lex.rkt" "ast.rkt") -#| -5.1 Literals - -A literal, is a predicate symbol followed by an optional parenthesized list of comma separated terms. A predicate symbol is either an identifier or a string. A term is either a variable or a constant. As with predicate symbols, a constant is either an identifier or a string. The following are literals: - - parent(john, douglas) - zero-arity-literal - aBcD(-0, "\n\FF") - "="(3,3) - ""(-0-0-0,&&&,***,"\00") -5.2 Clauses - -A clause is a head literal followed by an optional body. A body is a comma separated list of literals. A clause without a body is called a fact, and a rule when it has one. The punctuation `:-' separates the head of a rule from its body. A clause is safe if every variable in its head occurs in some literal in its body. The following are safe clauses: - - parent(john, douglas) - ancestor(A, B) :- - parent(A, B) - ancestor(A, B) :- - parent(A, C), - ancestor(C, B) -5.3 Programs - -A Datalog reader consumes a Datalog program. A program is a sequence of zero or more statements, followed by an optional query. A statement is an assertion or a retraction. An assertion is a clause followed by a period, and it adds the clause to the database if it is safe. A retraction is a clause followed by a tilde, and it removes the clause from the database. A query is a literal followed by a question mark. The effect of reading a Datalog program is to modify the database as directed by its statements, and then to return the literal designated as the query. If no query is specified, a reader returns a literal know to have no answers. The following is a program: - - edge(a, b). edge(b, c). edge(c, d). edge(d, a). - path(X, Y) :- edge(X, Y). - path(X, Y) :- edge(X, Z), path(Z, Y). - path(X, Y)? -|# - (define current-source-name (make-parameter #f)) (define (make-srcloc start-pos end-pos) diff --git a/collects/datalog/private/lex.rkt b/collects/datalog/private/lex.rkt index 459752d53a..58b9f498eb 100644 --- a/collects/datalog/private/lex.rkt +++ b/collects/datalog/private/lex.rkt @@ -2,22 +2,6 @@ (require parser-tools/lex (prefix-in : parser-tools/lex-sre)) -#| -5 Syntax - -In Datalog input, whitespace characters are ignored except when they separate adjacent tokens or when they occur in strings. Comments are also considered to be whitespace. The character `%' introduces a comment, which extends to the next line break. Comments do not occur inside strings. - -The characters in Datalog input are collected into tokens according to the rules that follow. There are four classes of tokens: punctuations, variables, identifiers, and strings. The punctuation tokens are: `(', `,', `)', `=', `:-', `.', `~', `?', and `"'. - -A variable is a sequence of Latin capital and small letters, digits, and the underscore character. A variable must begin with a Latin capital letter. - -An identifier is a sequence of printing characters that does not contain any of the following characters: `(', `,', `)', `=', `:', `.', `~', `?', `"', `%', and space. An identifier must not begin with a Latin capital letter. Note that the characters that start punctuation are forbidden in identifiers, but the hyphen character is allowed. - -A string is a sequence of characters enclosed in double quotes. Characters other than double quote, newline, and backslash may be directly included in a string. The remaining characters may be specified using escape characters, `\"', `\n', and `\\' respectively. - -Other escape characters can be used to improve the readability of the input. If a string is too long to fit conveniently on one line, all but the final line containing the string can be ended with a backslash character, and each backslash newline pair is ignored. The character escape codes from the C programming language are allowed—`\a', `\b', `\f', `\n', `\r', `\t', `\v', `\'', and `\?'. The numeric escape codes consist of exactly two uppercase hex digits. Thus the ASCII character newline is `\0A', and zero is `\00'. -|# - (define-tokens dtokens (VARIABLE IDENTIFIER STRING)) (define-empty-tokens dpunct (LPAREN COMMA RPAREN TSTILE DOT EQUAL TILDE QMARK EOF)) (define-lex-abbrev line-break #\newline) diff --git a/collects/datalog/scribblings/datalog.scrbl b/collects/datalog/scribblings/datalog.scrbl index cef43910e1..6942712205 100644 --- a/collects/datalog/scribblings/datalog.scrbl +++ b/collects/datalog/scribblings/datalog.scrbl @@ -30,7 +30,7 @@ In Datalog input, whitespace characters are ignored except when they separate ad Comments are also considered to be whitespace. The character @litchar["%"] introduces a comment, which extends to the next line break. Comments do not occur inside strings. -A variable is a sequence of Latin capital and small letters, digits, and the underscore character. A variable must begin with a Latin capital letter. +A variable is a sequence of Unicode "Uppercase" and "Lowercase" letters, digits, and the underscore character. A variable must begin with a Unicode "Uppercase" letter. An identifier is a sequence of printing characters that does not contain any of the following characters: @litchar["("], @litchar["`"], @litchar["'"], @litchar[")"], @litchar["="], @litchar[":"], @litchar["."], @litchar["~"], @litchar["?"], @litchar["\""], @litchar["%"], and space. @@ -113,6 +113,7 @@ The following BNF describes the syntax of Datalog. The effect of running a Datalog program is to modify the database as directed by its statements, and then to return the literals designated by the query. +The modified database is provided as @racket[theory]. The following is a program: diff --git a/collects/datalog/sexp/lang.rkt b/collects/datalog/sexp/lang.rkt index 4a613740ed..32a692b766 100644 --- a/collects/datalog/sexp/lang.rkt +++ b/collects/datalog/sexp/lang.rkt @@ -2,11 +2,10 @@ (require (for-syntax syntax/parse racket/list racket/base) + racket/contract datalog/stx datalog/runtime) -(define lang-theory (make-theory)) - (define-for-syntax (partition-requires es) (define-values (rs stmts) (partition @@ -24,18 +23,24 @@ (define-syntax (module-begin stx) (syntax-case stx () [(_ . es) - (with-syntax ([((requires ...) + (with-syntax ([theory (datum->syntax #'es 'theory)] + [((requires ...) (stmt ...)) (partition-requires #'es)]) (syntax/loc stx (#%module-begin requires ... - (datalog! lang-theory stmt ...))))])) + (define theory (make-theory)) + (datalog! theory stmt ...) + (provide/contract + [theory mutable-theory/c]))))])) -(define-syntax top-interaction - (syntax-rules () +(define-syntax (top-interaction stx) + (syntax-case stx () [(_ . stmt) - (datalog! lang-theory stmt)])) + (with-syntax ([theory (datum->syntax #'stmt 'theory)]) + (syntax/loc stx + (datalog! theory stmt)))])) (provide (rename-out [top-interaction #%top-interaction] [module-begin #%module-begin]) diff --git a/collects/tests/datalog/examples/path.txt b/collects/tests/datalog/examples/path.txt index cfe9daed0a..9319f8c51b 100644 --- a/collects/tests/datalog/examples/path.txt +++ b/collects/tests/datalog/examples/path.txt @@ -7,9 +7,9 @@ path(b, d). path(b, c). path(b, b). path(c, a). -path(c, b). -path(c, c). path(c, d). +path(c, c). +path(c, b). path(d, b). path(d, c). path(d, d). diff --git a/collects/tests/datalog/paren-examples/path.txt b/collects/tests/datalog/paren-examples/path.txt index cfe9daed0a..9319f8c51b 100644 --- a/collects/tests/datalog/paren-examples/path.txt +++ b/collects/tests/datalog/paren-examples/path.txt @@ -7,9 +7,9 @@ path(b, d). path(b, c). path(b, b). path(c, a). -path(c, b). -path(c, c). path(c, d). +path(c, c). +path(c, b). path(d, b). path(d, c). path(d, d). diff --git a/collects/tests/datalog/racket.rkt b/collects/tests/datalog/racket.rkt index 439aa743b0..a2536584d6 100644 --- a/collects/tests/datalog/racket.rkt +++ b/collects/tests/datalog/racket.rkt @@ -59,4 +59,26 @@ => (list '(add1 1 :- 2)) + (local [(local-require tests/datalog/examples/ancestor)] + (datalog theory + (? (ancestor A B)))) + => + '((ancestor ebbon bob) + (ancestor bob john) + (ancestor john douglas) + (ancestor bob douglas) + (ancestor ebbon john) + (ancestor ebbon douglas)) + + (local [(local-require tests/datalog/paren-examples/ancestor)] + (datalog theory + (? (ancestor A B)))) + => + '((ancestor ebbon bob) + (ancestor bob john) + (ancestor john douglas) + (ancestor bob douglas) + (ancestor ebbon john) + (ancestor ebbon douglas)) + ) \ No newline at end of file