Как проверить, является ли строка допустимым правилом LaTex?

Как проверить, является ли строка допустимым правилом LaTex?

Я использую библиотеку MathQuill дляввод формулыи пытаюсь ограничить количество операций. Есть ли способ, которым я могуразличать строку и правило LaTex?

Например:

def check('\sum') => True  #LaTex rule
def check('\myCustomVar') => False  #NOT a LaTex rule

Любая помощь будет оценена по достоинству!

решение1

По крайней мере, в Linux (насчет Windows не знаю) есть скрипт latexdefМартина Шаррера, который ищет определения LaTeX из командной строки:

latexdef section 

напечатает

\section
\long macro:->\@startsection {section}{1}{\z@ }{-3.5ex \@plus -1ex \@minus -.2ex}{2.3ex \@plus .2ex}{\normalfont \Large \bfseries }

тогда как

latexdef sausage 

напечатает

\sausage
undefined

Мы можем вызвать его latexdefиз Python следующим образом:

import subprocess, re

def latexdef(command_list, *args):
    '''
    call latexdef on a list of commands to be looked up
    *args can be used to pass options to latexdef
    '''
    p = subprocess.Popen(['latexdef'] + list(args) + command_list, \
                        stdout=subprocess.PIPE, \
                        stderr=subprocess.STDOUT)
    return p.communicate()[0].strip()

def are_commands(command_list, *args):
    '''
    look up multiple commands and return results in a dict
    '''
    result = latexdef(command_list, *args)
    frags = [ f.splitlines() for f in re.split(r'\n{2,}', result, re.MULTILINE) ]
    return { command[1:] : defn != 'undefined' for command, defn in frags }

def is_command(command, *args):
    '''
    look up a single command
    '''
    return are_commands([command],*args).values()[0]

if __name__ == '__main__':
    commands = "chapter section sausage".split()

    for command in commands:
        print command, is_command(command)

    print "\nwith book class loaded"

    for command in commands:
        print command, is_command(command, '-c', 'book')

    print "\nall at once, with class book"
    print are_commands(commands, '-c', 'book')

Это печатает

chapter False
section True
sausage False

with book class loaded
chapter True
section True
sausage False

all at once, with class book
{'sausage:': False, 'section:': True, 'chapter:': True}

Каждый отдельный вызов latexdefдовольно медленный, но время можно сэкономить, выполнив поиск нескольких команд за один вызов. Это цель are_commands, которая возвращает результат поиска для каждой команды в словаре.

Также обратите внимание, что latexdefэто скрипт Perl, поэтому в зависимости от того, насколько это для вас важно, может иметь смысл перевести все это на Python, таким образом убрав посредника. Но это довольно длинный скрипт, а Perl немного утомляет глаза...

решение2

Это не настоящий ответ, а скорее более длинный комментарий. Данный ответ Майкла Палмера работает в большинстве случаев, если эти макросы определены основными пакетами/классами.

Однако: Есть некоторые случаи, которые вы, возможно, захотите рассмотреть. Правило LaTeX, как вы его сформулируете, вероятно, означает последовательность команд. Типичная последовательность команд LaTeX (в следующих примерах я буду называть ее «cmd») может быть получена как следующая ABNF:

cmd = "\" 1*ALPHA

Но этого недостаточно. Вы должны отметить, что есть внутренние макросы, которые вы можете захотеть включить/исключить отдельно. Это означало бы, что вам придется проверить что-то вроде

cmd = "\" 1*(ALPHA | "@")

для внутренних макросов. Если такая последовательность команд действительна в точке ее использования, она зависит от контекста. Хотя это правило будет проверять действительность самой команды, в основном она должна использоваться в \makeatletter ... \makeatotherсреде, чтобы быть действительной (если ваша проверка должна включать контекст).

И то, что ваша проверка должна включать контекст, можно просто показать командой, например, \fracwhich является "допустимым правилом LaTeX" только при использовании в математическом режиме. Или что-то вроде \meterwhich допустимо только в siunitxкомандах .

Другой случай — expl3. Команды l3 также допустимы в LaTeX, если они заключены в \ExplSyntaxOnи \ExplSyntaxOff. Они будут построены примерно так:

cmd = "\" 1*(ALPHA | "_") ":" 0*ALPHA

что на самом деле не совсем так, поскольку символы после двоеточия ограничены, но этого должно быть достаточно.

А если вы захотите проверить действительность пользовательских макросов, ситуация станет еще хуже, \csname ...\endcsnameпоскольку здесь у пользователя гораздо больше возможностей.

Обновлять:Самая интересная часть в конце концов будет также проверять, является ли вызов допустимым. Это будет означать, что вам придется проверить также сигнатуру функции, а затем вызов команды. Это будет означать, что он \fracбудет допустимым, только если он вызывается из математического режима и имеет два обязательных аргумента. Например, $\frac{1}{2}$. Это тот момент, когда вы, вероятно, захотите скомпилировать образец документа, потому что настоящий парсер здесь будет очень сложным.

У всех этих методов есть одно предостережение: вы получите не только последовательности команд LaTeX, но и TeX. Если вы специально пытаетесь получить LaTeX, но хотите исключить TeX, у вас возникнут проблемы.

Обновление 2:Поскольку вас интересовала реализация для теста: Вот несколько регулярных выражений, которые вы можете использовать для сопоставления. Только при полном совпадении у вас будет действительная последовательность перед вами. Для контекстно-зависимой части вы можете захотеть работать с предпросмотрами и ретроспективными просмотрами.

  • стандартный LaTeX:\\[A-Za-z]*
  • внутренний LaTeX:\\[A-Za-z@]*
  • синтаксис expl:\\[A-za-z@_]*:[DNncVvoOxfTFpw]*
  • \csnameкоманды: что-то вроде\\.*$

Связанный контент