-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 0cb711e
Showing
77 changed files
with
2,892 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
/.vscode |
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
[kimura](https://script.meg.tokyo/) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
package tokyo.meg.script | ||
|
||
import java.io.IOException | ||
|
||
import scala.util._ | ||
import scala.util.chaining._ | ||
|
||
import tokyo.meg.script.io._ | ||
import tokyo.meg.script.util._ | ||
import tokyo.meg.script.lexer._ | ||
import tokyo.meg.script.parser._ | ||
import tokyo.meg.script.treewalker._ | ||
import tokyo.meg.script.treewalker.values._ | ||
|
||
@main def main(args: String*): Unit = | ||
val path = if (args.length == 0) None else Some(args(0)) | ||
|
||
val reader = path match | ||
case Some(path) => FileReader.open[Value](path) | ||
case None => Reader.open[Value](System.in) | ||
|
||
reader: reader => | ||
val cursor = Cursor(reader) | ||
val lexer = Lexer(cursor) | ||
val parser = Parser(lexer) | ||
val ast = parser.parse() | ||
val treeWalker = TreeWalker((ast, ".")) | ||
|
||
treeWalker.eval() | ||
match { | ||
case Failure(exception: IOException) => | ||
System.err.println( | ||
path match | ||
case Some(path) => | ||
s"An error occurred while processing the file \"$path\": ${exception.getMessage()}" | ||
|
||
case _ => | ||
s"An error occurred while processing the input: ${exception.getMessage()}" | ||
) | ||
|
||
1 | ||
|
||
case Failure(exception: Throwable) => | ||
System.err.println(exception) | ||
System.err.println( | ||
s"An unexpected error occurred: ${exception.getMessage()}" | ||
) | ||
exception.printStackTrace() | ||
|
||
1 | ||
|
||
case Success(value) => | ||
value match | ||
case IntValue(value) => value.toInt | ||
case RealValue(value) => value.toInt | ||
case _ => 0 | ||
|
||
} pipe System.exit |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
package tokyo.meg.script.io | ||
|
||
import java.io.{ | ||
BufferedReader, | ||
File, | ||
FileReader => JavaFileReader, | ||
InputStreamReader, | ||
FileInputStream | ||
} | ||
import java.nio.file.Paths | ||
|
||
import scala.util._ | ||
import scala.util.chaining._ | ||
|
||
object FileReader: | ||
def open[T](path: String): (FileReader => T) => Try[T] = | ||
Reader.open(() => FileReader(path)) | ||
|
||
final class FileReader(val path: String) extends Reader(FileInputStream(path)): | ||
val file = File(path) | ||
val parentPath = Paths | ||
.get(file.getAbsolutePath()) | ||
.normalize() | ||
.getParent() | ||
.toString() | ||
.replaceAll("\\\\", "/") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
package tokyo.meg.script.io | ||
|
||
import java.io.{BufferedReader, InputStream, InputStreamReader} | ||
import java.nio.file.Paths | ||
|
||
import scala.collection.mutable._ | ||
import scala.util._ | ||
import scala.util.chaining._ | ||
|
||
object Reader: | ||
def open[T](stream: InputStream): (Reader => T) => Try[T] = | ||
open(() => Reader(stream)) | ||
|
||
def open[T, U <: Reader](readerGenerator: () => U)(f: U => T): Try[T] = | ||
var reader: Option[U] = None | ||
|
||
Try: | ||
reader = Some(readerGenerator()) | ||
f(reader.get) | ||
.tap: _ => | ||
reader match | ||
case Some(reader) => reader.close() | ||
case None => () | ||
|
||
class Reader(val stream: InputStream): | ||
private val reader = BufferedReader(InputStreamReader(stream, "UTF-8")) | ||
private val joined = Stack[Reader]() | ||
|
||
def readLine(): Option[String] = | ||
if joined.length == 0 then | ||
reader.readLine() match | ||
case null => None | ||
case line => Some(line) | ||
else | ||
joined.top.readLine() match | ||
case None => | ||
joined.pop() | ||
readLine() | ||
|
||
case Some(line) => Some(line) | ||
|
||
def join: Reader => Reader = | ||
joined.push(_).pipe(_ => this) | ||
|
||
def close(): Unit = | ||
reader.close() | ||
joined.foreach(_.close()) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
package tokyo.meg.script.io | ||
|
||
import java.io.ByteArrayInputStream | ||
|
||
import scala.util._ | ||
import scala.util.chaining._ | ||
|
||
object StringReader: | ||
def open[T](string: String): (StringReader => T) => Try[T] = | ||
Reader.open(() => StringReader(string)) | ||
|
||
final class StringReader(val string: String) | ||
extends Reader(ByteArrayInputStream(string.getBytes("UTF-8"))) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
package tokyo.meg.script.lexer | ||
|
||
import scala.util.chaining._ | ||
|
||
import tokyo.meg.script.io._ | ||
|
||
final class Cursor(private val reader: Reader) extends Iterator[Char]: | ||
val parentPath = reader match | ||
case reader: FileReader => reader.parentPath | ||
case _ => "." | ||
|
||
private var _currentLine: Option[String] = Some("") | ||
private var _atEof = false | ||
private var (_line, _column) = (0, 1) | ||
private var (_currentChar, _nextChar) = ('\n', '\n') | ||
|
||
advance() | ||
|
||
override inline def hasNext: Boolean = | ||
!atEof | ||
|
||
override inline def next(): Char = | ||
currentChar tap advance | ||
|
||
inline def currentLine: Option[String] = | ||
_currentLine | ||
|
||
inline def atEof: Boolean = | ||
_atEof | ||
|
||
inline def line: Int = | ||
_line | ||
|
||
inline def column: Int = | ||
_column | ||
|
||
inline def currentChar: Char = | ||
_currentChar | ||
|
||
inline def nextChar: Char = | ||
_nextChar | ||
|
||
def join: Reader => Cursor = | ||
reader.join(_).pipe(_ => this) | ||
|
||
@annotation.tailrec | ||
def advance[T](value: T = this): T = | ||
_currentChar = _nextChar | ||
|
||
currentLine match | ||
case None => | ||
_nextChar = '\u0000' | ||
_atEof = 0 < column | ||
_column += 1 | ||
|
||
value | ||
|
||
case Some(string) => | ||
if string.length == column - 1 | ||
then fetchLine().advance(value) | ||
else | ||
_nextChar = if (string.length == column) '\n' else string(column) | ||
_column += 1 | ||
|
||
value | ||
|
||
def insert(deleteCount: Int, string: String): Unit = | ||
currentLine match | ||
case Some(currentLine) => | ||
_currentLine = Some( | ||
currentLine.slice(0, column - deleteCount - 1) | ||
+ string | ||
+ currentLine.slice(column - 1, currentLine.length) | ||
) | ||
|
||
_column -= deleteCount - 1 | ||
_currentChar = _currentLine.get(column - 2) | ||
_nextChar = try _currentLine.get(column - 1) catch _ => '\n' | ||
|
||
case _ => () | ||
|
||
private def fetchLine[T](value: T = this): T = | ||
_currentLine = reader.readLine() | ||
_column = 0 | ||
|
||
currentLine match | ||
case Some(nextLine) => | ||
_line += 1 | ||
|
||
if nextLine.filter(_.isWhitespace) == nextLine | ||
then fetchLine(value) | ||
else value | ||
|
||
case _ => value |
Oops, something went wrong.