fix: parsing of multi-character operators and tests.
This commit is contained in:
parent
1be3b17bae
commit
eb45ed5772
4 changed files with 60 additions and 10 deletions
|
@ -276,7 +276,7 @@ namespace Jellyfin.Plugin.SmartPlaylist.Lisp.Compiler {
|
|||
case AtomToken at:
|
||||
return parse_atom(at);
|
||||
case OperatorToken ot:
|
||||
return new Symbol(ot.value);
|
||||
return parse_operator(ot);
|
||||
case SpaceToken sp:
|
||||
return parse();
|
||||
}
|
||||
|
@ -330,5 +330,19 @@ namespace Jellyfin.Plugin.SmartPlaylist.Lisp.Compiler {
|
|||
_sts.commit();
|
||||
return new Symbol(at.value);
|
||||
}
|
||||
|
||||
Expression parse_operator(OperatorToken ot) {
|
||||
string v = ot.value;
|
||||
while (_sts.available() > 0) {
|
||||
Token<string> t = _sts.get();
|
||||
if (t is OperatorToken ot_) {
|
||||
v += ot_.value;
|
||||
continue;
|
||||
}
|
||||
_sts.rewind(1);
|
||||
break;
|
||||
}
|
||||
return new Symbol(v);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,6 +27,7 @@ namespace Jellyfin.Plugin.SmartPlaylist.Lisp {
|
|||
this["car"] = _car;
|
||||
this["cdr"] = _cdr;
|
||||
this["cons"] = _cons;
|
||||
this["not"] = _not;
|
||||
this["length"] = _length;
|
||||
this["haskeys"] = _haskeys;
|
||||
this["getitems"] = _getitems;
|
||||
|
@ -170,6 +171,12 @@ namespace Jellyfin.Plugin.SmartPlaylist.Lisp {
|
|||
}
|
||||
throw new ApplicationException();
|
||||
}
|
||||
private static Expression _not(IList<Expression> args) {
|
||||
if (args[0] == new Compiler.Boolean(false)) {
|
||||
return new Compiler.Boolean(true);
|
||||
}
|
||||
return new Compiler.Boolean(false);
|
||||
}
|
||||
private static Expression _length(IList<Expression> args) {
|
||||
return new Integer(((Compiler.List)args[0]).expressions.Count());
|
||||
}
|
||||
|
@ -231,9 +238,11 @@ namespace Jellyfin.Plugin.SmartPlaylist.Lisp {
|
|||
this["if"] = _if;
|
||||
this["define"] = _define;
|
||||
this["apply"] = _apply;
|
||||
this["and"] = _and;
|
||||
this["or"] = _or;
|
||||
}
|
||||
private static Expression _if(Executor e, IList<Expression> args) {
|
||||
bool test = ((Compiler.Boolean) e.eval(args[0])).value;
|
||||
bool test = e.eval(args[0]) != (new Compiler.Boolean(false));
|
||||
return e.eval(args[1 + (test ? 0 : 1)]);
|
||||
}
|
||||
private static Expression _define(Executor e, IList<Expression> args) {
|
||||
|
@ -251,6 +260,22 @@ namespace Jellyfin.Plugin.SmartPlaylist.Lisp {
|
|||
Compiler.List other_args = (Compiler.List) args[1];
|
||||
return e.EvalFunction(arg0, other_args.expressions);
|
||||
}
|
||||
private static Expression _and(Executor e, IList<Expression> args) {
|
||||
Expression result = new Compiler.Boolean(false);
|
||||
foreach (var exp in args) {
|
||||
result = e.eval(exp);
|
||||
if (result == new Compiler.Boolean(false)) { return result; }
|
||||
}
|
||||
return result;
|
||||
}
|
||||
private static Expression _or(Executor e, IList<Expression> args) {
|
||||
Expression result = new Compiler.Boolean(false);
|
||||
foreach (var exp in args) {
|
||||
result = e.eval(exp);
|
||||
if (result != new Compiler.Boolean(false)) { return result; }
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
public class Executor {
|
||||
|
|
|
@ -110,7 +110,7 @@ namespace Jellyfin.Plugin.SmartPlaylist.ScheduledTasks {
|
|||
_logger.LogDebug("Item {0} evaluated to {1}", i, r.ToString());
|
||||
if (r is Lisp_Boolean r_bool) {
|
||||
if (r_bool.value) {
|
||||
_logger.LogDebug("Added "{0}" to Smart Playlist {1}", i, smartPlaylist.Name);
|
||||
_logger.LogDebug("Added '{0}' to Smart Playlist {1}", i, smartPlaylist.Name);
|
||||
results.Add(i.Id);
|
||||
}
|
||||
} else {
|
||||
|
|
|
@ -21,7 +21,7 @@ namespace Tests
|
|||
public class Test {
|
||||
[Fact]
|
||||
public static void TestTokenizer() {
|
||||
StringTokenStream sts = StringTokenStream.generate("(\"some literal string\" def ghj +100 -+300 1 ++ !=)");
|
||||
StringTokenStream sts = StringTokenStream.generate("(\"some literal string\" def ghj +100 -+300 1 >= ++ !=)");
|
||||
Assert.Equal(sts.get().value, "(");
|
||||
Assert.Equal(sts.get().value, "\"");
|
||||
Assert.Equal(sts.get().value, "some");
|
||||
|
@ -44,9 +44,14 @@ namespace Tests
|
|||
Assert.Equal(sts.get().value, " ");
|
||||
Assert.Equal(sts.get().value, "1");
|
||||
Assert.Equal(sts.get().value, " ");
|
||||
Assert.Equal(sts.get().value, "++");
|
||||
Assert.Equal(sts.get().value, ">");
|
||||
Assert.Equal(sts.get().value, "=");
|
||||
Assert.Equal(sts.get().value, " ");
|
||||
Assert.Equal(sts.get().value, "!=");
|
||||
Assert.Equal(sts.get().value, "+");
|
||||
Assert.Equal(sts.get().value, "+");
|
||||
Assert.Equal(sts.get().value, " ");
|
||||
Assert.Equal(sts.get().value, "!");
|
||||
Assert.Equal(sts.get().value, "=");
|
||||
Assert.Equal(sts.get().value, ")");
|
||||
sts.commit();
|
||||
Assert.Equal(sts.available(), 0);
|
||||
|
@ -97,6 +102,12 @@ namespace Tests
|
|||
|
||||
e = new Executor().eval("(length (cons 1 (2 3)))");
|
||||
Assert.Equal(string.Format("{0}", e), "3");
|
||||
|
||||
e = new Executor().eval("(>= 2 2)");
|
||||
Assert.Equal(string.Format("{0}", e), "t");
|
||||
|
||||
e = new Executor().eval("(> 2 2))");
|
||||
Assert.Equal(string.Format("{0}", e), "nil");
|
||||
}
|
||||
[Fact]
|
||||
public static void ObjectTest() {
|
||||
|
|
Loading…
Reference in a new issue