void parseStruct() { Token name = parseData.tokens[parseData.cursor += 1]; if (name.type != TT.IDENTIFIER) { throw Jolly.unexpected(token); } Token next = parseData.tokens[parseData.cursor += 1]; AST_Struct structNode = new AST_Struct(token.location); DataType_Struct structType = new DataType_Struct(); SymbolTable structTable = new SymbolTable(scope); structNode.index = parseData.ast.Count; parseData.ast.Add(structNode); int startNodeCount = parseData.ast.Count; if (next.type == TT.LESS) { parseData.cursor += 1; new ExpressionParser(parseData, TT.GREATER, structTable, DefineMode.TEMPLATE, end) .parse(false); next = parseData.tokens[parseData.cursor += 1]; // Skip greater than } if (next.type == TT.COLON) { parseData.cursor += 1; structNode.inherits = new ExpressionParser(parseData, TT.BRACE_OPEN, structTable, DefineMode.EXPRESSION, end) .parse(false) .getValue(); next = parseData.tokens[parseData.cursor]; } if (next.type != TT.BRACE_OPEN) { throw Jolly.unexpected(next); } structNode.symbol = structTable; structNode.text = structType.name = name.text; structNode.result = structTable.declaration = new IR { irType = NT.STRUCT, dType = structType, dKind = ValueKind.STATIC_TYPE }; scope.addChild(name.text, structTable); parseData.cursor += 1; new ScopeParser(parseData, next.partnerIndex, structTable) .parse(ScopeParseMethod.STRUCT); structNode.memberCount = parseData.ast.Count - startNodeCount; structType.members = new DataType[structType.memberMap.Count]; }
void parseEnum() { Token identifier = parseData.tokens[parseData.cursor + 1]; if (identifier.type != TT.IDENTIFIER) { throw Jolly.unexpected(identifier); } Token brace = parseData.tokens[parseData.cursor + 2]; if (brace.type != TT.BRACE_OPEN) { throw Jolly.unexpected(brace); } parseData.cursor += 3; AST_Struct enumNode = new AST_Struct(token.location); // Use struct node for now DataType_Enum enumType = new DataType_Enum(); SymbolTable enumTable = new SymbolTable(scope); // enumNode.inherits = inherits; enumNode.nodeType = NT.ENUM; enumNode.symbol = enumTable; enumNode.text = enumType.name = identifier.text; enumNode.result = enumTable.declaration = new IR { irType = NT.ENUM, dType = enumType, dKind = ValueKind.STATIC_TYPE }; scope.addChild(identifier.text, enumTable); parseData.ast.Add(enumNode); int startNodeCount = parseData.ast.Count; var parser = new ExpressionParser(parseData, TT.BRACE_CLOSE, enumTable, DefineMode.EXPRESSION, brace.partnerIndex) .parse(false); AST_Node[] memberNodes = (parser.getValue() as AST_Tuple)?.values.ToArray() ?? new AST_Node[] { parser.getValue() }; enumNode.memberCount = parseData.ast.Count - startNodeCount; int nextValue = 0; foreach (var memberNode in memberNodes) { if (memberNode.nodeType != NT.NAME) { throw Jolly.unexpected(memberNode); } var symbol = new Symbol(enumTable) { declaration = new IR_Literal { dType = enumType, data = nextValue++ } }; enumTable.addChild(((AST_Symbol)memberNode).text, symbol); } }
} // parseExpression() void parseIdentifier() { currentTokenKind = TokenKind.VALUE; string name = token.text; AST_Node target = null; // If function it's the return type otherwhise it's the variable type switch (prevTokenKind) { case TokenKind.VALUE: // Pop eventual period and comma operators while (operators.Count > 0) { pushOperator(operators.Pop()); } target = values.Pop(); break; case TokenKind.SEPARATOR: while (contextStack.Peek().kind == Context.Kind.DECLARATION) { contextEnd(contextStack.Pop()); } if (defineMode != DefineMode.ARGUMENT && prevDefinedType != null && contextStack.Peek().kind == Context.Kind.STATEMENT) { target = prevDefinedType; break; } goto default; default: var symbol = new AST_Symbol(token.location, null, name) { templateArguments = parseTemplateArguments() }; values.Push(symbol); ast.Add(symbol); return; } Token nextToken = tokens[cursor + 1]; int startNodeCount = contextStack.Peek().index; if (!canDefine) { throw Jolly.addError(token.location, "Can't define the {0} \"{1}\" here.".fill( (nextToken.type == TT.PARENTHESIS_OPEN) ? "function" : "variable", token.text)); } // Declare if (nextToken.type == TT.PARENTHESIS_OPEN || nextToken.type == TT.LESS) { // Function if (defineMode != DefineMode.STATEMENT) { throw Jolly.addError(token.location, "Can't define the function \"{0}\" here".fill(name)); } DataType_Function functionType = new DataType_Function(); AST_Function functionNode = new AST_Function(token.location); FunctionTable functionTable = new FunctionTable(scope); functionNode.templateArguments = parseTemplate(functionTable); nextToken = tokens[cursor + 1]; functionNode.index = ast.Count; functionNode.symbol = functionTable; functionNode.text = functionType.name = name; functionNode.result = functionTable.declaration = new IR_Function { dType = functionType }; scope.addChild(name, functionTable, true); ast.Insert(startNodeCount, functionNode); functionNode.returnCount = ast.Count - (startNodeCount += 1); // Skip the function node itself cursor += 2; new ExpressionParser(parseData, TT.UNDEFINED, functionTable, DefineMode.ARGUMENT, nextToken.partnerIndex) .parse(false); functionNode.returns = target; functionType.arguments = new DataType[functionTable.arguments.Count]; // TODO: This is the wrong count, I think functionNode.definitionCount = ast.Count - startNodeCount; Token brace = tokens[cursor + 1]; if (brace.type != TT.BRACE_OPEN) { throw Jolly.unexpected(brace); } cursor += 2; // Skip parenthesis close and brace open new ScopeParser(parseData, brace.partnerIndex, functionTable) .parse(ScopeParseMethod.BLOCK); functionNode.memberCount = ast.Count - startNodeCount; terminator = TT.BRACE_CLOSE; // HACK: stop parsing cursor = brace.partnerIndex - 1; } else { // Variable AST_Declaration variableNode; if (defineMode == DefineMode.MEMBER) { var structType = (DataType_Struct)scope.declaration.dType; if (structType.memberMap.ContainsKey(name)) { throw Jolly.addError(token.location, "Type {0} already contains a member named {1}".fill(structType.name, name)); } structType.memberMap.Add(name, structType.memberMap.Count); variableNode = new AST_Declaration(token.location, target, scope, name); } else if ((defineMode & (DefineMode.STATEMENT | DefineMode.ARGUMENT)) != 0) { Symbol variableSymbol = new Symbol(scope); variableNode = new AST_Declaration(token.location, target); variableSymbol.isGeneric = (target.nodeType == NT.TEMPLATE_NAME); //TODO: Fix generic in tuple variableSymbol.defineIndex = defineIndex++; variableNode.symbol = variableSymbol; variableNode.text = name; if (defineMode == DefineMode.ARGUMENT) { ((FunctionTable)scope).arguments.Add(name, variableSymbol); } else { scope.addChild(name, variableSymbol); } } else { throw Jolly.addError(token.location, "Can't define the variable \"{0}\" here.".fill(name)); } prevDefinedType = target; values.Push(variableNode); ast.Add(variableNode); contextStack.Push(new Context(ast.Count, Context.Kind.DECLARATION) { target = variableNode }); } } // parseIdentifier()