Поддержка внутренних полей и функций у строк

This commit is contained in:
Victor 2019-01-04 21:59:37 +02:00
parent dbdc56f323
commit 0bbbeccda6
5 changed files with 59 additions and 2 deletions

View File

@ -0,0 +1,15 @@
package com.annimon.ownlang.exceptions;
public final class UnknownPropertyException extends RuntimeException {
private final String propertyName;
public UnknownPropertyException(String name) {
super("Unknown property " + name);
this.propertyName = name;
}
public String getPropertyName() {
return propertyName;
}
}

View File

@ -1,5 +1,6 @@
package com.annimon.ownlang.lib; package com.annimon.ownlang.lib;
import com.annimon.ownlang.exceptions.UnknownPropertyException;
import java.util.Objects; import java.util.Objects;
/** /**
@ -15,6 +16,19 @@ public final class StringValue implements Value {
public StringValue(String value) { public StringValue(String value) {
this.value = value; this.value = value;
} }
public Value access(Value property) {
switch (property.asString()) {
// Properties
case "length":
return NumberValue.of(length());
// Functions
case "trim":
return new FunctionValue(args -> new StringValue(value.trim()));
}
throw new UnknownPropertyException(property.asString());
}
public int length() { public int length() {
return value.length(); return value.length();
@ -82,5 +96,4 @@ public final class StringValue implements Value {
public String toString() { public String toString() {
return asString(); return asString();
} }
} }

View File

@ -782,7 +782,23 @@ public final class Parser {
return new ValueExpression(createNumber(current.getText(), 16)); return new ValueExpression(createNumber(current.getText(), 16));
} }
if (match(TokenType.TEXT)) { if (match(TokenType.TEXT)) {
return new ValueExpression(current.getText()); final ValueExpression strExpr = new ValueExpression(current.getText());
// "text".property || "text".func()
if (lookMatch(0, TokenType.DOT)) {
if (lookMatch(1, TokenType.WORD) && lookMatch(2, TokenType.LPAREN)) {
match(TokenType.DOT);
return functionChain(new ContainerAccessExpression(
strExpr, Collections.singletonList(
new ValueExpression(consume(TokenType.WORD).getText())
)));
}
final List<Expression> indices = variableSuffix();
if (indices.isEmpty()) {
return strExpr;
}
return new ContainerAccessExpression(strExpr, indices);
}
return strExpr;
} }
throw new ParseException("Unknown expression: " + current); throw new ParseException("Unknown expression: " + current);
} }

View File

@ -48,6 +48,9 @@ public final class ContainerAccessExpression implements Expression, Accessible {
case Types.MAP: case Types.MAP:
return ((MapValue) container).get(lastIndex); return ((MapValue) container).get(lastIndex);
case Types.STRING:
return ((StringValue) container).access(lastIndex);
default: default:
throw new TypeException("Array or map expected. Got " + Types.typeToString(container.type())); throw new TypeException("Array or map expected. Got " + Types.typeToString(container.type()));

View File

@ -0,0 +1,10 @@
def testLength() {
assertEquals(3, "123".length)
s = "test"
assertEquals(4, s.length)
}
def testTrim() {
s = " test "
assertEquals("test", s.trim())
}