Home | History | Annotate | Download | only in declarations
      1 /*
      2  * Copyright (C) 2017 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package parser.elements.declarations
     18 
     19 import lexer.Token
     20 import lexer.TokenCategory
     21 import lexer.TokenGrammar
     22 import parser.elements.DocParser
     23 import parser.peekToken
     24 import writer.tokenValues
     25 import java.text.ParseException
     26 
     27 class EnumDeclarationParser(iter: ListIterator<Token>, var shouldResetIterator: Boolean = false) : AbstractDeclarationParser(iter) {
     28 
     29     lateinit override var name: String
     30     lateinit var type: String
     31     var members = mutableListOf<EnumMember>()
     32 
     33     init {
     34         parseTokens(scanTokens(iter))
     35         if (shouldResetIterator) resetIterator(iter)
     36     }
     37 
     38     override fun parseTokens(tokens: List<Token>) {
     39         val iter = tokens.listIterator()
     40         var token = iter.next()
     41         assert(token.identifier == TokenGrammar.ENUM)
     42         assert(tokens.last().identifier == TokenGrammar.SEMICOLON)
     43 
     44         //name
     45         token = iter.next()
     46         if (token.category != TokenCategory.Word)
     47             throw ParseException("Invalid enum name: ${tokenValues(tokens)}", this.indexStart)
     48         this.name = token.value
     49 
     50         token = iter.next() //':'
     51         if (token.identifier != TokenGrammar.COLON)
     52             throw ParseException("Invalid enum type syntax: ${tokenValues(tokens)}", this.indexStart)
     53 
     54         //type: can be type name or package
     55         assert(iter.hasNext())
     56         val sb = StringBuilder()
     57         while (iter.hasNext() && peekToken(iter)!!.identifier != TokenGrammar.BRACE_OPEN) {
     58             sb.append(iter.next().value)
     59         }
     60         this.type = sb.toString()
     61 
     62         //members
     63         //convert iterator sequence of comma separated tokens to list of lists
     64         scanDelimitedList(iter, openDelimiter = TokenGrammar.BRACE_OPEN, closeDelimiter = TokenGrammar.BRACE_CLOSE)
     65                 .forEach {
     66                     var statementTokens = it.toMutableList()
     67                     var docParser: DocParser? = null
     68                     assert(statementTokens.isNotEmpty())
     69 
     70                     //If doc, extract doc tokens and parse, and remove from statement tokens
     71                     if (statementTokens.first().identifier == TokenGrammar.DOC_START) {
     72                         val idx = statementTokens.indexOfFirst { it.identifier == TokenGrammar.DOC_END }
     73                         if (idx == -1) throw ParseException("Unable to find doc_end", this.indexStart)
     74 
     75                         val docTokens = statementTokens.subList(0, idx+1)
     76                         docParser = DocParser(docTokens.listIterator())
     77                         statementTokens = statementTokens.subList(idx+1, statementTokens.size)
     78                     }
     79                     if (statementTokens.isEmpty())
     80                         throw ParseException("Invalid member in enum: ${tokenValues(tokens)}", this.indexStart)
     81                     val member = EnumMember(statementTokens)
     82                     member.docParser = docParser
     83                     this.members.add(member)
     84                 }
     85     }
     86 }
     87 
     88 //split member: name [= value]
     89 class EnumMember(tokens: List<Token>) {
     90     val name: String
     91     var value: String? = null
     92     var docParser: DocParser? = null
     93 
     94     init {
     95         assert(tokens.isNotEmpty())
     96         this.name = tokens.first().value
     97 
     98         //check for assignment, take right side
     99         if (tokens.any { it.identifier == TokenGrammar.EQUAL }) {
    100             this.value = tokens.takeLastWhile { it.identifier != TokenGrammar.EQUAL }
    101                     .map { it.value }
    102                     .joinToString(" ")
    103         }
    104     }
    105 }