8000 add typedef and namespace by ygdrasil-io · Pull Request #7 · fabmax/webidl-util · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

add typedef and namespace #7

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 10 commits into from
Feb 23, 2025
19 changes: 19 additions & 0 deletions webidl-util/src/main/kotlin/de/fabmax/webidl/model/IdlConstant.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package de.fabmax.webidl.model

class IdlConstant private constructor(builder: Builder) : IdlDecoratedElement(builder) {
val type = builder.type
var defaultValue: String = builder.defaultValue

override fun toString(indent: String): String {
val str = StringBuilder(indent)
str.append("const ${type.typeName} $name = $defaultValue;")
return str.toString()
}

class Builder(name: String, var type: IdlType) : IdlDecoratedElement.Builder(name) {
lateinit var defaultValue: String

fun build() = IdlConstant(this)
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,17 @@ import java.util.*
class IdlModel private constructor(builder: Builder) : IdlElement(builder) {
val interfaces: List<IdlInterface>
val dictionaries: List<IdlDictionary>
val namespaces: List<IdlNamespace>
val enums: List<IdlEnum>
val typeDefs: List<IdlTypeDef>

val interfacesByName: Map<String, IdlInterface>

init {
interfaces = List(builder.interfaces.size) { builder.interfaces[it].build() }
dictionaries = List(builder.dictionaries.size) { builder.dictionaries[it].build() }
namespaces = List(builder.namespaces.size) { builder.namespaces[it].build() }
typeDefs = List(builder.typeDefs.size) { builder.typeDefs[it].build() }
interfacesByName = interfaces.associateBy { it.name }
enums = List(builder.enums.size) { builder.enums[it].build() }

Expand Down Expand Up @@ -64,12 +68,16 @@ class IdlModel private constructor(builder: Builder) : IdlElement(builder) {
val implements = mutableListOf<Pair<String, String>>()
val includes = mutableListOf<Pair<String, String>>()
val enums = mutableListOf<IdlEnum.Builder>()
val typeDefs = mutableListOf<IdlTypeDef.Builder>()
val namespaces = mutableListOf<IdlNamespace.Builder>()

fun addInterface(idlInterface: IdlInterface.Builder) { interfaces += idlInterface }
fun addDictionary(idlDictionary: IdlDictionary.Builder) { dictionaries += idlDictionary }
fun addImplements(concreteInterface: String, superInterface: String) { implements += concreteInterface to superInterface }
fun addIncludes(concreteInterface: String, superInterface: String) { includes += concreteInterface to superInterface }
fun addEnum(idlEnum: IdlEnum.Builder) { enums += idlEnum }
fun addTypeDef(idlTypeDef: IdlTypeDef.Builder) { typeDefs += idlTypeDef }
fun addNamespace(idlNamespace: IdlNamespace.Builder) { namespaces += idlNamespace }

fun build(): IdlModel {
implements.forEach { (ci, si) ->
Expand Down
29 changes: 29 additions & 0 deletions webidl-util/src/main/kotlin/de/fabmax/webidl/model/IdlNamespace.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package de.fabmax.webidl.model

class IdlNamespace(builder: Builder) : IdlDecoratedElement(builder) {
val constants = List(builder.constants.size) { builder.constants[it].build() }

override fun toString(indent: String): String {
val subIndent = "$indent "
val str = StringBuilder()
str.append(decoratorsToStringOrEmpty(indent, "\n"))
str.append("${indent}namespace $name { ")
if (constants.isNotEmpty()) {
str.append("\n")
str.append(constants.joinToString("\n", postfix = "\n", transform = { it.toString(subIndent) }))
}

str.append("$indent};")
return str.toString()
}

class Builder(name: String) : IdlDecoratedElement.Builder(name) {
val constants = mutableListOf<IdlConstant.Builder>()

fun build() = IdlNamespace(this)

fun addConstant(builder: IdlConstant.Builder) {
constants += builder
}
}
}
18 changes: 18 additions & 0 deletions webidl-util/src/main/kotlin/de/fabmax/webidl/model/IdlTypeDef.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package de.fabmax.webidl.model

class IdlTypeDef private constructor(builder: Builder) : IdlDecoratedElement(builder) {
val type = builder.type ?: throw IllegalArgumentException("Missing type")

override fun toString(indent: String): String {
val str = StringBuilder(indent)
str.append("typedef ${decoratorsToStringOrEmpty(postfix = " ")} $type $name;")
return str.toString()
}

class Builder : IdlDecoratedElement.Builder("") {
var type: IdlType? = null

fun build() = IdlTypeDef(this)
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package de.fabmax.webidl.parser

import de.fabmax.webidl.model.IdlConstant

class ConstantParser(parserState: WebIdlParser.ParserState) : ElementParser(
parserState,
WebIdlParserType.Constant
) {

override suspend fun parse(): String {
popToken("const")
val type = parseType()
val tokens = popUntilPattern(";") ?: parserException("Failed parsing constant")
val name = tokens.first.substringBefore("=").trim()
val builder = IdlConstant.Builder(name, type).also {
it.defaultValue = tokens.first.substringAfter("=").trim()
}
parserState.popDecorators(builder)
parserState.parentParser<NamespaceParser>().builder.addConstant(builder)

parserState.popParser()
return tokens.second
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,14 @@ abstract class ElementParser(val parserState: WebIdlParser.ParserState, val self

abstract suspend fun parse(): String?

suspend fun parseChildren() {
var child = selfType.possibleChildren().find { it.matches(stream) }
while (child != null) {
child.newParser(parserState).parse()
child = selfType.possibleChildren().find { it.matches(stream) }
}
}

suspend fun parseChildren(termToken: String?) {
var child = selfType.possibleChildren().find { it.matches(stream) }
var childTerm: String? = null
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package de.fabmax.webidl.parser

import de.fabmax.webidl.model.IdlNamespace

class NamespaceParser(parserState: WebIdlParser.ParserState) : ElementParser(parserState,
WebIdlParserType.Namespace
) {
lateinit var builder: IdlNamespace.Builder

override suspend fun parse(): String {
popToken("namespace")

val interfaceName = popUntilPattern("\\{") ?: parserException("Failed parsing interface name")
builder = IdlNamespace.Builder(interfaceName.first)
parserState.popDecorators(builder)
parserState.parentParser<RootParser>().builder.addNamespace(builder)

parseChildren("}")

popToken(";")
parserState.popParser()
return interfaceName.second
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package de.fabmax.webidl.parser

import de.fabmax.webidl.model.IdlTypeDef

class TypeDefParser(parserState: WebIdlParser.ParserState) : ElementParser(parserState,
WebIdlParserType.TypeDef
) {

override suspend fun parse(): String {
val builder = IdlTypeDef.Builder()
popToken("typedef")
parseChildren()
parserState.popDecorators(builder)
builder.type = parseType()
val tokens = popUntilPattern(";") ?: parserException("Failed parsing member")
builder.name = tokens.first.trim()
parserState.parentParser<RootParser>().builder.addTypeDef(builder)
parserState.popParser()
return tokens.second
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import de.fabmax.webidl.model.IdlType

enum class WebIdlParserType {
Root {
override fun possibleChildren() = listOf(Interface, Enum, LineComment, BlockComment, Decorators, Implements, Dictionary, Includes)
override fun possibleChildren() = listOf(Interface, Enum, LineComment, BlockComment, Decorators, Implements, Dictionary, Includes, TypeDef, Namespace)
override suspend fun matches(stream: WebIdlStream) = false
override fun newParser(parserState: WebIdlParser.ParserState) = RootParser(parserState)
},
Expand Down Expand Up @@ -152,7 +152,37 @@ enum class WebIdlParserType {
parserState
)
)
};
},

TypeDef {
override fun possibleChildren(): List<WebIdlParserType> = listOf(Decorators)
override suspend fun matches(stream: WebIdlStream) = stream.startsWith("typedef ")
override fun newParser(parserState: WebIdlParser.ParserState) = parserState.pushParser(
TypeDefParser(
parserState
)
)
},

Namespace {
override fun possibleChildren(): List<WebIdlParserType> = listOf(Constant)
override suspend fun matches(stream: WebIdlStream) = stream.startsWith("namespace ")
override fun newParser(parserState: WebIdlParser.ParserState) = parserState.pushParser(
NamespaceParser(
parserState
)
)
},

Constant {
override fun possibleChildren(): List<WebIdlParserType> = listOf()
override suspend fun matches(stream: WebIdlStream) = stream.startsWith("const ")
override fun newParser(parserState: WebIdlParser.ParserState) = parserState.pushParser(
ConstantParser(
parserState
)
)
},;

abstract fun possibleChildren(): List<WebIdlParserType>
abstract suspend fun matches(stream: WebIdlStream): Boolean
Expand Down
20 changes: 20 additions & 0 deletions webidl-util/src/test/kotlin/ParserTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ class ParserTest {

assertTrue(model.dictionaries.size == 1)
assertTrue(model.interfaces.size == 6)
assertTrue(model.typeDefs.size == 2)
assertTrue(model.namespaces.size == 1)
assertTrue(model.namespaces[0].constants.size == 2)


assertEquals("AnDictionary", model.dictionaries[0].name)
Expand Down Expand Up @@ -73,6 +76,23 @@ class ParserTest {
assertEquals("SetLikeInterface", model.interfaces[setLikeIndex].name)
assertNotNull(model.interfaces[setLikeIndex].setLike)
assertEquals("DOMString", model.interfaces[setLikeIndex].setLike?.type?.typeName)

assertEquals("ATypeDef", model.typeDefs[0].name)
assertEquals("unsigned long", model.typeDefs[0].type.typeName)
assertEquals("Value", model.typeDefs[0].decorators[0].key)
assertEquals("AnotherValue", model.typeDefs[0].decorators[1].key)

assertEquals("ATypeDef2", model.typeDefs[1].name)
assertEquals("sequence", model.typeDefs[1].type.typeName)
assertEquals("DOMString", model.typeDefs[1].type.parameterTypes!![0])

assertEquals("TypeDefs", model.names B4F0 paces[0].name)
assertEquals("CONST_1", model.namespaces[0].constants[0].name)
assertEquals("ATypeDef", model.namespaces[0].constants[0].type.typeName)
assertEquals("0x0001", model.namespaces[0].constants[0].defaultValue)
assertEquals("CONST_2", model.namespaces[0].constants[1].name)
assertEquals("ATypeDef", model.namespaces[0].constants[1].type.typeName)
assertEquals("0x0002", model.namespaces[0].constants[1].defaultValue)
}

@Test(expected = ParserException::class)
Expand Down
10 changes: 9 additions & 1 deletion webidl-util/src/test/resources/test.idl
Original file line number Diff line number Diff line change
Expand Up @@ -53,4 +53,12 @@ dictionary AnDictionary {

interface SetLikeInterface {
readonly setlike<DOMString>;
};
};

typedef [Value, AnotherValue] unsigned long ATypeDef;
typedef sequence<DOMString> ATypeDef2;

namespace TypeDefs {
const ATypeDef CONST_1 = 0x0001;
const ATypeDef CONST_2 = 0x0002;
};
Loading
0