Feature: Array in NeoLang

This commit is contained in:
zt515
2017-08-08 16:04:22 +08:00
parent 4b9bf83181
commit 44947f05aa
24 changed files with 254 additions and 56 deletions

View File

@ -5,6 +5,7 @@ import io.neolang.ast.NeoLangTokenType
import io.neolang.ast.NeoLangTokenValue
import io.neolang.ast.base.NeoLangAst
import io.neolang.ast.node.*
import io.neolang.runtime.type.NeoLangArrayElement
/**
* @author kiva
@ -84,14 +85,15 @@ class NeoLangParser {
val attributes = mutableListOf(attr)
while (token.tokenType !== NeoLangTokenType.EOF
&& token.tokenType !== NeoLangTokenType.BRACKET_END) {
&& token.tokenType !== NeoLangTokenType.BRACKET_END
&& token.tokenType !== NeoLangTokenType.ARRAY_END) {
attr = attribute()
if (attr == null) {
break
}
attributes.add(attr)
}
return NeoLangGroupNode(attributes)
return NeoLangGroupNode(attributes.toTypedArray())
}
return null
@ -101,15 +103,79 @@ class NeoLangParser {
val token = currentToken ?: throw InvalidTokenException("Unexpected token: null")
if (match(NeoLangTokenType.ID)) {
match(NeoLangTokenType.COLON, errorThrow = true)
val block = block() ?: NeoLangBlockNode.emptyNode()
return NeoLangAttributeNode(NeoLangStringNode(token), block)
val attrName = NeoLangStringNode(token)
val block = block(attrName) ?: NeoLangBlockNode.emptyNode()
return NeoLangAttributeNode(attrName, block)
}
return null
}
private fun block(): NeoLangBlockNode? {
private fun array(arrayName: NeoLangStringNode): NeoLangArrayNode? {
val token = currentToken ?: throw InvalidTokenException("Unexpected token: null")
// TODO: Multiple Array
var block = blockNonArrayElement(arrayName)
var index = 0
if (block != null) {
val elements = mutableListOf(NeoLangArrayElement(index++, block))
if (match(NeoLangTokenType.COMMA)) {
// More than one elements
while (token.tokenType !== NeoLangTokenType.EOF
&& token.tokenType !== NeoLangTokenType.ARRAY_END) {
block = blockNonArrayElement(arrayName)
if (block == null) {
break
}
elements.add(NeoLangArrayElement(index++, block))
// Meet the last element
if (!match(NeoLangTokenType.COMMA)) {
break
}
}
}
return NeoLangArrayNode(arrayName, elements.toTypedArray())
}
return null
}
/**
* @attrName The block holder's name
*/
private fun block(attrName: NeoLangStringNode): NeoLangBlockNode? {
val block = blockNonArrayElement(attrName)
if (block != null) {
return block
}
val token = currentToken ?: throw InvalidTokenException("Unexpected token: null")
when (token.tokenType) {
NeoLangTokenType.ARRAY_START -> {
match(NeoLangTokenType.ARRAY_START, errorThrow = true)
val array = array(attrName)
match(NeoLangTokenType.ARRAY_END, errorThrow = true)
// Allow empty arrays
return if (array != null) NeoLangBlockNode(array) else NeoLangBlockNode.emptyNode()
}
else -> throw InvalidTokenException("Unexpected token `${token.tokenValue}' typed `${token.tokenType}' for block")
}
}
private fun blockNonArrayElement(attrName: NeoLangStringNode): NeoLangBlockNode? {
val token = currentToken ?: throw InvalidTokenException("Unexpected token: null")
return when (token.tokenType) {
NeoLangTokenType.NUMBER -> {
match(NeoLangTokenType.NUMBER, errorThrow = true)
return NeoLangBlockNode(NeoLangNumberNode(token))
@ -130,10 +196,7 @@ class NeoLangParser {
// Allow empty blocks
return if (group != null) NeoLangBlockNode(group) else NeoLangBlockNode.emptyNode()
}
else -> throw InvalidTokenException("Unexpected token `$token' for block, " +
"expected `${NeoLangTokenType.NUMBER}', `${NeoLangTokenType.ID}' or `${NeoLangTokenType.BRACKET_START}'")
else -> null
}
}
}