private static Executable ParseStruct(TokenStream tokens, Executable owner) { Token structToken = tokens.PopExpected("struct"); Token structNameToken = tokens.Pop(); Parser.VerifyIdentifier(structNameToken); tokens.PopExpected("{"); List <Token> fieldTokens = new List <Token>(); List <Annotation> typeAnnotations = new List <Annotation>(); bool nextForbidden = false; while (!tokens.PopIfPresent("}")) { if (nextForbidden) { tokens.PopExpected("}"); // crash } Annotation annotation = tokens.IsNext("@") ? AnnotationParser.ParseAnnotation(tokens) : null; Token fieldToken = tokens.Pop(); Parser.VerifyIdentifier(fieldToken); nextForbidden = !tokens.PopIfPresent(","); fieldTokens.Add(fieldToken); typeAnnotations.Add(annotation); } return(new StructDefinition(structToken, structNameToken, fieldTokens, typeAnnotations, owner)); }
public static Expression Parse(TokenStream tokens, Executable owner) { Dictionary <string, Annotation> annotations = null; if (tokens.IsNext("@")) { annotations = new Dictionary <string, Annotation>(); while (tokens.IsNext("@")) { Annotation annotation = AnnotationParser.ParseAnnotation(tokens); annotations[annotation.Type] = annotation; } } Expression output = ParseTernary(tokens, owner); output.Annotations = annotations; return(output); }
private static Executable ParseFunction(Parser parser, TokenStream tokens, Executable nullableOwner) { bool isStatic = nullableOwner != null && nullableOwner is ClassDefinition && tokens.PopIfPresent("static"); Token functionToken = tokens.PopExpected("function"); List <Annotation> functionAnnotations = new List <Annotation>(); while (tokens.IsNext("@")) { functionAnnotations.Add(AnnotationParser.ParseAnnotation(tokens)); } Token functionNameToken = tokens.Pop(); Parser.VerifyIdentifier(functionNameToken); FunctionDefinition fd = new FunctionDefinition(functionToken, nullableOwner, isStatic, functionNameToken, functionAnnotations, parser.CurrentNamespace); tokens.PopExpected("("); List <Token> argNames = new List <Token>(); List <Expression> defaultValues = new List <Expression>(); List <Annotation> argAnnotations = new List <Annotation>(); bool optionalArgFound = false; while (!tokens.PopIfPresent(")")) { if (argNames.Count > 0) { tokens.PopExpected(","); } Annotation annotation = tokens.IsNext("@") ? AnnotationParser.ParseAnnotation(tokens) : null; Token argName = tokens.Pop(); Expression defaultValue = null; Parser.VerifyIdentifier(argName); if (tokens.PopIfPresent("=")) { optionalArgFound = true; defaultValue = ExpressionParser.Parse(tokens, fd); } else if (optionalArgFound) { throw new ParserException(argName, "All optional arguments must come at the end of the argument list."); } argAnnotations.Add(annotation); argNames.Add(argName); defaultValues.Add(defaultValue); } IList <Executable> code = Parser.ParseBlock(parser, tokens, true, fd); fd.ArgNames = argNames.ToArray(); fd.DefaultValues = defaultValues.ToArray(); fd.ArgAnnotations = argAnnotations.ToArray(); fd.Code = code.ToArray(); return(fd); }
private static Executable ParseClassDefinition(Parser parser, TokenStream tokens, Executable owner, Token staticToken, Token finalToken) { Token classToken = tokens.PopExpected("class"); Token classNameToken = tokens.Pop(); Parser.VerifyIdentifier(classNameToken); List <Token> baseClassTokens = new List <Token>(); List <string> baseClassStrings = new List <string>(); if (tokens.PopIfPresent(":")) { if (baseClassTokens.Count > 0) { tokens.PopExpected(","); } Token baseClassToken = tokens.Pop(); string baseClassName = baseClassToken.Value; Parser.VerifyIdentifier(baseClassToken); while (tokens.PopIfPresent(".")) { Token baseClassTokenNext = tokens.Pop(); Parser.VerifyIdentifier(baseClassTokenNext); baseClassName += "." + baseClassTokenNext.Value; } baseClassTokens.Add(baseClassToken); baseClassStrings.Add(baseClassName); } ClassDefinition cd = new ClassDefinition( classToken, classNameToken, baseClassTokens, baseClassStrings, parser.CurrentNamespace, owner, staticToken, finalToken); tokens.PopExpected("{"); List <FunctionDefinition> methods = new List <FunctionDefinition>(); List <FieldDeclaration> fields = new List <FieldDeclaration>(); ConstructorDefinition constructorDef = null; ConstructorDefinition staticConstructorDef = null; while (!tokens.PopIfPresent("}")) { Dictionary <string, List <Annotation> > annotations = null; while (tokens.IsNext("@")) { annotations = annotations ?? new Dictionary <string, List <Annotation> >(); Annotation annotation = AnnotationParser.ParseAnnotation(tokens); if (!annotations.ContainsKey(annotation.Type)) { annotations[annotation.Type] = new List <Annotation>(); } annotations[annotation.Type].Add(annotation); } if (tokens.IsNext("function") || tokens.AreNext("static", "function")) { methods.Add((FunctionDefinition)ExecutableParser.ParseFunction(parser, tokens, cd)); } else if (tokens.IsNext("constructor")) { if (constructorDef != null) { throw new ParserException(tokens.Pop(), "Multiple constructors are not allowed. Use optional arguments."); } constructorDef = (ConstructorDefinition)ExecutableParser.ParseConstructor(parser, tokens, cd); if (annotations != null && annotations.ContainsKey("private")) { constructorDef.PrivateAnnotation = annotations["private"][0]; annotations["private"].RemoveAt(0); } } else if (tokens.AreNext("static", "constructor")) { tokens.Pop(); // static token if (staticConstructorDef != null) { throw new ParserException(tokens.Pop(), "Multiple static constructors are not allowed."); } staticConstructorDef = (ConstructorDefinition)ExecutableParser.ParseConstructor(parser, tokens, cd); } else if (tokens.IsNext("field") || tokens.AreNext("static", "field")) { fields.Add(ExecutableParser.ParseField(tokens, cd)); } else { tokens.PopExpected("}"); } if (annotations != null) { foreach (List <Annotation> annotationsOfType in annotations.Values) { if (annotationsOfType.Count > 0) { throw new ParserException(annotationsOfType[0].FirstToken, "Unused or extra annotation."); } } } } cd.Methods = methods.ToArray(); cd.Constructor = constructorDef; cd.StaticConstructor = staticConstructorDef; cd.Fields = fields.ToArray(); return(cd); }