image thumbnail
from Growing a Compiler by Bill McKeeman
Bootstrap compilers starting from a tiny compiler-compiler.

testGem6()
% FILE:     testGem6.m 
% PURPOSE:  test gem (the grammar executing machine)
% METHOD:   multichar phase name
% REQUIRES: gem6.m iog6.c iog6.h
% EXAMPLE:    
%   testGem6() % for all tests

% COPYRIGHT: 2009 W. M. McKeeman.  See license.txt.

function testGem6()  
  EOL = char(10);                                 % ascii newline
  tests  = 0;                                     % none yet
  passed = 0;                                     % none yet
  
  G = gem6();                                     % instantiate GEM object

  positiveTest(strcmp('',     G.run('', 'g=;'))); 
  positiveTest(strcmp('abc',  G.run('', '<goal>="abc";')));
  positiveTest(strcmp('Hello World!', G.run('', '   <goal>   =   "Hello World!"   ;   ')));
  positiveTest(strcmp('abc', G.run('123', '<goal>=''123'' "abc";')));
  positiveTest(strcmp('abc', G.run('123', '<goal>=s"abc";s=''123'';')));
  
  positiveTest(strcmp('abc', G.run('123', '<goal>=<s>"abc";<s>=''123'';')));
  positiveTest(strcmp('abc', G.run('123', '<goal>=<sub>"abc";<sub>=''123'';')));
  positiveTest(strcmp('bac', G.run('123', '<goal>=''1''<sub>"a"<other>;<sub>=''2''"b";<other>=''3''"c";')));
  positiveTest(strcmp('bca', G.run('123', '<goal>=''1''<sub>"a";<sub>="c"<other>;<sub>=''2''"b"<other>;<other>=''24'';<other>=''3''"c";')));
  positiveTest(strcmp('',     G.run('ab', 'g=''ab''<sub>;<sub>=;')));
 
  positiveTest(strcmp('',     G.run('''x', '<goal>='''''' ''x'';')));
  positiveTest(strcmp('"',    G.run('xyz', '  <goal>  = """ <sub>; <sub>  = ''xyz''; ')));
  positiveTest(strcmp('',     G.run('1', '<goal> = <a>; <goal> = b; <a>=''1'';b=''2'';')));
  positiveTest(strcmp('',     G.run('123', '<goal>=d<goal>;<goal>=;', 'd')));  
  positiveTest(strcmp('123',  G.run('123', '<goal>= D <goal> D D; <goal> = ;', 'D')));  

  positiveTest(strcmp('',     G.run('1', '<g>=<a>;<a>=b;b=<c>;c=d "2";<c>=d; d= <ff> ;<ff>=''1'';')));
  
  % test pretty, invert and nowhite
  in = '<game>                =        <s>        ;  <s>  = s ;  s = ;';
  out = ['<game> = <s>;',EOL,'<s> = s;',EOL,'s =;',EOL];
  positiveTest(strcmp(out,G.run(in,G.pretty,'ULA')));
  in = 'g=''124'' "fe"; <fame>=''vege'' "fefe";';
  out = 'g="124" ''fe''; <fame>="vege" ''fefe'';';
  positiveTest(strcmp(out,G.run(in,G.invert,'LA')));
  in = '<game> = <eere4343> a  '' 1'';';
  out = '<game>=<eere4343>a'' 1'';';
  positiveTest(strcmp(out, G.run(in, G.nowhite,'A')));
  % test noplus and nostar
  in   = '<my_goal>=<sub_1>x+;<sub_1>=<b>+;<b>=<c>*;<c>=x*;x=;';
  out1 = ['<my_goal>=<sub_1>xx*;' ...
         '<sub_1>=<b><b>*;'      ...
         '<b>=<c>*;'             ...
         '<c>=x*;'               ...
         'x=;'];
  out2 = ['<my_goal>=<sub_1>xX;' ...
          '<sub_1>=<b><b*>;'     ...
          '<b>=<c*>;'            ...
          '<c>=X;'               ...
          'x=;'];
  out3 = 'X=xX;X=;X=xX;X=;';
  out4 = '<b*>=<b><b*>;<b*>=;<c*>=<c><c*>;<c*>=;';  
  positiveTest(strcmp(out1, G.scan(G.run(in,  G.noplus, 'ALUD'))));
  
  positiveTest(strcmp(out2, G.scan(G.run(out1,G.nostar1,'ALUD'))));  
  positiveTest(strcmp(out3, G.scan(G.run(out1,G.nostar2,'alud'))));  
  positiveTest(strcmp(out4, G.run(out1,G.nostar3,'alud')));
  positiveTest(0==G.exe('5589E5606133C0C9C3'));           % execute X86 code

  negativeTest('',    'g=g;', '');                        % left recursion
  negativeTest('',    '<goal>=<goal>;', '');              % left recursion
  negativeTest('',    '<goal>=r<goal>;r="a";','');        % infinite output
  negativeTest('a',   '<goal>=r<go>;r="a";<goal>=;','');  % bad input
  negativeTest('a',   'g=''a''<pp>; <pp ','');            % bad format
  negativeTest('123', ...
    ['<goal>=''1''<sub>"a"<other>;' ...
     '<sub>="c"<other>;'            ...
     '<sub>=''2''"b"<other>;'       ...
     '<other>=''24'';'              ...
     '<other>=''3''"c";',''
     ]);
    
  fprintf('gem6: passed %d tests out of %d\n', passed, tests);
  
  %return;
  
  function positiveTest(bexpr)
    tests = tests + 1;
    if bexpr; passed = passed + 1; end
    %tests, passed
  end

  function negativeTest(i, g, f)  
    try
      res = G.run(i, g, f);
      positiveTest(false);    % should not get here
    catch err
      positiveTest(true);     % should get here
      %fprintf('gem test %d, %s', tests, err.message);
    end
  end

end

Contact us at files@mathworks.com