diff --git a/app/src/main/java/com/annimon/hotarufx/lexer/HotaruLexer.java b/app/src/main/java/com/annimon/hotarufx/lexer/HotaruLexer.java index 939b9b6..2519f5c 100644 --- a/app/src/main/java/com/annimon/hotarufx/lexer/HotaruLexer.java +++ b/app/src/main/java/com/annimon/hotarufx/lexer/HotaruLexer.java @@ -34,6 +34,13 @@ public class HotaruLexer extends Lexer { OPERATORS.put("@", HotaruTokenId.AT); } + private static final Map KEYWORDS; + static { + KEYWORDS = new HashMap<>(); + KEYWORDS.put("true", HotaruTokenId.TRUE); + KEYWORDS.put("false", HotaruTokenId.FALSE); + } + public HotaruLexer(String input) { super(input); } @@ -91,7 +98,7 @@ public class HotaruLexer extends Lexer { } val word = getBuffer().toString(); - return addToken(HotaruTokenId.WORD, word); + return addToken(KEYWORDS.getOrDefault(word, HotaruTokenId.WORD)); } private Token tokenizeText(char openChar) { diff --git a/app/src/main/java/com/annimon/hotarufx/lexer/HotaruTokenId.java b/app/src/main/java/com/annimon/hotarufx/lexer/HotaruTokenId.java index 264b397..e1f5bff 100644 --- a/app/src/main/java/com/annimon/hotarufx/lexer/HotaruTokenId.java +++ b/app/src/main/java/com/annimon/hotarufx/lexer/HotaruTokenId.java @@ -10,6 +10,9 @@ public enum HotaruTokenId { WORD(Category.IDENTIFIER), TEXT(Category.STRING), + TRUE(Category.KEYWORD), + FALSE(Category.KEYWORD), + EQ(Category.OPERATOR), PLUS(Category.OPERATOR), MINUS(Category.OPERATOR), @@ -31,7 +34,7 @@ public enum HotaruTokenId { EOF(Category.WHITESPACE); private enum Category { - NUMBER, IDENTIFIER, STRING, OPERATOR, COMMENT, WHITESPACE + NUMBER, IDENTIFIER, STRING, KEYWORD, OPERATOR, COMMENT, WHITESPACE } private final Category category; diff --git a/app/src/main/java/com/annimon/hotarufx/parser/HotaruParser.java b/app/src/main/java/com/annimon/hotarufx/parser/HotaruParser.java index 3d31295..75d59e0 100644 --- a/app/src/main/java/com/annimon/hotarufx/parser/HotaruParser.java +++ b/app/src/main/java/com/annimon/hotarufx/parser/HotaruParser.java @@ -3,6 +3,7 @@ package com.annimon.hotarufx.parser; import com.annimon.hotarufx.exceptions.ParseException; import com.annimon.hotarufx.lexer.HotaruTokenId; import com.annimon.hotarufx.lexer.Token; +import com.annimon.hotarufx.lib.NumberValue; import com.annimon.hotarufx.parser.ast.*; import java.util.ArrayList; import java.util.HashMap; @@ -219,6 +220,12 @@ public class HotaruParser extends Parser { private Node value() { val current = get(0); + if (match(HotaruTokenId.TRUE)) { + return new ValueNode(NumberValue.ONE); + } + if (match(HotaruTokenId.FALSE)) { + return new ValueNode(NumberValue.ZERO); + } if (match(HotaruTokenId.NUMBER)) { return new ValueNode(createNumber(current.getText(), 10)); } diff --git a/app/src/main/resources/main.hfx b/app/src/main/resources/main.hfx index dd90345..fdb5df2 100644 --- a/app/src/main/resources/main.hfx +++ b/app/src/main/resources/main.hfx @@ -87,7 +87,7 @@ POLYLINE = polyline(points, { }) LINE = line({ - visible: 0, + visible: false, startX: -600 startY: 300 endX: 600 @@ -95,7 +95,7 @@ LINE = line({ stroke: "#777", strokeDashOffset: 45 }) -LINE@visible.add(100, 1) +LINE@visible.add(100, true) LINE@strokeWidth.add(100, 0).add(140, 10) arcRadius = 200 diff --git a/app/src/test/java/com/annimon/hotarufx/parser/HotaruParserTest.java b/app/src/test/java/com/annimon/hotarufx/parser/HotaruParserTest.java index 9170c00..c198d09 100644 --- a/app/src/test/java/com/annimon/hotarufx/parser/HotaruParserTest.java +++ b/app/src/test/java/com/annimon/hotarufx/parser/HotaruParserTest.java @@ -2,6 +2,7 @@ package com.annimon.hotarufx.parser; import com.annimon.hotarufx.exceptions.ParseException; import com.annimon.hotarufx.lexer.HotaruLexer; +import com.annimon.hotarufx.lib.NumberValue; import com.annimon.hotarufx.parser.ast.AssignNode; import com.annimon.hotarufx.parser.ast.BlockNode; import com.annimon.hotarufx.parser.ast.FunctionNode; @@ -9,6 +10,8 @@ import com.annimon.hotarufx.parser.ast.MapNode; import com.annimon.hotarufx.parser.ast.Node; import com.annimon.hotarufx.parser.ast.ValueNode; import com.annimon.hotarufx.parser.ast.VariableNode; +import java.util.Arrays; +import lombok.val; import org.junit.jupiter.api.Test; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.allOf; @@ -59,6 +62,33 @@ class HotaruParserTest { )); } + @Test + void testParseTrueFalse() { + String input = "A = true\nB = false"; + Node node = p(input); + assertThat(node, instanceOf(BlockNode.class)); + + val block = (BlockNode) node; + assertThat(block.statements.size(), is(2)); + + val expectedValues = Arrays.asList( + NumberValue.fromBoolean(true), + NumberValue.fromBoolean(false) + ); + val it = expectedValues.iterator(); + + for (Node statement : block.statements) { + assertThat(statement, instanceOf(AssignNode.class)); + + val assignNode = (AssignNode) statement; + assertThat(assignNode.target, instanceOf(VariableNode.class)); + assertThat(assignNode.value, instanceOf(ValueNode.class)); + + val value = ((ValueNode) assignNode.value).value; + assertThat(value, is(it.next())); + } + } + @Test void testParseErrors() { assertThrows(ParseException.class, () -> p("A ="));