• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
parseTokensnull38     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
<lambda>null99         if (tokens.any { it.identifier == TokenGrammar.EQUAL }) {
<lambda>null100             this.value = tokens.takeLastWhile { it.identifier != TokenGrammar.EQUAL }
<lambda>null101                     .map { it.value }
102                     .joinToString(" ")
103         }
104     }
105 }