예제 #1
0
        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];
        }
예제 #2
0
        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);
            }
        }
예제 #3
0
        } // 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()