mirror of
				https://github.com/GayPizzaSpecifications/pork.git
				synced 2025-11-04 09:59:39 +00:00 
			
		
		
		
	An actual command line tool to run pork programs.
This commit is contained in:
		
							
								
								
									
										39
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										39
									
								
								README.md
									
									
									
									
									
								
							@ -5,28 +5,21 @@ A small BBQ language.
 | 
				
			|||||||
Very WIP. Like VERY.
 | 
					Very WIP. Like VERY.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
```pork
 | 
					```pork
 | 
				
			||||||
main = {
 | 
					/* fibonacci sequence */
 | 
				
			||||||
  three = 3
 | 
					fib = { n in
 | 
				
			||||||
  two = 2
 | 
					  if n == 0
 | 
				
			||||||
  calculateSimple = {
 | 
					    then 0
 | 
				
			||||||
    (50 + three) * two
 | 
					  else if n == 1
 | 
				
			||||||
  }
 | 
					    then 1
 | 
				
			||||||
  calculateComplex = {
 | 
					  else fib(n - 1) + fib(n - 2)
 | 
				
			||||||
    three + two + 50
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  calculateSimpleResult = calculateSimple()
 | 
					 | 
				
			||||||
  calculateComplexResult = calculateComplex()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  list = [10, 20, 30]
 | 
					 | 
				
			||||||
  trueValue = true
 | 
					 | 
				
			||||||
  falseValue = false
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  [
 | 
					 | 
				
			||||||
    calculateSimpleResult,
 | 
					 | 
				
			||||||
    calculateComplexResult,
 | 
					 | 
				
			||||||
    list,
 | 
					 | 
				
			||||||
    trueValue,
 | 
					 | 
				
			||||||
    falseValue
 | 
					 | 
				
			||||||
  ]
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					result = fib(20)
 | 
				
			||||||
 | 
					println(result)
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Usage
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					./gradlew -q run --args 'run examples/fib.pork'
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
 | 
				
			|||||||
@ -23,6 +23,7 @@ java {
 | 
				
			|||||||
dependencies {
 | 
					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")
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
tasks.withType<KotlinCompile> {
 | 
					tasks.withType<KotlinCompile> {
 | 
				
			||||||
@ -34,15 +35,17 @@ tasks.withType<Wrapper> {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
application {
 | 
					application {
 | 
				
			||||||
  mainClass.set("gay.pizza.pork.MainKt")
 | 
					  mainClass.set("gay.pizza.pork.cli.MainKt")
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
graalvmNative {
 | 
					graalvmNative {
 | 
				
			||||||
  binaries {
 | 
					  binaries {
 | 
				
			||||||
    named("main") {
 | 
					    named("main") {
 | 
				
			||||||
      imageName.set("pork")
 | 
					      imageName.set("pork")
 | 
				
			||||||
      mainClass.set("gay.pizza.pork.MainKt")
 | 
					      mainClass.set("gay.pizza.pork.cli.MainKt")
 | 
				
			||||||
      sharedLibrary.set(false)
 | 
					      sharedLibrary.set(false)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					tasks.run.get().outputs.upToDateWhen { false }
 | 
				
			||||||
 | 
				
			|||||||
@ -7,4 +7,5 @@ fib = { n in
 | 
				
			|||||||
  else fib(n - 1) + fib(n - 2)
 | 
					  else fib(n - 1) + fib(n - 2)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
main = { in fib(20) }
 | 
					result = fib(20)
 | 
				
			||||||
 | 
					println(result)
 | 
				
			||||||
 | 
				
			|||||||
@ -1,7 +0,0 @@
 | 
				
			|||||||
check = { value in
 | 
					 | 
				
			||||||
  if value then 50
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
main = { in
 | 
					 | 
				
			||||||
  value = check(100)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@ -1,42 +1,40 @@
 | 
				
			|||||||
/* main function */
 | 
					three = 3
 | 
				
			||||||
main = { in
 | 
					two = 2
 | 
				
			||||||
  three = 3
 | 
					 | 
				
			||||||
  two = 2
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  calculateSimple = { in
 | 
					calculateSimple = { in
 | 
				
			||||||
  (50 + three) * two
 | 
					  (50 + three) * two
 | 
				
			||||||
  }
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  calculateComplex = { in
 | 
					calculateComplex = { in
 | 
				
			||||||
  three + two + 50
 | 
					  three + two + 50
 | 
				
			||||||
  }
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  multiply = { a, b in
 | 
					multiply = { a, b in
 | 
				
			||||||
  a * b
 | 
					  a * b
 | 
				
			||||||
  }
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // calculates the result
 | 
					// calculates the result
 | 
				
			||||||
  calculateSimpleResult = calculateSimple()
 | 
					calculateSimpleResult = calculateSimple()
 | 
				
			||||||
  calculateComplexResult = calculateComplex()
 | 
					calculateComplexResult = calculateComplex()
 | 
				
			||||||
  multiplyResult = multiply(50, 50)
 | 
					multiplyResult = multiply(50, 50)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  list = [10, 20, 30]
 | 
					list = [10, 20, 30]
 | 
				
			||||||
  trueValue = true
 | 
					trueValue = true
 | 
				
			||||||
  falseValue = false
 | 
					falseValue = false
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  invert = { value in
 | 
					invert = { value in
 | 
				
			||||||
  !value
 | 
					  !value
 | 
				
			||||||
  }
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  notEqual = { a, b in
 | 
					notEqual = { a, b in
 | 
				
			||||||
  a != b
 | 
					  a != b
 | 
				
			||||||
  }
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  equal = { a, b in
 | 
					equal = { a, b in
 | 
				
			||||||
  a == b
 | 
					  a == b
 | 
				
			||||||
  }
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  [
 | 
					results = [
 | 
				
			||||||
  calculateSimpleResult,
 | 
					  calculateSimpleResult,
 | 
				
			||||||
  calculateComplexResult,
 | 
					  calculateComplexResult,
 | 
				
			||||||
  multiplyResult,
 | 
					  multiplyResult,
 | 
				
			||||||
@ -49,5 +47,6 @@ main = { in
 | 
				
			|||||||
  equal(5, 6),
 | 
					  equal(5, 6),
 | 
				
			||||||
  notEqual(5, 5),
 | 
					  notEqual(5, 5),
 | 
				
			||||||
  notEqual(5, 6)
 | 
					  notEqual(5, 6)
 | 
				
			||||||
  ]
 | 
					]
 | 
				
			||||||
}
 | 
					
 | 
				
			||||||
 | 
					println(results)
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										23
									
								
								src/main/kotlin/gay/pizza/pork/cli/GenerateKotlinCommand.kt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								src/main/kotlin/gay/pizza/pork/cli/GenerateKotlinCommand.kt
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,23 @@
 | 
				
			|||||||
 | 
					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.compiler.KotlinCompiler
 | 
				
			||||||
 | 
					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 kotlin.io.path.readText
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class GenerateKotlinCommand : CliktCommand(help = "Generate Kotlin Code", name = "generate-kotlin") {
 | 
				
			||||||
 | 
					  val path by argument("file").path(mustExist = true, canBeDir = false)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  override fun run() {
 | 
				
			||||||
 | 
					    val content = path.readText()
 | 
				
			||||||
 | 
					    val tokenStream = PorkTokenizer(StringCharSource(content)).tokenize()
 | 
				
			||||||
 | 
					    val program = PorkParser(TokenStreamSource(tokenStream)).readProgram()
 | 
				
			||||||
 | 
					    val compiler = KotlinCompiler()
 | 
				
			||||||
 | 
					    println(compiler.visit(program))
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										21
									
								
								src/main/kotlin/gay/pizza/pork/cli/HighlightCommand.kt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								src/main/kotlin/gay/pizza/pork/cli/HighlightCommand.kt
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,21 @@
 | 
				
			|||||||
 | 
					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.parse.AnsiHighlightScheme
 | 
				
			||||||
 | 
					import gay.pizza.pork.parse.Highlighter
 | 
				
			||||||
 | 
					import gay.pizza.pork.parse.PorkTokenizer
 | 
				
			||||||
 | 
					import gay.pizza.pork.parse.StringCharSource
 | 
				
			||||||
 | 
					import kotlin.io.path.readText
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class HighlightCommand : CliktCommand(help = "Syntax Highlighter", name = "highlight") {
 | 
				
			||||||
 | 
					  val path by argument("file").path(mustExist = true, canBeDir = false)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  override fun run() {
 | 
				
			||||||
 | 
					    val content = path.readText()
 | 
				
			||||||
 | 
					    val tokenStream = PorkTokenizer(StringCharSource(content)).tokenize()
 | 
				
			||||||
 | 
					    val highlighter = Highlighter(AnsiHighlightScheme())
 | 
				
			||||||
 | 
					    print(highlighter.highlight(tokenStream).joinToString(""))
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										20
									
								
								src/main/kotlin/gay/pizza/pork/cli/RootCommand.kt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								src/main/kotlin/gay/pizza/pork/cli/RootCommand.kt
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,20 @@
 | 
				
			|||||||
 | 
					package gay.pizza.pork.cli
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import com.github.ajalt.clikt.core.CliktCommand
 | 
				
			||||||
 | 
					import com.github.ajalt.clikt.core.subcommands
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class RootCommand : CliktCommand(
 | 
				
			||||||
 | 
					  help = "Pork - The BBQ Language",
 | 
				
			||||||
 | 
					  name = "pork"
 | 
				
			||||||
 | 
					) {
 | 
				
			||||||
 | 
					  init {
 | 
				
			||||||
 | 
					    subcommands(
 | 
				
			||||||
 | 
					      RunCommand(),
 | 
				
			||||||
 | 
					      HighlightCommand(),
 | 
				
			||||||
 | 
					      TokenizeCommand(),
 | 
				
			||||||
 | 
					      GenerateKotlinCommand()
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  override fun run() {}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										32
									
								
								src/main/kotlin/gay/pizza/pork/cli/RunCommand.kt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								src/main/kotlin/gay/pizza/pork/cli/RunCommand.kt
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,32 @@
 | 
				
			|||||||
 | 
					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.eval.CallableFunction
 | 
				
			||||||
 | 
					import gay.pizza.pork.eval.PorkEvaluator
 | 
				
			||||||
 | 
					import gay.pizza.pork.eval.Scope
 | 
				
			||||||
 | 
					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 kotlin.io.path.readText
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class RunCommand : CliktCommand(help = "Run Program", name = "run") {
 | 
				
			||||||
 | 
					  val path by argument("file").path(mustExist = true, canBeDir = false)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  override fun run() {
 | 
				
			||||||
 | 
					    val content = path.readText()
 | 
				
			||||||
 | 
					    val tokenStream = PorkTokenizer(StringCharSource(content)).tokenize()
 | 
				
			||||||
 | 
					    val program = PorkParser(TokenStreamSource(tokenStream)).readProgram()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    val scope = Scope()
 | 
				
			||||||
 | 
					    scope.define("println", CallableFunction { arguments ->
 | 
				
			||||||
 | 
					      for (argument in arguments.values) {
 | 
				
			||||||
 | 
					        println(argument)
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    })
 | 
				
			||||||
 | 
					    val evaluator = PorkEvaluator(scope)
 | 
				
			||||||
 | 
					    evaluator.visit(program)
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										25
									
								
								src/main/kotlin/gay/pizza/pork/cli/TokenizeCommand.kt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								src/main/kotlin/gay/pizza/pork/cli/TokenizeCommand.kt
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,25 @@
 | 
				
			|||||||
 | 
					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.parse.PorkTokenizer
 | 
				
			||||||
 | 
					import gay.pizza.pork.parse.StringCharSource
 | 
				
			||||||
 | 
					import kotlin.io.path.readText
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class TokenizeCommand : CliktCommand(help = "Tokenize Program", name = "tokenize") {
 | 
				
			||||||
 | 
					  val path by argument("file").path(mustExist = true, canBeDir = false)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  override fun run() {
 | 
				
			||||||
 | 
					    val content = path.readText()
 | 
				
			||||||
 | 
					    val tokenStream = PorkTokenizer(StringCharSource(content)).tokenize()
 | 
				
			||||||
 | 
					    for (token in tokenStream.tokens) {
 | 
				
			||||||
 | 
					      println("${token.start} ${token.type.name} '${sanitize(token.text)}'")
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  private fun sanitize(input: String): String =
 | 
				
			||||||
 | 
					    input
 | 
				
			||||||
 | 
					      .replace("\n", "\\n")
 | 
				
			||||||
 | 
					      .replace("\r", "\\r")
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										3
									
								
								src/main/kotlin/gay/pizza/pork/cli/main.kt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								src/main/kotlin/gay/pizza/pork/cli/main.kt
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,3 @@
 | 
				
			|||||||
 | 
					package gay.pizza.pork.cli
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					fun main(args: Array<String>) = RootCommand().main(args)
 | 
				
			||||||
@ -1,65 +0,0 @@
 | 
				
			|||||||
package gay.pizza.pork
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import gay.pizza.pork.ast.Printer
 | 
					 | 
				
			||||||
import gay.pizza.pork.ast.nodes.Program
 | 
					 | 
				
			||||||
import gay.pizza.pork.eval.Arguments
 | 
					 | 
				
			||||||
import gay.pizza.pork.eval.PorkEvaluator
 | 
					 | 
				
			||||||
import gay.pizza.pork.eval.Scope
 | 
					 | 
				
			||||||
import gay.pizza.pork.parse.*
 | 
					 | 
				
			||||||
import kotlin.io.path.Path
 | 
					 | 
				
			||||||
import kotlin.io.path.readText
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
fun eval(ast: Program) {
 | 
					 | 
				
			||||||
  val scope = Scope()
 | 
					 | 
				
			||||||
  val evaluator = PorkEvaluator(scope)
 | 
					 | 
				
			||||||
  evaluator.visit(ast)
 | 
					 | 
				
			||||||
  println("> ${scope.call("main", Arguments.Zero)}")
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
fun validateTokenSoundness(input: String, stream: TokenStream) {
 | 
					 | 
				
			||||||
  var expectedIndex = 0
 | 
					 | 
				
			||||||
  for (token in stream.tokens) {
 | 
					 | 
				
			||||||
    if (token.start != expectedIndex) {
 | 
					 | 
				
			||||||
      throw RuntimeException("Expected token to be at index $expectedIndex but was ${token.start}")
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    val slice = input.slice(token.start until token.start + token.text.length)
 | 
					 | 
				
			||||||
    if (slice != token.text) {
 | 
					 | 
				
			||||||
      throw RuntimeException(
 | 
					 | 
				
			||||||
        "Expected index ${token.start} for length ${token.text.length} to" +
 | 
					 | 
				
			||||||
        " equal '${token.text}' but was '$slice'")
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    expectedIndex += token.text.length
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
fun main(args: Array<String>) {
 | 
					 | 
				
			||||||
  val code = Path(args[0]).readText()
 | 
					 | 
				
			||||||
  val stream = tokenize(code)
 | 
					 | 
				
			||||||
  println(stream.tokens.joinToString("\n"))
 | 
					 | 
				
			||||||
  val program = parse(stream)
 | 
					 | 
				
			||||||
  eval(program)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  val exactCode = stream.tokens.joinToString("") { it.text }
 | 
					 | 
				
			||||||
  validateTokenSoundness(code, stream)
 | 
					 | 
				
			||||||
  if (exactCode != code) {
 | 
					 | 
				
			||||||
    throw RuntimeException("Token reconstruction didn't succeed.")
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  val generated = buildString { Printer(this).visit(program) }
 | 
					 | 
				
			||||||
  val parsedAst = parse(tokenize(generated))
 | 
					 | 
				
			||||||
  parse(tokenize(generated))
 | 
					 | 
				
			||||||
  println(generated)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  if (program != parsedAst) {
 | 
					 | 
				
			||||||
    throw RuntimeException("Equality of parsed AST from printer was not proven.")
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  val highlighter = Highlighter(AnsiHighlightScheme())
 | 
					 | 
				
			||||||
  println(highlighter.highlight(stream).joinToString(""))
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
fun tokenize(input: String): TokenStream =
 | 
					 | 
				
			||||||
  PorkTokenizer(StringCharSource(input)).tokenize()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
fun parse(stream: TokenStream): Program =
 | 
					 | 
				
			||||||
  PorkParser(TokenStreamSource(stream)).readProgram()
 | 
					 | 
				
			||||||
@ -108,7 +108,9 @@ class PorkParser(source: PeekableSource<Token>) {
 | 
				
			|||||||
      }
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      else -> {
 | 
					      else -> {
 | 
				
			||||||
        throw RuntimeException("Failed to parse token: ${token.type} '${token.text}' as expression")
 | 
					        throw RuntimeException(
 | 
				
			||||||
 | 
					          "Failed to parse token: ${token.type} '${token.text}' as expression" +
 | 
				
			||||||
 | 
					          " (index ${unsanitizedSource.currentIndex})")
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user