Formats and Languages

The formats and languages used by Tangible Bit are explained in English and (in some cases) formally defined in EBNF.

EBNF Grammar

We use the EBNF notation as used in the Go Language Specification, which is almost identical to a subset of standard ISO EBNF.

Additionally, we use the “except” construct from ISO EBNF:

A - B
Matches any string that matches A but does not match B.

We use #xN, where N is a hexadecimal integer, to match the character whose Unicode code point is N.

Predefined Rules

The following EBNF rules are assumed to be predefined and not formally defined in this document:

Char
Any Unicode character.
UnicodeLetter
A character classified as “Letter” in the Unicode database.
UnicodeDigit
A character classified as “Digit” in the Unicode database.

Polyps

Here’s the EBNF of the Polyps language:


Polyp = { Statement ";" } .

Statement = Declaration | Call .

Declaration = VariableDeclaration | FunctionDeclaration .

VariableDeclaration = [ "var" ] VariableList  ":=" ExpressionList .
FunctionDeclaration = [ "def" ] Function ":=" Expression .

VariableList = variable { "," variable } .
ExpressionList = Expression { "," Expression } .

// ForLoop = "for" Condition Block .

// Block = "{" Polyp "}" .

Function = identifier Parameters .
Parameters = "(" [ ParameterList ] ")" .
ParameterList = variable { "," variable } .

Call = identifier "(" [ ExpressionList ] ")" .
BuiltinCall = identifier "(" [ ExpressionList ] ")" .

Expression = Expr { log_op Expr } .

Expr = UnaryExpr | Expr binary_op UnaryExpr .

UnaryExpr = [ "(" ] PrimaryExpr [ ")" ] | unary_op [ "(" ] PrimaryExpr [ ")" ] .

PrimaryExpr = BuiltinCall | Call | Expr | Operand .

Operand = Literal | identifier .
Literal = int_lit | float_lit .

binary_op = rel_op | math_op .
log_op = "|" | "&" .
rel_op = "=" | "!=" | "<" | ">" | "<=" | ">=" | "<>" .
math_op = "+" | "-" | "*" | "/" | "%" | "^" | "**" .
unary_op = "+" | "-" | "!" | "¬" | "~" .

// Boolean = true | false .
// true = "True" .
// false = "False" .
// none = "None" .

variable = identifier .

identifier = letter { letter | unicode_digit } .

unicode_letter = "a" ... "z" | "A" ... "Z" .
unicode_digit = decimal_digit .
letter        = unicode_letter | "_" .
decimal_digit = "0" ... "9" .
octal_digit   = "0" ... "7" .
hex_digit     = "0" ... "9" | "A" ... "F" | "a" ... "f" .

int_lit     = decimal_lit | octal_lit | hex_lit .
decimal_lit = ( "1" ... "9" ) { decimal_digit }  | "0" .
octal_lit   = "0" octal_digit { octal_digit } .
hex_lit     = "0" ( "x" | "X" ) hex_digit { hex_digit } .

float_lit = decimals "." [ decimals ] [ exponent ] |
            decimals exponent |
            "." decimals [ exponent ] |
            [ "+" | "-" ] "nan" | [ "+" | "-" ] "inf" .
decimals  = decimal_digit { decimal_digit } .
exponent  = ( "e" | "E" ) [ "+" | "-" ] decimals .

// char_lit         = "'" ( unicode_value | byte_value ) "'" .
// unicode_value    = unicode_char | little_u_value | big_u_value | escaped_char .
// byte_value       = octal_byte_value | hex_byte_value .
// octal_byte_value = `\` octal_digit octal_digit octal_digit .
// hex_byte_value   = `\` "x" hex_digit hex_digit .
// little_u_value   = `\` "u" hex_digit hex_digit hex_digit hex_digit .
// big_u_value      = `\` "U" hex_digit hex_digit hex_digit hex_digit
//                           hex_digit hex_digit hex_digit hex_digit .
// escaped_char     = `\` ( "a" | "b" | "f" | "n" | "r" | "t" | "v" | `\` | "'" | `"` ) .

// StringLit              = string_lit { string_lit } .
// string_lit             = raw_string_lit | interpreted_string_lit .
// raw_string_lit         = "`" { unicode_char } "`" .
// interpreted_string_lit = `"` { unicode_value | byte_value } `"` .


TODO unicode_letter and unicode_digit should really be Unicode letters (as defined above), not just ASCII letters.

Tangible Data Format (TDF)

TDF is used as general-purpose data serialization format for object definitions and representations (and possibly other purposes). The data model is roughly equivalent to JSON, but TDF is meant to be easily readable and writable by humans, as well as being easily parsable and serializable by computers. TDF is a superset of the popular RFC 5322 “name: value” format, adding support for lists and nested content as well as for Windows-INI-style “[section]” blocks (as syntactic sugar).

For examples, see the .tt files in the data/types directory and the .tb files in the sample directory.

Tangible Bit Query Language (TQL)

Used to query for objects, locations and other items contained in the TBit database. Here’s the EBNF:

query		=	tablename '?' statement .

statement 	= 	'(' + statement + ')' 
		| 	booleanstatement 
		|	logicalstatement .

booleanstatement = 	statement '&' statement 
		| 	statement '|' statement 
		| 	'!' statement .

logicalstatement =	logicalstatement ('<'|'>'|'<='|'=>'|'=='|'!='|'~')
                        logicalstatement .
		|	value .
		|	variable .

value		=	floatnumber | decimalnumber | hexnumber |
                        octalnumber | string .

variable	=	 identifier .

tablename	=	 identifier .

identifier = UnicodeLetter { UnicodeLetter | UnicodeDigit } .

floatnumber = decimals "." [ decimals ] [ exponent ] |
              decimals exponent |
              "." decimals [ exponent ] |
              [ "+" | "-" ] "nan" | [ "+" | "-" ] "inf" .
decimals  = decimal_digit { decimal_digit } .
exponent  = ( "e" | "E" ) [ "+" | "-" ] decimals .

decimalnumber = ( "1" ... "9" ) { decimal_digit }  | "0" .
hexnumber     = 0" ( "x" | "X" ) hex_digit { hex_digit }.
octalnumber   = "0" octal_digit { octal_digit } .
decimal_digit = "0" ... "9" .
hex_digit     = "0" ... "9" | "A" ... "F" | "a" ... "f" .
octal_digit   = "0" ... "7" .

string = '"' { normalchar | escapedchar } '"'.
normalchar  = Char - '"' - "\" .
escapedchar = "\" Char .

# Char, UnicodeLetter and UnicodeDigit are assumed to be predefined.
# Example: materials ? (30 <= shearmodulus <= 50)

Tangible Bit Declaration Language (TDL)

Used to the declare the properties of objects and processes. TODO describe

Tangible Bit Type Definitions (TTD)

TODO describe interpretation of TTD; object and complex type declarations: uri and desc fields, 4 keywords blocks: req, opt, reqlist, optlist (all optional, order doesn’t matter); describe variant used for basetypes.tt (basic types). Possibly define additional optlist field for child categories: parent contains the URI of the parent category/categories (but in the base types, we just specify the parent type in parentheses after the name)—probably unify name and URI and allow declaring a @prefix field for relative URIs (cf. prefixes used in N3/RDF). Each file should contain the declaration of an object category as well as any complex types used in its definition.