1
1
mirror of https://github.com/kanaka/mal.git synced 2024-09-20 18:18:51 +03:00
mal/matlab/reader.m
Joel Martin 4769962955 matlab: support Octave 4.0.0
- Workarounds for Octave 4.0.0:
    - no containers.Map yet so use new Dict
      structure when running under Octave.
    - weird error when +FOO/ directory and FOO.m file both exist so
      rename types.m to type_utils.m
    - no getReport so implement custom stack printer
    - workaround weird issue that happens when a class initializer is
      called with the first argument of the same class as per
      Env(outer, ...). The class is not properly initialized. So for
      now, wrap the outer in a cell as Env({outer}, ...)
    - missing MException object types so when in Octave, use a global
      variable to store the error object.
    - missing native2unicode so just use 0xff character for keyword
      prefix.
    - workaround some function calling/passing differences. For
      example, the "@" anonymous function symbol does not seem to work
      for conveying an existing function but only for defininign a new
      one. E.g. this works:
          @(a,b) a+b
      but this doesn't
          @my_adder_fn.
      so just do this:
          @(a,b) my_adder_fn(a,b)

- Add Dockerfile with Octave

- Active Travis for matlab implementation using Octave
2015-12-31 13:55:18 -06:00

126 lines
4.3 KiB
Matlab

% this is just being used as a namespace
classdef reader
methods (Static = true)
function tokens = tokenize(str)
re = '[\s,]*(~@|[\[\]{}()''`~^@]|"(?:\\.|[^\\"])*"|;[^\n]*|[^\s\[\]{}(''"`,;)]*)';
% extract the capture group (to ignore spaces and commas)
tokens = cellfun(@(x) x(1), regexp(str, re, 'tokens'));
comments = cellfun(@(x) length(x) > 0 && x(1) == ';', tokens);
tokens = tokens(~comments);
end
function atm = read_atom(rdr)
token = rdr.next();
%fprintf('in read_atom: %s\n', token);
if not(isempty(regexp(token, '^-?[0-9]+$', 'match')))
atm = str2double(token);
elseif strcmp(token(1), '"')
atm = token(2:length(token)-1);
atm = strrep(atm, '\"', '"');
atm = strrep(atm, '\n', char(10));
atm = strrep(atm, '\\', '\');
elseif strcmp(token(1), ':')
s = token(2:end);
atm = type_utils.keyword(s);
elseif strcmp(token, 'nil')
atm = type_utils.nil;
elseif strcmp(token, 'true')
atm = true;
elseif strcmp(token, 'false')
atm = false;
else
atm = types.Symbol(token);
end
end
function seq = read_seq(rdr, start, last)
%fprintf('in read_seq\n');
seq = {};
token = rdr.next();
if not(strcmp(token, start))
error(sprintf('expected ''%s''', start));
end
token = rdr.peek();
while true
if eq(token, false)
error(sprintf('expected ''%s''', last));
end
if strcmp(token, last), break, end
seq{end+1} = reader.read_form(rdr);
token = rdr.peek();
end
rdr.next();
end
function lst = read_list(rdr)
seq = reader.read_seq(rdr, '(', ')');
lst = types.List(seq{:});
end
function vec = read_vector(rdr)
seq = reader.read_seq(rdr, '[', ']');
vec = types.Vector(seq{:});
end
function map = read_hash_map(rdr)
seq = reader.read_seq(rdr, '{', '}');
map = types.HashMap(seq{:});
end
function ast = read_form(rdr)
%fprintf('in read_form\n');
token = rdr.peek();
switch token
case ''''
rdr.next();
ast = types.List(types.Symbol('quote'), ...
reader.read_form(rdr));
case '`'
rdr.next();
ast = types.List(types.Symbol('quasiquote'), ...
reader.read_form(rdr));
case '~'
rdr.next();
ast = types.List(types.Symbol('unquote'), ...
reader.read_form(rdr));
case '~@'
rdr.next();
ast = types.List(types.Symbol('splice-unquote'), ...
reader.read_form(rdr));
case '^'
rdr.next();
meta = reader.read_form(rdr);
ast = types.List(types.Symbol('with-meta'), ...
reader.read_form(rdr), meta);
case '@'
rdr.next();
ast = types.List(types.Symbol('deref'), ...
reader.read_form(rdr));
case ')'
error('unexpected '')''');
case '('
ast = reader.read_list(rdr);
case ']'
error('unexpected '']''');
case '['
ast = reader.read_vector(rdr);
case '}'
error('unexpected ''}''');
case '{'
ast = reader.read_hash_map(rdr);
otherwise
ast = reader.read_atom(rdr);
end
end
function ast = read_str(str)
%fprintf('in read_str\n');
tokens = reader.tokenize(str);
%disp(tokens);
rdr = types.Reader(tokens);
ast = reader.read_form(rdr);
end
end
end