/* * Copyright (C) 2017 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package parser.elements.declarations import lexer.Token import lexer.TokenCategory import lexer.TokenGrammar import parser.elements.DocParser import writer.tokenValues import java.text.ParseException /** * Used for Structs and Unions */ class CompoundDeclarationParser(iter: ListIterator<Token>, var shouldResetIterator: Boolean = false) : AbstractDeclarationParser(iter) { lateinit var type: TokenGrammar lateinit override var name: String var members = mutableListOf<IMemberDeclaration>() //defined below init { parseTokens(scanTokens(iter)) if (shouldResetIterator) resetIterator(iter) } override fun parseTokens(tokens: List<Token>) { val iter = tokens.listIterator() var token = iter.next() assert(token.identifier == TokenGrammar.STRUCT || token.identifier == TokenGrammar.UNION) assert(tokens.last().identifier == TokenGrammar.SEMICOLON) //type - struct or union this.type = token.identifier //name token = iter.next() if (token.category != TokenCategory.Word) throw ParseException("Invalid struct name: ${tokenValues(tokens)}", this.indexStart) this.name = token.value //parse each semicolon-delimited statement scanDelimitedList(iter, delimiter = TokenGrammar.SEMICOLON, openDelimiter = TokenGrammar.BRACE_OPEN, closeDelimiter = TokenGrammar.BRACE_CLOSE) .forEach { var docParser: DocParser? = null var statementTokens = it.toMutableList() if (statementTokens.isEmpty()) throw ParseException("Invalid statement in: ${tokenValues(tokens)}", this.indexStart) //If doc, extract doc tokens and parse, and remove from statement tokens if (statementTokens.first().identifier == TokenGrammar.DOC_START) { val idx = statementTokens.indexOfFirst { it.identifier == TokenGrammar.DOC_END } if (idx == -1) throw ParseException("Unable to find doc_end", this.indexStart) val docTokens = statementTokens.subList(0, idx+1) docParser = DocParser(docTokens.listIterator()) statementTokens = statementTokens.subList(idx+1, statementTokens.size) } if (statementTokens.isEmpty()) throw ParseException("Invalid statement in: ${tokenValues(tokens)}", this.indexStart) when(statementTokens.first().identifier) { TokenGrammar.STRUCT, TokenGrammar.UNION -> { assert(statementTokens.first().category == TokenCategory.TypeDef) this.members.add(CompoundMemberDeclaration( typeDef = statementTokens.first().identifier, type = statementTokens.get(1).value, name = statementTokens.last().value, docParser = docParser, tokens = statementTokens.subList(2, statementTokens.size-1) )) } TokenGrammar.ENUM -> { assert(statementTokens.size > 1) this.members.add(MemberDeclaration( type = statementTokens.first().value, name = statementTokens.get(1).value, docParser = docParser, tokens = statementTokens )) } else -> { this.members.add(MemberDeclaration( type = statementTokens.first().value, name = statementTokens.last().value, docParser = docParser, tokens = statementTokens )) } } } } } interface IMemberDeclaration { val type: String val name: String val docParser: DocParser? val tokens: List<Token> //TODO: doesn't seem needed } class MemberDeclaration(override val type: String, override val name: String, override val docParser: DocParser?, override val tokens: List<Token>) : IMemberDeclaration class CompoundMemberDeclaration(override val type: String, override val name: String, override val docParser: DocParser?, override val tokens: List<Token>, val typeDef: TokenGrammar) : IMemberDeclaration