Appendix: EBNF
The EBNF used here is defined in XML 1.0 EBNF-NOTATION with the addition that each rule in the grammar ends with a semicolon character ;
.
program ::= processing-instruction* ( fact | rule | query )* ;
/* ************************************************************************* */
fact ::= assertion | retraction ;
assertion
::= fact-body "." ;
retraction
::= fact-body "~" ;
fact-body
::= predicate ( "(" constant ( "," constant )* ")" )? ;
predicate
::= LC_ALPHA ( ALPHA | DIGIT | UNDERSCORE )* ;
/* ************************************************************************* */
constant
::= string | number | boolean ;
string ::= identifier-string | literal-string ;
identifier-string
::= predicate ( ":" ALPHA ( ALPHA | DIGIT | UNDERSCORE )* )? ;
literal-string
::= DQUOTE ( string-escape | [^#x22] )* DQUOTE ;
string-escape
::= "\\" ( DQUOTE | [tnr] )
| "\u{" HEXDIGIT HEXDIGIT HEXDIGIT HEXDIGIT
( HEXDIGIT HEXDIGIT HEXDIGIT HEXDIGIT )? "}" ;
number ::= float # Optional
| decimal # Optional
| integer ; # Required
integer ::= ( "+" | "-" )? DIGIT+ ;
decimal ::= integer "." DIGIT+ ;
float ::= ( decimal ( "e" | "E" ) integer )
| "+inf.0"
| "-inf.0"
| "+nan.0" ;
boolean ::= "true" | "false" ;
/* ************************************************************************* */
rule ::= head? ( ":-" | "<-" | "⟵" ) body "." ;
head ::= ( atom ( ( ";" | "|" | "OR" | "∨" ) atom )* )
| "⊥" ;
body ::= literal ( ( "," | "&" | "AND" | "∧" ) literal )* ;
/* ************************************************************************* */
atom ::= predicate "(" term ( "," term )* ")" ;
term ::= variable | constant ;
variable
::= named-variable | anon-variable ;
named-variable
::= UC_ALPHA ( ALPHA | DIGIT | UNDERSCORE )* ;
anon-variable
::= UNDERSCORE ;
/* ************************************************************************* */
literal ::= ( "!" | "NOT" | "¬" )?
( relational-literal
| arithmetic-literal ) ;
/* ************************************************************************* */
relational-literal
::= atom ;
arithmetic-literal
::= operand operator operand ;
operand ::= ( named-variable | constant ) ;
operator
::= "="
| ("!=" | "/=" | "≠")
| "<"
| ("<=" | "≤")
| ">"
| (">=" | "≥")
| ("*=" | "≛" | "MATCHES") ;
/* ************************************************************************* */
query ::= ( "?-" atom "." )
| ( atom "?" ) ;
/* ************************************************************************* */
processing-instruction
::= "."
( pi-pragma
| pi-assert
| pi-infer
| pi-input
| pi-output )
"." ;
pi-pragma
::= "pragma" predicate ( "=" constant )? ;
pi-assert
::= "assert" relation-decl functional-dependency-list? ;
relation-decl
::= predicate attribute-decl-list ;
attribute-decl-list
::= "(" attribute-decl ( "," attribute-decl )* ")" ;
attribute-decl
::= ( predicate ":" )?
( "boolean" | "float" | "decimal" | "integer" | "string" ) ;
functional-dependency-list
::= ":" functional-dependency ( ";" functional-dependency )* ;
functional-dependency
::= attribute-index-list ( "-->" | "⟶" ) attribute-index-list ;
attribute-index-list
::= attribute-index ( "," attribute-index )* ;
attribute-index
::= integer | predicate ;
pi-infer
::= "infer" ( relation-decl | "from" predicate ) ;
pi-input
::= "input" io-details ;
io-details
::= predicate parameter-list ;
parameter-list
::= "(" parameter-assignment ( "," parameter-assignment )* ")" ;
parameter-assignment
::= predicate "=" constant ;
/*
Known Parameter types:
uri ::= URI ;
type ::= predicate | media-type ;
headers ::= "present" | "absent" ;
columns ::= column ( "," column )* ;
column ::= integer |
"[" integer? ":" integer? "]" ;
table ::= identifier-string ;
db-columns
::= identifier-string ( "," identifier-string )* ;
*/
pi-output
::= "output" parameter-list ;
/* ************************************************************************* */
comment ::= line-comment | block-comment ;
line-comment
::= "%" [^\r\n]* EOL ;
block-comment
::= '/*' ( [^*] | '*'+ [^*/] )* '*'* '*/' ;
/* ************************************************************************* */
EOL ::= "\n" | "\r" "\n"? ;
DQUOTE ::= #x22 ;
UNDERSCORE
::= "_" ;
SPACE_SEP
::= ? corresponds to the Unicode category 'Zs' ? ;
WHITESPACE
::= SPACE_SEP | "\t" | EOL ;
LC_ALPHA
::= ? corresponds to the Unicode category 'Ll' ? ;
UC_ALPHA
::= ? corresponds to the Unicode category 'Lu' ? ;
TC_ALPHA
::= ? corresponds to the Unicode category 'Lt' ? ;
ALPHA ::= LC_ALPHA | UC_ALPHA | TC_ALPHA ;
DIGIT ::= ? corresponds to the Unicode category 'Nd' (decimal number) ? ;
HEXDIGIT
::= [0-9a-fA-F] ;