Грамматика у него простая как три копейки: программа состоит из слов, которые следуют друг за другом.
Про любой язык можно сказать, что программа на нём состоит из лексем (слов) следующих друг за другом. ;)
Например есть слова которые начинают какую-либо конструкцию и сответствующие им завершающие слова, типа : NAME ... ;, CODE name ... ENDCODE и управляющие конструкции, разве они в совокупности не образуют синтаксические конструкции?
В добавок и лексическое строение в виде слов, разделяемых пробелами, нарушается уже стандартными словами для строковых литералов, комментариев и т.п. слов, захватывающих произвольную часть исходника, что уж говорить о пользовательских словах.
Конечно можно, почему нет? Судя по всему вы спорите о том, чего не знаете.
Как я уже сказал, в форте есть полный контроль над разбором текста прямо во время этого самого разбора, это слова:
SOURCE — адрес и длина текущей интерпретируемой строки;
>IN — переменная (доступна и для чтения и для изменения) хранящая смещение первого непросмотренного символа от начала строки;
REFILL — прочитать следующую строку из входного источника.
Мне кажется уже этого достаточно для того, чтобы придумать синтаксис какой только в голову взбредёт.
В добавок есть слова для парсинга: WORD PARSE
для создания словарей: WORDLIST VOCABULARY
для поиска слов: FIND SEARCH-WORDLIST
для управления контекстом поиска: GET-ORDER SET-ORDER ALSO ONLY PREVIOUS
В форте семантика влияет на синтаксис. Форт не регулярный язык, его нельзя разобрать конечным автоматом.
Пример попроще:
( это комментарий, транслятор его игнорирует, а вернее это делает слово "(" )
: ( ; \ переопределение слова "("
( такого синтаксиса для комментария у нас больше нет, никто ничего не пропустил, и интерпретатор попытается выполнить эти слова, и произойдёт ошибка)
Вы сможете описать это хоть какой-нибудь грамматикой?
У форта неограниченная грамматика: все части форт-системы (даже такие как интерпретатор и компилятор) являются самыми обычнымм определениями на равне с другими форт-словами и могут быть изменены, переопределены и вызваны в любой момент, также исходный текст программы и состояние интерпретатора доступны прямо во время исполнения для чтения и изменения. Возможно придумать любой синтаксис на какой только хватит фантазии программиста и памяти системы.
Например здесь синтаксис зависит от введёного символа:
: PARSE&TYPE ( c "ccc<char>" -- c-addr u )
." PARSED: " PARSE TYPE CR ;
: AAA ." AAA CALLED" CR ;
: BBB ." BBB CALLED" CR ;
\ ограничитель - символ '1'
.( TEST 1:) CR
CHAR 1 PARSE&TYPE AAA 1 BBB 2 CR
\ ограничитель заранее не известен
.( TEST 2:) CR
KEY PARSE&TYPE AAA 1 BBB 2 CR
.( TEST 3:) CR
KEY PARSE&TYPE AAA 1 BBB 2 CR
BYE
Да, оксюморон получается. Но, наверное, к форту вполне это определение подходит, сам форт язык универсальный, но программирование на нём обычно сводится к определению новых слов и конструкций, специфичных для решения конкретной задачи.
Подсчет токенов работает неправильно даже в вашем языке. Например здесь:
tokenCount[str_String]:=Length[tokens[str]];
ваш «токенизатор» насчитал 6 токенов. Это не токенизатор, он работает только как счетчик идентификаторов в Mathematica, и к другим языкам не применим.
P.S. Еще как оказалось во многих решениях на APL и J представлен не только код, а копия команд из REPL'а и их результат. Так, например, транспонирование матрицы на J плюс вывод созданной матрицы размером 5 строк, плюс результат транспонирования размером 4 строки, превращается в 11 строк, при том что реального кода здесь 2 строки.
Callback (англ. call — вызов, англ. back — обратный) или фу́нкция обра́тного вы́зова в программировании — передача исполняемого кода в качестве одного из параметров другого кода.
Что мы делаем? Передаем исполняемый код (эту лямбду) в качестве параметра в другой код (в reduceRight). Подходит под определение выше?
Насчет токенов. Вы считаете неправильно и нечестно, многие языки имеют совершенно разное лексическое строение. Например:
вы не учли знак подчеркивания в именах
вы не учли строки
многие си-подобные языки позволяют использовать знак доллара в идентификаторах
в перле у идентификаторов используются префиксы из спецсимволов, в старых бейсиках — суффиксы
в типичной программе на APL, J или K буквы встречаются не часто :)
кстати, сколько токенов ваш парсер насчитает в brainfuck'е?
в форте и ему подобных в словах используются любые печатаемые непробельные символы, и это только в простом случае, т.к. в форте программа может сама парсить свой текст в общем случае чтобы разбить его на токены его понадобиться выполнить
наконец на Rosetta Code часто можно встретить хорошо комментированный код, это немного портит и правильность подсчета строк и симолов
Этот «кусок кода» — содержимое функции передаваемой в reduceRight. Функция, передаваемая в другую функцию для последующего вызова называется callback, если вы не в курсе.
И да, я также считаю, что код трудночитаемый, но совсем не из-за r[0][0], а из-за вложенного тренарника и использования && для ветвления; вложенные условия человеку всегда тяжело анализировать, особенно если записать их в одно выражение. В добавок первое условие r.length (или, если более явно r.length != 0) выполняется только в первый раз, и можно было передать этот элемент вторым аргументом в reduceRight, а из массива его исключить. Когда читаешь код, обычно пытаешься мысленно его выполнить, а лишние условия только сбивают с толку.
Кстати, существуют языки программирования изначально ориентированные на обработку массивов, например APL или J. Они еще и очень лаконичные, большинство ваших примеров можно записать в одну-две коротенькие строчки.
От ассемблера зависит. Как директива препроцессора наверное почти везде есть. На многих их можно реализовать на макросах. В форт-ассемблерах почти всегда есть высокоуровневые конструкции из форта.
Естественный как раз hsl, ведь при смешивании синего с желтым как раз получается зелёный.
Непорядок!
Про любой язык можно сказать, что программа на нём состоит из лексем (слов) следующих друг за другом. ;)
Например есть слова которые начинают какую-либо конструкцию и сответствующие им завершающие слова, типа
: NAME ... ;
,CODE name ... ENDCODE
и управляющие конструкции, разве они в совокупности не образуют синтаксические конструкции?В добавок и лексическое строение в виде слов, разделяемых пробелами, нарушается уже стандартными словами для строковых литералов, комментариев и т.п. слов, захватывающих произвольную часть исходника, что уж говорить о пользовательских словах.
Как я уже сказал, в форте есть полный контроль над разбором текста прямо во время этого самого разбора, это слова:
Мне кажется уже этого достаточно для того, чтобы придумать синтаксис какой только в голову взбредёт.
В добавок есть слова для парсинга: WORD PARSE
для создания словарей: WORDLIST VOCABULARY
для поиска слов: FIND SEARCH-WORDLIST
для управления контекстом поиска: GET-ORDER SET-ORDER ALSO ONLY PREVIOUS
Пример попроще:
Вы сможете описать это хоть какой-нибудь грамматикой?
Try it online!
Форт также может быть сам себе препроцессором и так иногда делают, но часто проще сразу скомпилировать нужный код чем заниматься подстановкой текста.
ЧИТАТЬ ДАЛЕЕ >>>
Что же тепепь делать? Как быть?
Подсчет токенов работает неправильно даже в вашем языке. Например здесь:
ваш «токенизатор» насчитал 6 токенов. Это не токенизатор, он работает только как счетчик идентификаторов в Mathematica, и к другим языкам не применим.
P.S. Еще как оказалось во многих решениях на APL и J представлен не только код, а копия команд из REPL'а и их результат. Так, например, транспонирование матрицы на J плюс вывод созданной матрицы размером 5 строк, плюс результат транспонирования размером 4 строки, превращается в 11 строк, при том что реального кода здесь 2 строки.
Даже педивики говорит:
Что мы делаем? Передаем исполняемый код (эту лямбду) в качестве параметра в другой код (в reduceRight). Подходит под определение выше?
Но получилось красиво.
Этот «кусок кода» — содержимое функции передаваемой в reduceRight. Функция, передаваемая в другую функцию для последующего вызова называется callback, если вы не в курсе.
И да, я также считаю, что код трудночитаемый, но совсем не из-за
r[0][0]
, а из-за вложенного тренарника и использования&&
для ветвления; вложенные условия человеку всегда тяжело анализировать, особенно если записать их в одно выражение. В добавок первое условиеr.length
(или, если более явноr.length != 0
) выполняется только в первый раз, и можно было передать этот элемент вторым аргументом вreduceRight
, а из массива его исключить. Когда читаешь код, обычно пытаешься мысленно его выполнить, а лишние условия только сбивают с толку.Если интересно вот есть простой туториал по J.
Или вы предлагаете ввести константу FIRST_ARRAY_ELEMENT?