Skip to content

Commit

Permalink
parser: various code and quality enhancements
Browse files Browse the repository at this point in the history
  • Loading branch information
azenla committed Oct 8, 2023
1 parent fdac4fb commit 73a458b
Show file tree
Hide file tree
Showing 23 changed files with 316 additions and 193 deletions.
6 changes: 4 additions & 2 deletions ast/src/main/kotlin/gay/pizza/pork/ast/gen/NodeCoalescer.kt
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// GENERATED CODE FROM PORK AST CODEGEN
package gay.pizza.pork.ast.gen

class NodeCoalescer(val handler: (Node) -> Unit) : NodeVisitor<Unit> {
class NodeCoalescer(val followChildren: Boolean = true, val handler: (Node) -> Unit) : NodeVisitor<Unit> {
override fun visitArgumentSpec(node: ArgumentSpec): Unit =
handle(node)

Expand Down Expand Up @@ -97,6 +97,8 @@ class NodeCoalescer(val handler: (Node) -> Unit) : NodeVisitor<Unit> {

fun handle(node: Node) {
handler(node)
node.visitChildren(this)
if (followChildren) {
node.visitChildren(this)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,11 @@ class AstStandardCodegen(pkg: String, outputDirectory: Path, world: AstWorld) :
"NodeCoalescer",
inherits = mutableListOf("NodeVisitor<Unit>"),
members = mutableListOf(
KotlinMember(
"followChildren",
"Boolean",
value = "true"
),
KotlinMember(
"handler",
"(Node) -> Unit"
Expand Down Expand Up @@ -227,7 +232,9 @@ class AstStandardCodegen(pkg: String, outputDirectory: Path, world: AstWorld) :
)
)
handleFunction.body.add("handler(node)")
handleFunction.body.add("node.visitChildren(this)")
handleFunction.body.add("if (followChildren) {")
handleFunction.body.add(" node.visitChildren(this)")
handleFunction.body.add("}")
coalescerClass.functions.add(handleFunction)

write("NodeCoalescer.kt", KotlinWriter(coalescerClass))
Expand Down
16 changes: 16 additions & 0 deletions common/src/main/kotlin/gay/pizza/pork/common/IndentBuffer.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package gay.pizza.pork.common

class IndentBuffer(
val buffer: StringBuilder = StringBuilder(),
indent: String = " "
) : IndentTracked(indent), Appendable by buffer, CharSequence by buffer {
override fun emit(text: String) {
append(text)
}

override fun emitLine(text: String) {
appendLine(text)
}

override fun toString(): String = buffer.toString()
}
35 changes: 5 additions & 30 deletions common/src/main/kotlin/gay/pizza/pork/common/IndentPrinter.kt
Original file line number Diff line number Diff line change
@@ -1,36 +1,11 @@
package gay.pizza.pork.common

class IndentPrinter(
val buffer: StringBuilder = StringBuilder(),
val indent: String = " "
) : Appendable by buffer, CharSequence by buffer {
private var indentLevel: Int = 0
private var indentLevelText: String = ""

fun emitIndent() {
append(indentLevelText)
}

fun emitIndentedLine(line: String) {
emitIndent()
appendLine(line)
}

fun increaseIndent() {
indentLevel++
indentLevelText += indent
}

fun decreaseIndent() {
indentLevel--
indentLevelText = indent.repeat(indentLevel)
class IndentPrinter(indent: String = " ") : IndentTracked(indent) {
override fun emit(text: String) {
print(text)
}

inline fun indented(block: IndentPrinter.() -> Unit) {
increaseIndent()
block(this)
decreaseIndent()
override fun emitLine(text: String) {
println(text)
}

override fun toString(): String = buffer.toString()
}
37 changes: 37 additions & 0 deletions common/src/main/kotlin/gay/pizza/pork/common/IndentTracked.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package gay.pizza.pork.common

abstract class IndentTracked(val indent: String) {
private var internalIndentLevel = 0
private var indentLevelText = ""

val indentLevel: Int
get() = internalIndentLevel

fun emitIndent() {
emit(indentLevelText)
}

fun emitIndentedLine(line: String) {
emitIndent()
emitLine(line)
}

fun increaseIndent() {
internalIndentLevel++
indentLevelText += indent
}

fun decreaseIndent() {
internalIndentLevel--
indentLevelText = indent.repeat(indentLevel)
}

inline fun indented(block: IndentTracked.() -> Unit) {
increaseIndent()
block(this)
decreaseIndent()
}

abstract fun emit(text: String)
abstract fun emitLine(text: String)
}
Original file line number Diff line number Diff line change
Expand Up @@ -337,7 +337,6 @@ class EvaluationVisitor(root: Scope, val stack: CallStack) : NodeVisitor<Any> {
InfixOperator.Minus -> subtract(convert(left), convert(right))
InfixOperator.Multiply -> multiply(convert(left), convert(right))
InfixOperator.Divide -> divide(convert(left), convert(right))
InfixOperator.Equals, InfixOperator.NotEquals, InfixOperator.BooleanAnd, InfixOperator.BooleanOr -> throw RuntimeException("Unable to handle operation $op")
InfixOperator.BinaryAnd -> binaryAnd(convert(left), convert(right))
InfixOperator.BinaryOr -> binaryOr(convert(left), convert(right))
InfixOperator.BinaryExclusiveOr -> binaryExclusiveOr(convert(left), convert(right))
Expand All @@ -347,6 +346,8 @@ class EvaluationVisitor(root: Scope, val stack: CallStack) : NodeVisitor<Any> {
InfixOperator.Greater -> greater(convert(left), convert(right))
InfixOperator.LesserEqual -> lesserEqual(convert(left), convert(right))
InfixOperator.GreaterEqual -> greaterEqual(convert(left), convert(right))
InfixOperator.Equals, InfixOperator.NotEquals, InfixOperator.BooleanAnd, InfixOperator.BooleanOr ->
throw RuntimeException("Unable to handle operation $op")
}
}

Expand Down
5 changes: 5 additions & 0 deletions parser/src/main/kotlin/gay/pizza/pork/parser/CharConsumer.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package gay.pizza.pork.parser

interface CharConsumer {
fun consume(type: TokenType, tokenizer: Tokenizer): String?
}
4 changes: 3 additions & 1 deletion parser/src/main/kotlin/gay/pizza/pork/parser/CharSource.kt
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
package gay.pizza.pork.parser

interface CharSource : PeekableSource<Char> {
fun peek(index: Int): Char

companion object {
@Suppress("ConstPropertyName")
const val NullChar = 0.toChar()
const val EndOfFile = 0.toChar()
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package gay.pizza.pork.parser

fun CharSource.readToString(): String = buildString {
while (peek() != CharSource.NullChar) {
while (peek() != CharSource.EndOfFile) {
append(next())
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package gay.pizza.pork.parser

@Suppress("CanBeParameter")
class MatchedCharConsumer(
val start: CharSequence,
val end: CharSequence,
vararg val options: Options
) : CharConsumer {
private val eofTerminationAllowed = options.contains(Options.AllowEofTermination)

override fun consume(type: TokenType, tokenizer: Tokenizer): String? {
if (!tokenizer.peek(start)) {
return null
}
val buffer = StringBuilder()
tokenizer.read(start.length, buffer)
var endsNeededToTerminate = 1
while (true) {
if (tokenizer.peek(start)) {
endsNeededToTerminate++
tokenizer.read(start.length, buffer)
continue
}

if (tokenizer.peek(end)) {
endsNeededToTerminate--
tokenizer.read(end.length, buffer)
}

if (endsNeededToTerminate == 0) {
return buffer.toString()
}

val char = tokenizer.source.next()
if (char == CharSource.EndOfFile) {
if (eofTerminationAllowed) {
return buffer.toString()
}
throw UnterminatedTokenError(type.name, tokenizer.source.currentSourceIndex())
}
buffer.append(char)
}
}

enum class Options {
AllowEofTermination
}
}
Loading

0 comments on commit 73a458b

Please sign in to comment.