Автор |
Сообщение |
|
|
Заголовок сообщения: |
Re: Трансляторы Си в Форт |
 |
|
А дальше еще смешнее.  Зашил интерпретатор в Форт-процессор в ПЛИС, частоту поставил 1.5MHz, тест с ферзями выполняется за 2:16. Если сравнивать с соседями по турнирной таблице отсюда https://www.hpmuseum.org/cgi-bin/articles.cgi?read=700 (рассматривал только те, которые на бейсике и для которых в этом же документе указана частота процессора) Код: 2:45 SHARP PC-1248 @ 1.024MHz 2:29 TEXAS INSTRUMENTS CC-40 TMS70C20 @ 2.5MHz 2:18 TEXAS INSTRUMENTS TI-74 BASICALC TMS70C46 @ 2MHz 2:00 ЭЛЕКТРОНИКА МК-85 (Fast Mode x5.3) КА1013ВМ1 @ 0.36x5.3=1.9MHz , то мой подопечный смотрится вполне достойно Код: 2:16 f44 @ 1.5MHz При этом сам бейсик скомпилирован самодельным транслятором Си, качество кода на выходе которого оставляет желать лучшего. Но главное, что текст программы в моем случае пока хранится в неизменном текстовом виде, в то время как в ретро-бейсиках для экономии места и увеличения скорости традиционно выполняется "предварительная компиляция": команды языка кодируются одним байтом, числа и адреса прыжков переводятся в двоичный вид и т.д. Т.е. сейчас каждый раз для интерпретируемого слова выполняется сравнение строк (вместо многократно более быстрого сравнения чисел), при каждом прыжке заново производится поиск метки (снова сравнение строк!) в тексте программы (вместо того, чтобы один раз при запуске вычислить адрес перехода и дальше прыгать по этому адресу), а числа каждый раз набиваются поразрядно домножением текущего значения на 10 и добавлением очередного разряда (вместо того, чтобы однократно перегнать число из текстового представления в двоичное). И боюсь даже представить, как сильно вырастет скорость, если переписать интерпретатор BASIC на Форте/ассемблере и/или реализовать предварительную компиляцию.  ссылка на изображение ссылка на изображение
А дальше еще смешнее. :) Зашил интерпретатор в Форт-процессор в ПЛИС, частоту поставил 1.5MHz, тест с ферзями выполняется за 2:16. Если сравнивать с соседями по турнирной таблице отсюда [url]https://www.hpmuseum.org/cgi-bin/articles.cgi?read=700[/url] (рассматривал только те, которые на бейсике и для которых в этом же документе указана частота процессора)[code]2:45 SHARP PC-1248 @ 1.024MHz 2:29 TEXAS INSTRUMENTS CC-40 TMS70C20 @ 2.5MHz 2:18 TEXAS INSTRUMENTS TI-74 BASICALC TMS70C46 @ 2MHz 2:00 ЭЛЕКТРОНИКА МК-85 (Fast Mode x5.3) КА1013ВМ1 @ 0.36x5.3=1.9MHz[/code], то мой подопечный смотрится вполне достойно[code]2:16 f44 @ 1.5MHz[/code]При этом сам бейсик скомпилирован самодельным транслятором Си, качество кода на выходе которого оставляет желать лучшего. Но главное, что текст программы в моем случае пока хранится в неизменном текстовом виде, в то время как в ретро-бейсиках для экономии места и увеличения скорости традиционно выполняется "предварительная компиляция": команды языка кодируются одним байтом, числа и адреса прыжков переводятся в двоичный вид и т.д. Т.е. сейчас каждый раз для интерпретируемого слова выполняется сравнение строк (вместо многократно более быстрого сравнения чисел), при каждом прыжке заново производится поиск метки (снова сравнение строк!) в тексте программы (вместо того, чтобы один раз при запуске вычислить адрес перехода и дальше прыгать по этому адресу), а числа каждый раз набиваются поразрядно домножением текущего значения на 10 и добавлением очередного разряда (вместо того, чтобы однократно перегнать число из текстового представления в двоичное). И боюсь даже представить, как сильно вырастет скорость, если переписать интерпретатор BASIC на Форте/ассемблере и/или реализовать предварительную компиляцию. :)
[img]http://totalvacuum.ru/UB/nq0.jpg[/img] [url=http://totalvacuum.ru/UB/nq0.jpg]ссылка на изображение[/url] [img]http://totalvacuum.ru/UB/nq1.jpg[/img] [url=http://totalvacuum.ru/UB/nq1.jpg]ссылка на изображение[/url]
|
|
|
 |
Добавлено: Вт июн 03, 2025 12:29 |
|
|
 |
|
|
Заголовок сообщения: |
Re: Трансляторы Си в Форт |
 |
|
 Немного подлечил транслятор basic-в-esoteric forth. http://totalvacuum.ru/UB/ubasic.zipРаньше в нем были ровно те же ограничения, что и в целевой платформе (ef \ esoteric forth \): не умел компилировать 2/3/...-разрядные числа и переменные с именами c/b/h/s/x/o/g, т.к. эти имена были задействованы в библиотеке ввода-вывода. Теперь понимает и длинные числа и переменные a-z. А еще двухсимвольные операторы сравнения <= <> >= добавились в дополнение к односимвольным < = >. И операторы poke/push/pop, а также функция peek. Компилируется теперь под win, а не под dos. Но транслятор до сих пор так и весит в районе 100 строк, а в скомпилированном виде - 3 с хвостиком Kb. Оно выглядит смешно и даже "игрушечно", но легко транслирует простые тесты или, например, калькуляторный тест с ферзями отсюда: https://www.hpmuseum.org/cgi-bin/articles.cgi?read=700 А вообще тут главное идея: трансляция с языка высокого уровня в форт-подобное представление - это просто. 
:) Немного подлечил транслятор basic-в-esoteric forth. [url]http://totalvacuum.ru/UB/ubasic.zip[/url] Раньше в нем были ровно те же ограничения, что и в целевой платформе (ef \ esoteric forth \): не умел компилировать 2/3/...-разрядные числа и переменные с именами c/b/h/s/x/o/g, т.к. эти имена были задействованы в библиотеке ввода-вывода. Теперь понимает и длинные числа и переменные a-z. А еще двухсимвольные операторы сравнения <= <> >= добавились в дополнение к односимвольным < = >. И операторы poke/push/pop, а также функция peek. Компилируется теперь под win, а не под dos. Но транслятор до сих пор так и весит в районе 100 строк, а в скомпилированном виде - 3 с хвостиком Kb. Оно выглядит смешно и даже "игрушечно", но легко транслирует простые тесты или, например, калькуляторный тест с ферзями отсюда: [url]https://www.hpmuseum.org/cgi-bin/articles.cgi?read=700[/url] А вообще тут главное идея: трансляция с языка высокого уровня в форт-подобное представление - это просто. :)
|
|
|
 |
Добавлено: Пн июн 02, 2025 16:43 |
|
|
 |
|
|
Заголовок сообщения: |
Re: Трансляторы Си в Форт |
 |
|
Victor__v писал(а): Лесолёд Достаточно спорное утверждение
[quote="Victor__v"]Лесолёд[/quote]Достаточно спорное утверждение
|
|
|
 |
Добавлено: Чт май 29, 2025 21:13 |
|
|
 |
|
|
Заголовок сообщения: |
Re: Трансляторы Си в Форт |
 |
|
Total Vacuum писал(а): Запускаю программу Код: print "bezzlobie?" Но выводит мистическое Код: hryukostyag! К чему бы это? Лесолёд
[quote="Total Vacuum"]Запускаю программу[code]print "bezzlobie?"[/code]Но выводит мистическое[code]hryukostyag![/code]К чему бы это?[/quote] Лесолёд
|
|
|
 |
Добавлено: Чт май 29, 2025 11:28 |
|
|
 |
|
|
Заголовок сообщения: |
Re: Трансляторы Си в Форт |
 |
|
Запускаю программу Код: print "bezzlobie?" Но выводит мистическое Код: hryukostyag! К чему бы это?
Запускаю программу[code]print "bezzlobie?"[/code]Но выводит мистическое[code]hryukostyag![/code]К чему бы это?
|
|
|
 |
Добавлено: Чт май 29, 2025 11:25 |
|
|
 |
|
|
Заголовок сообщения: |
Re: Трансляторы Си в Форт |
 |
|
Victor__v писал(а): [*] CLEAR – очистка кэша [*] LIST – создание списка [*] RUN – запуск сторонней программы из оболочки форта[/list] Наверное, это задумывалось как одна сверхмощная суперкоманда "начать с чистого листа", но Гоголь-переводчик сплоховал и выдал "clear list run" 
[quote="Victor__v"][*] CLEAR – очистка кэша [*] LIST – создание списка [*] RUN – запуск сторонней программы из оболочки форта[/list][/quote] Наверное, это задумывалось как одна сверхмощная суперкоманда "начать с чистого листа", но Гоголь-переводчик сплоховал и выдал "clear list run" :)
|
|
|
 |
Добавлено: Чт май 29, 2025 00:51 |
|
|
 |
|
|
Заголовок сообщения: |
Re: Трансляторы Си в Форт |
 |
|
Вот этот вот бейсик у меня накидан на скорую руку в нескольких вариантах: - компилятор, транслирует в uf \ micro forth \ или ef \ esoteric forth \ - интерпретатор, исполняет код из файла через командную строку; - интерпретатор, запускается в интерактивном режиме и ожидает ввода текста программы с клавиатуры И только в последнем варианте нужны clear/list/run, более того, сюда же следует добавить exit. Но вообще в каждом варианте примерно 100 строк и 3-5Kb в скомпилированном виде. При этом легко расширяется. Допустим, добавляем peek/poke, после чего спокойно запускаем калькуляторный тест с ферзями отсюда: https://www.hpmuseum.org/cgi-bin/articles.cgi?read=700Типа такого: Код: 1 let x = 0 let s = 0 2 let r = 8 3 let a = 3000 4 if x = r goto 18 5 let x = x + 1 6 poke ( a + x ) r 7 let s = s + 1 8 let y = x 9 let y = y - 1 10 if y = 0 goto 4 11 let t = peek ( a + x ) - peek ( a + y ) 12 if t = 0 goto 14 13 if t < 0 let t = - t if x - y <> t goto 9 14 poke ( a + x ) ( peek ( a + x ) - 1 ) 15 if peek ( a + x ) <> 0 goto 7 16 let x = x - 1 17 if x <> 0 goto 14 18 print s А если еще добавить push/pop для передачи в функции/из функций параметров/результатов, то такой бейсик превращается в виртуальный процессор с регистрами a-z, командами перехода (goto), в т.ч. и по условию (if), подпрограммами (gosub/return), командами для доступа к памяти и периферии (peek/poke) и небольшим количеством арифметики  Получится вполне достаточная для написания любых программ "система команд"
Вот этот вот бейсик у меня накидан на скорую руку в нескольких вариантах: - компилятор, транслирует в uf \ micro forth \ или ef \ esoteric forth \ - интерпретатор, исполняет код из файла через командную строку; - интерпретатор, запускается в интерактивном режиме и ожидает ввода текста программы с клавиатуры И только в последнем варианте нужны clear/list/run, более того, сюда же следует добавить exit. Но вообще в каждом варианте примерно 100 строк и 3-5Kb в скомпилированном виде. При этом легко расширяется. Допустим, добавляем peek/poke, после чего спокойно запускаем калькуляторный тест с ферзями отсюда: [url]https://www.hpmuseum.org/cgi-bin/articles.cgi?read=700[/url] Типа такого: [code] 1 let x = 0 let s = 0 2 let r = 8 3 let a = 3000 4 if x = r goto 18 5 let x = x + 1 6 poke ( a + x ) r 7 let s = s + 1 8 let y = x 9 let y = y - 1 10 if y = 0 goto 4 11 let t = peek ( a + x ) - peek ( a + y ) 12 if t = 0 goto 14 13 if t < 0 let t = - t if x - y <> t goto 9 14 poke ( a + x ) ( peek ( a + x ) - 1 ) 15 if peek ( a + x ) <> 0 goto 7 16 let x = x - 1 17 if x <> 0 goto 14 18 print s[/code]
А если еще добавить push/pop для передачи в функции/из функций параметров/результатов, то такой бейсик превращается в виртуальный процессор с регистрами a-z, командами перехода (goto), в т.ч. и по условию (if), подпрограммами (gosub/return), командами для доступа к памяти и периферии (peek/poke) и небольшим количеством арифметики :) Получится вполне достаточная для написания любых программ "система команд"
|
|
|
 |
Добавлено: Чт май 29, 2025 00:38 |
|
|
 |
|
|
Заголовок сообщения: |
Re: Трансляторы Си в Форт |
 |
|
Цитата: А вообще странно, что они сделали CLEAR/LIST/RUN частью спецификации. Идём в ногу со временем [сарказм] Я бы дал этим словам такой функционал - CLEAR – очистка кэша
- LIST – создание списка
- RUN – запуск сторонней программы из оболочки форта
[quote]А вообще странно, что они сделали CLEAR/LIST/RUN частью спецификации.[/quote] Идём в ногу со временем [сарказм]
Я бы дал этим словам такой функционал [list] [*] CLEAR – очистка кэша [*] LIST – создание списка [*] RUN – запуск сторонней программы из оболочки форта[/list]
|
|
|
 |
Добавлено: Ср май 07, 2025 17:27 |
|
|
 |
|
|
Заголовок сообщения: |
Re: Трансляторы Си в Форт |
 |
|
Total Vacuum писал(а): Вот есть такое: https://en.wikipedia.org/wiki/Tiny_BASICГрамматика в части операторов там совсем простая: Код: statement ::= PRINT expr-list IF expression relop expression THEN statement GOTO expression INPUT var-list LET var = expression GOSUB expression RETURN CLEAR LIST RUN END А вообще странно, что они сделали CLEAR/LIST/RUN частью спецификации. Скорее уж это команды редактора или даже операционной системы, но никак не самого языка. Где-то они могут быть полезны (например, при построчном вводе программы через терминал), а где-то полноценный встроенный редактор и запуск по F9, либо внешний редактор и интерпретация или компиляция файлов через командную строку, и вот здесь-то эти команды точно не нужны. Впрочем, спецификация Tiny BASIC уходит корнями в покрытую мхом почтенную древность, так что простительно.  В этом даже какой-то шарм безвозвратно ушедшей в прошлое 8-битной эпохи. Ну а в текущих реалиях надо отделять мух от котлет: редактор (если он вообще нужен) будет отдельно, а интерпретатор (BASIC, Forth, любой другой или все сразу) - отдельно.
[quote="Total Vacuum"]Вот есть такое: [url]https://en.wikipedia.org/wiki/Tiny_BASIC[/url] Грамматика в части операторов там совсем простая:[code] statement ::= PRINT expr-list IF expression relop expression THEN statement GOTO expression INPUT var-list LET var = expression GOSUB expression RETURN CLEAR LIST RUN END[/code][/quote] А вообще странно, что они сделали CLEAR/LIST/RUN частью спецификации. Скорее уж это команды редактора или даже операционной системы, но никак не самого языка. Где-то они могут быть полезны (например, при построчном вводе программы через терминал), а где-то полноценный встроенный редактор и запуск по F9, либо внешний редактор и интерпретация или компиляция файлов через командную строку, и вот здесь-то эти команды точно не нужны. Впрочем, спецификация Tiny BASIC уходит корнями в покрытую мхом почтенную древность, так что простительно. :) В этом даже какой-то шарм безвозвратно ушедшей в прошлое 8-битной эпохи. Ну а в текущих реалиях надо отделять мух от котлет: редактор (если он вообще нужен) будет отдельно, а интерпретатор (BASIC, Forth, любой другой или все сразу) - отдельно.
|
|
|
 |
Добавлено: Ср май 07, 2025 12:01 |
|
|
 |
|
|
Заголовок сообщения: |
Re: Трансляторы Си в Форт |
 |
|
Собственно, лежит тут: http://totalvacuum/UB/ubasic.zipСам ubasic.c компилировал при помощи TCC, но должно любым сишным компилироваться. В скомпилированном виде весит 3K. В папке TEST пара тестов, перекомпилируются при помощи соответствующих *.bat по схеме basic => ef => asm => com, хотя можно и под win сделать, если транслятор ef \ esoteric forth \ подменить. Натравил на него свой сишный транслятор, там меньше 2K исполняемый файл получается, правда это 16-битный com-файл. Для форт-процессора будет и того меньше, раза в 2, наверное. Интерпретатор в 100 строк, скорее всего, не уложится, он будет сложнее компилятора, но точно не в разы. Да, кстати, для добавления poke/peek (а это ведь по сути фортовские !/@) достаточно в stmt() перед label дописать строки Код: if (t("poke")) {expr(); expr(); op(ASSIGN);} else if (t("peek")) {var(); expr(); op(LOAD); op(ASSIGN);} else А, например, для push/pop: Код: if (t("push")) {expr();} else if (t("pop")) {var(); op("!");} else Хотя peek можно оформить в виде функции, чтобы была возможность использования в выражениях. В этом случае нужно добавить в prim() строку Код: else if (t("peek")) {unary(); op(LOAD);} Забавно будет, если по итогу интерпретатор BASIC на борту Форт-процессора в ПЛИС окажется шустрее спектрумовского 
Собственно, лежит тут: [url]http://totalvacuum/UB/ubasic.zip[/url] Сам ubasic.c компилировал при помощи TCC, но должно любым сишным компилироваться. В скомпилированном виде весит 3K. В папке TEST пара тестов, перекомпилируются при помощи соответствующих *.bat по схеме basic => ef => asm => com, хотя можно и под win сделать, если транслятор ef \ esoteric forth \ подменить. Натравил на него свой сишный транслятор, там меньше 2K исполняемый файл получается, правда это 16-битный com-файл. Для форт-процессора будет и того меньше, раза в 2, наверное.
Интерпретатор в 100 строк, скорее всего, не уложится, он будет сложнее компилятора, но точно не в разы.
Да, кстати, для добавления poke/peek (а это ведь по сути фортовские !/@) достаточно в stmt() перед label дописать строки[code] if (t("poke")) {expr(); expr(); op(ASSIGN);} else if (t("peek")) {var(); expr(); op(LOAD); op(ASSIGN);} else[/code] А, например, для push/pop:[code] if (t("push")) {expr();} else if (t("pop")) {var(); op("!");} else[/code] Хотя peek можно оформить в виде функции, чтобы была возможность использования в выражениях. В этом случае нужно добавить в prim() строку[code] else if (t("peek")) {unary(); op(LOAD);}[/code]
Забавно будет, если по итогу интерпретатор BASIC на борту Форт-процессора в ПЛИС окажется шустрее спектрумовского :D
|
|
|
 |
Добавлено: Вт май 06, 2025 01:33 |
|
|
 |
|
|
Заголовок сообщения: |
Re: Трансляторы Си в Форт |
 |
|
Hishnik писал(а): Из добавляемого очень уж просятся именованные подпрограммы.  И да, есть возможность использования именованных подпрограмм. Например: Код: let r = 1 let n = 8 gosub fact print r end
fact let r = r * n let n = n - 1 if n > 1 gosub fact return А всё потому, что поленился сделать обработку ошибок. В результате всё непонятное автоматически считается меткой. Лень - двигатель прогресса, однако.  Кроме того, строки не обязаны начинаться с метки, в строке допускается размещать несколько операторов и меток. И наоборот: допускается размещать опкод и операнды на разных строках. Т.е. в каком-то смысле полная свобода в оформлении кода.
[quote="Hishnik"]Из добавляемого очень уж просятся именованные подпрограммы.[/quote] :) И да, есть возможность использования именованных подпрограмм. Например:[code]let r = 1 let n = 8 gosub fact print r end
fact let r = r * n let n = n - 1 if n > 1 gosub fact return[/code]А всё потому, что поленился сделать обработку ошибок. В результате всё непонятное автоматически считается меткой. Лень - двигатель прогресса, однако. :) Кроме того, строки не обязаны начинаться с метки, в строке допускается размещать несколько операторов и меток. И наоборот: допускается размещать опкод и операнды на разных строках. Т.е. в каком-то смысле полная свобода в оформлении кода.
|
|
|
 |
Добавлено: Пн май 05, 2025 23:26 |
|
|
 |
|
|
Заголовок сообщения: |
Re: Трансляторы Си в Форт |
 |
|
Платформо-зависимые вещи убраны в отдельный файл в шапке: Код: #include "x86.h"
#include <stdlib.h> #include <stdio.h> #include <string.h> Транслируется в uf \ micro forth \ и ef \ esoteric forth \  При желании можно и напрямую в асм перегонять, достаточно лишь заменить соответствующие дефайны в подключаемом файле. Например, Код: #define ADD "+" заменить на что-то вроде Код: #define ADD "pop ax\npop bx\nadd ax,bx\npush ax\n" и т.д. В сумме 2 файла занимают ровно 100 строк  В версии под ef \ esoteric forth \ нельзя использовать двух- и более- значные числа, а также переменные c/b/h/s/x/o/g (они задействованы в stdio), ну а в остальном отличий нет. Примеры выложу чуть позже здесь: [url]totalvacuum.ru/UB/ubasic.zip[/url]
Платформо-зависимые вещи убраны в отдельный файл в шапке:[code] #include "x86.h"
#include <stdlib.h> #include <stdio.h> #include <string.h>[/code]Транслируется в uf \ micro forth \ и ef \ esoteric forth \ :) При желании можно и напрямую в асм перегонять, достаточно лишь заменить соответствующие дефайны в подключаемом файле. Например,[code]#define ADD "+"[/code]заменить на что-то вроде[code]#define ADD "pop ax\npop bx\nadd ax,bx\npush ax\n"[/code]и т.д. В сумме 2 файла занимают ровно 100 строк :)
В версии под ef \ esoteric forth \ нельзя использовать двух- и более- значные числа, а также переменные c/b/h/s/x/o/g (они задействованы в stdio), ну а в остальном отличий нет. Примеры выложу чуть позже здесь: [url]totalvacuum.ru/UB/ubasic.zip[/url]
|
|
|
 |
Добавлено: Пн май 05, 2025 23:13 |
|
|
 |
|
|
Заголовок сообщения: |
Re: Трансляторы Си в Форт |
 |
|
Ну и операторы: Код: /* stmt */
void print () { token(); hold(); if (s[0]=='"') {expr(); op(PUTS);} else {expr(); op(PUTH);} }
int stmt () { if (n("")) return 0; if (t("print")) {print();} else if (t("if")) {cmp(); op(IF); stmt(); op(ENDIF);} else if (t("goto")) {token(); printf(JMP,s);} else /* if (t("input")) {var(); op(INPUT);} else */ if (t("let")) {var(); token(); expr(); op(ASSIGN);} else if (t("gosub")) {token(); printf(CALL,s);} else if (t("return")) {op(RET);} else /* if (t("clear")||t("list")||t("run")) {} else */ if (t("end")) {op(EXIT);} else {printf(LABEL,s); stmt();} return 1; }
void main () {op(TARGET); while (stmt());} clear/list/run в режиме "компиляции" не нужны, поэтому убрал. input тоже убрал, т.к. в ПЛИС реализация будет другая, а проверять пока можно и без него.
Ну и операторы:[code]/* stmt */
void print () { token(); hold(); if (s[0]=='"') {expr(); op(PUTS);} else {expr(); op(PUTH);} }
int stmt () { if (n("")) return 0; if (t("print")) {print();} else if (t("if")) {cmp(); op(IF); stmt(); op(ENDIF);} else if (t("goto")) {token(); printf(JMP,s);} else /* if (t("input")) {var(); op(INPUT);} else */ if (t("let")) {var(); token(); expr(); op(ASSIGN);} else if (t("gosub")) {token(); printf(CALL,s);} else if (t("return")) {op(RET);} else /* if (t("clear")||t("list")||t("run")) {} else */ if (t("end")) {op(EXIT);} else {printf(LABEL,s); stmt();} return 1; }
void main () {op(TARGET); while (stmt());}[/code]clear/list/run в режиме "компиляции" не нужны, поэтому убрал. input тоже убрал, т.к. в ПЛИС реализация будет другая, а проверять пока можно и без него.
|
|
|
 |
Добавлено: Пн май 05, 2025 22:58 |
|
|
 |
|
|
Заголовок сообщения: |
Re: Трансляторы Си в Форт |
 |
|
Разбор выражений: Код: /* expr */
void op (char *s) {printf(CMD,s);}
void expr ();
void prim () { if (t("(")) {expr(); token();} else {op(s); if ((s[0]>='a')&&(s[0]<='z')) op(LOAD);} }
void unary () {if (n("-")) {unary(); op(NEGATE);} else prim();}
void mul () { unary(); while (n("*")||t("/")) if (t("*")) {unary(); op(MUL);} else {unary(); op(DIV);} hold(); }
void expr () { mul(); while (n("+")||t("-")) if (t("+")) {mul(); op(ADD);} else {mul(); op(SUB);} hold(); }
void cmp () {char r[3]; expr(); token(); strcpy(r,s); expr(); op(r);}
void var () {token(); op(s);} Это следует читать так: Выражение - это сумма слагаемых, слагаемое - это произведение множителей, множитель - это первичное выражение со знаком или без, а первичное выражение - это выражение в скобках, число или переменная.
Разбор выражений:[code]/* expr */
void op (char *s) {printf(CMD,s);}
void expr ();
void prim () { if (t("(")) {expr(); token();} else {op(s); if ((s[0]>='a')&&(s[0]<='z')) op(LOAD);} }
void unary () {if (n("-")) {unary(); op(NEGATE);} else prim();}
void mul () { unary(); while (n("*")||t("/")) if (t("*")) {unary(); op(MUL);} else {unary(); op(DIV);} hold(); }
void expr () { mul(); while (n("+")||t("-")) if (t("+")) {mul(); op(ADD);} else {mul(); op(SUB);} hold(); }
void cmp () {char r[3]; expr(); token(); strcpy(r,s); expr(); op(r);}
void var () {token(); op(s);}[/code]Это следует читать так: Выражение - это сумма слагаемых, слагаемое - это произведение множителей, множитель - это первичное выражение со знаком или без, а первичное выражение - это выражение в скобках, число или переменная.
|
|
|
 |
Добавлено: Пн май 05, 2025 22:53 |
|
|
 |
|
|
Заголовок сообщения: |
Re: Трансляторы Си в Форт |
 |
|
Немного упростил себе жизнь на первом этапе, заменив expr-list и var-list на expr и var соответственно, еще токены пока надо вручную разделять пробелами, ну и then в операторе if убрал за ненадобностью. Все это пока не так принципиально. В итоге набросалось на скорую руку такое: Сканер (потрошит исходник на отдельные лексемы): Код: /* scan */
char h = 0, c, s[32];
int gc () {return c = getchar();}
void hold () {h = 1;}
void token () { if (h) {h = 0; return;} s[0] = 0; while (gc()<'!') if (c==-1) return; s[0] = c; int p = 1; if (c=='"') do s[p++] = gc(); while (c!='"'); else while (gc()>' ') s[p++] = c; s[p] = 0; }
int t (char *x) {return !strcmp(s,x);}
int n (char *x) {token(); return t(x);}
Немного упростил себе жизнь на первом этапе, заменив expr-list и var-list на expr и var соответственно, еще токены пока надо вручную разделять пробелами, ну и then в операторе if убрал за ненадобностью. Все это пока не так принципиально. В итоге набросалось на скорую руку такое:
Сканер (потрошит исходник на отдельные лексемы):[code]/* scan */
char h = 0, c, s[32];
int gc () {return c = getchar();}
void hold () {h = 1;}
void token () { if (h) {h = 0; return;} s[0] = 0; while (gc()<'!') if (c==-1) return; s[0] = c; int p = 1; if (c=='"') do s[p++] = gc(); while (c!='"'); else while (gc()>' ') s[p++] = c; s[p] = 0; }
int t (char *x) {return !strcmp(s,x);}
int n (char *x) {token(); return t(x);}[/code]
|
|
|
 |
Добавлено: Пн май 05, 2025 22:50 |
|
|
 |
|