Compare commits

...

2 commits

4 changed files with 26 additions and 5 deletions

View file

@ -74,7 +74,7 @@ namespace Jellyfin.Plugin.SmartPlaylist.Api {
})));
return Lisp.Boolean.TRUE;
};
executor.builtins["print"] = (x) => {
executor.builtins["println"] = (x) => {
sb.Append(string.Join(" ", x.Select((i) => {
if (i is Lisp.String i_s) {
return i_s.Value();

View file

@ -3,7 +3,7 @@ using Jellyfin.Plugin.SmartPlaylist.Lisp;
namespace Jellyfin.Plugin.SmartPlaylist.Lisp.Compiler {
public class Parser {
private StringTokenStream _sts;
internal StringTokenStream _sts;
public Parser(StringTokenStream tokens) {
_sts = tokens;
}
@ -29,13 +29,18 @@ namespace Jellyfin.Plugin.SmartPlaylist.Lisp.Compiler {
Debug.Assert(start.value == end.value);
Debug.Assert("\"".Contains(start.value));
string r = "";
bool exit_ok = false;
while (_sts.Available() > 0) {
Token<string> t = _sts.Get();
if (t.value == end.value) {
exit_ok = true;
break;
}
r += t.value;
}
if (!exit_ok) {
throw new ApplicationException($"Failed to parse string, are you missing the closing quotes? String is: {r}");
}
_sts.Commit();
return new String(r);
}
@ -69,11 +74,16 @@ namespace Jellyfin.Plugin.SmartPlaylist.Lisp.Compiler {
if (";".Contains(start.value)) {
return parse_comment(start, end);
}
Debug.Assert(end != null);
if (end == null) {
throw new ApplicationException($"Don't know how to parse grouping starting with token '{start.value}'");
}
IList<Expression> expressions = new List<Expression>();
bool exit_ok = false;
while (_sts.Available() > 0) {
Token<string> t = _sts.Get();
if (t.value == end.value) {
exit_ok = true;
_sts.Commit();
break;
}
@ -87,7 +97,11 @@ namespace Jellyfin.Plugin.SmartPlaylist.Lisp.Compiler {
_sts.Rewind(1);
expressions.Add(parse());
}
return Cons.FromList(expressions);
var r = Cons.FromList(expressions);
if (!exit_ok) {
throw new ApplicationException($"Failed to parse grouping, are you missing some closing braces? Parsed expressions: {r}");
}
return r;
}
Expression parse_atom(AtomToken at) {

View file

@ -601,7 +601,11 @@ namespace Jellyfin.Plugin.SmartPlaylist.Lisp {
throw new ApplicationException($"Not handled case '{expression}'");
}
public Expression eval(Parser p) {
return eval(p.parse());
Expression r = eval(p.parse());
if (p._sts.Available() > 0) {
throw new ApplicationException($"Did not consume all tokens, remaining program is {string.Join(" ", p._sts.Remainder())}");
}
return r;
}
public Expression eval(StringTokenStream sts) {
return eval(new Parser(sts));

View file

@ -56,6 +56,9 @@ namespace Jellyfin.Plugin.SmartPlaylist.Util {
public IStream<T> Copy() {
return new Stream<T>(_items, _cursor, _ephemeralCursor);
}
public IList<T> Remainder() {
return _items.Skip(_cursor).ToList();
}
}
}