mirror of
https://github.com/GayPizzaSpecifications/pork.git
synced 2025-08-03 05:10:55 +00:00
Implement AST serialization.
This commit is contained in:
parent
05cb52bc32
commit
4ec53e1209
@ -24,6 +24,7 @@ dependencies {
|
|||||||
implementation("org.jetbrains.kotlin:kotlin-bom")
|
implementation("org.jetbrains.kotlin:kotlin-bom")
|
||||||
implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8")
|
implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8")
|
||||||
implementation("com.github.ajalt.clikt:clikt:4.2.0")
|
implementation("com.github.ajalt.clikt:clikt:4.2.0")
|
||||||
|
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.6.0-RC")
|
||||||
}
|
}
|
||||||
|
|
||||||
tasks.withType<KotlinCompile> {
|
tasks.withType<KotlinCompile> {
|
||||||
|
@ -1,7 +1,11 @@
|
|||||||
package gay.pizza.pork.ast.nodes
|
package gay.pizza.pork.ast.nodes
|
||||||
|
|
||||||
import gay.pizza.pork.ast.NodeType
|
import gay.pizza.pork.ast.NodeType
|
||||||
|
import kotlinx.serialization.SerialName
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
@SerialName("booleanLiteral")
|
||||||
class BooleanLiteral(val value: Boolean) : Expression() {
|
class BooleanLiteral(val value: Boolean) : Expression() {
|
||||||
override val type: NodeType = NodeType.BooleanLiteral
|
override val type: NodeType = NodeType.BooleanLiteral
|
||||||
|
|
||||||
|
@ -2,7 +2,11 @@ package gay.pizza.pork.ast.nodes
|
|||||||
|
|
||||||
import gay.pizza.pork.ast.NodeType
|
import gay.pizza.pork.ast.NodeType
|
||||||
import gay.pizza.pork.ast.NodeVisitor
|
import gay.pizza.pork.ast.NodeVisitor
|
||||||
|
import kotlinx.serialization.SerialName
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
@SerialName("define")
|
||||||
class Define(val symbol: Symbol, val value: Expression) : Expression() {
|
class Define(val symbol: Symbol, val value: Expression) : Expression() {
|
||||||
override val type: NodeType = NodeType.Define
|
override val type: NodeType = NodeType.Define
|
||||||
|
|
||||||
|
@ -1,3 +1,6 @@
|
|||||||
package gay.pizza.pork.ast.nodes
|
package gay.pizza.pork.ast.nodes
|
||||||
|
|
||||||
abstract class Expression : Node()
|
import kotlinx.serialization.Serializable
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
sealed class Expression : Node()
|
||||||
|
@ -2,7 +2,11 @@ package gay.pizza.pork.ast.nodes
|
|||||||
|
|
||||||
import gay.pizza.pork.ast.NodeType
|
import gay.pizza.pork.ast.NodeType
|
||||||
import gay.pizza.pork.ast.NodeVisitor
|
import gay.pizza.pork.ast.NodeVisitor
|
||||||
|
import kotlinx.serialization.SerialName
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
@SerialName("functionCall")
|
||||||
class FunctionCall(val symbol: Symbol, val arguments: List<Expression>) : Expression() {
|
class FunctionCall(val symbol: Symbol, val arguments: List<Expression>) : Expression() {
|
||||||
override val type: NodeType = NodeType.FunctionCall
|
override val type: NodeType = NodeType.FunctionCall
|
||||||
|
|
||||||
@ -13,4 +17,11 @@ class FunctionCall(val symbol: Symbol, val arguments: List<Expression>) : Expres
|
|||||||
if (other !is FunctionCall) return false
|
if (other !is FunctionCall) return false
|
||||||
return other.symbol == symbol && other.arguments == arguments
|
return other.symbol == symbol && other.arguments == arguments
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun hashCode(): Int {
|
||||||
|
var result = symbol.hashCode()
|
||||||
|
result = 31 * result + arguments.hashCode()
|
||||||
|
result = 31 * result + type.hashCode()
|
||||||
|
return result
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,11 @@ package gay.pizza.pork.ast.nodes
|
|||||||
|
|
||||||
import gay.pizza.pork.ast.NodeType
|
import gay.pizza.pork.ast.NodeType
|
||||||
import gay.pizza.pork.ast.NodeVisitor
|
import gay.pizza.pork.ast.NodeVisitor
|
||||||
|
import kotlinx.serialization.SerialName
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
@SerialName("if")
|
||||||
class If(
|
class If(
|
||||||
val condition: Expression,
|
val condition: Expression,
|
||||||
val thenExpression: Expression,
|
val thenExpression: Expression,
|
||||||
|
@ -2,7 +2,11 @@ package gay.pizza.pork.ast.nodes
|
|||||||
|
|
||||||
import gay.pizza.pork.ast.NodeType
|
import gay.pizza.pork.ast.NodeType
|
||||||
import gay.pizza.pork.ast.NodeVisitor
|
import gay.pizza.pork.ast.NodeVisitor
|
||||||
|
import kotlinx.serialization.SerialName
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
@SerialName("infixOperation")
|
||||||
class InfixOperation(
|
class InfixOperation(
|
||||||
val left: Expression,
|
val left: Expression,
|
||||||
val op: InfixOperator,
|
val op: InfixOperator,
|
||||||
|
@ -1,5 +1,10 @@
|
|||||||
package gay.pizza.pork.ast.nodes
|
package gay.pizza.pork.ast.nodes
|
||||||
|
|
||||||
|
import kotlinx.serialization.SerialName
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
@SerialName("infixOperator")
|
||||||
enum class InfixOperator(val token: String) {
|
enum class InfixOperator(val token: String) {
|
||||||
Plus("+"),
|
Plus("+"),
|
||||||
Minus("-"),
|
Minus("-"),
|
||||||
|
@ -1,7 +1,11 @@
|
|||||||
package gay.pizza.pork.ast.nodes
|
package gay.pizza.pork.ast.nodes
|
||||||
|
|
||||||
import gay.pizza.pork.ast.NodeType
|
import gay.pizza.pork.ast.NodeType
|
||||||
|
import kotlinx.serialization.SerialName
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
@SerialName("intLiteral")
|
||||||
class IntLiteral(val value: Int) : Expression() {
|
class IntLiteral(val value: Int) : Expression() {
|
||||||
override val type: NodeType = NodeType.IntLiteral
|
override val type: NodeType = NodeType.IntLiteral
|
||||||
|
|
||||||
|
@ -2,7 +2,11 @@ package gay.pizza.pork.ast.nodes
|
|||||||
|
|
||||||
import gay.pizza.pork.ast.NodeType
|
import gay.pizza.pork.ast.NodeType
|
||||||
import gay.pizza.pork.ast.NodeVisitor
|
import gay.pizza.pork.ast.NodeVisitor
|
||||||
|
import kotlinx.serialization.SerialName
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
@SerialName("lambda")
|
||||||
class Lambda(val arguments: List<Symbol>, val expressions: List<Expression>) : Expression() {
|
class Lambda(val arguments: List<Symbol>, val expressions: List<Expression>) : Expression() {
|
||||||
override val type: NodeType = NodeType.Lambda
|
override val type: NodeType = NodeType.Lambda
|
||||||
|
|
||||||
|
@ -2,7 +2,11 @@ package gay.pizza.pork.ast.nodes
|
|||||||
|
|
||||||
import gay.pizza.pork.ast.NodeType
|
import gay.pizza.pork.ast.NodeType
|
||||||
import gay.pizza.pork.ast.NodeVisitor
|
import gay.pizza.pork.ast.NodeVisitor
|
||||||
|
import kotlinx.serialization.SerialName
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
@SerialName("listLiteral")
|
||||||
class ListLiteral(val items: List<Expression>) : Expression() {
|
class ListLiteral(val items: List<Expression>) : Expression() {
|
||||||
override val type: NodeType = NodeType.ListLiteral
|
override val type: NodeType = NodeType.ListLiteral
|
||||||
|
|
||||||
|
@ -3,8 +3,10 @@ package gay.pizza.pork.ast.nodes
|
|||||||
import gay.pizza.pork.ast.NodeType
|
import gay.pizza.pork.ast.NodeType
|
||||||
import gay.pizza.pork.ast.Printer
|
import gay.pizza.pork.ast.Printer
|
||||||
import gay.pizza.pork.ast.NodeVisitor
|
import gay.pizza.pork.ast.NodeVisitor
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
|
||||||
abstract class Node {
|
@Serializable
|
||||||
|
sealed class Node {
|
||||||
abstract val type: NodeType
|
abstract val type: NodeType
|
||||||
open fun <T> visitChildren(visitor: NodeVisitor<T>): List<T> = emptyList()
|
open fun <T> visitChildren(visitor: NodeVisitor<T>): List<T> = emptyList()
|
||||||
|
|
||||||
|
@ -2,7 +2,11 @@ package gay.pizza.pork.ast.nodes
|
|||||||
|
|
||||||
import gay.pizza.pork.ast.NodeType
|
import gay.pizza.pork.ast.NodeType
|
||||||
import gay.pizza.pork.ast.NodeVisitor
|
import gay.pizza.pork.ast.NodeVisitor
|
||||||
|
import kotlinx.serialization.SerialName
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
@SerialName("parentheses")
|
||||||
class Parentheses(val expression: Expression) : Expression() {
|
class Parentheses(val expression: Expression) : Expression() {
|
||||||
override val type: NodeType = NodeType.Parentheses
|
override val type: NodeType = NodeType.Parentheses
|
||||||
|
|
||||||
|
@ -2,7 +2,11 @@ package gay.pizza.pork.ast.nodes
|
|||||||
|
|
||||||
import gay.pizza.pork.ast.NodeType
|
import gay.pizza.pork.ast.NodeType
|
||||||
import gay.pizza.pork.ast.NodeVisitor
|
import gay.pizza.pork.ast.NodeVisitor
|
||||||
|
import kotlinx.serialization.SerialName
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
@SerialName("prefixOperation")
|
||||||
class PrefixOperation(val op: PrefixOperator, val expression: Expression) : Expression() {
|
class PrefixOperation(val op: PrefixOperator, val expression: Expression) : Expression() {
|
||||||
override val type: NodeType = NodeType.PrefixOperation
|
override val type: NodeType = NodeType.PrefixOperation
|
||||||
|
|
||||||
|
@ -1,5 +1,10 @@
|
|||||||
package gay.pizza.pork.ast.nodes
|
package gay.pizza.pork.ast.nodes
|
||||||
|
|
||||||
|
import kotlinx.serialization.SerialName
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
@SerialName("prefixOperator")
|
||||||
enum class PrefixOperator(val token: String) {
|
enum class PrefixOperator(val token: String) {
|
||||||
Negate("!")
|
Negate("!")
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,11 @@ package gay.pizza.pork.ast.nodes
|
|||||||
|
|
||||||
import gay.pizza.pork.ast.NodeType
|
import gay.pizza.pork.ast.NodeType
|
||||||
import gay.pizza.pork.ast.NodeVisitor
|
import gay.pizza.pork.ast.NodeVisitor
|
||||||
|
import kotlinx.serialization.SerialName
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
@SerialName("program")
|
||||||
class Program(val expressions: List<Expression>) : Node() {
|
class Program(val expressions: List<Expression>) : Node() {
|
||||||
override val type: NodeType = NodeType.Program
|
override val type: NodeType = NodeType.Program
|
||||||
|
|
||||||
|
@ -1,7 +1,11 @@
|
|||||||
package gay.pizza.pork.ast.nodes
|
package gay.pizza.pork.ast.nodes
|
||||||
|
|
||||||
import gay.pizza.pork.ast.NodeType
|
import gay.pizza.pork.ast.NodeType
|
||||||
|
import kotlinx.serialization.SerialName
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
@SerialName("symbol")
|
||||||
class Symbol(val id: String) : Node() {
|
class Symbol(val id: String) : Node() {
|
||||||
override val type: NodeType = NodeType.Symbol
|
override val type: NodeType = NodeType.Symbol
|
||||||
|
|
||||||
|
@ -2,7 +2,11 @@ package gay.pizza.pork.ast.nodes
|
|||||||
|
|
||||||
import gay.pizza.pork.ast.NodeType
|
import gay.pizza.pork.ast.NodeType
|
||||||
import gay.pizza.pork.ast.NodeVisitor
|
import gay.pizza.pork.ast.NodeVisitor
|
||||||
|
import kotlinx.serialization.SerialName
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
@SerialName("symbolReference")
|
||||||
class SymbolReference(val symbol: Symbol) : Expression() {
|
class SymbolReference(val symbol: Symbol) : Expression() {
|
||||||
override val type: NodeType = NodeType.SymbolReference
|
override val type: NodeType = NodeType.SymbolReference
|
||||||
|
|
||||||
|
31
src/main/kotlin/gay/pizza/pork/cli/AstCommand.kt
Normal file
31
src/main/kotlin/gay/pizza/pork/cli/AstCommand.kt
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
package gay.pizza.pork.cli
|
||||||
|
|
||||||
|
import com.github.ajalt.clikt.core.CliktCommand
|
||||||
|
import com.github.ajalt.clikt.parameters.arguments.argument
|
||||||
|
import com.github.ajalt.clikt.parameters.types.path
|
||||||
|
import gay.pizza.pork.ast.nodes.Node
|
||||||
|
import gay.pizza.pork.parse.PorkParser
|
||||||
|
import gay.pizza.pork.parse.PorkTokenizer
|
||||||
|
import gay.pizza.pork.parse.StringCharSource
|
||||||
|
import gay.pizza.pork.parse.TokenStreamSource
|
||||||
|
import kotlinx.serialization.ExperimentalSerializationApi
|
||||||
|
import kotlinx.serialization.json.Json
|
||||||
|
import kotlin.io.path.readText
|
||||||
|
|
||||||
|
@OptIn(ExperimentalSerializationApi::class)
|
||||||
|
class AstCommand : CliktCommand(help = "Print AST", name = "ast") {
|
||||||
|
val path by argument("file").path(mustExist = true, canBeDir = false)
|
||||||
|
|
||||||
|
private val json = Json {
|
||||||
|
prettyPrint = true
|
||||||
|
prettyPrintIndent = " "
|
||||||
|
classDiscriminator = "\$"
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun run() {
|
||||||
|
val content = path.readText()
|
||||||
|
val tokenStream = PorkTokenizer(StringCharSource(content)).tokenize()
|
||||||
|
val program = PorkParser(TokenStreamSource(tokenStream)).readProgram()
|
||||||
|
println(json.encodeToString(Node.serializer(), program))
|
||||||
|
}
|
||||||
|
}
|
@ -13,6 +13,7 @@ class RootCommand : CliktCommand(
|
|||||||
HighlightCommand(),
|
HighlightCommand(),
|
||||||
TokenizeCommand(),
|
TokenizeCommand(),
|
||||||
ReprintCommand(),
|
ReprintCommand(),
|
||||||
|
AstCommand(),
|
||||||
GenerateKotlinCommand()
|
GenerateKotlinCommand()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user