public override bool Std(out Stmt s) { s = null; bool afterRes = false; Tokenizer.SetLocalLabelParsingEnable(true); if (this.Column != 0) throw new ParseException("DAT must be in 1st column", this); Tokenizer.Advance(); // past "DAT" if (Tokenizer.Current.Text == "(eol)") Tokenizer.Advance("(eol)"); while (!(Tokenizer.Current is BlockDesignatorToken) && Tokenizer.Current.Text != "(eof)") { IdToken labelToken = null; if (Tokenizer.Current is IdToken) { labelToken = Tokenizer.GetToken() as IdToken; } if (Tokenizer.Current.Text.ToUpper() == "ORG") { SimpleToken orgToken = Tokenizer.GetToken(); if (labelToken != null) SymbolTable.AddDatLabelEntry(4, labelToken, false); Expr orgExpr = null; if (Tokenizer.Current.Text != "(eol)") orgExpr = ParseExpression(Tokenizer, 13); else Tokenizer.PrintWarning("ORG without address (defaults to 0)", Tokenizer.Current); SymbolTable.AddDatOrgEntry(orgToken, orgExpr, Tokenizer.Current.LineNumber); Tokenizer.Advance("(eol)"); afterRes = false; continue; } else if (Tokenizer.Current.Text.ToUpper() == "ORGX") { SimpleToken orgxToken = Tokenizer.GetToken(); if (labelToken != null) SymbolTable.AddDatLabelEntry(0, labelToken, false); SymbolTable.AddDatOrgxEntry(orgxToken); Tokenizer.Advance("(eol)"); afterRes = false; continue; } else if (Tokenizer.Current.Text.ToUpper() == "RES") { SimpleToken resToken = Tokenizer.GetToken(); if (labelToken != null) SymbolTable.AddDatLabelEntry(4, labelToken, false); Expr e = null; if (Tokenizer.Current.Text != "(eol)") e = ParseExpression(Tokenizer, 13); else Tokenizer.PrintWarning("RES without count (defaults to 1)", Tokenizer.Current); SymbolTable.AddDatResEntry(resToken, e, Tokenizer.Current.LineNumber); Tokenizer.Advance("(eol)"); afterRes = true; continue; } else if (Tokenizer.Current.Text.ToUpper() == "FIT") { SimpleToken fitToken = Tokenizer.GetToken(); if (labelToken != null) SymbolTable.AddDatLabelEntry(0, labelToken, false); Expr e = null; if (Tokenizer.Current.Text != "(eol)") e = ParseExpression(Tokenizer, 13); SymbolTable.AddDatFitEntry(fitToken, e); Tokenizer.Advance("(eol)"); continue; } else if (Tokenizer.Current.Text.ToUpper() == "FILE") { if (afterRes) Tokenizer.PrintWarning("FILE after RES", Tokenizer.Current); SimpleToken fileToken = Tokenizer.GetToken(); if (labelToken != null) SymbolTable.AddDatLabelEntry(0, labelToken, false); SimpleToken filenameToken = Tokenizer.Current; string filename = ""; while (true) { Expr e = ParseExpression(Tokenizer, 13); filename += (char)(Expr.EvaluateIntConstant(e)); if (Tokenizer.Current.Text != ",") break; Tokenizer.Advance(","); } try { filenameToken.Text = filename; string path = Options.TryPaths(filenameToken); FileStream fs = new FileStream(path + filename, FileMode.Open); BinaryReader br = new BinaryReader(fs); byte[] bytes = br.ReadBytes((int)fs.Length); SymbolTable.AddDatFileEntry(fileToken, filenameToken, bytes, Tokenizer.Current.LineNumber); } catch (Exception e) { throw new ParseException(e.Message, filenameToken); } Tokenizer.Advance("(eol)"); continue; } if (Tokenizer.Current.Text == "(eol)") { if (labelToken != null) SymbolTable.AddDatLabelEntry(0, labelToken, true); } else if (Tokenizer.Current is SizeToken) { if (afterRes) Tokenizer.PrintWarning("Data after RES", Tokenizer.Current); SizeToken alignmentToken = Tokenizer.GetToken() as SizeToken; int alignment = SizeSpecifier(alignmentToken.Text); SimpleToken firstToken = alignmentToken; if (labelToken != null) { SymbolTable.AddDatLabelEntry(alignment, labelToken, false); firstToken = labelToken; } if (Tokenizer.Current.Text != "(eol)") { while (true) { int size = alignment; if (Tokenizer.Current is SizeToken) { SizeToken sizeToken = Tokenizer.GetToken() as SizeToken; size = SizeSpecifier(sizeToken.Text); if (size < alignment) throw new ParseException("Size override must be larger", sizeToken); } Expr dataExpr = ParseExpression(Tokenizer, 13); Expr countExpr = null; if (Tokenizer.Current.Text == "[") { Tokenizer.Advance("["); countExpr = ParseExpression(Tokenizer, 13); Tokenizer.Advance("]"); } SymbolTable.AddDatDataEntry(alignment, size, dataExpr, countExpr, firstToken); if (Tokenizer.Current.Text != ",") break; Tokenizer.Advance(","); } } else { SymbolTable.AddDatDataEntry(alignment, alignment, new IntExpr(null, 0), new IntExpr(null, 0), firstToken); } SymbolTable.AddDatSourceReference(Tokenizer.Current); } else // assembly language { if (labelToken != null) // handle label if there is one SymbolTable.AddDatLabelEntry(4, labelToken, false); SimpleToken token = Tokenizer.Current; int cond = 0x0f; // default is IF_ALWAYS CondToken condToken = null; if (Tokenizer.Current is CondToken) { condToken = Tokenizer.GetToken() as CondToken; cond = condToken.CondValue; } if (!(Tokenizer.Current is IPropInstruction)) throw new ParseException("Expected instruction mnemonic", Tokenizer.Current); if (afterRes) Tokenizer.PrintWarning("Assembly language after RES", Tokenizer.Current); string mnemonic = Tokenizer.Current.Text.ToUpper(); IPropInstruction instruction = Tokenizer.GetToken() as IPropInstruction; if (instruction.Propcode == 0) { if (condToken != null) throw new ParseException("Condition not allowed on NOP", condToken); cond = 0; } Expr eD = null; Expr eS = null; bool immediate = false; if (instruction.InstructionType == InstructionTypeEnum.D || instruction.InstructionType == InstructionTypeEnum.DS) { eD = ParseExpression(Tokenizer, 13); } if (instruction.InstructionType == InstructionTypeEnum.DS) { Tokenizer.Advance(","); } if (instruction.InstructionType == InstructionTypeEnum.S || instruction.InstructionType == InstructionTypeEnum.DS) { if ((mnemonic == "JMP" || mnemonic == "DJNZ" || mnemonic == "TJNZ" || mnemonic == "TJZ") && Tokenizer.Current.Text != "#") Tokenizer.PrintWarning(mnemonic + " with non-immediate operand", Tokenizer.Current); if (Tokenizer.Current.Text == "#" || mnemonic == "CALL") { Tokenizer.Advance("#"); immediate = true; } eS = ParseExpression(Tokenizer, 13); } if (mnemonic == "CALL") { if (!(eS is IdExpr)) throw new ParseException("Expected label", eS.Token); eD = new IdExpr(new SimpleToken(Tokenizer, SimpleTokenType.Id, eS.Token.Text + "_ret", eS.Token.LineNumber, eS.Token.Column)); } bool memoryInstruction = mnemonic.StartsWith("RD") || mnemonic.StartsWith("WR"); int effect = 0; // bit 0 - WR // bit 1 - WC // bit 2 - WZ // bit 3 - NR if (Tokenizer.Current is EffectToken && instruction.Propcode != 0) // No effects allowed on NOP { while (true) { Token effectToken = Tokenizer.GetToken(); int e = (effectToken as EffectToken).Effect; if (e == 1) // WR { if (memoryInstruction) throw new ParseException("Memory instructions cannot use WR/NR", effectToken); effect &= 7; // clear NR bit } else if (e == 8) // NR? { if (memoryInstruction) throw new ParseException("Memory instructions cannot use WR/NR", effectToken); effect &= 0xe; // clear WR bit } effect |= e; if (Tokenizer.Current.Text == "(eol)") break; Tokenizer.Advance(","); } } SymbolTable.AddDatInstructionEntry(instruction, cond, eD, eS, immediate, effect, token, Tokenizer.Current.LineNumber); } Tokenizer.Advance("(eol)"); } Tokenizer.SetLocalLabelParsingEnable(false); return true; }
public void Visit(IdExpr e) { SymbolInfo symbolInfo = e.SymbolTable.LookupExisting(e.Token); if (symbolInfo is DatSymbolInfo) { if (insideDat) { int x = (symbolInfo as DatSymbolInfo).CogAddressX4; if ((x & 3) != 0) throw new ParseException("Address is not long", e.Token); result = new FloInt(x / 4); return; } // else result = new FloInt((symbolInfo as DatSymbolInfo).Dp); return; } ConSymbolInfo conSymbolInfo = e.SymbolTable.LookupExisting(e.Token) as ConSymbolInfo; if (conSymbolInfo == null) throw new ParseException("Non-constant symbol", e.Token); result = conSymbolInfo.Value; }