public void Clear() { Macros.Clear(); Definitions.Clear(); Raws.Clear(); Inclusion = ImmutableStack <bool> .Nil; CurrentOffset = 0; pastOffsets.Clear(); }
public bool IsReservedName(string name) { return(Raws.ContainsKey(name.ToUpper()) || SpecialCodes.Contains(name.ToUpper())); }
private Maybe <ILineNode> ParseStatement(MergeableGenerator <Token> tokens, ImmutableStack <Closure> scopes) { while (ExpandIdentifier(tokens, scopes)) { } head = tokens.Current; tokens.MoveNext(); //TODO: Replace with real raw information, and error if not valid. IList <IParamNode> parameters; //TODO: Make intelligent to reject malformed parameters. //TODO: Parse parameters after checking code validity. if (tokens.Current.Type != TokenType.NEWLINE && tokens.Current.Type != TokenType.SEMICOLON) { parameters = ParseParamList(tokens, scopes); } else { parameters = new List <IParamNode>(); tokens.MoveNext(); } string upperCodeIdentifier = head.Content.ToUpperInvariant(); if (SpecialCodes.Contains(upperCodeIdentifier)) { switch (upperCodeIdentifier) { case "ORG": if (parameters.Count != 1) { Error(head.Location, "Incorrect number of parameters in ORG: " + parameters.Count); } else { parameters[0].AsAtom().IfJust( (IAtomNode atom) => atom.TryEvaluate((Exception e) => { Error(parameters[0].MyLocation, e.Message); }).IfJust( (int temp) => { if (temp > 0x2000000) { Error(parameters[0].MyLocation, "Tried to set offset to 0x" + temp.ToString("X")); } else { CurrentOffset = temp; } }), () => { Error(parameters[0].MyLocation, "Expected atomic param to ORG."); } ); } break; case "PUSH": if (parameters.Count != 0) { Error(head.Location, "Incorrect number of parameters in PUSH: " + parameters.Count); } else { pastOffsets.Push(new Tuple <int, bool>(CurrentOffset, offsetInitialized)); } break; case "POP": if (parameters.Count != 0) { Error(head.Location, "Incorrect number of parameters in POP: " + parameters.Count); } else if (pastOffsets.Count == 0) { Error(head.Location, "POP without matching PUSH."); } else { Tuple <int, bool> tuple = pastOffsets.Pop(); CurrentOffset = tuple.Item1; offsetInitialized = tuple.Item2; } break; case "MESSAGE": Message(head.Location, PrettyPrintParams(parameters)); break; case "WARNING": Warning(head.Location, PrettyPrintParams(parameters)); break; case "ERROR": Error(head.Location, PrettyPrintParams(parameters)); break; case "ASSERT": if (parameters.Count != 1) { Error(head.Location, "Incorrect number of parameters in ASSERT: " + parameters.Count); } else { parameters[0].AsAtom().IfJust( (IAtomNode atom) => { atom.TryEvaluate((Exception e) => { Error(parameters[0].MyLocation, e.Message); }).IfJust( (int temp) => { if (temp < 0) { Error(parameters[0].MyLocation, "Assertion error: " + temp); } }); }, () => { Error(parameters[0].MyLocation, "Expected atomic param to ASSERT."); } ); } break; case "PROTECT": if (parameters.Count == 1) { parameters[0].AsAtom().IfJust( (IAtomNode atom) => atom.TryEvaluate((Exception e) => { Error(parameters[0].MyLocation, e.Message); }).IfJust( (int temp) => { protectedRegions.Add(new Tuple <int, int, Location>(temp, 4, head.Location)); }), () => { Error(parameters[0].MyLocation, "Expected atomic param to PROTECT"); }); } else if (parameters.Count == 2) { int start = 0, end = 0; bool errorOccurred = false; parameters[0].AsAtom().IfJust( (IAtomNode atom) => atom.TryEvaluate((Exception e) => { Error(parameters[0].MyLocation, e.Message); errorOccurred = true; }).IfJust( (int temp) => { start = temp; }), () => { Error(parameters[0].MyLocation, "Expected atomic param to PROTECT"); errorOccurred = true; }); parameters[1].AsAtom().IfJust( (IAtomNode atom) => atom.TryEvaluate((Exception e) => { Error(parameters[0].MyLocation, e.Message); errorOccurred = true; }).IfJust( (int temp) => { end = temp; }), () => { Error(parameters[0].MyLocation, "Expected atomic param to PROTECT"); errorOccurred = true; }); if (!errorOccurred) { int length = end - start; if (length > 0) { protectedRegions.Add(new Tuple <int, int, Location>(start, length, head.Location)); } else { Warning(head.Location, "Protected region not valid (end offset not after start offset). No region protected."); } } } else { Error(head.Location, "Incorrect number of parameters in PROTECT: " + parameters.Count); } break; case "ALIGN": if (parameters.Count != 1) { Error(head.Location, "Incorrect number of parameters in ALIGN: " + parameters.Count); } else { parameters[0].AsAtom().IfJust( (IAtomNode atom) => atom.TryEvaluate((Exception e) => { Error(parameters[0].MyLocation, e.Message); }).IfJust( (int temp) => { CurrentOffset = CurrentOffset % temp != 0 ? CurrentOffset + temp - CurrentOffset % temp : CurrentOffset; }), () => { Error(parameters[0].MyLocation, "Expected atomic param to ALIGN"); } ); } break; case "FILL": if (parameters.Count > 2 || parameters.Count == 0) { Error(head.Location, "Incorrect number of parameters in FILL: " + parameters.Count); } else { // FILL <amount> [value] int amount = 0; int value = 0; if (parameters.Count == 2) { // param 2 (if given) is fill value parameters[1].AsAtom().IfJust( (IAtomNode atom) => atom.TryEvaluate((Exception e) => { Error(parameters[0].MyLocation, e.Message); }).IfJust( (int val) => { value = val; }), () => { Error(parameters[0].MyLocation, "Expected atomic param to FILL"); }); } // param 1 is amount of bytes to fill parameters[0].AsAtom().IfJust( (IAtomNode atom) => atom.TryEvaluate((Exception e) => { Error(parameters[0].MyLocation, e.Message); }).IfJust( (int val) => { amount = val; }), () => { Error(parameters[0].MyLocation, "Expected atomic param to FILL"); }); var data = new byte[amount]; for (int i = 0; i < amount; ++i) { data[i] = (byte)value; } var node = new DataNode(CurrentOffset, data); CheckDataWrite(amount); CurrentOffset += amount; return(new Just <ILineNode>(node)); } break; } return(new Nothing <ILineNode>()); } else if (Raws.ContainsKey(upperCodeIdentifier)) { //TODO: Check for matches. Currently should type error. foreach (Raw r in Raws[upperCodeIdentifier]) { if (r.Fits(parameters)) { if ((CurrentOffset % r.Alignment) != 0) { Error(head.Location, string.Format("Bad code alignment (offset: {0:X8})", CurrentOffset)); } StatementNode temp = new RawNode(r, head, CurrentOffset, parameters); CheckDataWrite(temp.Size); CurrentOffset += temp.Size; //TODO: more efficient spacewise to just have contiguous writing and not an offset with every line? return(new Just <ILineNode>(temp)); } } //TODO: Better error message (a la EA's ATOM ATOM [ATOM,ATOM]) Error(head.Location, "Incorrect parameters in raw " + head.Content + '.'); IgnoreRestOfStatement(tokens); return(new Nothing <ILineNode>()); } else //TODO: Move outside of this else. { Error(head.Location, "Unrecognized code: " + head.Content); return(new Nothing <ILineNode>()); } }
/// <summary> /// Releases any resources used by the index entry. /// </summary> public void Dispose() { Raws.Dispose(); Strings.Clear(); TagData = null; }