language: floating point support

This commit is contained in:
2023-09-09 00:08:30 -04:00
parent bf474f6b69
commit e8766323ee
19 changed files with 187 additions and 39 deletions

View File

@ -5,8 +5,14 @@ import gay.pizza.pork.ast.*
class Parser(source: PeekableSource<Token>, val attribution: NodeAttribution) {
private val unsanitizedSource = source
private fun readIntLiteral(): IntLiteral = within {
expect(TokenType.IntLiteral) { IntLiteral(it.text.toInt()) }
private fun readNumberLiteral(): Expression = within {
expect(TokenType.NumberLiteral) {
if (it.text.contains(".")) {
DoubleLiteral(it.text.toDouble())
} else {
IntegerLiteral(it.text.toInt())
}
}
}
private fun readStringLiteral(): StringLiteral = within {
@ -97,8 +103,8 @@ class Parser(source: PeekableSource<Token>, val attribution: NodeAttribution) {
fun readExpression(): Expression {
val token = peek()
val expression = when (token.type) {
TokenType.IntLiteral -> {
readIntLiteral()
TokenType.NumberLiteral -> {
readNumberLiteral()
}
TokenType.StringLiteral -> {

View File

@ -20,7 +20,11 @@ class Printer(buffer: StringBuilder) : NodeVisitor<Unit> {
autoIndentState = true
}
override fun visitIntLiteral(node: IntLiteral) {
override fun visitIntegerLiteral(node: IntegerLiteral) {
append(node.value.toString())
}
override fun visitDoubleLiteral(node: DoubleLiteral) {
append(node.value.toString())
}

View File

@ -4,8 +4,13 @@ import gay.pizza.pork.parser.TokenTypeProperty.*
import gay.pizza.pork.parser.TokenFamily.*
enum class TokenType(vararg properties: TokenTypeProperty) {
Symbol(SymbolFamily, CharConsumer { (it in 'a'..'z') || (it in 'A'..'Z') || it == '_' }, KeywordUpgrader),
IntLiteral(NumericLiteralFamily, CharConsumer { it in '0'..'9' }),
NumberLiteral(NumericLiteralFamily, CharIndexConsumer { it, index ->
(it in '0'..'9') || (index > 0 && it == '.') }),
Symbol(SymbolFamily, CharConsumer {
(it in 'a'..'z') ||
(it in 'A'..'Z') ||
(it == '_') ||
(it in '0' .. '9')}, KeywordUpgrader),
StringLiteral(StringLiteralFamily),
Equality(OperatorFamily),
Inequality(OperatorFamily),
@ -40,17 +45,24 @@ enum class TokenType(vararg properties: TokenTypeProperty) {
LineComment(CommentFamily),
EndOfFile;
val promotions: List<Promotion> = properties.filterIsInstance<Promotion>()
val keyword: Keyword? = properties.filterIsInstance<Keyword>().singleOrNull()
val singleChar: SingleChar? = properties.filterIsInstance<SingleChar>().singleOrNull()
val promotions: List<Promotion> =
properties.filterIsInstance<Promotion>()
val keyword: Keyword? =
properties.filterIsInstance<Keyword>().singleOrNull()
val singleChar: SingleChar? =
properties.filterIsInstance<SingleChar>().singleOrNull()
val family: TokenFamily =
properties.filterIsInstance<TokenFamily>().singleOrNull() ?: OtherFamily
val charConsumer: CharConsumer? = properties.filterIsInstance<CharConsumer>().singleOrNull()
val tokenUpgrader: TokenUpgrader? = properties.filterIsInstance<TokenUpgrader>().singleOrNull()
val charIndexConsumer: CharIndexConsumer? =
properties.filterIsInstance<CharIndexConsumer>().singleOrNull()
val tokenUpgrader: TokenUpgrader? =
properties.filterIsInstance<TokenUpgrader>().singleOrNull()
companion object {
val Keywords = entries.filter { item -> item.keyword != null }
val SingleChars = entries.filter { item -> item.singleChar != null }
val CharConsumers = entries.filter { item -> item.charConsumer != null }
val CharConsumers = entries.filter { item ->
item.charConsumer != null || item.charIndexConsumer != null }
}
}

View File

@ -5,6 +5,7 @@ interface TokenTypeProperty {
class Promotion(val nextChar: Char, val type: TokenType) : TokenTypeProperty
class Keyword(val text: String) : TokenTypeProperty
class CharConsumer(val isValid: (Char) -> Boolean) : TokenTypeProperty
class CharIndexConsumer(val isValid: (Char, Int) -> Boolean) : TokenTypeProperty
open class TokenUpgrader(val maybeUpgrade: (Token) -> Token?) : TokenTypeProperty
object KeywordUpgrader : TokenUpgrader({ token ->

View File

@ -90,15 +90,29 @@ class Tokenizer(val source: CharSource) {
return Token(type, tokenStart, text)
}
var index = 0
for (item in TokenType.CharConsumers) {
val consumer = item.charConsumer ?: continue
if (!consumer.isValid(char)) {
continue
if (item.charConsumer != null) {
if (!item.charConsumer.isValid(char)) {
continue
}
} else if (item.charIndexConsumer != null) {
if (!item.charIndexConsumer.isValid(char, index)) {
continue
}
} else {
throw RuntimeException("Unknown Char Consumer")
}
val text = buildString {
append(char)
while (consumer.isValid(source.peek())) {
while (
if (item.charConsumer != null)
item.charConsumer.isValid(source.peek())
else
item.charIndexConsumer!!.isValid(source.peek(), ++index)
) {
append(source.next())
}
}