This document describes the POPCORN representation of OpenMath [20]: a human readable and writable OpenMath Representation that is intended for direct user interaction. The acronym POPCORN stands for ``Possibly Only Practical Convenient OpenMath Replacement Notation'' and is written as ``Popcorn'' for typographic beauty.
In this document, we present Popcorn in a way following the structure of the OpenMath Standard.
In the SCIEnce EU FP6 Project 26133 [21], OpenMath (OM) is heavily used to marshal mathematical objects to send them between Computer Algebra Systems (CASes). When developing the OM libraries for the CASes, there was a lot of `manual' inspection and typing of OM necessary to streamline the code. And, whenever discussions about `how-to-do', everybody started to use some de-xml'ed OM representation that was well understandable but by no means standardized.
Here, the fact that the OpenMath language allows for different representations anyway, inspired us to develop an OpenMath representation that can easily be handled by humans.
Furthermore, Popcorn is a great starting point when entering the world of OM XML, since you can type your semantics in a more ``what you type is how you think""™ way and convert that to ``proper'' OpenMath and vice versa.
start | ||
start | → | expr |
expr | → | blockExpr |
blockExpr | → | assignExpr (';' assignExpr)* |
assignExpr | → | implExpr (':=' implExpr)? |
implExpr | → | orExpr (('==>' | '<=>') orExpr)? |
orExpr | → | andExpr ('or' andExpr)* |
andExpr | → | relExpr ('and' relExpr)* |
relExpr | → | intervalExpr (('=' | '<' | '<=' | '>' | '>=' | '!=' | '<>') intervalExpr)? |
intervalExpr | → | addExpr ('..' addExpr)? |
addExpr | → | multExpr (('-' | '+') multExpr)* |
multExpr | → | powerExpr (('/' | '*') powerExpr)* |
powerExpr | → | complexExpr ('^' complexExpr)? |
complexExpr | → | rationalExpr ('|' rationalExpr)? |
rationalExpr | → | negExpr ('//' negExpr)? |
negExpr | → | ('-' | 'not') compExpr |
| | compExpr; | |
compExpr | → | paraExpr |
| | ecall | |
| | attribution | |
| | binding | |
| | listExpr | |
| | setExpr | |
| | anchor | |
commalist | → | EMPTYCOMMALIST |
| | expr (',' expr)* | |
call | → | anchor '(' commalist ')' |
ecall | → | anchor '!' '(' commalist ')' |
listExpr | → | '[' commalist ']' |
setExpr | → | '{' commalist '}' |
foreignExpr | → | '`' FOREIGN '`' |
attribution | → | anchor '{' attributionList '}' |
attributionList | → | attributionPair (',' attributionPair) |
attributionPair | → | expr '->' expr |
binding | → | anchor '[' commalist '->' expr ']' |
anchor | → | atom (':' ID) |
atom | → | paraExpr |
| | ID | |
| | symbol | |
| | var | |
| | intt | |
| | floatt | |
| | ref | |
| | OMB | |
| | FOREIGN | |
| | STRING | |
| | ifExpr | |
| | whileExpr | |
paraExpr | → | '(' expr ')' |
ifExpr | → | 'if' expr 'then' expr 'else' expr 'endif' |
whileExpr | → | 'while' expr 'do' expr 'endwhile' |
unaryOp | → | '-' | 'not' |
ID | → | (('a'..'z' | 'A'..'Z' | '_')('a'..'z' | 'A'..'Z' | '0'..'9' | '_')*)| |
('\''('a'..'z' | 'A'..'Z' | '_')('a'..'z' | 'A'..'Z' | '0'..'9' | '_' | '.' | ':' | '_' | ...)*'\'') | ||
(see here for Details.) | ||
symbol | → | ID '.' ID |
var | → | '$' ID; |
ref | → | lref | GREF |
lref | → | '#' ID |
GREF | → | '##' .+ '##' |
OMB | → | '\%'('a'..'z' | 'A'..'Z' | '0'..'9' | '=')+'\%' |
intt | → | HEXINT | DECINT |
DECINT | → | '0'..'9'+ |
HEXINT | → | '0x'('a'..'f' | 'A'..'F' | '0'..'9')+ |
floatt | → | HEXFLOAT | DECFLOAT |
HEXFLOAT | → | '0f'('a'..'f' | 'A'..'F' | '0'..'9'){8,8} |
DECFLOAT | → | '0'..'9'+ '.' '0'..'9'+ ('e' '-'? '0'..'9'+)? |
STRING | → | ('"' .* '"') |
FOREIGN | → | '`' .* '<' .+ '>`' |
WS | → | (' ' | '\t' | '\n' | '\r')+ |
COMMENT | → | '/*' .* '*/' |
Figure 3.7 gives a grammar for the Popcorn encoding ("start" is the start symbol). Characters within ' are considered as literals, and |, +, ?, ., and * have the usual regexp meaning.
An OpenMath object is encoded as a sequence of characters, where the tree structure is defined in a rather intuitive way, very much as in programming languages, mathematics, or CASes.
Here is a description of the Popcorn encodings of every kind of OpenMath object:
can be encoded in two ways, either decimally or hexadecimally. In the decimal representation, an integer is typed simply as a sequence of '0',...,'9' with the most signifacts decimals first.
For the hexadecimal encoding, the hex-digits are typed as '0',...,'9' and 'a',...,'f' (where case does not matter), and the whole number is prefixed with '0x' as in C. Again, the most significant nibbles come first.
are encoded as the name of the cd, immediately followed by a dot and the name of the symbol, e.g. arith1.plus. Additionally, for some symbols, there is a cdname free representations, cf. section 3.4.4.
Above that, for the application of some symbols, there is a `cannonical' infix notation available, cf. section ``infix''.
are encoded as the name of the variable prefixed with an $.
are encoded by either the decimal representation known from the xml encoding, or by the hexadecimal ecoding, which has to be prefixed with a 0f.
are encoded by wrapping them in ", where the usual substitutions \n, \r, \t, \\, and \" can be used.
are encoded as a base64 character stream wrapped in %. Whitespaces are ignored, here.
are encoded as an xml string wrapped in `, where the value of the encoding attribute may preceed the actual xml encoded string, e.g., `xhtml 1.0<h1>text</h1>`.
are not yet dealt with. They will be added later on by postfixing the cdbase url behind an @.
are encoded by postfixing the ()-paranthesized list of comma seperated arguments to the object to be applied. The argument list may of cause be empty.
are encoded by appending a []-bracketed pair of comma seperated bound variables and the bound expression to the binding operator. Inside the brackets, the variables and the expression are seperated with ->.
are encoded by appending a {}-braced, comma sperated list of attribution pairs. Each attribution pair is seperated with ->.
are encoded as an application where a ! is inserted between the error symbol and the parantheses.
are encoded by prefixing the local name with #.
are encoded by wrapping the external url in ##.
As a convenience addition, there are several infix operators defined in Popcorn:
Operator | Corresponding Symbol | arity | Comments |
---|---|---|---|
; | prog1.block | n | |
:= | prog1.assign | 2 | |
==> | logic1.implies | 2 | |
<=> | logic1.equivalent | 2 | |
or | logic1.or | n | |
and | logic1.and | n | |
< | relation1.lt | 2 | |
<= | relation1.leq | 2 | |
> | relation1.gt | 2 | |
= | relation1.eq | 2 | |
>= | relation1.geq | 2 | |
<> | relation1.neq | 2 | |
!= | relation1.neq | 2 | |
.. | interval1.interval | n | |
+ | arith1.plus | n | |
- | arith1.minus | 2 | |
* | arith1.times | n | |
/ | arith1.divide | 2 | |
^ | arith1.power | 2 | |
| | complex1.complex_cartesian | 2 | |
// | nums1.rational | 2 | |
[...] | list1.list | n | Not really a infix operator |
{...} | set1.set | n | Not really a infix operator |
if...then...else...endif | prog1.if | n | Not really a infix operator |
while...do...endwhile | prog1.while | n | Not really a infix operator |
As another convenience addition, for some commonly used symbols there is a cdname-free version available:
cos | → | transc1.cos |
cosh | → | transc1.cosh |
cot | → | transc1.cot |
coth | → | transc1.coth |
csc | → | transc1.csc |
csch | → | transc1.csch |
exp | → | transc1.exp |
sec | → | transc1.sec |
sech | → | transc1.sech |
sin | → | transc1.sin |
sinh | → | transc1.sinh |
tan | → | transc1.tan |
tanh | → | transc1.tanh |
abs | → | arith1.abs |
root | → | arith1.root |
sum | → | arith1.sum |
product | → | arith1.product |
diff | → | calculus1.diff |
int | → | calculus1.int |
defint | → | calculus1.defint |
pi | → | nums1.pi |
e | → | nums1.e |
i | → | nums1.i |
infinity | → | nums1.infinity |
min | → | minmax1.min |
max | → | minmax1.max |
lambda | → | fns1.lambda |
true | → | logic1.true |
false | → | logic1.false |
binomial | → | combinat1.binomial |
factorial | → | integer1.factorial |
To clarify the concept of Popcorn, we give a couple of examples:
Popcorn Representation | xml Representation |
---|---|
sin(3) |
<OMA> <OMS cd="arith1" name="sin" > <OMI>3</OMI> </OMA> |
lambda[$x->1+$x] |
<OMBIND> <OMS cd="fns1" name="lambda" /> <OMBVAR> <OMV name="x" /> </OMBVAR> <OMA> <OMS cd="arith1" name="plus" /> <OMI>1</OMI> <OMV name="x" /> </OMA> </OMBIND> |
$a := [1//2, (2|8):x] |
<OMA> <OMS cd="prog1" name="assign" /> <OMV name="a" /> <OMA> <OMS cd="list1" name="list" /> <OMA> <OMS cd="nums1" name="rational" /> <OMI>1</OMI><OMI>2</OMI> </OMA> <OMA id="x"{}> <OMS cd="nums1" name="complex_cartesian" /> <OMI>2</OMI><OMI>8</OMI> </OMA> </OMA> </OMA> |
1.2{aa.bb -> "cc"} |
<OMATTR> <OMATP> <OMS cd="aa" name="bb" /> <OMSTR>cc</OMSTR> </OMATP> <OMF dec="1.2" /> </OMATTR> |
A Popcorn parser and a Popcorn renderer are implemented in the symcomp.org java package written by the authors. It is implemented using the ANTLR v3 parser generator, and therefore the grammar files can easily be used to produce e.g. C output, too.
Since the library is published under an Apache 2 license, it may be freely used, although we appreciate every kind of feedback.
Popcorn offers an easy entry into the world of OpenMath, by allowing humans to easily read and write OpenMath objects.
Notice: We want to stress, again, that Popcorn is not intended as a 'global' replacement for the other OM representations, but merely as a more intuitive option to deal with OM whenever human interaction is required.