The start nonterminal is UnitPattern.
White Space
Syntax
  {wsopt, wsreq}
WhiteSpaceCharacter 
	«TAB» | «VT» | «FF» | «SP» | «u00A0»
|	«u2000» | «u2001» | «u2002» | «u2003» | «u2004» | «u2005» | «u2006» | «u2007»
|	«u2008» | «u2009» | «u200A» | «u200B»
|	«u3000»
LineTerminator  «LF» | «CR» | «u2028» | «u2029»
RequiredWhiteSpace 
	WhiteSpaceCharacter
|	LineTerminator
|	RequiredWhiteSpace WhiteSpaceCharacter
|	RequiredWhiteSpace LineTerminator
WhiteSpacewsopt 
	RequiredWhiteSpace
|	«empty»
WhiteSpacewsreq  RequiredWhiteSpace
Unit Patterns
Syntax
UnitPattern  WhiteSpacewsopt UnitQuotient
UnitQuotient 
	UnitProductwsopt
|	UnitProductwsopt / WhiteSpacewsopt UnitProductwsopt
UnitProduct 
	UnitFactor
|	UnitProductwsopt * WhiteSpacewsopt UnitFactor
|	UnitProductwsreq UnitFactor
UnitFactor 
	1 WhiteSpace
|	1 WhiteSpacewsopt ^ WhiteSpacewsopt SignedInteger WhiteSpace
|	Identifier WhiteSpace
|	Identifier WhiteSpacewsopt ^ WhiteSpacewsopt SignedInteger WhiteSpace
Semantics
tuple UnitFactor
identifier: String,
exponent: Integer
end tuple;
UnitList = UnitFactor[];
proc unitReciprocal(value: UnitList): UnitList
return [UnitFactoridentifier: f.identifier, exponent: –(f.exponent) | f  value]
end proc;
Value[UnitPattern  WhiteSpacewsopt UnitQuotient]: UnitList = Value[UnitQuotient];
Value[UnitQuotient]: UnitList;
Value[UnitQuotient  UnitProductwsopt] = Value[UnitProductwsopt];
Value[UnitQuotient  UnitProductwsopt1 / WhiteSpacewsopt UnitProductwsopt2] = Value[UnitProductwsopt1]  unitReciprocal(Value[UnitProductwsopt2]);
Value[UnitProduct]: UnitList;
Value[UnitProduct  UnitFactor] = Value[UnitFactor];
Value[UnitProduct0  UnitProductwsopt1 * WhiteSpacewsopt UnitFactor] = Value[UnitProductwsopt1]  Value[UnitFactor];
Value[UnitProduct0  UnitProductwsreq1 UnitFactor] = Value[UnitProductwsreq1]  Value[UnitFactor];
Value[UnitFactor]: UnitList;
Value[UnitFactor  1 WhiteSpace] = [];
Value[UnitFactor  1 WhiteSpacewsopt ^ WhiteSpacewsopt SignedInteger WhiteSpace] = [];
Value[UnitFactor  Identifier WhiteSpace] = [UnitFactoridentifier: Name[Identifier], exponent: 1];
Value[UnitFactor  Identifier WhiteSpacewsopt ^ WhiteSpacewsopt SignedInteger WhiteSpace] = [UnitFactoridentifier: Name[Identifier], exponent: IntegerValue[SignedInteger]];
Signed Integers
Syntax
SignedInteger 
	DecimalDigits
|	+ DecimalDigits
|	- DecimalDigits
DecimalDigits 
	ASCIIDigit
|	DecimalDigits ASCIIDigit
ASCIIDigit  0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9
Semantics
IntegerValue[SignedInteger]: Integer;
IntegerValue[SignedInteger  DecimalDigits] = IntegerValue[DecimalDigits];
IntegerValue[SignedInteger  + DecimalDigits] = IntegerValue[DecimalDigits];
IntegerValue[SignedInteger  - DecimalDigits] = –IntegerValue[DecimalDigits];
IntegerValue[DecimalDigits]: Integer;
IntegerValue[DecimalDigits  ASCIIDigit] = DecimalValue[ASCIIDigit];
IntegerValue[DecimalDigits0  DecimalDigits1 ASCIIDigit] = 10IntegerValue[DecimalDigits1] + DecimalValue[ASCIIDigit];
DecimalValue[ASCIIDigit]: Integer = digitValue(ASCIIDigit);
Identifiers
Syntax
Identifier 
	InitialIdentifierCharacter
|	Identifier ContinuingIdentifierCharacter
InitialIdentifierCharacter  UnicodeInitialAlphabetic | $ | _
ContinuingIdentifierCharacter  UnicodeAlphanumeric | $ | _
UnicodeInitialAlphabetic  Any Unicode initial alphabetic character (includes ASCII A‑Z and a‑z)
UnicodeAlphanumeric  Any Unicode alphabetic or decimal digit character (includes ASCII 0‑9, A‑Z, and a‑z)
Semantics
Name[Identifier]: String;
Name[Identifier  InitialIdentifierCharacter] = [InitialIdentifierCharacter];
Name[Identifier0  Identifier1 ContinuingIdentifierCharacter] = Name[Identifier1]  [ContinuingIdentifierCharacter];
Index
Nonterminals
Update fields to generate this index
Semantic Domains
Update fields to generate this index
Globals
Update fields to generate this index