Commit 5e2c1f02 authored by Jean-Benoist Leger's avatar Jean-Benoist Leger

Initial commit

parents
# Copyright (c) 2016, Jean-Benoist Leger <jb@leger.tf>
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
from .conv import converter
# Copyright (c) 2016, Jean-Benoist Leger <jb@leger.tf>
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
from . import data
from .transliteration import transliterator,transliterate
import regex
from . import latexfuntypes
from . import parser
class LatexSyntaxError(SyntaxError):
pass
class converter:
def __init__(self):
# transliteration
self.__cmds = {
r'\bb': transliterator(data.bb),
r'\bf': transliterator(data.bf),
r'\cal': transliterator(data.cal),
r'\frak': transliterator(data.frak),
r'\it': transliterator(data.it),
r'\mono': transliterator(data.mono),
}
# symbols
def makefun(symb):
return lambda x: symb
for cmd in data.symbols:
self.__cmds[cmd] = latexfuntypes.latexfun(
makefun(data.symbols[cmd]),
0)
# combinings
def makefun(comb):
return lambda x: self.__latexfun_comb(comb,x)
for cmd in data.combinings:
self.__cmds[cmd] = latexfuntypes.latexfun(
makefun(data.combinings[cmd]),
1)
# others
self.__cmds[r'\frac'] = latexfuntypes.latexfun(self.__latexfun_frac,2)
# config section
self.allow_zw = True
self.allow_combinings = True
def convert(self, expr):
parsed = parser.parse(expr)
outvec = []
idx = 0
while(idx < len(parsed)):
element = parsed[idx]
if element[0] == 'oper':
outvec.append(('oper',element[1]))
idx+=1
continue
if element[0] == 'char':
outvec.append(('char',element[1]))
idx+=1
continue
if element[0] == 'cmd':
try:
pycmd = self.__cmds[element[1]]
except KeyError:
outvec.append(('char',element[1]))
idx+=1
continue
if len(parsed) <= idx+pycmd.nargs:
raise LatexSyntaxError
args = [
self.convert(parsed[idx+k+1][1])
for k in range(pycmd.nargs)
]
outvec.append(('char',pycmd.fun(args)))
idx+=1+pycmd.nargs
continue
if element[0] == 'subexpr':
outvec.append(('char',self.convert(element[1])))
idx+=1
continue
raise Exception
#subandsuperscript
for idx in range(len(outvec)):
if outvec[idx][0] == 'oper':
if len(outvec) <= idx+1:
raise LatexSyntaxError
if outvec[idx+1][0] == 'oper':
raise LatexSyntaxError
for idx in range(len(outvec)):
if outvec[idx][0] == 'oper' and outvec[idx][1] =='^':
if idx+2 < len(outvec):
if outvec[idx+2][0] == 'oper' and outvec[idx+2][1]=='_':
# we invert ^ and _
(
outvec[idx],
outvec[idx+1],
outvec[idx+2],
outvec[idx+3],
) = (
outvec[idx+2],
outvec[idx+3],
outvec[idx],
outvec[idx+1],
)
# sub
newoutvec = []
idx = 0
while idx<len(outvec):
if idx+1<len(outvec):
if outvec[idx+1][0] == 'oper' and outvec[idx+1][1] == '_':
newoutvec.append(
(
'char',
self.__indexed(
outvec[idx][1],
outvec[idx+2][1]
),
)
)
idx+=3
continue
newoutvec.append(outvec[idx])
idx+=1
outvec = newoutvec
# super
newoutvec = []
idx = 0
while idx<len(outvec):
if idx+1<len(outvec):
if outvec[idx+1][0] == 'oper' and outvec[idx+1][1] == '^':
newoutvec.append(
(
'char',
self.__exponent(
outvec[idx][1],
outvec[idx+2][1]
),
)
)
idx+=3
continue
newoutvec.append(outvec[idx])
idx+=1
outvec = newoutvec
return ''.join([x[1] for x in outvec])
def __indexed(self,a,b):
f_sub = transliterate(data.subscript)
bsub,ok = f_sub(b)
if ok:
return a+bsub
if self.__is_complex_expr(a):
a = '('+a+')'
return a+'['+b+']'
def __exponent(self,a,b):
f_sup = transliterate(data.superscript)
bsup,ok = f_sup(b)
if ok:
return a+bsup
if self.__is_complex_expr(a):
a = '('+a+')'
if self.__is_complex_expr(b):
b = '('+b+')'
return a+'^'+b
def __is_complex_expr(self, expr):
return (len(expr)>1)
def __latexfun_comb(self, comb, inputs):
expr = inputs[0]
if(len(expr)==1):
if self.allow_combinings:
return expr + comb[0]
return comb[1] + '(' + expr + ')'
def __latexfun_frac(self,inputs):
a = inputs[0]
b = inputs[1]
try:
ret = data.known_fracts[(a,b)]
return ret
except KeyError:
pass
if self.allow_zw:
f_sub = transliterate(data.subscript)
f_sup = transliterate(data.superscript)
a_sup,ok_sup = f_sup(a)
b_sub,ok_sub = f_sub(b)
if ok_sup and ok_sub:
return a_sup+'⁄'+b_sub
if self.__is_complex_expr(a):
a = '('+a+')'
if self.__is_complex_expr(b):
b = '('+b+')'
return a+'/'+b
This diff is collapsed.
# Copyright (c) 2016, Jean-Benoist Leger <jb@leger.tf>
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
class latexfun:
def __init__(self, fun, nargs):
self.fun = fun
self.nargs = nargs
# Copyright (c) 2016, Jean-Benoist Leger <jb@leger.tf>
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
import regex
def parse_one_element(s):
R = r'((?>\\(?:[^A-Za-z]|[A-Za-z]+))|(?>[^\{\}\\])|\{(?1)*\})'
r = regex.match(R,s)
s = s[r.span()[1]:]
c = r.captures()[0]
if c[0] == '\\':
return ( ('cmd', c), s)
if c[0] == '{':
return ( ('subexpr', c[1:-1]), s)
if c in ('_','^'):
return ( ('oper', c), s)
return ( ('char', c), s)
def parse(s):
l = []
while len(s)>0:
m,s = parse_one_element(s)
if not (m[1] == ' '):
l.append(m)
return l
# Copyright (c) 2016, Jean-Benoist Leger <jb@leger.tf>
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
from . import latexfuntypes
def transliterate(alphabet):
alphabet_keys = alphabet.keys()
def fun(flat_input):
flat_output = ''
success = True
for c in flat_input:
if c in alphabet_keys:
flat_output += alphabet[c]
else:
flat_output += c
success = False
return (flat_output, success)
return fun
def transliterator(alphabet):
return latexfuntypes.latexfun(lambda x: transliterate(alphabet)(x[0])[0],1)
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment