online compiler and debugger for c/c++

code. compile. run. debug. share.
Source Code    Language
{ This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. Simple Forth-inspired language interpreter Author: Kruchinin Tim } type Pstack = ^stack; stack = record next: Pstack; value: longint; end; function stack_init(val: longint): Pstack; var t: Pstack; begin new(t); t^.value := val; t^.next := nil; stack_init := t; end; function stack_depth(s: Pstack): longint; var d: integer; begin d := 0; while s^.next <> nil do begin inc(d); s := s^.next; end; stack_depth := d; end; procedure stack_delete(var s: Pstack); var t: Pstack; begin while (s^.next <> nil) do begin t := s; s := s^.next; dispose(t); end end; type Pdict = ^dict; dict = record name: string; code: string; next: Pdict; end; function dict_init(name, code: string): Pdict; var t: Pdict; begin new(t); t^.name := name; t^.code := code; t^.next := nil; dict_init := t; end; const RAMsize = 65536; type vars = record arr: array of byte; size: word; end; procedure push(var s: Pstack; n: longint; var e: boolean); // ( -- n ) var t: Pstack; begin e := false; t := stack_init(n); t^.next := s; s := t; end; procedure pop(var s: Pstack; var n: longint; var e: boolean); // ( n -- ) var t: Pstack; begin e := false; if (s^.next = nil) then begin e := true; write('Error: stack underflow '); end else begin n := s^.value; t := s; s := s^.next; dispose(t); end; end; procedure add(var s: Pstack; var e: boolean); // ( a b -- {a + b} ) var a,b: longint; begin e := false; pop(s,a,e); if (not e) then begin pop(s,b,e); if (not e) then push(s,a+b,e); end; end; procedure sub(var s: Pstack; var e: boolean); // ( a b -- { a - b } ) var a,b: longint; begin e := false; pop(s,a,e); if (not e) then begin pop(s,b,e); if (not e) then push(s,b-a,e); end; end; procedure mult(var s: Pstack; var e: boolean); // ( a b -- { a * b} ) var a,b: longint; begin e := false; pop(s,a,e); if (not e) then begin pop(s,b,e); if (not e) then push(s,a*b,e); end; end; procedure divmod(var s: Pstack; var e: boolean); // ( a b -- {a div b} {a mod b} ) var a,b: longint; begin e := false; pop(s,a,e); if (not e) then begin pop(s,b,e); if (not e) then begin push(s,b mod a,e); push(s,b div a,e); end; end; end; procedure dup(var s: Pstack; var e: boolean); // ( a -- a a ) var n: longint; begin pop(s,n,e); if (not e) then begin push(s,n,e); push(s,n,e); end; end; procedure swap(var s: Pstack; var e: boolean); // ( a b -- b a ) var a,b: longint; begin pop(s,a,e); if (not e) then begin pop(s,b,e); if (not e) then begin push(s,a,e); push(s,b,e); end; end; end; procedure over(var s: Pstack; var e: boolean); // ( a b -- a b a ) var a,b: longint; begin pop(s,a,e); if (not e) then begin pop(s,b,e); if (not e) then begin push(s,b,e); push(s,a,e); push(s,b,e); end; end; end; procedure drop(var s: Pstack; var e: boolean); // ( a -- ) var t: longint; begin pop(s,t,e); end; procedure rot(var s: Pstack; var e: boolean); // ( a b c -- b c a ) var a,b,c: longint; begin pop(s,a,e); if (not e) then begin pop(s,b,e); if not e then begin pop(s,c,e); if (not e) then begin push(s,b,e); push(s,a,e); push(s,c,e); end; end; end; end; procedure print(var s: Pstack; var e: boolean); // ( a -- ) var a: longint; begin e := false; pop(s,a,e); if (not e) then write(a,' ') end; procedure printUns(var s: Pstack; var e: boolean); // ( u -- ) var a: longint; b: longword; begin pop(s,a,e); b := a; if (not e) then write(b,' '); end; procedure emit(var s: Pstack; var e: boolean); // ( a -- ) var a: longint; begin e := false; pop(s,a,e); if (not e) then write(chr(a mod 256)) end; function isNumeric(s: string): boolean; var n,e: longint; begin val(s,n,e); isNumeric := e = 0; end; function value(s: string): longint; var n,e: longint; begin val(s,n,e); value := n; end; procedure printStack(s: Pstack); // ( -- ) var i: longint; begin write('S<',stack_depth(s),'> '); for i := 1 to stack_depth(s) do begin write(s^.value,' '); s := s^.next; end; writeln; end; procedure pushret(var ret,stk: Pstack; var e: boolean); // ( a -- , a ) var n: longint; begin pop(stk,n,e); if not e then push(ret,n,e); end; procedure popret(var ret,stk: Pstack; var e: boolean); // ( , a -- a ) var n: longint; begin pop(ret,n,e); if not e then push(stk,n,e); end; procedure copyret(var ret,stk: Pstack; var e: boolean); // ( , a -- a , a ) var n: longint; begin pop(ret,n,e); if not e then begin push(ret,n,e); if not e then push(stk,n,e); end; end; procedure eq(var stk: Pstack; var e: boolean); // ( a b -- {a == b} ) var a,b: longint; begin pop(stk,a,e); if not e then begin pop(stk,b,e); if not e then if a = b then push(stk,-1,e) else push(stk,0,e); end; end; procedure less(var stk: Pstack; var e: boolean); // ( a b -- {a < b} ) var a,b: longint; begin pop(stk,a,e); if not e then begin pop(stk,b,e); if not e then if b < a then push(stk,-1,e) else push(stk,0,e); end; end; procedure more(var stk: Pstack; var e: boolean); // ( a b -- { a > b } ) var a,b: longint; begin pop(stk,a,e); if not e then begin pop(stk,b,e); if not e then if b > a then push(stk,-1,e) else push(stk,0,e); end; end; procedure unsLess(var stk: Pstack; var e: boolean); // ( u1 u2 -- { u1 < u2 } ) var a,b: longint; c,d: longword; begin pop(stk,a,e); if not e then begin pop(stk,b,e); if not e then begin c := a; d := b; if d < c then push(stk,-1,e) else push(stk,0,e); end; end; end; procedure unsMore(var stk: Pstack; var e: boolean); // ( u1 u2 -- { u1 > u2 } ) var a,b: longint; c,d: longword; begin pop(stk,a,e); if not e then begin pop(stk,b,e); if not e then begin c := a; d := b; if d > c then push(stk,-1,e) else push(stk,0,e); end; end; end; procedure opand(var stk: Pstack; var e: boolean); // ( a b -- {a & b} ) var a,b: longint; begin pop(stk,a,e); if not e then begin pop(stk,b,e); if not e then push(stk,a and b,e); end; end; procedure opor(var stk: Pstack; var e: boolean); // ( a b -- {a || b} ) var a,b: longint; begin pop(stk,a,e); if not e then begin pop(stk,b,e); if not e then push(stk,a or b,e); end; end; procedure opxor(var stk: Pstack; var e: boolean); // ( a b -- {a ^ b} ) var a,b: longint; begin pop(stk,a,e); if not e then begin pop(stk,b,e); if not e then push(stk,a xor b,e); end; end; procedure opnot(var stk: Pstack; var e: boolean); var n: longint; begin pop(stk,n,e); if not e then if n = 0 then push(stk,-1,e) else push(stk,0,e); end; procedure opinc(var stk: Pstack; var e: boolean); var n: longint; begin pop(stk,n,e); if not e then begin inc(n); push(stk,n,e); end; end; procedure opdec(var stk: Pstack; var e: boolean); var n: longint; begin pop(stk,n,e); if not e then begin dec(n); push(stk,n,e); end; end; procedure writeRAM(var s: Pstack; var RAM: vars; var e: boolean); // ( n addr -- ) var a,k: longint; n: longword; begin pop(s,a,e); if not e then begin pop(s,k,e); if not e then if (a >= RAMsize-1) or (a < 0) then begin write('Error: Adress does not exist '); e := true; end else n := k; RAM.arr[a] := n div 16777216; RAM.arr[a+1] := n div 65536 mod 256; RAM.arr[a+2] := n div 256 mod 256; RAM.arr[a+3] := n mod 256; end; end; procedure readRAM(var s: Pstack; var RAM: vars; var e: boolean); // ( addr -- n ) var a: longint; n: longword; begin pop(s,a,e); if not e then if (a >= RAMsize-1) or (a < 0) then begin write('Error: Adress does not exist '); e := true; end else begin n := RAM.arr[a]*16777216+RAM.arr[a+1]*65536+RAM.arr[a+2]*256+RAM.arr[a+3]; push(s,n,e); end end; procedure plusRAM(var s: Pstack; var RAM: vars; var e: boolean); begin dup(s,e); if not e then begin readRAM(s,RAM,e); if not e then begin rot(s,e); if not e then begin add(s,e); if not e then begin swap(s,e); if not e then writeRAM(s,RAM,e); end; end; end end; end; procedure writeChr(var s: Pstack; var RAM: vars; var e: boolean); var k,a: longint; n: longword; begin pop(s,a,e); if not e then begin if (a < 0) or (a > RAMsize-1) then begin e := true; write('Error: Adress does not exist '); end else begin pop(s,k,e); if not e then begin n := k; RAM.arr[a] := n mod 256; end; end; end end; procedure readChr(var s: Pstack; var RAM: vars; var e: boolean); var a: longint; n: byte; begin pop(s,a,e); if not e then begin if (a < 0) or (a > RAMsize-1) then begin e := true; write('Error: Adress does not exist '); end else begin n := RAM.arr[a]; push(s,n,e); end; end end; function exec(str: string; var stk, ret: Pstack; var words: Pdict; var RAM: vars; automatic: boolean; var e: boolean): boolean; forward; function parse(slovo: string; var stk,ret: Pstack; var words: Pdict; var RAM: vars; var e: boolean): boolean; var isWOrd: boolean; t: Pdict; begin parse := false; isWord := false; t := words; while (t^.next <> nil) do begin if (not isWord) and (t^.name = slovo) then begin exec(t^.code, stk, ret, words, RAM, true, e); isWord := true; end; t := t^.next; end; if not isWord then begin if slovo = '+' then add(stk,e) else if slovo = '-' then sub(stk,e) else if slovo = '*' then mult(stk,e) else if slovo = '/MOD' then divmod(stk,e) else if slovo = '/' then begin divmod(stk,e); if not e then begin swap(stk,e); if not e then drop(stk,e); end; end else if slovo = 'MOD' then begin divmod(stk,e); if not e then drop(stk,e); end else if slovo = '1+' then opinc(stk,e) else if slovo = '1-' then opdec(stk,e) else if (slovo = '=') or (slovo = 'U=') then eq(stk,e) else if slovo = '>' then more(stk,e) else if slovo = '<' then less(stk,e) else if slovo = 'U>' then unsMore(stk,e) else if slovo = 'U<' then unsLess(stk,e) else if (slovo = 'NOT') or (slovo = '0=') then opnot(stk,e) else if slovo = 'AND' then opand(stk,e) else if slovo = 'OR' then opor(stk,e) else if slovo = 'XOR' then opxor(stk,e) else if slovo = 'DUP' then dup(stk,e) else if slovo = '2DUP' then begin over(stk,e); if not e then over(stk,e); end else if slovo = '2DROP' then begin drop(stk,e); if not e then drop(stk,e); end else if slovo = 'SWAP' then swap(stk,e) else if slovo = 'OVER' then over(stk,e) else if slovo = 'ROT' then rot(stk,e) else if slovo = 'DROP' then drop(stk,e) else if slovo = 'NIP' then begin swap(stk,e); if not e then drop(stk,e); end else if slovo = '>R' then pushret(ret,stk,e) else if slovo = 'R>' then popret(ret,stk,e) else if (slovo = 'R@') or (slovo = 'I') then copyret(ret,stk,e) else if (slovo = '!') then writeRAM(stk,ram,e) else if (slovo = '!+') then plusRAM(stk,ram,e) else if (slovo = '@') then readRAM(stk,ram,e) else if (slovo = 'C!') then writeChr(stk,ram,e) else if (slovo = 'C@') then readChr(stk,ram,e) else if (slovo = '?') then exec('@ . ',stk,ret,words,RAM,true,e) else if slovo = '.' then print(stk,e) else if slovo = 'U.' then printUns(stk,e) else if slovo = 'EMIT' then emit(stk,e) else if slovo = '.S' then printStack(stk) else if (slovo = 'BYE') or (slovo = 'LEAVE') then begin parse := true; end else if isNumeric(slovo) then push(stk,value(slovo),e) else begin e := true; write(slovo,'?') end; end; end; procedure format(var str: string); begin while (pos(' ', str) <> 0) do //Пока есть двойные пробелы delete(str,pos(' ',str),1); // Уничтожаем их if copy(str,1,1) <> ' ' then //Если первый символ не пробел str := ' ' + str; // Добавляем его if copy(str,length(str),1) <> ' ' then //Если последний символ не пробел str := str + ' '; // Добавляем его end; procedure upperCase(var str: string); var min,max: string; i: integer; begin min := 'abcdefghijklmnopqrstuvwxyz'; max := 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'; for i := 1 to length(str) do //Проходимся по строке begin if pos(copy(str,i,1), min) <> 0 then // Если перед нами маленькая буква begin insert(copy(max,pos(copy(str,i,1), min),1),str,i); // Добавляем большую delete(str,i+1,1); // А маленькую удаляем end; end; end; procedure macro(var str: string); var i: longint; begin for i := 2 to length(str)-1 do // Проходимся по строке if copy(str,i-1,3) = ' ( ' then // Если есть слово ( if pos(')',str) = 0 then // Если нет ограничителя delete(str,i,length(str)) // Удаляем до конца строки else // Иначе delete(str,i,pos(')',str)-i+1); // Удаляем до ограничителя upperCase(str); //Делаем все буквы большими while pos(' DO ', str) <> 0 do //Пока есть слова DO begin insert(' SWAP >R >R BEGIN ',str,pos(' DO ', str)); // Применяем макрос delete(str,pos(' DO ', str),4); // Удаляем слово DO end; while pos(' LOOP ', str) <> 0 do //Пока есть слова LOOP begin insert(' R> R> SWAP 1+ SWAP 2DUP >R >R = UNTIL R> R> 2DROP ', str,pos(' LOOP ', str)); // Применяем макрос delete(str,pos(' LOOP ', str),6); // Удаляем слово LOOP end; end; procedure addword(var words: Pdict; wordname, wordcode: string; var e: boolean); var t: Pdict; begin e := false; t := dict_init(wordname, wordcode); t^.next := words; words := t; end; procedure newWord(var str: string; var words: Pdict; var e: boolean); var wst, slovo: string; begin wst := ''; repeat //Повторяем slovo := copy(str,1,pos(' ', str) - 1); // Достаём слово delete(str,1,pos(' ', str)); // Удаляем слово if (slovo <> ';') and (slovo <> ':') then // Если слово не относится к словообразованию wst := wst + slovo + ' ' // Добавляем его until not ((str <> '') and (slovo <> ';') and (slovo <> ':')); //Пока строка не пуста и слово не относится к словообразованию if (str = '') and (slovo <> ';') then //Если строка закончилась begin e := true; // ОШИБКА write('Error: multiline definition '); // Выводим сообщение end; if (slovo = ':') then //Если слово объявляется в слове begin e := true; // ОШИБКА write('Error: word loop '); // Выводим сообщение end; if (slovo = ';') then //Если слово закончилось begin format(wst); // Приводим строку в нормальный вид delete(wst,1,1); // Удалем первый пробел addword(words,copy(wst,1,pos(' ',wst)-1), copy(wst,pos(' ',wst),length(wst)),e); // Добавляем статью end; end; procedure execIf(var str: string; var stk: Pstack; var e: boolean); var slovo: string; n: longint; begin pop(stk,n,e); //Получаем значение со стека if not e then //Если нет ошибки if n = 0 then // Если условие не выполнено begin n := 1; repeat // Повторяем slovo := copy(str,1,pos(' ', str) - 1); // Достаём слово delete(str,1,pos(' ', str)); // Удаляем слово if (slovo = 'IF') then // Если слово IF inc(n) // Увеличиваем вложенность else if (slovo = 'THEN') then // Иначе если слово THEN dec(n) // Уменьшаем вложенность else if (slovo = 'ELSE') and (n = 1) then // Если нет вложенности и слово ELSE dec(n); // Уменьшаем вложенность until (str = '') or (n = 0); // Пока строка не пуста и м в ифе if (str = '') and (slovo <> 'THEN') and (slovo <> 'ELSE') then // Если строка пуста и мы в ифе begin e := true; // ОШИБКА write('Error: multiline IF '); // Выводим сообщение end; end; end; procedure execElse(var str: string; var e: boolean); var n: longint; slovo: string; begin n := 1; repeat //Повторяем slovo := copy(str,1,pos(' ', str) - 1); // Достаём слово delete(str,1,pos(' ', str)); // Удаляем его if (slovo = 'IF') then // Если слово IF inc(n) // Увеличиваем вложенность else if (slovo = 'THEN') then // Иначе если слово THEN dec(n); // Уменьшаем вложенность until (str = '') or (n = 0); //Пока мы не вышли из ифа или строка не пуста if (str = '') and (slovo <> 'THEN') then //Если строка пуста, а мы не вышли из ифа begin e := true; // ОШИБКА write('Error: multiline IF '); // Выводим сообщение end; end; procedure execCycle(var str: string; var stk,ret: Pstack; var words: Pdict; var RAM: vars; var e: boolean); var wst, nst, slovo: string; n: longint; f: boolean; begin wst := ''; nst := ''; n := 1; f := true; repeat //Повторяем slovo := copy(str,1,pos(' ', str) - 1); // Достаём слово delete(str,1,pos(' ', str)); // Удаляем его if (slovo = 'WHILE') and (n = 1) then // Если нет вложенности и цикл WHILE f := false // Начинаем тело else if (slovo = 'UNTIL') or (slovo = 'REPEAT') then // Иначе если слово закрывает цикл dec(n) // Уменьшаем вложенность else if (slovo = 'BEGIN') then // Иначе если слово открывает цикл inc(n); // Увеличиваем вложенность if not((((slovo = 'UNTIL') or (slovo = 'REPEAT')) and (n = 0)) or ((slovo = 'WHILE') and (n = 1))) then // Если слово не образует текущий цикл if f then // Если мы пишем тело цикла BEGIN-UNTIL или условие цикла BEGIN-WHILE-REPEAT wst := wst + slovo + ' ' // Добавляем слово в одну строку else // Иначе nst := nst + slovo + ' ' // Добавляем его в другую строку until not (str <> '') or (n = 0) ; //Пока строка не закончислась и мы в цикле f := false; if (str = '') and (slovo <> 'UNTIL') and (slovo <> 'REPEAT') then //Если строка пуста и мы не дошли до конца цикла begin e := true; // ОШИБКА write('Error: multiline BEGIN-(WHILE)-UNTIL(REPEAT) '); // Выводим сообщение end else if (slovo = 'REPEAT') then //Иначе если наш цикл BEGIN-WHILE-REPEAT begin format(wst); // Приводим в нормальный вид условие format(nst); // Приводим в нормальный вид тело exec(wst,stk,ret,words,RAM,true,e); // Выполняем условие pop(stk,n,e); // Снимаем флаг while not e and not f and (n <> 0) do // Пока нет ошибки и флаг истинный begin f := exec(nst,stk,ret,words,RAM,true,e); // Выполняем тело if not e and not f then // Если нет ошибки begin exec(wst,stk,ret,words,RAM,true,e); // Выполняем условие if not e and not f then // Если нет ошибки pop(stk,n,e); // Снимаем флаг end; end; end else if (slovo = 'UNTIL') then //Иначе если наши цикл BEGIN-UNTIL begin format(wst); // Приводим в нормальнй вид тело repeat // Повторяем f := exec(wst,stk,ret,words,RAM,true,e); // Выполняем тело if not e and not f then // Если нет ошибки pop(stk,n,e); // Снимаем флаг until (n <> 0) or e or f; // Пока нет ошибки и флаг ложен end; end; function exec(str: string; var stk,ret: Pstack; var words: Pdict; var RAM: vars; automatic: boolean; var e: boolean): boolean; var slovo: string; f: boolean; begin e := false; f := false; exec := false; while ((str <> '') and not e and not f) do //Пока нет ошибок и есть чего исполнять begin slovo := copy(str,1,pos(' ', str) - 1); // Выбираем слово delete(str,1,pos(' ', str)); // Удаляем его из строки if slovo = ':' then // Если слово : newWord(str,words,e) // Добавляем новое слово else if (slovo = 'IF') then // Иначе если слово IF execIf(str,stk,e) // Обрабатываем условие else if (slovo = 'ELSE') then // Иначе если слово ELSE execElse(str,e) // Обходим ветвь ELSE THEN else if (slovo = 'THEN') then // Иначе если слово THEN slovo := '' // Пропускаем его else if (slovo = 'BEGIN') then // Иначе если слово BEGIN execCycle(str,stk,ret,words,RAM,e) // Запускаем цикл else if slovo <> '' then // Иначе если слово не пустое f := parse(slovo, stk, ret, words, RAM, e); // Выполняем его end; exec := f; if not automatic then //Если мы запускались вручную begin if (not e and not f) then // Если нет ошибки write(' ok'); // Всё OK writeln; // Пропускаем строку end; if e then //Если ошибка stack_delete(stk); // Очищаем стек end; procedure init(var stk,ret: Pstack; var words: Pdict; var RAM: vars); begin stk := stack_init(0); ret := stack_init(0); words := dict_init('', ''); RAM.size := 0; setLength(RAM.arr,RAMsize); end; function getfile(filename: string): string; var f: text; st, t: string; begin assign(f, filename); reset(f); st := ''; while not eof(f) do begin readln(f, t); st := st + t + ' '; end; getfile := st; end; var bye,e: boolean; stk, ret: Pstack; words: Pdict; RAM: vars; str: string; begin init(stk,ret,words,RAM); //Инициализируем структуры bye := false; if ParamCount = 0 then //Если нет аргументов while not bye and not eof do // Пока не закончили begin readln(str); // Вводим строку format(str); // Форматируем строку macro(str); // Применяем маросы bye := exec(str,stk,ret,words,RAM,false,e); // Исполняем end else //Иначе begin str := getfile(ParamStr(1)); // Вводим файл format(str); // Форматируем строку macro(str); // Применяем макросы exec(str, stk, ret, words, RAM, true, e); // Исполняем end; end.

Compiling Program...

Command line arguments:
Standard Input: Interactive Console Text
×

                

                

Program is not being debugged. Click "Debug" button to start program in debug mode.

#FunctionFile:Line
VariableValue
RegisterValue
ExpressionValue