void ParseAttributeParameters(List <string> parameters) { // Attribute parameters are funny // The contents between the brackets vary. // They may be comma separated. They may not. // Therefore this code is likely to break, but since I'm responsible for // generating the text of the attributes parsed here, I can try to ensure // that it will always fit the pattern. while (true) { if (tokenizer.Peek().Kind == TypeTokenKind.RightBracket) { tokenizer.Next(); return; } TypeSpecToken value = tokenizer.Next(); if (value.Kind != TypeTokenKind.TypeName) { throw ErrorHelper.CreateError(ReflectorError.kTypeParseBase + 6, $"Unexpected token {value.Value} while parsing attribute parameter."); } parameters.Add(value.Value); if (tokenizer.Peek().Kind == TypeTokenKind.Comma) { tokenizer.Next(); } } }
public TypeSpecToken Next() { if (curr != null) { TypeSpecToken retval = curr; curr = null; return(retval); } TypeSpecToken token = null; do { switch (state) { case State.InName: token = DoName(); break; case State.InArrow: token = DoArrow(); break; case State.Start: token = DoStart(); break; } } while (token == null); return(token); }
TypeSpecToken DoName() { int curr = reader.Peek(); if (curr < 0 || InvalidNameCharacter((char)curr)) { if (curr == ':') { reader.Read(); // drop the colon state = State.Start; TypeSpecToken token = TypeSpecToken.LabelFromString(buffer.ToString()); buffer.Clear(); return(token); } else { state = State.Start; TypeSpecToken token = TypeSpecToken.FromString(buffer.ToString()); buffer.Clear(); return(token); } } else { buffer.Append((char)reader.Read()); return(null); } }
public TypeSpecToken Peek() { if (curr == null) { curr = Next(); } return(curr); }
TypeSpec Parse() { TypeSpecToken token = tokenizer.Peek(); TypeSpec type = null; List <TypeSpecAttribute> attrs = null; var inout = false; string typeLabel = null; // Prefix // parse any attributes if (token.Kind == TypeTokenKind.At) { attrs = ParseAttributes(); token = tokenizer.Peek(); } // looks like it's inout if (token.Kind == TypeTokenKind.TypeName && token.Value == "inout") { inout = true; tokenizer.Next(); token = tokenizer.Peek(); } if (token.Kind == TypeTokenKind.TypeLabel) { typeLabel = token.Value; tokenizer.Next(); token = tokenizer.Peek(); } // meat if (token.Kind == TypeTokenKind.LeftParenthesis) // tuple { tokenizer.Next(); TupleTypeSpec tuple = ParseTuple(); type = tuple.Elements.Count == 1 ? tuple.Elements [0] : tuple; typeLabel = type.TypeLabel; } else if (token.Kind == TypeTokenKind.TypeName) // name { tokenizer.Next(); var tokenValue = token.Value.StartsWith("ObjectiveC.", StringComparison.Ordinal) ? "Foundation" + token.Value.Substring("ObjectiveC".Length) : token.Value; type = new NamedTypeSpec(tokenValue); } else if (token.Kind == TypeTokenKind.LeftBracket) // array { tokenizer.Next(); type = ParseArray(); } else // illegal { throw ErrorHelper.CreateError(ReflectorError.kTypeParseBase + 0, $"Unexpected token {token.Value}."); } // look-ahead for closure if (tokenizer.Peek().Kind == TypeTokenKind.TypeName && tokenizer.Peek().Value == "throws") { tokenizer.Next(); if (tokenizer.Peek().Kind != TypeTokenKind.Arrow) { throw ErrorHelper.CreateError(ReflectorError.kTypeParseBase + 1, $"Unexpected token {tokenizer.Peek ().Value} after a 'throws' in a closure."); } tokenizer.Next(); type = ParseClosure(type, true); } if (tokenizer.Peek().Kind == TypeTokenKind.Arrow) { tokenizer.Next(); type = ParseClosure(type, false); } else if (tokenizer.Peek().Kind == TypeTokenKind.LeftAngle) { tokenizer.Next(); type = Genericize(type); } if (tokenizer.Peek().Kind == TypeTokenKind.Period) { tokenizer.Next(); var currType = type as NamedTypeSpec; if (currType == null) { throw ErrorHelper.CreateError(ReflectorError.kTypeParseBase + 2, $"In parsing an inner type (type.type), first element is a {type.Kind} instead of a NamedTypeSpec."); } var nextType = Parse() as NamedTypeSpec; if (nextType == null) { throw ErrorHelper.CreateError(ReflectorError.kTypeParseBase + 3, $"In parsing an inner type (type.type), the second element is a {nextType.Kind} instead of a NamedTypeSpec"); } currType.InnerType = nextType; } // Postfix if (tokenizer.Peek().Kind == TypeTokenKind.Ampersand) { type = ParseProtocolList(type as NamedTypeSpec); } while (tokenizer.Peek().Kind == TypeTokenKind.QuestionMark) { tokenizer.Next(); type = WrapAsBoundGeneric(type, "Swift.Optional"); } if (tokenizer.Peek().Kind == TypeTokenKind.ExclamationPoint) { tokenizer.Next(); type = WrapAsBoundGeneric(type, "Swift.ImplicitlyUnwrappedOptional"); } type.IsInOut = inout; type.TypeLabel = typeLabel; if (type != null && attrs != null) { type.Attributes.AddRange(attrs); } return(type); }