From: <md...@us...> - 2007-07-16 15:08:16
|
Revision: 3540 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=3540&view=rev Author: mdboom Date: 2007-07-16 08:08:12 -0700 (Mon, 16 Jul 2007) Log Message: ----------- Got nested sub/superscripts working. Improved formatting of grammar to be more readable to newbies (like me). Modified Paths: -------------- branches/mathtext_mgd/lib/matplotlib/mathtext.py Modified: branches/mathtext_mgd/lib/matplotlib/mathtext.py =================================================================== --- branches/mathtext_mgd/lib/matplotlib/mathtext.py 2007-07-16 14:06:59 UTC (rev 3539) +++ branches/mathtext_mgd/lib/matplotlib/mathtext.py 2007-07-16 15:08:12 UTC (rev 3540) @@ -119,7 +119,6 @@ KNOWN ISSUES: - - nested subscripts, eg, x_i_j not working; but you can do x_{i_j} - nesting fonts changes in sub/superscript groups not parsing - I would also like to add a few more layout commands, like \frac. @@ -136,7 +135,7 @@ from matplotlib.pyparsing import Literal, Word, OneOrMore, ZeroOrMore, \ Combine, Group, Optional, Forward, NotAny, alphas, nums, alphanums, \ StringStart, StringEnd, ParseException, FollowedBy, Regex, \ - operatorPrecedence, opAssoc, ParseResults + operatorPrecedence, opAssoc, ParseResults, Or from matplotlib.afm import AFM from matplotlib.cbook import enumerate, iterable, Bunch @@ -1014,6 +1013,7 @@ self.dpi = dpi for loc, element in self.neighbors.items(): if loc in ('subscript', 'superscript'): + print type(element), element element.set_size_info(0.7*self.fontsize, dpi) else: element.set_size_info(self.fontsize, dpi) @@ -1257,8 +1257,10 @@ def clear(self): self.symbols = [] + self.subscript_stack = [] def expression(self, s, loc, toks): + print "expression", toks self.expr = ExpressionElement(toks) return [self.expr] @@ -1279,7 +1281,7 @@ assert(len(toks)==1) s = toks[0] - #~ print 'sym', toks[0] + print 'sym', toks[0] if charOverChars.has_key(s): under, over, pad = charOverChars[s] font, tok, scale = under @@ -1360,172 +1362,209 @@ grp.set_font(name[1:]) # suppress the slash return [grp] - def subscript(self, s, loc, toks): + _subsuperscript_names = { + 'normal': ['subscript', 'superscript'], + 'overUnder': ['below', 'above'] + } + + _subsuperscript_indices = { + '_': (0, 1), + '^': (1, 0) + } + + def subsuperscript(self, s, loc, toks): assert(len(toks)==1) - #print 'subsup', toks - if len(toks[0])==2: - under, next = toks[0] - prev = SpaceElement(0) - else: - prev, under, next = toks[0] + print 'subscript', toks - if self.is_overunder(prev): - prev.neighbors['below'] = next - else: - prev.neighbors['subscript'] = next + if len(toks[0])==3: + prev, op, next = toks[0] + index, other_index = self._subsuperscript_indices[op] + if self.is_overunder(prev): + names = self._subsuperscript_names['overUnder'] + else: + names = self._subsuperscript_names['normal'] + + prev.neighbors[names[index]] = next - return loc, [prev] + for compound in self._subsuperscript_names.values(): + if compound[other_index] in next.neighbors: + prev.neighbors[names[other_index]] = next.neighbors[compound[other_index]] + del next.neighbors[compound[other_index]] + return [prev] + return toks[0].asList() def is_overunder(self, prev): return isinstance(prev, SymbolElement) and overunder.has_key(prev.sym) - def superscript(self, s, loc, toks): - assert(len(toks)==1) - #print 'subsup', toks - if len(toks[0])==2: - under, next = toks[0] - prev = SpaceElement(0,0.6) - else: - prev, under, next = toks[0] - if self.is_overunder(prev): - prev.neighbors['above'] = next - else: - prev.neighbors['superscript'] = next - - return [prev] - - def subsuperscript(self, s, loc, toks): - assert(len(toks)==1) - #print 'subsup', toks - prev, undersym, down, oversym, up = toks[0] - - if self.is_overunder(prev): - prev.neighbors['below'] = down - prev.neighbors['above'] = up - else: - prev.neighbors['subscript'] = down - prev.neighbors['superscript'] = up - - return [prev] - - - handler = Handler() -lbrace = Literal('{').suppress() -rbrace = Literal('}').suppress() -lbrack = Literal('[') -rbrack = Literal(']') -lparen = Literal('(') -rparen = Literal(')') -grouping = lbrack | rbrack | lparen | rparen +# All forward declarations are here +font = Forward().setParseAction(handler.font).setName("font") +subsuper = Forward().setParseAction(handler.subsuperscript).setName("subsuper") +placeable = Forward().setName("placeable") -bslash = Literal('\\') +lbrace = Literal('{').suppress() +rbrace = Literal('}').suppress() +lbrack = Literal('[') +rbrack = Literal(']') +lparen = Literal('(') +rparen = Literal(')') +grouping =(lbrack + | rbrack + | lparen + | rparen) -langle = Literal('<') -rangle = Literal('>') -equals = Literal('=') -relation = langle | rangle | equals +subscript = Literal('_') +superscript = Literal('^') -colon = Literal(':') -comma = Literal(',') -period = Literal('.') -semicolon = Literal(';') -exclamation = Literal('!') +bslash = Literal('\\') -punctuation = colon | comma | period | semicolon +langle = Literal('<') +rangle = Literal('>') +equals = Literal('=') +relation =(langle + | rangle + | equals) -at = Literal('@') -percent = Literal('%') -ampersand = Literal('&') -misc = exclamation | at | percent | ampersand +colon = Literal(':') +comma = Literal(',') +period = Literal('.') +semicolon = Literal(';') +exclamation = Literal('!') +punctuation =(colon + | comma + | period + | semicolon) -over = Literal('over') -under = Literal('under') -#~ composite = over | under -overUnder = over | under +at = Literal('@') +percent = Literal('%') +ampersand = Literal('&') +misc =(exclamation + | at + | percent + | ampersand) -accent = Literal('hat') | Literal('check') | Literal('dot') | \ - Literal('breve') | Literal('acute') | Literal('ddot') | \ - Literal('grave') | Literal('tilde') | Literal('bar') | \ - Literal('vec') | Literal('"') | Literal("`") | Literal("'") |\ - Literal('~') | Literal('.') | Literal('^') +over = Literal('over') +under = Literal('under') +overUnder =(over + | under) +accent =(Literal('hat') | Literal('check') | Literal('dot') | + Literal('breve') | Literal('acute') | Literal('ddot') | + Literal('grave') | Literal('tilde') | Literal('bar') | + Literal('vec') | Literal('"') | Literal("`") | Literal("'") | + Literal('~') | Literal('.') | Literal('^')) +number = Combine(Word(nums) + Optional(Literal('.')) + Optional( Word(nums) )) +plus = Literal('+') +minus = Literal('-') +times = Literal('*') +div = Literal('/') +binop =(plus + | minus + | times + | div) -number = Combine(Word(nums) + Optional(Literal('.')) + Optional( Word(nums) )) +roman = Literal('rm') +cal = Literal('cal') +italics = Literal('it') +typewriter = Literal('tt') +fontname =(roman + | cal + | italics + | typewriter) -plus = Literal('+') -minus = Literal('-') -times = Literal('*') -div = Literal('/') -binop = plus | minus | times | div +texsym = Combine(bslash + Word(alphanums) + NotAny("{")) +char = Word(alphanums + ' ', exact=1).leaveWhitespace() -roman = Literal('rm') -cal = Literal('cal') -italics = Literal('it') -typewriter = Literal('tt') -fontname = roman | cal | italics | typewriter +space =(FollowedBy(bslash) + + (Literal(r'\ ') + | Literal(r'\/') + | Group(Literal(r'\hspace{') + number + Literal('}')) + ) + ).setParseAction(handler.space).setName('space') -texsym = Combine(bslash + Word(alphanums) + NotAny("{")) +symbol = Regex("(" + ")|(".join( + [ + r"\\[a-zA-Z0-9]+(?!{)", + r"[a-zA-Z0-9 ]", + r"[+\-*/]", + r"[<>=]", + r"[:,.;!]", + r"[!@%&]", + r"[[\]()]", + ]) + + ")" + ).setParseAction(handler.symbol).leaveWhitespace() -char = Word(alphanums + ' ', exact=1).leaveWhitespace() +_symbol =(texsym + | char + | binop + | relation + | punctuation + | misc + | grouping + ).setParseAction(handler.symbol).leaveWhitespace() -space = FollowedBy(bslash) + (Literal(r'\ ') | Literal(r'\/') | Group(Literal(r'\hspace{') + number + Literal('}'))).setParseAction(handler.space).setName('space') +accent = Group( + Combine(bslash + accent) + + Optional(lbrace) + + symbol + + Optional(rbrace) + ).setParseAction(handler.accent).setName("accent") -symbol = Regex("("+")|(".join( - [ - r"\\[a-zA-Z0-9]+(?!{)", - r"[a-zA-Z0-9 ]", - r"[+\-*/]", - r"[<>=]", - r"[:,.;!]", - r"[!@%&]", - r"[[\]()]", - ])+")" - ).setParseAction(handler.symbol).leaveWhitespace() +group = Group( + lbrace + + OneOrMore( + space + ^ font + ^ subsuper + ^ placeable + ) + + rbrace + ).setParseAction(handler.group).setName("group") -#~ symbol = (texsym ^ char ^ binop ^ relation ^ punctuation ^ misc ^ grouping ).setParseAction(handler.symbol).leaveWhitespace() -_symbol = (texsym | char | binop | relation | punctuation | misc | grouping ).setParseAction(handler.symbol).leaveWhitespace() +composite = Group( + Combine( + bslash + + overUnder + ) + + group + + group + ).setParseAction(handler.composite).setName("composite") -subscript = Forward().setParseAction(handler.subscript).setName("subscript") -superscript = Forward().setParseAction(handler.superscript).setName("superscript") -subsuperscript = Forward().setParseAction(handler.subsuperscript).setName("subsuperscript") +font << Group( + Combine( + bslash + + fontname) + + group) -font = Forward().setParseAction(handler.font).setName("font") +placeable <<(accent + ^ symbol + ^ group + ^ composite + ) +subsuper << Group( + placeable + + ZeroOrMore( + ( subscript + | superscript + ) + + subsuper + ) + ) -accent = Group( Combine(bslash + accent) + Optional(lbrace) + symbol + Optional(rbrace)).setParseAction(handler.accent).setName("accent") -group = Group( lbrace + OneOrMore(symbol^subscript^superscript^subsuperscript^space^font^accent) + rbrace).setParseAction(handler.group).setName("group") -#~ group = Group( lbrace + OneOrMore(subsuperscript | subscript | superscript | symbol | space ) + rbrace).setParseAction(handler.group).setName("group") +expression = OneOrMore( + space + ^ font + ^ subsuper + ^ placeable + ).setParseAction(handler.expression).setName("expression") -#composite = Group( Combine(bslash + composite) + lbrace + symbol + rbrace + lbrace + symbol + rbrace).setParseAction(handler.composite).setName("composite") -#~ composite = Group( Combine(bslash + composite) + group + group).setParseAction(handler.composite).setName("composite") -composite = Group( Combine(bslash + overUnder) + group + group).setParseAction(handler.composite).setName("composite") - - - - - - -symgroup = font | group | symbol - -subscript << Group( Optional(symgroup) + Literal('_') + symgroup ) -superscript << Group( Optional(symgroup) + Literal('^') + symgroup ) -subsuperscript << Group( symgroup + Literal('_') + symgroup + Literal('^') + symgroup ) - -font << Group( Combine(bslash + fontname) + group) - - - -expression = OneOrMore( - space ^ font ^ accent ^ symbol ^ subscript ^ superscript ^ subsuperscript ^ group ^ composite ).setParseAction(handler.expression).setName("expression") -#~ expression = OneOrMore( - #~ group | composite | space | font | subsuperscript | subscript | superscript | symbol ).setParseAction(handler.expression).setName("expression") - #### @@ -1577,7 +1616,9 @@ expression.parseString( s ) handler.expr.set_size_info(fontsize, dpi) - + print handler.expr + print handler.symbols + # set the origin once to allow w, h compution handler.expr.set_origin(0, 0) xmin = min([e.xmin() for e in handler.symbols]) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |