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; }
public void Visit(AsmStatement.AlignStatement alignStatement) { }