mirror of
https://github.com/GayPizzaSpecifications/pork.git
synced 2025-08-03 21:21:33 +00:00
language: floating point support
This commit is contained in:
@ -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 -> {
|
||||
|
@ -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())
|
||||
}
|
||||
|
||||
|
@ -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 }
|
||||
}
|
||||
}
|
||||
|
@ -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 ->
|
||||
|
@ -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())
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user