//=========================================================================
//
//  Part of units package -- a Java version of GNU Units program.
//
//  Units is a program for unit conversion originally written in C
//  by Adrian Mariano (adrian@cam.cornell.edu.).
//  Copyright (C) 1996, 1997, 1999, 2000, 2001, 2002, 2003, 2004,
//  2005, 2006, 2007, 2010 by Free Software Foundation, Inc.
//
//  Java version Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008,
//  2009, 2010 by Roman R Redziejowski (roman.redz@tele2.se).
//
//  This program is free software: you can redistribute it and/or modify
//  it under the terms of the GNU General Public License as published by
//  the Free Software Foundation, either version 3 of the License, or
//  (at your option) any later version.
//
//  This program is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
//  GNU General Public License for more details.
//
//  You should have received a copy of the GNU General Public License
//  along with this program. If not, see <http://www.gnu.org/licenses/>.
//
//-------------------------------------------------------------------------
//
//  Change log
//
//    091024 Created for version 1.87.J01.
//    101101 Version 1.88.J01: Removed superfluous '?' after 'space'.
//
//=========================================================================

unitexpr = space expr? EOT {unitexpr} ~{error};

expr     = term ((PLUS / MINUS) term)* {expr} 
         / (SLASH / PER) product {inverse} ;

term     = product ((STAR / SLASH / PER) product)* {term} ;

product  = factor (![+-] factor)* {product} ; // [+-] between factors IS NOT unary!

factor   = unary ((HAT / STARSTAR) unary)* {factor};

unary    = (PLUS / MINUS)? primary {unary} ;

primary  = numexpr {makeNumUnit} 
         / LPAR expr RPAR {pass2}
         / unitname {pass}
         / bfunc LPAR expr RPAR {evalBfunc}
         / opttilde dfunc LPAR expr RPAR {evalUfunc} ;
           
numexpr  = number (BAR number)* {numexpr};

number   = mantissa exponent? space {number} ; 

mantissa = "." digits / digits ("." digits?)? ; 

exponent = [Ee] sign? digits ;

sign     = [+-] <sign> ;

digits   = digit+ ;

digit    = [0-9] ;

word     = ![.0123456789~]namechar+ ;

namechar = ![\t\n^ +-*/|()]_ <more name> ;

opttilde = TILDE? <~> ;

unitname = word space {&unitname} <unit name> ;
bfunc    = word space {&bfunc}    <function name> ;
dfunc    = word space {&ufunc}    <function name> ;

BAR      = "|" space  <|> ;
HAT      = "^" space  <^> ;
TILDE    = "~" space  <~> ;
LPAR     = "(" space  <(> ;
MINUS    = "-" space  <-> ;
PLUS     = "+" space  <+> ;
RPAR     = ")" space  <)> ;
SLASH    = "/" space  </> ;
STARSTAR = "**" space <**> ;
STAR     = "*" !"*" space <*> ;
PER      = "per" &[\t\n^ +-*/|()] space  <'per'> ;

space       = [ \t]* {space} ;

EOT         = !_ <end of input> ;

