fix: make the parser more robust and no longer accept invalid input silently.
This commit is contained in:
parent
1d472ed61f
commit
2624b83a79
3 changed files with 25 additions and 4 deletions
|
@ -3,7 +3,7 @@ using Jellyfin.Plugin.SmartPlaylist.Lisp;
|
||||||
|
|
||||||
namespace Jellyfin.Plugin.SmartPlaylist.Lisp.Compiler {
|
namespace Jellyfin.Plugin.SmartPlaylist.Lisp.Compiler {
|
||||||
public class Parser {
|
public class Parser {
|
||||||
private StringTokenStream _sts;
|
internal StringTokenStream _sts;
|
||||||
public Parser(StringTokenStream tokens) {
|
public Parser(StringTokenStream tokens) {
|
||||||
_sts = tokens;
|
_sts = tokens;
|
||||||
}
|
}
|
||||||
|
@ -29,13 +29,18 @@ namespace Jellyfin.Plugin.SmartPlaylist.Lisp.Compiler {
|
||||||
Debug.Assert(start.value == end.value);
|
Debug.Assert(start.value == end.value);
|
||||||
Debug.Assert("\"".Contains(start.value));
|
Debug.Assert("\"".Contains(start.value));
|
||||||
string r = "";
|
string r = "";
|
||||||
|
bool exit_ok = false;
|
||||||
while (_sts.Available() > 0) {
|
while (_sts.Available() > 0) {
|
||||||
Token<string> t = _sts.Get();
|
Token<string> t = _sts.Get();
|
||||||
if (t.value == end.value) {
|
if (t.value == end.value) {
|
||||||
|
exit_ok = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
r += t.value;
|
r += t.value;
|
||||||
}
|
}
|
||||||
|
if (!exit_ok) {
|
||||||
|
throw new ApplicationException($"Failed to parse string, are you missing the closing quotes? String is: {r}");
|
||||||
|
}
|
||||||
_sts.Commit();
|
_sts.Commit();
|
||||||
return new String(r);
|
return new String(r);
|
||||||
}
|
}
|
||||||
|
@ -69,11 +74,16 @@ namespace Jellyfin.Plugin.SmartPlaylist.Lisp.Compiler {
|
||||||
if (";".Contains(start.value)) {
|
if (";".Contains(start.value)) {
|
||||||
return parse_comment(start, end);
|
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>();
|
IList<Expression> expressions = new List<Expression>();
|
||||||
|
bool exit_ok = false;
|
||||||
while (_sts.Available() > 0) {
|
while (_sts.Available() > 0) {
|
||||||
Token<string> t = _sts.Get();
|
Token<string> t = _sts.Get();
|
||||||
if (t.value == end.value) {
|
if (t.value == end.value) {
|
||||||
|
exit_ok = true;
|
||||||
_sts.Commit();
|
_sts.Commit();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -87,7 +97,11 @@ namespace Jellyfin.Plugin.SmartPlaylist.Lisp.Compiler {
|
||||||
_sts.Rewind(1);
|
_sts.Rewind(1);
|
||||||
expressions.Add(parse());
|
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) {
|
Expression parse_atom(AtomToken at) {
|
||||||
|
|
|
@ -601,7 +601,11 @@ namespace Jellyfin.Plugin.SmartPlaylist.Lisp {
|
||||||
throw new ApplicationException($"Not handled case '{expression}'");
|
throw new ApplicationException($"Not handled case '{expression}'");
|
||||||
}
|
}
|
||||||
public Expression eval(Parser p) {
|
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) {
|
public Expression eval(StringTokenStream sts) {
|
||||||
return eval(new Parser(sts));
|
return eval(new Parser(sts));
|
||||||
|
|
|
@ -56,6 +56,9 @@ namespace Jellyfin.Plugin.SmartPlaylist.Util {
|
||||||
public IStream<T> Copy() {
|
public IStream<T> Copy() {
|
||||||
return new Stream<T>(_items, _cursor, _ephemeralCursor);
|
return new Stream<T>(_items, _cursor, _ephemeralCursor);
|
||||||
}
|
}
|
||||||
|
public IList<T> Remainder() {
|
||||||
|
return _items.Skip(_cursor).ToList();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue