Во-первых, большое примечание. : Я не программист на Python. Я просто знаю достаточно, прочитав документацию Pygments и просматривая источники доступных лексеров Pygments на Github, чтобы знать, как написать лексер Pygments.
Я работал над подсветкой синтаксиса сборки Jazz / SASM Saturn в Pygments. Когда я впервые начал это начинание, я думал, что задача будет чрезвычайно простой, но вскоре я столкнулся с проблемами, связанными с особенностями обработки Pygments новой строки и пробелов, в деталях которых я не разбираюсь и дергаю себя за волосы. безуспешно пытаюсь заставить лексер работать, поэтому мой пост здесь.
Синтаксис Jazz/SASM имеет некоторые требования, чувствительные к пробелам, в частности, метка должна начинаться в первом столбце или два — я не знаю, является ли это частью проблемы.
Первая проблема заключается в том, что когда метка начинается во втором столбце и ей предшествует пустая строка (т. просто '\n' ) метка помечается как ошибка лексики или вся строка помечается как ошибка лексики, если комментарий следует за меткой в той же строке. РЕДАКТИРОВАТЬ Кажется, что что-то (т. е. любой допустимый ассемблерный код Jazz/SASM, комментарии и т. д.) должно предшествовать пустой строке, чтобы воспроизвести эту проблему.
ВВОД:
Код: Выделить всё
* Replace this with any valid Jazz / SASM comments or code
=lbl1 * This is a comment
[img]https://i.sstatic.net /530twm0H.png[/img]
Вторая проблема довольно странная, и я понятия не имею, что ее вызывает: если комментарий на всю строку (который должен начинаться со звездочки в первом столбце) предшествует пустая строка, то если в тексте есть инструкция, которая, как можно подумать, будет закомментирована, вместо этого генерируется лексическая ошибка для указанного текста инструкции. EDIT Кажется, я не могу точно воспроизвести эту проблему (возможно, что-то не так с лексическим кортежем для класса инструкций, который я использовал, или инструкция была неправильно сформирована?), но я заметил, что то, что должно быть комментарием, обрабатывается как инструкция. Кроме того, как и в случае с первой проблемой, перед пустой строкой должно быть что-то, чтобы возникла проблема.
ВВОД:
Код: Выделить всё
* Replace this with any valid Jazz / SASM comments or code
* B=0 S
[img]https://i.sstatic.net /26XdiFyM.png[/img]
Для решения третьей проблемы необходимо дальнейшее объяснение синтаксиса Jazz/SASM: за всеми условными инструкциями должна следовать метка GOYES или просто RTNYES. на следующей строке. Первая проблема, с которой я здесь сталкиваюсь, заключается в том, что если условная инструкция имеет конечные пробелы, которые должны обрабатываться кодом обработки комментариев, тогда Pygments помечает указанные пробелы как ошибку лексирования.< /p>
ВВОД:
Код: Выделить всё
* Replace this with any valid Jazz / SASM comments or code
?A=B W
GOYES lbl1
[img]https://i.sstatic.net /TO9hz5Jj.png[/img]
Кроме того, условные инструкции, по-видимому, невосприимчивы к чему-либо, вызывающему ошибки лексики, связанные с первой проблемой, т.е. если условной инструкции предшествует метка в той же строке, независимо от того, начинается ли она в первом или втором столбце, и ей предшествует пустая строка, то Pygments, похоже, обрабатывает всю строку без лексических ошибок.
ВВОД:
Код: Выделить всё
* Replace this with any valid Jazz / SASM comments or code
?A=B W
GOYES lbl1
[img]https://i.sstatic.net /UmDpS8QE.png[/img]
Наконец, обязательная метка GOYES или RTNYES на следующей строке после условия всегда помечается как лексическая. ошибка Pygments.
ВВОД:
Код: Выделить всё
* Replace this with any valid Jazz / SASM comments or code
?D=C W
GOYES lbl1
?B=A P
RTNYES
[img]https://i.sstatic.net /jtrcnP8F.png[/img]
Я знаю, что все вышеперечисленное может не иметь особого смысла, поскольку оно отделено от исходного кода, поэтому, WLOG, я включил Код лексера Pygments, который просто обрабатывает два класса инструкций: пробелы, метки и комментарии. Классы инструкций: установка регистра в ноль и условные инструкции, выполняющие сравнение двух регистров на равенство.
( Обратите внимание, что следующий фрагмент исходного кода был обновлен, поэтому проблемы, описанные выше, за исключением проблем, связанных с условными инструкциями, были устранены)
Код: Выделить всё
from pygments.lexer import RegexLexer, bygroups
from pygments.token import *
import logging
class SasmJazzLexer(RegexLexer):
name = 'SASM'
aliases = ['SASM', 'Sasm', 'sasm', 'JAZZ', 'Jazz', 'jazz']
filenames = ['*.A', '*.a']
# Register fields
fields = r'(P|WP|XS|X|S|M|B|A|W)'
# Regex for label or symbol
symbol = r'((?:[:=][(=:#0-9][^,\s)]{,11})|(?:[:=]?[^(=:#0-9*,\s)\n][^,\s]{,11}))'
tokens = {
'root': [
# Whitespace
(r'^\s+$', Whitespace),
# Single line comment starting with '*' in column one
(r'^\*.*$', Comment.Single),
# Whitespace or instructions
(r'^( {2,})|(\t)\s*', Whitespace, 'possible_instructions'),
# Label starting on column one or two and followed by a comment
(r'(^ ?)' + symbol + r'(\s+)(\*.*$)', bygroups(Whitespace, Name.Label, Whitespace, Comment.Single)),
# Label starting in column one or two and followed by whitespace or instructions
(r'(^ ?)' + symbol + r'(\s+)', bygroups(Whitespace, Name.Label, Whitespace), 'possible_instructions'),
],
'possible_instructions': [
# Just whitespace or empty line -- emit token and bail
(r'\s+$', Whitespace, '#pop'),
#
# Register tests
#
(r'(\?)([A-C])(=)([A-C])(\s+)' + fields, bygroups(Punctuation, Name.Builtin, Operator, Name.Builtin, Whitespace, Name.Builtin), ('possible_comment_cond', 'conditionals')),
(r'(\?)([CD])(=)([CD])(\s+)' + fields, bygroups(Punctuation, Name.Builtin, Operator, Name.Builtin, Whitespace, Name.Builtin), ('possible_comment_cond', 'conditionals')),
(r'(\?)(([A-D])(=)(\3))(\s+)' + fields, bygroups(Punctuation, Error, Name.Builtin, Operator, Name.Builtin, Whitespace, Name.Builtin), ('possible_comment_cond', 'conditionals')),
#
# Arithmetic instructions
#
# r=0 fs
# possibly followed by a comment
(r'([A-D])(=)(0)(\s+)' + fields, bygroups(Name.Builtin, Operator, Name.Builtin, Whitespace, Name.Builtin), 'possible_comment'),
],
'possible_comment': [
#
# Comment processing code
#
# Just whitespace or empty line -- emit token and bail
(r'\s*$', Whitespace, '#pop:2'),
# Trailing comment
(r'\s+\S.*$', Comment.Single, '#pop:2')
],
'possible_comment_cond': [
#
# Comment processing code for conditionals
#
# Just whitespace or empty line -- emit token and bail
(r'\s*$', Whitespace, '#pop'),
# Trailing comment
(r'\s+\S.*$', Comment.Single, '#pop')
],
'conditionals': [
#
# GOYES and RTNYES processing code
#
(r'(^ {2,}\s*)(GOYES)(\s+)' + symbol, bygroups(Whitespace, Keyword, Whitespace, Name.Label), 'possible_comment'),
(r'(^ {2,}\s*)(RTNYES)', bygroups(Whitespace, Keyword), 'possible_comment'),
]
}
Для условные инструкции, в стек помещаются два состояния:
Код: Выделить всё
('possible_comment_cond', 'conditionals')
Обратите внимание, что я создал полный HTML-документ для проверки моего лексера, используя
Код: Выделить всё
python3 -m pygments -f html -O full -o test.html -x -l pygments_sasm_lexer_5.py:SasmJazzLexer test.txt
Кроме того, я прошу прощения за уродливые скриншоты отображаемого выходного HTML-кода, но я не могу вставить все пять выходных HTML-кодов, не превысив ограничение на число символов Stackoverflow. >
Ну, я заменил переменную 'symbol' регулярным выражением, которое должно решить хотя бы некоторые из вышеперечисленных проблем, особенно проблема с однострочным комментарием (звездочка в первом столбце), который иногда интерпретируется как инструкция, но я не увидел никаких изменений в выводе.
Код: Выделить всё
symbol = r'((?:[:=][(=:#0-9][^, )]{,11})|(?:[:=]?[^(=:#0-9*, ][^, )]{,11}))'
Насколько я вижу, предоставленное мной регулярное выражение работает так, как я объяснил выше.
Кроме того, в обработке пробелов была небольшая ошибка: указанный пробел передавался в группах захвата регулярных выражений в обратный вызов «bygroups» — теперь он обрабатывается отдельно и получает тип токена «Пробелы». однако не производит никаких изменений в выводе.
Я не понимаю, что вызывает лексические ошибки, перечисленные в этом вопросе.
Я зарегистрировал/установил свой собственный лексер с Pygments на общесистемном уровне и запустил на нем отладчик лексера с тестовым вводом, и он выглядит, как проблема вызвана переводами строк.
В частности, я думаю, что нашел проблему или, по крайней мере, часть проблемы: регулярные выражения в моем коде неправильно обрабатывают символы новой строки. , точнее, вообще ими не занимаюсь - совсем вылетело из головы - упс.
Когда у меня будет время, если я смогу решить проблемы вызвано этим, тогда я отвечу на свой вопрос.
Ну, я ошибочно подумал, судя по выводам отладчика lexer, что часть проблемы заключалась в вызвано пустыми строками, состоящими только из новой строки, но, похоже, Pygments по умолчанию просто поглощает пустые строки.
Проблемы, которые я представил здесь, за исключением проблем с условными инструкциями, появляются Это было вызвано отсутствием кортежа, который обрабатывает строки, состоящие полностью из пробелов, а также глупой ошибкой в регулярном выражении символа. Что касается регулярного выражения, я случайно дополнил класс символов в квадратных скобках, который включал пробел, хотя мне действительно нужен был класс экранированных символов '\s' вместо пробела.
Правильное регулярное выражение следует:< /p>
Код: Выделить всё
r'((?:[:=][(=:#0-9][^,\s)]{,11})|(?:[:=]?[^(=:#0-9*,\s)\n][^,\s]{,11}))'
Что касается проблем с условными инструкциями, я думал, что добавление '\s*' в начальную часть регулярного выражения с пробелами может решить проблему, но, к сожалению, "метка GOYES" или "RTNYES" по-прежнему помечено как лексическая ошибка (а также любые комментарии в той же строке и после тестовой инструкции). Почему, понятия не имею.
Подробнее здесь: https://stackoverflow.com/questions/785 ... ing-errors