예제 #1
0
        AsmStatement ParseAsmStatement(IBlockNode Scope, IStatement Parent)
        {
            Step();
            var s = new AsmStatement() { Location = t.Location, Parent = Parent };

            Expect(OpenCurlyBrace);

            var l = new List<AbstractStatement>();
            while (!IsEOF && laKind != (CloseCurlyBrace))
            {
                bool retrying = false;
            Retry:
                bool noStatement = false;
                if (laKind == Align)
                {
                    var als = new AsmStatement.AlignStatement() { Location = la.Location, Parent = s };
                    Step();
                    als.ValueExpression = Expression(Scope);
                    l.Add(als);
                    Step();
                }
                else if (laKind == Identifier)
                {
                    var opCode = AsmStatement.InstructionStatement.OpCode.__UNKNOWN__;
                    var dataType = AsmStatement.RawDataStatement.DataType.__UNKNOWN__;
                    if (Peek(1).Kind == Colon)
                    {
                        l.Add(new LabeledStatement() { Location = la.Location, Parent = s, Identifier = la.Value, EndLocation = Peek(1).EndLocation });
                        Step();
                        Step();
                        if (laKind == Semicolon)
                            Step();
                        continue;
                    }

                    if (AsmStatement.RawDataStatement.TryParseDataType(la.Value, out dataType))
                        l.Add(new AsmStatement.RawDataStatement() { Location = la.Location, Parent = s, TypeOfData = dataType });
                    else if (AsmStatement.InstructionStatement.TryParseOpCode(la.Value, out opCode))
                        l.Add(new AsmStatement.InstructionStatement() { Location = la.Location, Parent = s, Operation = opCode });
                    else switch (la.Value.ToLower())
                    {
                        case "pause":
                            SynErr(Identifier, "Pause is not supported by dmd's assembler. Use `rep; nop;` instead to achieve the same effect.");
                            break;
                        case "even":
                            var als = new AsmStatement.AlignStatement() { Location = la.Location, Parent = s };
                            als.ValueExpression = new IdentifierExpression(2) { Location = la.Location, EndLocation = la.EndLocation };
                            l.Add(als);
                            break;
                        case "naked":
                            noStatement = true;
                            break;
                        default:
                            SynErr(Identifier, "Unknown op-code!");
                            l.Add(new AsmStatement.InstructionStatement() { Location = la.Location, Parent = s, Operation = AsmStatement.InstructionStatement.OpCode.__UNKNOWN__ });
                            break;
                    }
                    Step();

                    if (noStatement && laKind != Semicolon)
                        SynErr(Semicolon);
                    var parentStatement = noStatement ? s : l[l.Count - 1];
                    var args = new List<IExpression>();
                    if (IsEOF)
                        args.Add(new TokenExpression(Incomplete));
                    else if (laKind != Semicolon)
                    {
                        while (true)
                        {
                            if (laKind == CloseCurlyBrace)
                            {
                                // This is required as a custom error message because
                                // it would complain about finding an identifier instead.
                                SynErr(Semicolon, "; expected, } found");
                                break;
                            }
                            var e = ParseAsmExpression(Scope, parentStatement);
                            if (e != null)
                                args.Add(e);
                            if (laKind == Comma)
                            {
                                Step();
                                continue;
                            }
                            if (IsEOF)
                                args.Add(new TokenExpression(Incomplete));
                            if (!Expect(Semicolon))
                            {
                                while (laKind != Semicolon && laKind != CloseCurlyBrace && !IsEOF)
                                    Step();
                                if (laKind == Semicolon)
                                    Step();
                            }

                            break;
                        }
                    }
                    else
                        Step();
                    if (parentStatement is AsmStatement.InstructionStatement)
                        ((AsmStatement.InstructionStatement)parentStatement).Arguments = args.ToArray();
                    else if (parentStatement is AsmStatement.RawDataStatement)
                        ((AsmStatement.RawDataStatement)parentStatement).Data = args.ToArray();
                }
                else if (laKind != Semicolon)
                {
                    string val;
                    if (!retrying && Keywords.TryGetValue(laKind, out val))
                    {
                        la.LiteralValue = val;
                        la.Kind = Identifier;
                        Lexer.laKind = Identifier;
                        retrying = true;
                        goto Retry;
                    }
                    else
                    {
                        noStatement = true;
                        SynErr(Identifier);
                        Step();
                    }
                }
                else
                    Step();

                if (!noStatement)
                    l[l.Count - 1].EndLocation = t.Location;
            }

            if (!Expect(CloseCurlyBrace) && (t.Kind == OpenCurlyBrace || t.Kind == Semicolon) && IsEOF)
                l.Add(new AsmStatement.InstructionStatement() { Operation = AsmStatement.InstructionStatement.OpCode.__UNKNOWN__ });

            s.EndLocation = t.EndLocation;
            s.Instructions = l.ToArray();
            return s;
        }
예제 #2
0
 public void Visit(AsmStatement.AlignStatement alignStatement)
 {
 }