[tlox] Initial Expression parsing and evaluation
This commit is contained in:
@@ -15,6 +15,7 @@
|
|||||||
gcc = pkgs.gcc;
|
gcc = pkgs.gcc;
|
||||||
openjdk = pkgs.openjdk;
|
openjdk = pkgs.openjdk;
|
||||||
maven = pkgs.maven;
|
maven = pkgs.maven;
|
||||||
|
antlr = pkgs.antlr;
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
devShell = pkgs.mkShell {
|
devShell = pkgs.mkShell {
|
||||||
@@ -22,6 +23,7 @@
|
|||||||
gcc
|
gcc
|
||||||
openjdk
|
openjdk
|
||||||
maven
|
maven
|
||||||
|
antlr
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,11 +6,11 @@
|
|||||||
|
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>xyz.ctsk.lox</groupId>
|
<groupId>xyz.ctsk.lox</groupId>
|
||||||
<artifactId>lox</artifactId>
|
<artifactId>jlox</artifactId>
|
||||||
<version>1.0-SNAPSHOT</version>
|
<version>1.0-SNAPSHOT</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<artifactId>interpreter</artifactId>
|
<artifactId>lox</artifactId>
|
||||||
<packaging>jar</packaging>
|
<packaging>jar</packaging>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
<groupId>xyz.ctsk.lox</groupId>
|
<groupId>xyz.ctsk.lox</groupId>
|
||||||
<artifactId>lox</artifactId>
|
<artifactId>jlox</artifactId>
|
||||||
<version>1.0-SNAPSHOT</version>
|
<version>1.0-SNAPSHOT</version>
|
||||||
|
|
||||||
<packaging>pom</packaging>
|
<packaging>pom</packaging>
|
||||||
@@ -10,6 +10,7 @@
|
|||||||
<modules>
|
<modules>
|
||||||
<module>tools</module>
|
<module>tools</module>
|
||||||
<module>lox</module>
|
<module>lox</module>
|
||||||
|
<module>tlox</module>
|
||||||
</modules>
|
</modules>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
|
|||||||
57
jlox/tlox/pom.xml
Normal file
57
jlox/tlox/pom.xml
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<parent>
|
||||||
|
<groupId>xyz.ctsk.lox</groupId>
|
||||||
|
<artifactId>jlox</artifactId>
|
||||||
|
<version>1.0-SNAPSHOT</version>
|
||||||
|
</parent>
|
||||||
|
|
||||||
|
<artifactId>tlox</artifactId>
|
||||||
|
<packaging>jar</packaging>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<maven.compiler.source>17</maven.compiler.source>
|
||||||
|
<maven.compiler.target>17</maven.compiler.target>
|
||||||
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.graalvm.truffle</groupId>
|
||||||
|
<artifactId>truffle-api</artifactId>
|
||||||
|
<version>22.2.0</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.antlr</groupId>
|
||||||
|
<artifactId>antlr4</artifactId>
|
||||||
|
<version>4.11.1</version>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.antlr</groupId>
|
||||||
|
<artifactId>antlr4-maven-plugin</artifactId>
|
||||||
|
<version>4.11.1</version>
|
||||||
|
<configuration>
|
||||||
|
<sourceDirectory>src/main/resources</sourceDirectory>
|
||||||
|
</configuration>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<id>antlr</id>
|
||||||
|
<goals>
|
||||||
|
<goal>antlr4</goal>
|
||||||
|
</goals>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
|
||||||
|
</project>
|
||||||
38
jlox/tlox/src/main/java/xyz/ctsk/lox/Main.java
Normal file
38
jlox/tlox/src/main/java/xyz/ctsk/lox/Main.java
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
package xyz.ctsk.lox;
|
||||||
|
|
||||||
|
import com.oracle.truffle.api.Truffle;
|
||||||
|
import xyz.ctsk.lox.nodes.LoxRootNode;
|
||||||
|
import xyz.ctsk.lox.parser.LoxParser;
|
||||||
|
|
||||||
|
import java.io.BufferedReader;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
|
||||||
|
public class Main {
|
||||||
|
|
||||||
|
public static void repl() throws IOException {
|
||||||
|
var input = new InputStreamReader(System.in);
|
||||||
|
var reader = new BufferedReader(input);
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
System.out.print(" >> ");
|
||||||
|
var line = reader.readLine();
|
||||||
|
if (line == null) break;
|
||||||
|
run(line);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void run(String program) {
|
||||||
|
var parsed = LoxParser.parseLox(program);
|
||||||
|
|
||||||
|
if (parsed instanceof LoxParser.ExpressionContext expr) {
|
||||||
|
var root = new LoxRootNode(expr.result);
|
||||||
|
var callTarget = root.getCallTarget();
|
||||||
|
System.out.println(callTarget.call());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(String[] args) throws IOException {
|
||||||
|
repl();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
package xyz.ctsk.lox.nodes;
|
||||||
|
|
||||||
|
import com.oracle.truffle.api.frame.VirtualFrame;
|
||||||
|
|
||||||
|
public abstract class LoxExpressionNode extends LoxNode {
|
||||||
|
public abstract double executeDouble(VirtualFrame frame);
|
||||||
|
}
|
||||||
6
jlox/tlox/src/main/java/xyz/ctsk/lox/nodes/LoxNode.java
Normal file
6
jlox/tlox/src/main/java/xyz/ctsk/lox/nodes/LoxNode.java
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
package xyz.ctsk.lox.nodes;
|
||||||
|
|
||||||
|
import com.oracle.truffle.api.nodes.Node;
|
||||||
|
|
||||||
|
public class LoxNode extends Node {
|
||||||
|
}
|
||||||
20
jlox/tlox/src/main/java/xyz/ctsk/lox/nodes/LoxRootNode.java
Normal file
20
jlox/tlox/src/main/java/xyz/ctsk/lox/nodes/LoxRootNode.java
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
package xyz.ctsk.lox.nodes;
|
||||||
|
|
||||||
|
import com.oracle.truffle.api.frame.VirtualFrame;
|
||||||
|
import com.oracle.truffle.api.nodes.RootNode;
|
||||||
|
|
||||||
|
public class LoxRootNode extends RootNode {
|
||||||
|
@SuppressWarnings("FieldMayBeFinal")
|
||||||
|
@Child
|
||||||
|
private LoxExpressionNode exprNode;
|
||||||
|
|
||||||
|
public LoxRootNode(LoxExpressionNode exprNode) {
|
||||||
|
super(null);
|
||||||
|
this.exprNode = exprNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object execute(VirtualFrame frame) {
|
||||||
|
return this.exprNode.executeDouble(frame);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
package xyz.ctsk.lox.nodes.expr;
|
||||||
|
|
||||||
|
import com.oracle.truffle.api.frame.VirtualFrame;
|
||||||
|
import com.oracle.truffle.api.nodes.Node;
|
||||||
|
import xyz.ctsk.lox.nodes.LoxExpressionNode;
|
||||||
|
|
||||||
|
public class LoxAddNode extends LoxExpressionNode {
|
||||||
|
@SuppressWarnings("FieldMayBeFinal")
|
||||||
|
@Node.Child
|
||||||
|
private LoxExpressionNode leftNode, rightNode;
|
||||||
|
|
||||||
|
public LoxAddNode(LoxExpressionNode leftNode, LoxExpressionNode rightNode) {
|
||||||
|
this.leftNode = leftNode;
|
||||||
|
this.rightNode = rightNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public double executeDouble(VirtualFrame frame) {
|
||||||
|
var leftValue = leftNode.executeDouble(frame);
|
||||||
|
var rightValue = rightNode.executeDouble(frame);
|
||||||
|
return leftValue + rightValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
package xyz.ctsk.lox.nodes.expr;
|
||||||
|
|
||||||
|
import com.oracle.truffle.api.frame.VirtualFrame;
|
||||||
|
import xyz.ctsk.lox.nodes.LoxExpressionNode;
|
||||||
|
|
||||||
|
public class LoxDivNode extends LoxExpressionNode {
|
||||||
|
@SuppressWarnings("FieldMayBeFinal")
|
||||||
|
@Child
|
||||||
|
private LoxExpressionNode leftNode, rightNode;
|
||||||
|
|
||||||
|
public LoxDivNode(LoxExpressionNode leftNode, LoxExpressionNode rightNode) {
|
||||||
|
this.leftNode = leftNode;
|
||||||
|
this.rightNode = rightNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public double executeDouble(VirtualFrame frame) {
|
||||||
|
var leftValue = leftNode.executeDouble(frame);
|
||||||
|
var rightValue = rightNode.executeDouble(frame);
|
||||||
|
return leftValue / rightValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
package xyz.ctsk.lox.nodes.expr;
|
||||||
|
|
||||||
|
import com.oracle.truffle.api.frame.VirtualFrame;
|
||||||
|
import xyz.ctsk.lox.nodes.LoxExpressionNode;
|
||||||
|
|
||||||
|
public class LoxMulNode extends LoxExpressionNode {
|
||||||
|
@SuppressWarnings("FieldMayBeFinal")
|
||||||
|
@Child
|
||||||
|
private LoxExpressionNode leftNode, rightNode;
|
||||||
|
|
||||||
|
public LoxMulNode(LoxExpressionNode leftNode, LoxExpressionNode rightNode) {
|
||||||
|
this.leftNode = leftNode;
|
||||||
|
this.rightNode = rightNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public double executeDouble(VirtualFrame frame) {
|
||||||
|
var leftValue = leftNode.executeDouble(frame);
|
||||||
|
var rightValue = rightNode.executeDouble(frame);
|
||||||
|
return leftValue * rightValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
package xyz.ctsk.lox.nodes.expr;
|
||||||
|
|
||||||
|
import com.oracle.truffle.api.frame.VirtualFrame;
|
||||||
|
import xyz.ctsk.lox.nodes.LoxExpressionNode;
|
||||||
|
|
||||||
|
public class LoxNumberLiteralNode extends LoxExpressionNode {
|
||||||
|
private final double value;
|
||||||
|
|
||||||
|
public LoxNumberLiteralNode(double value) {
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double executeDouble(VirtualFrame frame) {
|
||||||
|
return this.value;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
package xyz.ctsk.lox.nodes.expr;
|
||||||
|
|
||||||
|
import com.oracle.truffle.api.frame.VirtualFrame;
|
||||||
|
import xyz.ctsk.lox.nodes.LoxExpressionNode;
|
||||||
|
|
||||||
|
public class LoxSubNode extends LoxExpressionNode {
|
||||||
|
@SuppressWarnings("FieldMayBeFinal")
|
||||||
|
@Child
|
||||||
|
private LoxExpressionNode leftNode, rightNode;
|
||||||
|
|
||||||
|
public LoxSubNode(LoxExpressionNode leftNode, LoxExpressionNode rightNode) {
|
||||||
|
this.leftNode = leftNode;
|
||||||
|
this.rightNode = rightNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public double executeDouble(VirtualFrame frame) {
|
||||||
|
var leftValue = leftNode.executeDouble(frame);
|
||||||
|
var rightValue = rightNode.executeDouble(frame);
|
||||||
|
return leftValue - rightValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
package xyz.ctsk.lox.parser;
|
||||||
|
|
||||||
|
import org.antlr.v4.runtime.Token;
|
||||||
|
import xyz.ctsk.lox.nodes.LoxExpressionNode;
|
||||||
|
import xyz.ctsk.lox.nodes.expr.*;
|
||||||
|
|
||||||
|
public class LoxNodeFactory {
|
||||||
|
public static LoxNumberLiteralNode createNumberLiteral(Token literalToken) {
|
||||||
|
var value = Double.parseDouble(literalToken.getText());
|
||||||
|
return new LoxNumberLiteralNode(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static LoxExpressionNode createBinaryNode(Token op, LoxExpressionNode left, LoxExpressionNode right) {
|
||||||
|
return switch (op.getText()) {
|
||||||
|
case "+" -> new LoxAddNode(left, right);
|
||||||
|
case "-" -> new LoxSubNode(left, right);
|
||||||
|
case "*" -> new LoxMulNode(left, right);
|
||||||
|
case "/" -> new LoxDivNode(left, right);
|
||||||
|
default -> null;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
92
jlox/tlox/src/main/resources/xyz/ctsk/lox/parser/Lox.g4
Normal file
92
jlox/tlox/src/main/resources/xyz/ctsk/lox/parser/Lox.g4
Normal file
@@ -0,0 +1,92 @@
|
|||||||
|
grammar Lox;
|
||||||
|
|
||||||
|
|
||||||
|
@parser::header {
|
||||||
|
|
||||||
|
import com.oracle.truffle.api.source.Source;
|
||||||
|
|
||||||
|
import xyz.ctsk.lox.nodes.LoxExpressionNode;
|
||||||
|
import xyz.ctsk.lox.parser.*;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@parser::members {
|
||||||
|
private LoxNodeFactory factory;
|
||||||
|
|
||||||
|
public static Object parseLox(String source) {
|
||||||
|
LoxLexer lexer = new LoxLexer(CharStreams.fromString(source));
|
||||||
|
LoxParser parser = new LoxParser(new CommonTokenStream(lexer));
|
||||||
|
|
||||||
|
parser.factory = new LoxNodeFactory();
|
||||||
|
|
||||||
|
return parser.expression();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
file returns [LoxExpressionNode result]
|
||||||
|
: expression EOF { $result = $expression.result; }
|
||||||
|
;
|
||||||
|
|
||||||
|
expression returns [LoxExpressionNode result]
|
||||||
|
: literal { $result = $literal.result; }
|
||||||
|
| left=expression op=( '*' | '/' ) right=expression { $result = factory.createBinaryNode($op, $left.result, $right.result); }
|
||||||
|
| left=expression op=( '+' | '-' ) right=expression { $result = factory.createBinaryNode($op, $left.result, $right.result); }
|
||||||
|
;
|
||||||
|
|
||||||
|
literal returns [LoxExpressionNode result]
|
||||||
|
: NUMBER { $result = factory.createNumberLiteral($NUMBER); }
|
||||||
|
;
|
||||||
|
|
||||||
|
AND: 'and' ;
|
||||||
|
CLASS: 'class' ;
|
||||||
|
ELSE: 'else' ;
|
||||||
|
FALSE: 'false' ;
|
||||||
|
FOR: 'for' ;
|
||||||
|
FUN: 'fun' ;
|
||||||
|
IF: 'if' ;
|
||||||
|
NIL: 'nil' ;
|
||||||
|
OR: 'or' ;
|
||||||
|
PRINT: 'print' ;
|
||||||
|
RETURN: 'return' ;
|
||||||
|
SUPER: 'super' ;
|
||||||
|
THIS: 'this' ;
|
||||||
|
TRUE: 'true' ;
|
||||||
|
VAR: 'var' ;
|
||||||
|
WHILE: 'while';
|
||||||
|
|
||||||
|
LESS: '<' ;
|
||||||
|
LESS_EQUAL: '<=';
|
||||||
|
GREATER: '>' ;
|
||||||
|
GREATER_EQUAL: '>=' ;
|
||||||
|
BANG: '!' ;
|
||||||
|
BANG_EQUAL: '!=' ;
|
||||||
|
EQUAL: '=' ;
|
||||||
|
EQUAL_EQUAL: '==' ;
|
||||||
|
|
||||||
|
NUMBER
|
||||||
|
: DIGIT+ ('.' DIGIT+)?
|
||||||
|
;
|
||||||
|
|
||||||
|
STRING
|
||||||
|
: '"' ~["]* '"'
|
||||||
|
;
|
||||||
|
|
||||||
|
IDENTIFIER
|
||||||
|
: LETTER ( LETTER | DIGIT | UNDERSCORE )*
|
||||||
|
;
|
||||||
|
|
||||||
|
fragment LETTER
|
||||||
|
: [a-zA-Z]
|
||||||
|
;
|
||||||
|
|
||||||
|
fragment DIGIT
|
||||||
|
: [0-9]
|
||||||
|
;
|
||||||
|
|
||||||
|
fragment UNDERSCORE
|
||||||
|
: '_'
|
||||||
|
;
|
||||||
|
|
||||||
|
WS
|
||||||
|
: [ \t\r\n]+ -> skip
|
||||||
|
;
|
||||||
@@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>xyz.ctsk.lox</groupId>
|
<groupId>xyz.ctsk.lox</groupId>
|
||||||
<artifactId>lox</artifactId>
|
<artifactId>jlox</artifactId>
|
||||||
<version>1.0-SNAPSHOT</version>
|
<version>1.0-SNAPSHOT</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user