Skip to content

Commit

Permalink
feat: not committed works
Browse files Browse the repository at this point in the history
  • Loading branch information
RanolP committed Dec 5, 2023
1 parent 70719f8 commit a711e94
Show file tree
Hide file tree
Showing 11 changed files with 227 additions and 4 deletions.
2 changes: 2 additions & 0 deletions fumico-core/src/main/kotlin/io/typecraft/fumico/core/Ast.kt
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ sealed class Ast {

data class Lambda(val arguments: List<Token>, val body: Expression) : Expression()

data class If(val cond: Expression, val then: Expression, val otherwise: Expression?) : Expression()

data class Name(val token: Token) : Expression()

data class FunctionCall(val function: Expression, val argument: Expression) : Expression()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,4 +31,5 @@ fun FumicoEvaluationContext.evaluate(node: Ast.Child.Expression): FumicoEvaluate
is Ast.Child.Expression.Name -> evaluate(node)
is Ast.Child.Expression.Tuple -> evaluate(node)
is Ast.Child.Expression.Lambda -> evaluate(node)
is Ast.Child.Expression.If -> evaluate(node)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package io.typecraft.fumico.core.evaluator.expression

import io.typecraft.fumico.core.Ast
import io.typecraft.fumico.core.FumicoEvaluated
import io.typecraft.fumico.core.FumicoEvaluationContext


fun FumicoEvaluationContext.evaluate(node: Ast.Child.Expression.If): FumicoEvaluated {
TODO("boolean type should be implemented")
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package io.typecraft.fumico.core.parser

import io.typecraft.fumico.core.Ast
import io.typecraft.fumico.core.tokenizer.Token
import io.typecraft.parsecom.functions.mapResult
import io.typecraft.parsecom.functions.opt
import io.typecraft.parsecom.functions.preceded
import io.typecraft.parsecom.functions.tuple

val parseIf by lazy {
mapResult(
tuple(
token(Token.Kind.KeywordIf),
skipHorizontalSpaces,
::parseExpression,
skipHorizontalSpaces,
token(Token.Kind.PunctuationHyphenMinus),
token(Token.Kind.PunctuationGreaterThanSign),
skipAllSpaces,
::parseExpression,
opt(
tuple(
skipAllSpaces,
token(Token.Kind.KeywordElse),
skipHorizontalSpaces,
token(Token.Kind.PunctuationHyphenMinus),
token(Token.Kind.PunctuationGreaterThanSign),
skipAllSpaces,
::parseExpression,
)
)
)
) { (_, _, condition, _, _, _, _, then, otherwise) ->
Ast.Child.Expression.If(condition, then, otherwise?.seventh)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,12 @@ val parsePostfixOperatorExpression: FumicoParseFunction<Ast.Child.Expression> by
parseInfixOperatorExpressionWithPrecedence,
skipHorizontalSpaces,
defaulting(
separatedList(parseSpecialIdentifier, skipHorizontalSpaces),
separatedList(
filter(parseSpecialIdentifier) {
it.actual != "->"
},
skipHorizontalSpaces
),
emptyList()
)
)
Expand Down Expand Up @@ -122,7 +127,8 @@ fun createInfixOperatorParser(
}
val (_, input2) = skipHorizontalSpaces(input1)
val (operator, input3) = filter(parseSpecialIdentifier) { s ->
s.actual.firstOrNull()?.let { it in begin } == true
s.actual.firstOrNull()?.let { it in begin } == true &&
s.actual != "->"
}(input2).unwrapOr {
return buildResult(acc + Pair(lhs, null), input1)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,5 +61,6 @@ val parseBasicExpression: FumicoParseFunction<Ast.Child.Expression> by lazy {
parseName,
parseGroupTuple,
parseLambda,
parseIf,
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,17 @@ fun <Value> createToken(
kind: Token.Kind,
f: FumicoTokenizeFunction<Value>,
mapper: (Value) -> String,
): FumicoTokenizeFunction<Token> = createToken({ kind }, f, mapper)

fun <Value> createToken(
kind: (String) -> Token.Kind,
f: FumicoTokenizeFunction<Value>,
mapper: (Value) -> String,
): FumicoTokenizeFunction<Token> = { input ->
f(input).flatMap { (value, input1) ->
val begin = Span.LineColumn(input.start, input.meta.line, input.meta.lastOffset)
val end = Span.LineColumn(input1.start, input1.meta.line, input1.meta.lastOffset)
ParseResult.Ok(Token(kind, mapper(value), Span(begin, end)), input1)
val mapped = mapper(value)
ParseResult.Ok(Token(kind(mapped), mapped, Span(begin, end)), input1)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ data class Token(val kind: Kind, val visual: String, val actual: String, val spa
IdentifierInfix,
IdentifierPostfix,

KeywordIf,
KeywordElse,

Punctuations,

PunctuationExclamationMark,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ val tokenize: FumicoTokenizeFunction<List<Token>> by lazy {

tokenizePunctuation,

tokenizeIdentifierPlaceholderName,
tokenizeIdentifierIdentifier,
tokenizeIdentifierPrefix,
tokenizeIdentifierInfix,
Expand Down Expand Up @@ -158,9 +159,19 @@ val tokenizePunctuations: FumicoTokenizeFunction<List<Char>> by lazy {
takeWhile1 { it in punctuationMap }
}

val keywordMap = mapOf(
"if" to Token.Kind.KeywordIf,
"else" to Token.Kind.KeywordElse,
)

val tokenizeIdentifierIdentifier: FumicoTokenizeFunction<Token> =
createToken(
Token.Kind.IdentifierIdentifier,
{
when (it) {
in keywordMap -> keywordMap[it]!!
else -> Token.Kind.IdentifierIdentifier
}
},
filter(
mapResult(
concatWithFlatten(
Expand Down Expand Up @@ -195,6 +206,15 @@ val tokenizeIdentifierIdentifier: FumicoTokenizeFunction<Token> =
it
}


val tokenizeIdentifierPlaceholderName: FumicoTokenizeFunction<Token> =
createToken(
Token.Kind.IdentifierPlaceholderName,
tag('_')
) {
it.toString()
}

val tokenizeIdentifierPrefix: FumicoTokenizeFunction<Token> =
createToken(
Token.Kind.IdentifierPrefix,
Expand Down
29 changes: 29 additions & 0 deletions fumico-core/src/test/kotlin/io/typecraft/fumico/core/ParserTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -302,4 +302,33 @@ class ParserTest {
)
)
}

@Test
fun `it should parse if else`() {
assertEquals(
listOf(
Ast.Child.Expression.If(
identNameNode("true"),
integerNode("1"),
integerNode("2")
),
Ast.Child.Expression.If(
identNameNode("true"),
integerNode("1"),
null
),
),
parseSimple(
"""
if true ->
1
else ->
2
if true ->
1
""".trimIndent()
)
)
}
}
108 changes: 108 additions & 0 deletions parsecom/src/main/kotlin/io/typecraft/parsecom/functions/Tuple.kt
Original file line number Diff line number Diff line change
Expand Up @@ -114,4 +114,112 @@ inline fun <Meta, Token, A, B, C, D, E, F, G> tuple(
val (g, input7) = f6(input6).unwrapOr { return@body it.into() }

ParseResult.Ok(Tuple7(a, b, c, d, e, f, g), input7)
}

data class Tuple8<A, B, C, D, E, F, G, H>(
val first: A,
val second: B,
val third: C,
val fourth: D,
val fifth: E,
val sixth: F,
val seventh: G,
val eighth: H,
)

inline fun <Meta, Token, A, B, C, D, E, F, G, H> tuple(
crossinline f0: ParseFunction<Meta, Token, A>,
crossinline f1: ParseFunction<Meta, Token, B>,
crossinline f2: ParseFunction<Meta, Token, C>,
crossinline f3: ParseFunction<Meta, Token, D>,
crossinline f4: ParseFunction<Meta, Token, E>,
crossinline f5: ParseFunction<Meta, Token, F>,
crossinline f6: ParseFunction<Meta, Token, G>,
crossinline f7: ParseFunction<Meta, Token, H>,
): ParseFunction<Meta, Token, Tuple8<A, B, C, D, E, F, G, H>> = body@{ input ->
val (a, input1) = f0(input).unwrapOr { return@body it.into() }
val (b, input2) = f1(input1).unwrapOr { return@body it.into() }
val (c, input3) = f2(input2).unwrapOr { return@body it.into() }
val (d, input4) = f3(input3).unwrapOr { return@body it.into() }
val (e, input5) = f4(input4).unwrapOr { return@body it.into() }
val (f, input6) = f5(input5).unwrapOr { return@body it.into() }
val (g, input7) = f6(input6).unwrapOr { return@body it.into() }
val (h, input8) = f7(input7).unwrapOr { return@body it.into() }

ParseResult.Ok(Tuple8(a, b, c, d, e, f, g, h), input8)
}

data class Tuple9<A, B, C, D, E, F, G, H, I>(
val first: A,
val second: B,
val third: C,
val fourth: D,
val fifth: E,
val sixth: F,
val seventh: G,
val eighth: H,
val ninth: I,
)

inline fun <Meta, Token, A, B, C, D, E, F, G, H, I> tuple(
crossinline f0: ParseFunction<Meta, Token, A>,
crossinline f1: ParseFunction<Meta, Token, B>,
crossinline f2: ParseFunction<Meta, Token, C>,
crossinline f3: ParseFunction<Meta, Token, D>,
crossinline f4: ParseFunction<Meta, Token, E>,
crossinline f5: ParseFunction<Meta, Token, F>,
crossinline f6: ParseFunction<Meta, Token, G>,
crossinline f7: ParseFunction<Meta, Token, H>,
crossinline f8: ParseFunction<Meta, Token, I>,
): ParseFunction<Meta, Token, Tuple9<A, B, C, D, E, F, G, H, I>> = body@{ input ->
val (a, input1) = f0(input).unwrapOr { return@body it.into() }
val (b, input2) = f1(input1).unwrapOr { return@body it.into() }
val (c, input3) = f2(input2).unwrapOr { return@body it.into() }
val (d, input4) = f3(input3).unwrapOr { return@body it.into() }
val (e, input5) = f4(input4).unwrapOr { return@body it.into() }
val (f, input6) = f5(input5).unwrapOr { return@body it.into() }
val (g, input7) = f6(input6).unwrapOr { return@body it.into() }
val (h, input8) = f7(input7).unwrapOr { return@body it.into() }
val (i, input9) = f8(input8).unwrapOr { return@body it.into() }

ParseResult.Ok(Tuple9(a, b, c, d, e, f, g, h, i), input9)
}

data class Tuple10<A, B, C, D, E, F, G, H, I, J>(
val first: A,
val second: B,
val third: C,
val fourth: D,
val fifth: E,
val sixth: F,
val seventh: G,
val eighth: H,
val ninth: I,
val tenth: J,
)

inline fun <Meta, Token, A, B, C, D, E, F, G, H, I, J> tuple(
crossinline f0: ParseFunction<Meta, Token, A>,
crossinline f1: ParseFunction<Meta, Token, B>,
crossinline f2: ParseFunction<Meta, Token, C>,
crossinline f3: ParseFunction<Meta, Token, D>,
crossinline f4: ParseFunction<Meta, Token, E>,
crossinline f5: ParseFunction<Meta, Token, F>,
crossinline f6: ParseFunction<Meta, Token, G>,
crossinline f7: ParseFunction<Meta, Token, H>,
crossinline f8: ParseFunction<Meta, Token, I>,
crossinline f9: ParseFunction<Meta, Token, J>,
): ParseFunction<Meta, Token, Tuple10<A, B, C, D, E, F, G, H, I, J>> = body@{ input ->
val (a, input1) = f0(input).unwrapOr { return@body it.into() }
val (b, input2) = f1(input1).unwrapOr { return@body it.into() }
val (c, input3) = f2(input2).unwrapOr { return@body it.into() }
val (d, input4) = f3(input3).unwrapOr { return@body it.into() }
val (e, input5) = f4(input4).unwrapOr { return@body it.into() }
val (f, input6) = f5(input5).unwrapOr { return@body it.into() }
val (g, input7) = f6(input6).unwrapOr { return@body it.into() }
val (h, input8) = f7(input7).unwrapOr { return@body it.into() }
val (i, input9) = f8(input8).unwrapOr { return@body it.into() }
val (j, input10) = f9(input9).unwrapOr { return@body it.into() }

ParseResult.Ok(Tuple10(a, b, c, d, e, f, g, h, i, j), input10)
}

0 comments on commit a711e94

Please sign in to comment.