Commits

Stephen McKamey committed 5c9681a

- begin porting lexer
- porting literal and HTML entity processing
- using property lookup for HTML5 character references

Comments (0)

Files changed (9)

 			destdir="${bin.dir}"
 			debug="${javac.debug}"
 		/>
+		<!-- copy config into output -->
+		<copy file="${src.dir}/org/duelengine/duel/parsing/HTML5.properties"
+			todir="${bin.dir}/org/duelengine/duel/parsing/"/>
 	</target>
 
 	<target name="jar" depends="compile.src" description="Package as a jar">

src/org/duelengine/duel/parsing/CharUtility.java

+package org.duelengine.duel.parsing;
+
+/**
+ * Provides simplified (ASCII) definitions of character classes
+ */
+final class CharUtility {
+
+	public static boolean isWhiteSpace(int ch) {
+		switch (ch) {
+			case ' ':
+			case '\t':
+			case '\n':
+			case '\r':
+				return true;
+			default:
+				return false;
+		}
+	}
+
+	public static boolean isLetter(int ch) {
+		return
+			((ch >= 'a') && (ch <= 'z')) ||
+			((ch >= 'A') && (ch <= 'Z'));
+	}
+
+	public static boolean isDigit(int ch) {
+		return (ch >= '0') && (ch <= '9');
+	}
+
+	public static boolean isHexDigit(int ch) {
+		return
+			(ch >= '0' && ch <= '9') ||
+			(ch >= 'a' && ch <= 'f') ||
+			(ch >= 'A' && ch <= 'F');
+	}
+}

src/org/duelengine/duel/parsing/DuelGrammar.java

+package org.duelengine.duel.parsing;
+
+final class DuelGrammar {
+
+	// static class
+	private DuelGrammar() {}
+
+	public static final int EOF = -1;
+
+	public static final char OP_ELEM_BEGIN = '<';
+	public static final char OP_ELEM_END = '>';
+	public static final char OP_ELEM_CLOSE = '/';
+	public static final char OP_VALUE_DELIM = ' ';
+	public static final char OP_PAIR_DELIM = '=';
+	public static final char OP_PREFIX_DELIM = ':';
+
+	public static final char OP_STRING_DELIM = '"';
+	public static final char OP_STRING_DELIM_ALT = '\'';
+
+	public static final char OP_ENTITY_BEGIN = '&';
+	public static final char OP_ENTITY_NUM = '#';
+	public static final char OP_ENTITY_HEX = 'x';
+	public static final char OP_ENTITY_HEX_ALT = 'X';
+	public static final char OP_ENTITY_END = ';';
+
+	public static final char OP_COMMENT = '!';
+	public static final char OP_COMMENT_DELIM = '-';
+	public static final String OP_COMMENT_BEGIN = "--";
+	public static final String OP_COMMENT_END = "--";
+	public static final String OP_CDATA_BEGIN = "[CDATA[";
+	public static final String OP_CDATA_END = "]]";
+}

src/org/duelengine/duel/parsing/DuelLexer.java

+package org.duelengine.duel.parsing;
+
+import java.io.*;
+import java.util.*;
+
+public class DuelLexer implements Iterator<DuelToken> {
+
+	private static final String CONFIG_RESOURCE = "org.duelengine.duel.parsing.HTML5";
+	private static ResourceBundle htmlConfig;
+
+	private LineNumberReader reader;
+	private int index = -1;
+	private int column = -1;
+	private int line = -1;
+	private int ch;
+	private final StringBuilder buffer = new StringBuilder();
+	private DuelToken token = DuelToken.Start;
+	private Exception lastError;
+
+	public DuelLexer(String text) {
+		this(new StringReader(text));
+	}
+
+	public DuelLexer(Reader reader) {
+		this.reader = new LineNumberReader(reader);
+
+		try {
+			// prime the sequence
+			this.nextChar();
+
+		} catch (IOException ex) {
+			ex.printStackTrace();
+			this.lastError = ex;
+		}
+	}
+
+	public int getLine() {
+		return this.line;
+	}
+
+	public int getColumn() {
+		return this.column;
+	}
+
+	public int getIndex() {
+		return this.index;
+	}
+
+	/**
+	 * Returns the last exception encountered
+	 */
+	public Exception getLastError() {
+		return this.lastError;
+	}
+
+	/**
+	 * Clears the last error
+	 */
+	public void clearLastError() {
+		this.lastError = null;
+
+		if (this.token.equals(DuelToken.Error)) {
+			this.token = DuelToken.Start;
+		}
+	}
+
+	/**
+	 * Determines if any more tokens exist
+	 */
+	public boolean hasNext() {
+		return (this.ch != DuelGrammar.EOF) && !this.token.equals(DuelToken.End);
+	}
+
+	/**
+	 * Not supported.
+	 */
+	public void remove()
+		throws UnsupportedOperationException {
+
+		throw new UnsupportedOperationException("Not supported");
+	}
+
+	public DuelToken next()
+		throws NoSuchElementException {
+
+		if (this.token.equals(DuelToken.End)) {
+			throw new NoSuchElementException("Passed end of file.");
+		}
+
+		try {
+			switch (this.token.getToken()) {
+				case START:
+					switch (this.ch) {
+						case DuelGrammar.OP_ELEM_BEGIN:
+							if (this.tryScanTag()) {
+								return this.token;
+							}
+							break;
+						case DuelGrammar.EOF:
+							return (this.token = DuelToken.End);
+					}
+
+					return this.scanLiteral();
+			}
+
+			return this.token;
+
+		} catch (IOException ex) {
+			ex.printStackTrace();
+
+			this.lastError = ex;
+			return (this.token = DuelToken.Error);
+		}
+	}
+
+	private DuelToken scanLiteral()
+		throws IOException {
+
+		// reset the buffer
+		this.buffer.setLength(0);
+		this.buffer.append((char)this.ch);
+		this.nextChar();
+
+		while (true) {
+			switch (this.ch) {
+				case DuelGrammar.OP_ELEM_BEGIN:
+				case DuelGrammar.EOF:
+					// flush the buffer
+					return DuelToken.Literal(this.buffer.toString());
+
+				case DuelGrammar.OP_ENTITY_BEGIN:
+					this.decodeEntity();
+					break;
+
+				default:
+					// consume until reach a special char
+					this.buffer.append((char)this.ch);
+					this.nextChar();
+					break;
+			}
+
+		}
+	}
+
+	private void decodeEntity()
+		throws IOException {
+
+		this.reader.mark(16);
+
+		// should be short enough that string concat is pretty fast
+		StringBuilder entity = new StringBuilder(16);
+		boolean isValid = false;
+
+		if (this.nextChar() == DuelGrammar.OP_ENTITY_NUM) {
+			// entity is Unicode Code Point
+			this.nextChar();
+
+			boolean isHex =
+				(this.ch == DuelGrammar.OP_ENTITY_HEX) ||
+				(this.ch == DuelGrammar.OP_ENTITY_HEX_ALT);
+
+			if (isHex) {
+				// skip over the 'x'
+				// consume hex digits
+				while (CharUtility.isHexDigit(this.nextChar())) {
+					entity.append((char)this.ch);
+				}
+			} else {
+				// consume digits
+				while (CharUtility.isDigit(this.ch)) {
+					entity.append((char)this.ch);
+					this.nextChar();
+				}
+			}
+
+			int codePoint = Integer.parseInt(entity.toString(), isHex ? 16 : 10);
+			if (codePoint > 0) {
+				this.buffer.append(Character.toChars(codePoint));
+				isValid = true;
+			}
+
+		} else {
+
+			// consume letters
+			while (CharUtility.isLetter(this.ch)) {
+				entity.append((char)this.ch);
+				this.nextChar();
+			}
+
+			String value = DuelLexer.decodeEntityName(entity.toString());
+			if (value != null) {
+				this.buffer.append(value);
+				isValid = true;
+			}
+		}
+
+		if (!isValid) {
+			// not an entity, add as simple ampersand
+			this.buffer.append(DuelGrammar.OP_ENTITY_BEGIN);
+			this.reader.reset();
+			this.nextChar();
+
+		} else if (this.ch == DuelGrammar.OP_ENTITY_END) {
+			this.nextChar();
+		}
+	}
+
+	/**
+	 * Decodes HTML5 character references
+	 * @param name
+	 * @return
+	 */
+	private static String decodeEntityName(String name) {
+
+		if (name == null || name.length() == 0) {
+			return null;
+		}
+
+		if (htmlConfig == null) {
+			// definitions maintained in HTML5.properties
+			htmlConfig = ResourceBundle.getBundle(CONFIG_RESOURCE);
+		}
+
+		if (htmlConfig.containsKey(name)) {
+			return htmlConfig.getString(name);
+		}
+
+		return null;
+	}
+
+	private boolean tryScanTag()
+		throws IOException {
+
+		this.reader.mark(16);
+		this.buffer.setLength(0);
+
+		return false;
+	}
+
+	private int nextChar() throws IOException {
+		int prevLine = this.line;
+
+		this.ch = this.reader.read();
+		this.line = this.reader.getLineNumber();
+
+		// update statistics
+		if (prevLine != this.line) {
+			this.column = 0;
+		} else {
+			this.column++;
+		}
+		this.index++;
+
+		return this.ch;
+	}
+
+	public ArrayList<DuelToken> toList() {
+
+		ArrayList<DuelToken> list = new ArrayList<DuelToken>();
+		while (this.hasNext()) {
+			DuelToken token = this.next();
+			list.add(token);
+
+			if (token.equals(DuelToken.Error)) {
+				break;
+			}
+		}
+		return list;
+	}
+}

src/org/duelengine/duel/parsing/DuelToken.java

+package org.duelengine.duel.parsing;
+
+public class DuelToken {
+
+	private final DuelTokenType type;
+	private final String value;
+	private final UnparsedBlock unparsed;
+
+	private DuelToken(DuelTokenType type) {
+		this.type = type;
+		this.value = null;
+		this.unparsed = null;
+	}
+
+	private DuelToken(DuelTokenType type, String value) {
+		this.type = type;
+		this.value = value;
+		this.unparsed = null;
+	}
+
+	private DuelToken(DuelTokenType type, UnparsedBlock value) {
+		this.type = type;
+		this.value = null;
+		this.unparsed = value;
+	}
+
+	public DuelTokenType getToken() {
+		return this.type;
+	}
+
+	public String getValue() {
+		return this.value;
+	}
+
+	public UnparsedBlock getUnparsed() {
+		return this.unparsed;
+	}
+
+	@Override
+	public String toString() {
+		StringBuilder buffer = new StringBuilder(this.type+": ");
+		if (this.value != null) {
+			buffer.append(this.value);
+		}
+		else if (this.unparsed != null) {
+			buffer.append(this.unparsed);
+		}
+		return buffer.toString();
+	}
+
+	@Override
+	public boolean equals(Object arg) {
+		if (!(arg instanceof DuelToken)) {
+			// includes null
+			return false;
+		}
+
+		DuelToken that = (DuelToken)arg;
+		return
+			(this.type.equals(that.type)) &&
+			(this.value == null ? that.value == null : this.value.equals(that.value)) &&
+			(this.unparsed == null ? that.unparsed == null : this.unparsed.equals(that.unparsed));
+	}
+
+	@Override
+	public int hashCode() {
+		final int HASH_PRIME = 1000003;
+
+		int hash = this.type.hashCode();
+		if (this.value != null) {
+			hash = hash * HASH_PRIME + this.value.hashCode();
+		}
+		if (this.unparsed != null) {
+			hash = hash * HASH_PRIME + this.unparsed.hashCode();
+		}
+		return hash;
+	}
+
+	/* reusable tokens and helper methods */
+	
+	public static final DuelToken Start = new DuelToken(DuelTokenType.START);
+	public static final DuelToken End = new DuelToken(DuelTokenType.END);
+	public static final DuelToken Error = new DuelToken(DuelTokenType.ERROR);
+
+	public static DuelToken ElemBegin(String name) {
+		return new DuelToken(DuelTokenType.ELEM_BEGIN, name);
+	}
+
+	public static DuelToken ElemEnd(String name) {
+		return new DuelToken(DuelTokenType.ELEM_END, name);
+	}
+
+	public static DuelToken AttrName(String name) {
+		return new DuelToken(DuelTokenType.ATTR_NAME, name);
+	}
+
+	public static DuelToken AttrValue(String value) {
+		return new DuelToken(DuelTokenType.ATTR_LITERAL, value);
+	}
+
+	public static DuelToken AttrValue(UnparsedBlock value) {
+		return new DuelToken(DuelTokenType.ATTR_UNPARSED, value);
+	}
+
+	public static DuelToken Unparsed(UnparsedBlock value) {
+		return new DuelToken(DuelTokenType.UNPARSED, value);
+	}
+
+	public static DuelToken Literal(String value) {
+		return new DuelToken(DuelTokenType.LITERAL, value);
+	}
+}

src/org/duelengine/duel/parsing/DuelTokenType.java

+package org.duelengine.duel.parsing;
+
+public enum DuelTokenType {
+
+	START,
+
+	END,
+
+	ERROR,
+
+	ELEM_BEGIN,
+
+	ELEM_END,
+
+	ATTR_NAME,
+
+	ATTR_LITERAL,
+
+	ATTR_UNPARSED,
+
+	UNPARSED,
+
+	LITERAL
+}

src/org/duelengine/duel/parsing/HTML5.properties

+# HTML5 Character References
+# NOTE: entity names are case-sensitive
+# http://www.w3.org/TR/html5/named-character-references.html
+# http://www.w3.org/TR/xhtml-modularization/dtd_module_defs.html
+# http://www.w3.org/TR/REC-html40/sgml/entities.html
+AElig=\u00C6
+AMP=\u0026
+Aacute=\u00C1
+Abreve=\u0102
+Acirc=\u00C2
+Acy=\u0410
+Afr=\u1D504
+Agrave=\u00C0
+Alpha=\u0391
+Amacr=\u0100
+And=\u2A53
+Aogon=\u0104
+Aopf=\u1D538
+ApplyFunction=\u2061
+Aring=\u00C5
+Ascr=\u1D49C
+Assign=\u2254
+Atilde=\u00C3
+Auml=\u00C4
+Backslash=\u2216
+Barv=\u2AE7
+Barwed=\u2306
+Bcy=\u0411
+Because=\u2235
+Bernoullis=\u212C
+Beta=\u0392
+Bfr=\u1D505
+Bopf=\u1D539
+Breve=\u02D8
+Bscr=\u212C
+Bumpeq=\u224E
+CHcy=\u0427
+COPY=\u00A9
+Cacute=\u0106
+Cap=\u22D2
+CapitalDifferentialD=\u2145
+Cayleys=\u212D
+Ccaron=\u010C
+Ccedil=\u00C7
+Ccirc=\u0108
+Cconint=\u2230
+Cdot=\u010A
+Cedilla=\u00B8
+CenterDot=\u00B7
+Cfr=\u212D
+Chi=\u03A7
+CircleDot=\u2299
+CircleMinus=\u2296
+CirclePlus=\u2295
+CircleTimes=\u2297
+ClockwiseContourIntegral=\u2232
+CloseCurlyDoubleQuote=\u201D
+CloseCurlyQuote=\u2019
+Colon=\u2237
+Colone=\u2A74
+Congruent=\u2261
+Conint=\u222F
+ContourIntegral=\u222E
+Copf=\u2102
+Coproduct=\u2210
+CounterClockwiseContourIntegral=\u2233
+Cross=\u2A2F
+Cscr=\u1D49E
+Cup=\u22D3
+CupCap=\u224D
+DD=\u2145
+DDotrahd=\u2911
+DJcy=\u0402
+DScy=\u0405
+DZcy=\u040F
+Dagger=\u2021
+Darr=\u21A1
+Dashv=\u2AE4
+Dcaron=\u010E
+Dcy=\u0414
+Del=\u2207
+Delta=\u0394
+Dfr=\u1D507
+DiacriticalAcute=\u00B4
+DiacriticalDot=\u02D9
+DiacriticalDoubleAcute=\u02DD
+DiacriticalGrave=\u0060
+DiacriticalTilde=\u02DC
+Diamond=\u22C4
+DifferentialD=\u2146
+Dopf=\u1D53B
+Dot=\u00A8
+DotDot=\u20DC
+DotEqual=\u2250
+DoubleContourIntegral=\u222F
+DoubleDot=\u00A8
+DoubleDownArrow=\u21D3
+DoubleLeftArrow=\u21D0
+DoubleLeftRightArrow=\u21D4
+DoubleLeftTee=\u2AE4
+DoubleLongLeftArrow=\u27F8
+DoubleLongLeftRightArrow=\u27FA
+DoubleLongRightArrow=\u27F9
+DoubleRightArrow=\u21D2
+DoubleRightTee=\u22A8
+DoubleUpArrow=\u21D1
+DoubleUpDownArrow=\u21D5
+DoubleVerticalBar=\u2225
+DownArrow=\u2193
+DownArrowBar=\u2913
+DownArrowUpArrow=\u21F5
+DownBreve=\u0311
+DownLeftRightVector=\u2950
+DownLeftTeeVector=\u295E
+DownLeftVector=\u21BD
+DownLeftVectorBar=\u2956
+DownRightTeeVector=\u295F
+DownRightVector=\u21C1
+DownRightVectorBar=\u2957
+DownTee=\u22A4
+DownTeeArrow=\u21A7
+Downarrow=\u21D3
+Dscr=\u1D49F
+Dstrok=\u0110
+ENG=\u014A
+ETH=\u00D0
+Eacute=\u00C9
+Ecaron=\u011A
+Ecirc=\u00CA
+Ecy=\u042D
+Edot=\u0116
+Efr=\u1D508
+Egrave=\u00C8
+Element=\u2208
+Emacr=\u0112
+EmptySmallSquare=\u25FB
+EmptyVerySmallSquare=\u25AB
+Eogon=\u0118
+Eopf=\u1D53C
+Epsilon=\u0395
+Equal=\u2A75
+EqualTilde=\u2242
+Equilibrium=\u21CC
+Escr=\u2130
+Esim=\u2A73
+Eta=\u0397
+Euml=\u00CB
+Exists=\u2203
+ExponentialE=\u2147
+Fcy=\u0424
+Ffr=\u1D509
+FilledSmallSquare=\u25FC
+FilledVerySmallSquare=\u25AA
+Fopf=\u1D53D
+ForAll=\u2200
+Fouriertrf=\u2131
+Fscr=\u2131
+GJcy=\u0403
+GT=\u003E
+Gamma=\u0393
+Gammad=\u03DC
+Gbreve=\u011E
+Gcedil=\u0122
+Gcirc=\u011C
+Gcy=\u0413
+Gdot=\u0120
+Gfr=\u1D50A
+Gg=\u22D9
+Gopf=\u1D53E
+GreaterEqual=\u2265
+GreaterEqualLess=\u22DB
+GreaterFullEqual=\u2267
+GreaterGreater=\u2AA2
+GreaterLess=\u2277
+GreaterSlantEqual=\u2A7E
+GreaterTilde=\u2273
+Gscr=\u1D4A2
+Gt=\u226B
+HARDcy=\u042A
+Hacek=\u02C7
+Hat=\u005E
+Hcirc=\u0124
+Hfr=\u210C
+HilbertSpace=\u210B
+Hopf=\u210D
+HorizontalLine=\u2500
+Hscr=\u210B
+Hstrok=\u0126
+HumpDownHump=\u224E
+HumpEqual=\u224F
+IEcy=\u0415
+IJlig=\u0132
+IOcy=\u0401
+Iacute=\u00CD
+Icirc=\u00CE
+Icy=\u0418
+Idot=\u0130
+Ifr=\u2111
+Igrave=\u00CC
+Im=\u2111
+Imacr=\u012A
+ImaginaryI=\u2148
+Implies=\u21D2
+Int=\u222C
+Integral=\u222B
+Intersection=\u22C2
+InvisibleComma=\u2063
+InvisibleTimes=\u2062
+Iogon=\u012E
+Iopf=\u1D540
+Iota=\u0399
+Iscr=\u2110
+Itilde=\u0128
+Iukcy=\u0406
+Iuml=\u00CF
+Jcirc=\u0134
+Jcy=\u0419
+Jfr=\u1D50D
+Jopf=\u1D541
+Jscr=\u1D4A5
+Jsercy=\u0408
+Jukcy=\u0404
+KHcy=\u0425
+KJcy=\u040C
+Kappa=\u039A
+Kcedil=\u0136
+Kcy=\u041A
+Kfr=\u1D50E
+Kopf=\u1D542
+Kscr=\u1D4A6
+LJcy=\u0409
+LT=\u003C
+Lacute=\u0139
+Lambda=\u039B
+Lang=\u27EA
+Laplacetrf=\u2112
+Larr=\u219E
+Lcaron=\u013D
+Lcedil=\u013B
+Lcy=\u041B
+LeftAngleBracket=\u27E8
+LeftArrow=\u2190
+LeftArrowBar=\u21E4
+LeftArrowRightArrow=\u21C6
+LeftCeiling=\u2308
+LeftDoubleBracket=\u27E6
+LeftDownTeeVector=\u2961
+LeftDownVector=\u21C3
+LeftDownVectorBar=\u2959
+LeftFloor=\u230A
+LeftRightArrow=\u2194
+LeftRightVector=\u294E
+LeftTee=\u22A3
+LeftTeeArrow=\u21A4
+LeftTeeVector=\u295A
+LeftTriangle=\u22B2
+LeftTriangleBar=\u29CF
+LeftTriangleEqual=\u22B4
+LeftUpDownVector=\u2951
+LeftUpTeeVector=\u2960
+LeftUpVector=\u21BF
+LeftUpVectorBar=\u2958
+LeftVector=\u21BC
+LeftVectorBar=\u2952
+Leftarrow=\u21D0
+Leftrightarrow=\u21D4
+LessEqualGreater=\u22DA
+LessFullEqual=\u2266
+LessGreater=\u2276
+LessLess=\u2AA1
+LessSlantEqual=\u2A7D
+LessTilde=\u2272
+Lfr=\u1D50F
+Ll=\u22D8
+Lleftarrow=\u21DA
+Lmidot=\u013F
+LongLeftArrow=\u27F5
+LongLeftRightArrow=\u27F7
+LongRightArrow=\u27F6
+Longleftarrow=\u27F8
+Longleftrightarrow=\u27FA
+Longrightarrow=\u27F9
+Lopf=\u1D543
+LowerLeftArrow=\u2199
+LowerRightArrow=\u2198
+Lscr=\u2112
+Lsh=\u21B0
+Lstrok=\u0141
+Lt=\u226A
+Map=\u2905
+Mcy=\u041C
+MediumSpace=\u205F
+Mellintrf=\u2133
+Mfr=\u1D510
+MinusPlus=\u2213
+Mopf=\u1D544
+Mscr=\u2133
+Mu=\u039C
+NJcy=\u040A
+Nacute=\u0143
+Ncaron=\u0147
+Ncedil=\u0145
+Ncy=\u041D
+NegativeMediumSpace=\u200B
+NegativeThickSpace=\u200B
+NegativeThinSpace=\u200B
+NegativeVeryThinSpace=\u200B
+NestedGreaterGreater=\u226B
+NestedLessLess=\u226A
+NewLine=\u000A
+Nfr=\u1D511
+NoBreak=\u2060
+NonBreakingSpace=\u00A0
+Nopf=\u2115
+Not=\u2AEC
+NotCongruent=\u2262
+NotCupCap=\u226D
+NotDoubleVerticalBar=\u2226
+NotElement=\u2209
+NotEqual=\u2260
+NotExists=\u2204
+NotGreater=\u226F
+NotGreaterEqual=\u2271
+NotGreaterLess=\u2279
+NotGreaterTilde=\u2275
+NotLeftTriangle=\u22EA
+NotLeftTriangleEqual=\u22EC
+NotLess=\u226E
+NotLessEqual=\u2270
+NotLessGreater=\u2278
+NotLessTilde=\u2274
+NotPrecedes=\u2280
+NotPrecedesSlantEqual=\u22E0
+NotReverseElement=\u220C
+NotRightTriangle=\u22EB
+NotRightTriangleEqual=\u22ED
+NotSquareSubsetEqual=\u22E2
+NotSquareSupersetEqual=\u22E3
+NotSubsetEqual=\u2288
+NotSucceeds=\u2281
+NotSucceedsSlantEqual=\u22E1
+NotSupersetEqual=\u2289
+NotTilde=\u2241
+NotTildeEqual=\u2244
+NotTildeFullEqual=\u2247
+NotTildeTilde=\u2249
+NotVerticalBar=\u2224
+Nscr=\u1D4A9
+Ntilde=\u00D1
+Nu=\u039D
+OElig=\u0152
+Oacute=\u00D3
+Ocirc=\u00D4
+Ocy=\u041E
+Odblac=\u0150
+Ofr=\u1D512
+Ograve=\u00D2
+Omacr=\u014C
+Omega=\u03A9
+Omicron=\u039F
+Oopf=\u1D546
+OpenCurlyDoubleQuote=\u201C
+OpenCurlyQuote=\u2018
+Or=\u2A54
+Oscr=\u1D4AA
+Oslash=\u00D8
+Otilde=\u00D5
+Otimes=\u2A37
+Ouml=\u00D6
+OverBar=\u203E
+OverBrace=\u23DE
+OverBracket=\u23B4
+OverParenthesis=\u23DC
+PartialD=\u2202
+Pcy=\u041F
+Pfr=\u1D513
+Phi=\u03A6
+Pi=\u03A0
+PlusMinus=\u00B1
+Poincareplane=\u210C
+Popf=\u2119
+Pr=\u2ABB
+Precedes=\u227A
+PrecedesEqual=\u2AAF
+PrecedesSlantEqual=\u227C
+PrecedesTilde=\u227E
+Prime=\u2033
+Product=\u220F
+Proportion=\u2237
+Proportional=\u221D
+Pscr=\u1D4AB
+Psi=\u03A8
+QUOT=\u0022
+Qfr=\u1D514
+Qopf=\u211A
+Qscr=\u1D4AC
+RBarr=\u2910
+REG=\u00AE
+Racute=\u0154
+Rang=\u27EB
+Rarr=\u21A0
+Rarrtl=\u2916
+Rcaron=\u0158
+Rcedil=\u0156
+Rcy=\u0420
+Re=\u211C
+ReverseElement=\u220B
+ReverseEquilibrium=\u21CB
+ReverseUpEquilibrium=\u296F
+Rfr=\u211C
+Rho=\u03A1
+RightAngleBracket=\u27E9
+RightArrow=\u2192
+RightArrowBar=\u21E5
+RightArrowLeftArrow=\u21C4
+RightCeiling=\u2309
+RightDoubleBracket=\u27E7
+RightDownTeeVector=\u295D
+RightDownVector=\u21C2
+RightDownVectorBar=\u2955
+RightFloor=\u230B
+RightTee=\u22A2
+RightTeeArrow=\u21A6
+RightTeeVector=\u295B
+RightTriangle=\u22B3
+RightTriangleBar=\u29D0
+RightTriangleEqual=\u22B5
+RightUpDownVector=\u294F
+RightUpTeeVector=\u295C
+RightUpVector=\u21BE
+RightUpVectorBar=\u2954
+RightVector=\u21C0
+RightVectorBar=\u2953
+Rightarrow=\u21D2
+Ropf=\u211D
+RoundImplies=\u2970
+Rrightarrow=\u21DB
+Rscr=\u211B
+Rsh=\u21B1
+RuleDelayed=\u29F4
+SHCHcy=\u0429
+SHcy=\u0428
+SOFTcy=\u042C
+Sacute=\u015A
+Sc=\u2ABC
+Scaron=\u0160
+Scedil=\u015E
+Scirc=\u015C
+Scy=\u0421
+Sfr=\u1D516
+ShortDownArrow=\u2193
+ShortLeftArrow=\u2190
+ShortRightArrow=\u2192
+ShortUpArrow=\u2191
+Sigma=\u03A3
+SmallCircle=\u2218
+Sopf=\u1D54A
+Sqrt=\u221A
+Square=\u25A1
+SquareIntersection=\u2293
+SquareSubset=\u228F
+SquareSubsetEqual=\u2291
+SquareSuperset=\u2290
+SquareSupersetEqual=\u2292
+SquareUnion=\u2294
+Sscr=\u1D4AE
+Star=\u22C6
+Sub=\u22D0
+Subset=\u22D0
+SubsetEqual=\u2286
+Succeeds=\u227B
+SucceedsEqual=\u2AB0
+SucceedsSlantEqual=\u227D
+SucceedsTilde=\u227F
+SuchThat=\u220B
+Sum=\u2211
+Sup=\u22D1
+Superset=\u2283
+SupersetEqual=\u2287
+Supset=\u22D1
+THORN=\u00DE
+TRADE=\u2122
+TSHcy=\u040B
+TScy=\u0426
+Tab=\u0009
+Tau=\u03A4
+Tcaron=\u0164
+Tcedil=\u0162
+Tcy=\u0422
+Tfr=\u1D517
+Therefore=\u2234
+Theta=\u0398
+ThinSpace=\u2009
+Tilde=\u223C
+TildeEqual=\u2243
+TildeFullEqual=\u2245
+TildeTilde=\u2248
+Topf=\u1D54B
+TripleDot=\u20DB
+Tscr=\u1D4AF
+Tstrok=\u0166
+Uacute=\u00DA
+Uarr=\u219F
+Uarrocir=\u2949
+Ubrcy=\u040E
+Ubreve=\u016C
+Ucirc=\u00DB
+Ucy=\u0423
+Udblac=\u0170
+Ufr=\u1D518
+Ugrave=\u00D9
+Umacr=\u016A
+UnderBar=\u005F
+UnderBrace=\u23DF
+UnderBracket=\u23B5
+UnderParenthesis=\u23DD
+Union=\u22C3
+UnionPlus=\u228E
+Uogon=\u0172
+Uopf=\u1D54C
+UpArrow=\u2191
+UpArrowBar=\u2912
+UpArrowDownArrow=\u21C5
+UpDownArrow=\u2195
+UpEquilibrium=\u296E
+UpTee=\u22A5
+UpTeeArrow=\u21A5
+Uparrow=\u21D1
+Updownarrow=\u21D5
+UpperLeftArrow=\u2196
+UpperRightArrow=\u2197
+Upsi=\u03D2
+Upsilon=\u03A5
+Uring=\u016E
+Uscr=\u1D4B0
+Utilde=\u0168
+Uuml=\u00DC
+VDash=\u22AB
+Vbar=\u2AEB
+Vcy=\u0412
+Vdash=\u22A9
+Vdashl=\u2AE6
+Vee=\u22C1
+Verbar=\u2016
+Vert=\u2016
+VerticalBar=\u2223
+VerticalLine=\u007C
+VerticalSeparator=\u2758
+VerticalTilde=\u2240
+VeryThinSpace=\u200A
+Vfr=\u1D519
+Vopf=\u1D54D
+Vscr=\u1D4B1
+Vvdash=\u22AA
+Wcirc=\u0174
+Wedge=\u22C0
+Wfr=\u1D51A
+Wopf=\u1D54E
+Wscr=\u1D4B2
+Xfr=\u1D51B
+Xi=\u039E
+Xopf=\u1D54F
+Xscr=\u1D4B3
+YAcy=\u042F
+YIcy=\u0407
+YUcy=\u042E
+Yacute=\u00DD
+Ycirc=\u0176
+Ycy=\u042B
+Yfr=\u1D51C
+Yopf=\u1D550
+Yscr=\u1D4B4
+Yuml=\u0178
+ZHcy=\u0416
+Zacute=\u0179
+Zcaron=\u017D
+Zcy=\u0417
+Zdot=\u017B
+ZeroWidthSpace=\u200B
+Zeta=\u0396
+Zfr=\u2128
+Zopf=\u2124
+Zscr=\u1D4B5
+aacute=\u00E1
+abreve=\u0103
+ac=\u223E
+acd=\u223F
+acirc=\u00E2
+acute=\u00B4
+acy=\u0430
+aelig=\u00E6
+af=\u2061
+afr=\u1D51E
+agrave=\u00E0
+alefsym=\u2135
+aleph=\u2135
+alpha=\u03B1
+amacr=\u0101
+amalg=\u2A3F
+amp=\u0026
+and=\u2227
+andand=\u2A55
+andd=\u2A5C
+andslope=\u2A58
+andv=\u2A5A
+ang=\u2220
+ange=\u29A4
+angle=\u2220
+angmsd=\u2221
+angmsdaa=\u29A8
+angmsdab=\u29A9
+angmsdac=\u29AA
+angmsdad=\u29AB
+angmsdae=\u29AC
+angmsdaf=\u29AD
+angmsdag=\u29AE
+angmsdah=\u29AF
+angrt=\u221F
+angrtvb=\u22BE
+angrtvbd=\u299D
+angsph=\u2222
+angst=\u00C5
+angzarr=\u237C
+aogon=\u0105
+aopf=\u1D552
+ap=\u2248
+apE=\u2A70
+apacir=\u2A6F
+ape=\u224A
+apid=\u224B
+apos=\u0027
+approx=\u2248
+approxeq=\u224A
+aring=\u00E5
+ascr=\u1D4B6
+ast=\u002A
+asymp=\u2248
+asympeq=\u224D
+atilde=\u00E3
+auml=\u00E4
+awconint=\u2233
+awint=\u2A11
+bNot=\u2AED
+backcong=\u224C
+backepsilon=\u03F6
+backprime=\u2035
+backsim=\u223D
+backsimeq=\u22CD
+barvee=\u22BD
+barwed=\u2305
+barwedge=\u2305
+bbrk=\u23B5
+bbrktbrk=\u23B6
+bcong=\u224C
+bcy=\u0431
+bdquo=\u201E
+becaus=\u2235
+because=\u2235
+bemptyv=\u29B0
+bepsi=\u03F6
+bernou=\u212C
+beta=\u03B2
+beth=\u2136
+between=\u226C
+bfr=\u1D51F
+bigcap=\u22C2
+bigcirc=\u25EF
+bigcup=\u22C3
+bigodot=\u2A00
+bigoplus=\u2A01
+bigotimes=\u2A02
+bigsqcup=\u2A06
+bigstar=\u2605
+bigtriangledown=\u25BD
+bigtriangleup=\u25B3
+biguplus=\u2A04
+bigvee=\u22C1
+bigwedge=\u22C0
+bkarow=\u290D
+blacklozenge=\u29EB
+blacksquare=\u25AA
+blacktriangle=\u25B4
+blacktriangledown=\u25BE
+blacktriangleleft=\u25C2
+blacktriangleright=\u25B8
+blank=\u2423
+blk12=\u2592
+blk14=\u2591
+blk34=\u2593
+block=\u2588
+bnot=\u2310
+bopf=\u1D553
+bot=\u22A5
+bottom=\u22A5
+bowtie=\u22C8
+boxDL=\u2557
+boxDR=\u2554
+boxDl=\u2556
+boxDr=\u2553
+boxH=\u2550
+boxHD=\u2566
+boxHU=\u2569
+boxHd=\u2564
+boxHu=\u2567
+boxUL=\u255D
+boxUR=\u255A
+boxUl=\u255C
+boxUr=\u2559
+boxV=\u2551
+boxVH=\u256C
+boxVL=\u2563
+boxVR=\u2560
+boxVh=\u256B
+boxVl=\u2562
+boxVr=\u255F
+boxbox=\u29C9
+boxdL=\u2555
+boxdR=\u2552
+boxdl=\u2510
+boxdr=\u250C
+boxh=\u2500
+boxhD=\u2565
+boxhU=\u2568
+boxhd=\u252C
+boxhu=\u2534
+boxminus=\u229F
+boxplus=\u229E
+boxtimes=\u22A0
+boxuL=\u255B
+boxuR=\u2558
+boxul=\u2518
+boxur=\u2514
+boxv=\u2502
+boxvH=\u256A
+boxvL=\u2561
+boxvR=\u255E
+boxvh=\u253C
+boxvl=\u2524
+boxvr=\u251C
+bprime=\u2035
+breve=\u02D8
+brvbar=\u00A6
+bscr=\u1D4B7
+bsemi=\u204F
+bsim=\u223D
+bsime=\u22CD
+bsol=\u005C
+bsolb=\u29C5
+bsolhsub=\u27C8
+bull=\u2022
+bullet=\u2022
+bump=\u224E
+bumpE=\u2AAE
+bumpe=\u224F
+bumpeq=\u224F
+cacute=\u0107
+cap=\u2229
+capand=\u2A44
+capbrcup=\u2A49
+capcap=\u2A4B
+capcup=\u2A47
+capdot=\u2A40
+caret=\u2041
+caron=\u02C7
+ccaps=\u2A4D
+ccaron=\u010D
+ccedil=\u00E7
+ccirc=\u0109
+ccups=\u2A4C
+ccupssm=\u2A50
+cdot=\u010B
+cedil=\u00B8
+cemptyv=\u29B2
+cent=\u00A2
+centerdot=\u00B7
+cfr=\u1D520
+chcy=\u0447
+check=\u2713
+checkmark=\u2713
+chi=\u03C7
+cir=\u25CB
+cirE=\u29C3
+circ=\u02C6
+circeq=\u2257
+circlearrowleft=\u21BA
+circlearrowright=\u21BB
+circledR=\u00AE
+circledS=\u24C8
+circledast=\u229B
+circledcirc=\u229A
+circleddash=\u229D
+cire=\u2257
+cirfnint=\u2A10
+cirmid=\u2AEF
+cirscir=\u29C2
+clubs=\u2663
+clubsuit=\u2663
+colon=\u003A
+colone=\u2254
+coloneq=\u2254
+comma=\u002C
+commat=\u0040
+comp=\u2201
+compfn=\u2218
+complement=\u2201
+complexes=\u2102
+cong=\u2245
+congdot=\u2A6D
+conint=\u222E
+copf=\u1D554
+coprod=\u2210
+copy=\u00A9
+copysr=\u2117
+crarr=\u21B5
+cross=\u2717
+cscr=\u1D4B8
+csub=\u2ACF
+csube=\u2AD1
+csup=\u2AD0
+csupe=\u2AD2
+ctdot=\u22EF
+cudarrl=\u2938
+cudarrr=\u2935
+cuepr=\u22DE
+cuesc=\u22DF
+cularr=\u21B6
+cularrp=\u293D
+cup=\u222A
+cupbrcap=\u2A48
+cupcap=\u2A46
+cupcup=\u2A4A
+cupdot=\u228D
+cupor=\u2A45
+curarr=\u21B7
+curarrm=\u293C
+curlyeqprec=\u22DE
+curlyeqsucc=\u22DF
+curlyvee=\u22CE
+curlywedge=\u22CF
+curren=\u00A4
+curvearrowleft=\u21B6
+curvearrowright=\u21B7
+cuvee=\u22CE
+cuwed=\u22CF
+cwconint=\u2232
+cwint=\u2231
+cylcty=\u232D
+dArr=\u21D3
+dHar=\u2965
+dagger=\u2020
+daleth=\u2138
+darr=\u2193
+dash=\u2010
+dashv=\u22A3
+dbkarow=\u290F
+dblac=\u02DD
+dcaron=\u010F
+dcy=\u0434
+dd=\u2146
+ddagger=\u2021
+ddarr=\u21CA
+ddotseq=\u2A77
+deg=\u00B0
+delta=\u03B4
+demptyv=\u29B1
+dfisht=\u297F
+dfr=\u1D521
+dharl=\u21C3
+dharr=\u21C2
+diam=\u22C4
+diamond=\u22C4
+diamondsuit=\u2666
+diams=\u2666
+die=\u00A8
+digamma=\u03DD
+disin=\u22F2
+div=\u00F7
+divide=\u00F7
+divideontimes=\u22C7
+divonx=\u22C7
+djcy=\u0452
+dlcorn=\u231E
+dlcrop=\u230D
+dollar=\u0024
+dopf=\u1D555
+dot=\u02D9
+doteq=\u2250
+doteqdot=\u2251
+dotminus=\u2238
+dotplus=\u2214
+dotsquare=\u22A1
+doublebarwedge=\u2306
+downarrow=\u2193
+downdownarrows=\u21CA
+downharpoonleft=\u21C3
+downharpoonright=\u21C2
+drbkarow=\u2910
+drcorn=\u231F
+drcrop=\u230C
+dscr=\u1D4B9
+dscy=\u0455
+dsol=\u29F6
+dstrok=\u0111
+dtdot=\u22F1
+dtri=\u25BF
+dtrif=\u25BE
+duarr=\u21F5
+duhar=\u296F
+dwangle=\u29A6
+dzcy=\u045F
+dzigrarr=\u27FF
+eDDot=\u2A77
+eDot=\u2251
+eacute=\u00E9
+easter=\u2A6E
+ecaron=\u011B
+ecir=\u2256
+ecirc=\u00EA
+ecolon=\u2255
+ecy=\u044D
+edot=\u0117
+ee=\u2147
+efDot=\u2252
+efr=\u1D522
+eg=\u2A9A
+egrave=\u00E8
+egs=\u2A96
+egsdot=\u2A98
+el=\u2A99
+elinters=\u23E7
+ell=\u2113
+els=\u2A95
+elsdot=\u2A97
+emacr=\u0113
+empty=\u2205
+emptyset=\u2205
+emptyv=\u2205
+emsp13=\u2004
+emsp14=\u2005
+emsp=\u2003
+eng=\u014B
+ensp=\u2002
+eogon=\u0119
+eopf=\u1D556
+epar=\u22D5
+eparsl=\u29E3
+eplus=\u2A71
+epsi=\u03B5
+epsilon=\u03B5
+epsiv=\u03F5
+eqcirc=\u2256
+eqcolon=\u2255
+eqsim=\u2242
+eqslantgtr=\u2A96
+eqslantless=\u2A95
+equals=\u003D
+equest=\u225F
+equiv=\u2261
+equivDD=\u2A78
+eqvparsl=\u29E5
+erDot=\u2253
+erarr=\u2971
+escr=\u212F
+esdot=\u2250
+esim=\u2242
+eta=\u03B7
+eth=\u00F0
+euml=\u00EB
+euro=\u20AC
+excl=\u0021
+exist=\u2203
+expectation=\u2130
+exponentiale=\u2147
+fallingdotseq=\u2252
+fcy=\u0444
+female=\u2640
+ffilig=\uFB03
+fflig=\uFB00
+ffllig=\uFB04
+ffr=\u1D523
+filig=\uFB01
+flat=\u266D
+fllig=\uFB02
+fltns=\u25B1
+fnof=\u0192
+fopf=\u1D557
+forall=\u2200
+fork=\u22D4
+forkv=\u2AD9
+fpartint=\u2A0D
+frac12=\u00BD
+frac13=\u2153
+frac14=\u00BC
+frac15=\u2155
+frac16=\u2159
+frac18=\u215B
+frac23=\u2154
+frac25=\u2156
+frac34=\u00BE
+frac35=\u2157
+frac38=\u215C
+frac45=\u2158
+frac56=\u215A
+frac58=\u215D
+frac78=\u215E
+frasl=\u2044
+frown=\u2322
+fscr=\u1D4BB
+gE=\u2267
+gEl=\u2A8C
+gacute=\u01F5
+gamma=\u03B3
+gammad=\u03DD
+gap=\u2A86
+gbreve=\u011F
+gcirc=\u011D
+gcy=\u0433
+gdot=\u0121
+ge=\u2265
+gel=\u22DB
+geq=\u2265
+geqq=\u2267
+geqslant=\u2A7E
+ges=\u2A7E
+gescc=\u2AA9
+gesdot=\u2A80
+gesdoto=\u2A82
+gesdotol=\u2A84
+gesles=\u2A94
+gfr=\u1D524
+gg=\u226B
+ggg=\u22D9
+gimel=\u2137
+gjcy=\u0453
+gl=\u2277
+glE=\u2A92
+gla=\u2AA5
+glj=\u2AA4
+gnE=\u2269
+gnap=\u2A8A
+gnapprox=\u2A8A
+gne=\u2A88
+gneq=\u2A88
+gneqq=\u2269
+gnsim=\u22E7
+gopf=\u1D558
+grave=\u0060
+gscr=\u210A
+gsim=\u2273
+gsime=\u2A8E
+gsiml=\u2A90
+gt=\u003E
+gtcc=\u2AA7
+gtcir=\u2A7A
+gtdot=\u22D7
+gtlPar=\u2995
+gtquest=\u2A7C
+gtrapprox=\u2A86
+gtrarr=\u2978
+gtrdot=\u22D7
+gtreqless=\u22DB
+gtreqqless=\u2A8C
+gtrless=\u2277
+gtrsim=\u2273
+hArr=\u21D4
+hairsp=\u200A
+half=\u00BD
+hamilt=\u210B
+hardcy=\u044A
+harr=\u2194
+harrcir=\u2948
+harrw=\u21AD
+hbar=\u210F
+hcirc=\u0125
+hearts=\u2665
+heartsuit=\u2665
+hellip=\u2026
+hercon=\u22B9
+hfr=\u1D525
+hksearow=\u2925
+hkswarow=\u2926
+hoarr=\u21FF
+homtht=\u223B
+hookleftarrow=\u21A9
+hookrightarrow=\u21AA
+hopf=\u1D559
+horbar=\u2015
+hscr=\u1D4BD
+hslash=\u210F
+hstrok=\u0127
+hybull=\u2043
+hyphen=\u2010
+iacute=\u00ED
+ic=\u2063
+icirc=\u00EE
+icy=\u0438
+iecy=\u0435
+iexcl=\u00A1
+iff=\u21D4
+ifr=\u1D526
+igrave=\u00EC
+ii=\u2148
+iiiint=\u2A0C
+iiint=\u222D
+iinfin=\u29DC
+iiota=\u2129
+ijlig=\u0133
+imacr=\u012B
+image=\u2111
+imagline=\u2110
+imagpart=\u2111
+imath=\u0131
+imof=\u22B7
+imped=\u01B5
+in=\u2208
+incare=\u2105
+infin=\u221E
+infintie=\u29DD
+inodot=\u0131
+int=\u222B
+intcal=\u22BA
+integers=\u2124
+intercal=\u22BA
+intlarhk=\u2A17
+intprod=\u2A3C
+iocy=\u0451
+iogon=\u012F
+iopf=\u1D55A
+iota=\u03B9
+iprod=\u2A3C
+iquest=\u00BF
+iscr=\u1D4BE
+isin=\u2208
+isinE=\u22F9
+isindot=\u22F5
+isins=\u22F4
+isinsv=\u22F3
+isinv=\u2208
+it=\u2062
+itilde=\u0129
+iukcy=\u0456
+iuml=\u00EF
+jcirc=\u0135
+jcy=\u0439
+jfr=\u1D527
+jmath=\u0237
+jopf=\u1D55B
+jscr=\u1D4BF
+jsercy=\u0458
+jukcy=\u0454
+kappa=\u03BA
+kappav=\u03F0
+kcedil=\u0137
+kcy=\u043A
+kfr=\u1D528
+kgreen=\u0138
+khcy=\u0445
+kjcy=\u045C
+kopf=\u1D55C
+kscr=\u1D4C0
+lAarr=\u21DA
+lArr=\u21D0
+lAtail=\u291B
+lBarr=\u290E
+lE=\u2266
+lEg=\u2A8B
+lHar=\u2962
+lacute=\u013A
+laemptyv=\u29B4
+lagran=\u2112
+lambda=\u03BB
+lang=\u27E8
+langd=\u2991
+langle=\u27E8
+lap=\u2A85
+laquo=\u00AB
+larr=\u2190
+larrb=\u21E4
+larrbfs=\u291F
+larrfs=\u291D
+larrhk=\u21A9
+larrlp=\u21AB
+larrpl=\u2939
+larrsim=\u2973
+larrtl=\u21A2
+lat=\u2AAB
+latail=\u2919
+late=\u2AAD
+lbarr=\u290C
+lbbrk=\u2772
+lbrace=\u007B
+lbrack=\u005B
+lbrke=\u298B
+lbrksld=\u298F
+lbrkslu=\u298D
+lcaron=\u013E
+lcedil=\u013C
+lceil=\u2308
+lcub=\u007B
+lcy=\u043B
+ldca=\u2936
+ldquo=\u201C
+ldquor=\u201E
+ldrdhar=\u2967
+ldrushar=\u294B
+ldsh=\u21B2
+le=\u2264
+leftarrow=\u2190
+leftarrowtail=\u21A2
+leftharpoondown=\u21BD
+leftharpoonup=\u21BC
+leftleftarrows=\u21C7
+leftrightarrow=\u2194
+leftrightarrows=\u21C6
+leftrightharpoons=\u21CB
+leftrightsquigarrow=\u21AD
+leftthreetimes=\u22CB
+leg=\u22DA
+leq=\u2264
+leqq=\u2266
+leqslant=\u2A7D
+les=\u2A7D
+lescc=\u2AA8
+lesdot=\u2A7F
+lesdoto=\u2A81
+lesdotor=\u2A83
+lesges=\u2A93
+lessapprox=\u2A85
+lessdot=\u22D6
+lesseqgtr=\u22DA
+lesseqqgtr=\u2A8B
+lessgtr=\u2276
+lesssim=\u2272
+lfisht=\u297C
+lfloor=\u230A
+lfr=\u1D529
+lg=\u2276
+lgE=\u2A91
+lhard=\u21BD
+lharu=\u21BC
+lharul=\u296A
+lhblk=\u2584
+ljcy=\u0459
+ll=\u226A
+llarr=\u21C7
+llcorner=\u231E
+llhard=\u296B
+lltri=\u25FA
+lmidot=\u0140
+lmoust=\u23B0
+lmoustache=\u23B0
+lnE=\u2268
+lnap=\u2A89
+lnapprox=\u2A89
+lne=\u2A87
+lneq=\u2A87
+lneqq=\u2268
+lnsim=\u22E6
+loang=\u27EC
+loarr=\u21FD
+lobrk=\u27E6
+longleftarrow=\u27F5
+longleftrightarrow=\u27F7
+longmapsto=\u27FC
+longrightarrow=\u27F6
+looparrowleft=\u21AB
+looparrowright=\u21AC
+lopar=\u2985
+lopf=\u1D55D
+loplus=\u2A2D
+lotimes=\u2A34
+lowast=\u2217
+lowbar=\u005F
+loz=\u25CA
+lozenge=\u25CA
+lozf=\u29EB
+lpar=\u0028
+lparlt=\u2993
+lrarr=\u21C6
+lrcorner=\u231F
+lrhar=\u21CB
+lrhard=\u296D
+lrm=\u200E
+lrtri=\u22BF
+lsaquo=\u2039
+lscr=\u1D4C1
+lsh=\u21B0
+lsim=\u2272
+lsime=\u2A8D
+lsimg=\u2A8F
+lsqb=\u005B
+lsquo=\u2018
+lsquor=\u201A
+lstrok=\u0142
+lt=\u003C
+ltcc=\u2AA6
+ltcir=\u2A79
+ltdot=\u22D6
+lthree=\u22CB
+ltimes=\u22C9
+ltlarr=\u2976
+ltquest=\u2A7B
+ltrPar=\u2996
+ltri=\u25C3
+ltrie=\u22B4
+ltrif=\u25C2
+lurdshar=\u294A
+luruhar=\u2966
+mDDot=\u223A
+macr=\u00AF
+male=\u2642
+malt=\u2720
+maltese=\u2720
+map=\u21A6
+mapsto=\u21A6
+mapstodown=\u21A7
+mapstoleft=\u21A4
+mapstoup=\u21A5
+marker=\u25AE
+mcomma=\u2A29
+mcy=\u043C
+mdash=\u2014
+measuredangle=\u2221
+mfr=\u1D52A
+mho=\u2127
+micro=\u00B5
+mid=\u2223
+midast=\u002A
+midcir=\u2AF0
+middot=\u00B7
+minus=\u2212
+minusb=\u229F
+minusd=\u2238
+minusdu=\u2A2A
+mlcp=\u2ADB
+mldr=\u2026
+mnplus=\u2213
+models=\u22A7
+mopf=\u1D55E
+mp=\u2213
+mscr=\u1D4C2
+mstpos=\u223E
+mu=\u03BC
+multimap=\u22B8
+mumap=\u22B8
+nLeftarrow=\u21CD
+nLeftrightarrow=\u21CE
+nRightarrow=\u21CF
+nVDash=\u22AF
+nVdash=\u22AE
+nabla=\u2207
+nacute=\u0144
+nap=\u2249
+napos=\u0149
+napprox=\u2249
+natur=\u266E
+natural=\u266E
+naturals=\u2115
+nbsp=\u00A0
+ncap=\u2A43
+ncaron=\u0148
+ncedil=\u0146
+ncong=\u2247
+ncup=\u2A42
+ncy=\u043D
+ndash=\u2013
+ne=\u2260
+neArr=\u21D7
+nearhk=\u2924
+nearr=\u2197
+nearrow=\u2197
+nequiv=\u2262
+nesear=\u2928
+nexist=\u2204
+nexists=\u2204
+nfr=\u1D52B
+nge=\u2271
+ngeq=\u2271
+ngsim=\u2275
+ngt=\u226F
+ngtr=\u226F
+nhArr=\u21CE
+nharr=\u21AE
+nhpar=\u2AF2
+ni=\u220B
+nis=\u22FC
+nisd=\u22FA
+niv=\u220B
+njcy=\u045A
+nlArr=\u21CD
+nlarr=\u219A
+nldr=\u2025
+nle=\u2270
+nleftarrow=\u219A
+nleftrightarrow=\u21AE
+nleq=\u2270
+nless=\u226E
+nlsim=\u2274
+nlt=\u226E
+nltri=\u22EA
+nltrie=\u22EC
+nmid=\u2224
+nopf=\u1D55F
+not=\u00AC
+notin=\u2209
+notinva=\u2209
+notinvb=\u22F7
+notinvc=\u22F6
+notni=\u220C
+notniva=\u220C
+notnivb=\u22FE
+notnivc=\u22FD
+npar=\u2226
+nparallel=\u2226
+npolint=\u2A14
+npr=\u2280
+nprcue=\u22E0
+nprec=\u2280
+nrArr=\u21CF
+nrarr=\u219B
+nrightarrow=\u219B
+nrtri=\u22EB
+nrtrie=\u22ED
+nsc=\u2281
+nsccue=\u22E1
+nscr=\u1D4C3
+nshortmid=\u2224
+nshortparallel=\u2226
+nsim=\u2241
+nsime=\u2244
+nsimeq=\u2244
+nsmid=\u2224
+nspar=\u2226
+nsqsube=\u22E2
+nsqsupe=\u22E3
+nsub=\u2284
+nsube=\u2288
+nsubseteq=\u2288
+nsucc=\u2281
+nsup=\u2285
+nsupe=\u2289
+nsupseteq=\u2289
+ntgl=\u2279
+ntilde=\u00F1
+ntlg=\u2278
+ntriangleleft=\u22EA
+ntrianglelefteq=\u22EC
+ntriangleright=\u22EB
+ntrianglerighteq=\u22ED
+nu=\u03BD
+num=\u0023
+numero=\u2116
+numsp=\u2007
+nvDash=\u22AD
+nvHarr=\u2904
+nvdash=\u22AC
+nvinfin=\u29DE
+nvlArr=\u2902
+nvrArr=\u2903
+nwArr=\u21D6
+nwarhk=\u2923
+nwarr=\u2196
+nwarrow=\u2196
+nwnear=\u2927
+oS=\u24C8
+oacute=\u00F3
+oast=\u229B
+ocir=\u229A
+ocirc=\u00F4
+ocy=\u043E
+odash=\u229D
+odblac=\u0151
+odiv=\u2A38
+odot=\u2299
+odsold=\u29BC
+oelig=\u0153
+ofcir=\u29BF
+ofr=\u1D52C
+ogon=\u02DB
+ograve=\u00F2
+ogt=\u29C1
+ohbar=\u29B5
+ohm=\u03A9
+oint=\u222E
+olarr=\u21BA
+olcir=\u29BE
+olcross=\u29BB
+oline=\u203E
+olt=\u29C0
+omacr=\u014D
+omega=\u03C9