Beispiel #1
0
        private BlockNode ParseBlock(MergeableGenerator <Token> tokens, ImmutableStack <Closure> scopes)
        {
            Location start = tokens.Current.Location;

            tokens.MoveNext();
            BlockNode         temp = new BlockNode();
            Maybe <ILineNode> x;

            while (!tokens.EOS && tokens.Current.Type != TokenType.CLOSE_BRACE)
            {
                if (!(x = ParseLine(tokens, scopes)).IsNothing)
                {
                    temp.Children.Add(x.FromJust);
                }
            }
            if (!tokens.EOS)
            {
                tokens.MoveNext();
            }
            else
            {
                Error(start, "Unmatched brace.");
            }
            return(temp);
        }
Beispiel #2
0
        private IList <IAtomNode> ParseList(MergeableGenerator <Token> tokens, ImmutableStack <Closure> scopes)
        {
            Token head = tokens.Current;

            tokens.MoveNext();
            IList <IAtomNode> atoms = new List <IAtomNode>();

            while (tokens.Current.Type != TokenType.NEWLINE && tokens.Current.Type != TokenType.CLOSE_BRACKET)
            {
                Maybe <IAtomNode> res = ParseAtom(tokens, scopes);
                res.IfJust(
                    (IAtomNode n) => atoms.Add(n),
                    () => Error(tokens.Current.Location, "Expected atomic value, got " + tokens.Current.Type + "."));
                if (tokens.Current.Type == TokenType.COMMA)
                {
                    tokens.MoveNext();
                }
            }
            if (tokens.Current.Type == TokenType.CLOSE_BRACKET)
            {
                tokens.MoveNext();
            }
            else
            {
                Error(head.Location, "Unmatched open bracket.");
            }
            return(atoms);
        }
Beispiel #3
0
 private void IgnoreRestOfLine(MergeableGenerator <Token> tokens)
 {
     while (tokens.Current.Type != TokenType.NEWLINE && tokens.MoveNext())
     {
         ;
     }
 }
Beispiel #4
0
        public Maybe <ILineNode> Execute(EAParser p, Token self, IList <IParamNode> parameters, MergeableGenerator <Token> tokens)
        {
            BlockNode result = new BlockNode();

            // Iterating indices (and not values via foreach)
            // to avoid crashes occuring with AddToPool within AddToPool

            for (int i = 0; i < p.Pool.Lines.Count; ++i)
            {
                Pool.PooledLine line = p.Pool.Lines[i];

                MergeableGenerator <Token> tempGenerator = new MergeableGenerator <Token>(line.Tokens);
                tempGenerator.MoveNext();

                while (!tempGenerator.EOS)
                {
                    p.ParseLine(tempGenerator, line.Scope).IfJust(
                        (lineNode) => result.Children.Add(lineNode));
                }
            }

            p.Pool.Lines.Clear();

            return(new Just <ILineNode>(result));
        }
Beispiel #5
0
        public IList <ILineNode> ParseAll(IEnumerable <Token> tokenStream)
        {
            //TODO: Make BlockNode or EAProgramNode?
            //Note must be strict to get all information on the closure before evaluating terms.
            IList <ILineNode>          myLines = new List <ILineNode>();
            MergeableGenerator <Token> tokens  = new MergeableGenerator <Token>(tokenStream);

            tokens.MoveNext();
            while (!tokens.EOS)
            {
                if (tokens.Current.Type != TokenType.NEWLINE || tokens.MoveNext())
                {
                    Maybe <ILineNode> retVal = ParseLine(tokens, GlobalScope);
                    retVal.IfJust((ILineNode n) => myLines.Add(n));
                }
            }
            return(myLines);
        }
Beispiel #6
0
 private void IgnoreRestOfStatement(MergeableGenerator <Token> tokens)
 {
     while (tokens.Current.Type != TokenType.NEWLINE && tokens.Current.Type != TokenType.SEMICOLON && tokens.MoveNext())
     {
         ;
     }
     if (tokens.Current.Type == TokenType.SEMICOLON)
     {
         tokens.MoveNext();
     }
 }
Beispiel #7
0
        private Maybe <IParamNode> ParseParam(MergeableGenerator <Token> tokens, ImmutableStack <Closure> scopes, bool expandDefs = true)
        {
            Token head = tokens.Current;

            switch (tokens.Current.Type)
            {
            case TokenType.OPEN_BRACKET:
                return(new Just <IParamNode>(new ListNode(head.Location, ParseList(tokens, scopes)).Simplify()));

            case TokenType.STRING:
                tokens.MoveNext();
                return(new Just <IParamNode>(new StringNode(head)));

            case TokenType.MAYBE_MACRO:
                //TODO: Move this and the one in ExpandId to a separate ParseMacroNode that may return an Invocation.
                if (expandDefs && ExpandIdentifier(tokens, scopes))
                {
                    return(ParseParam(tokens, scopes));
                }
                else
                {
                    tokens.MoveNext();
                    IList <IList <Token> > param = ParseMacroParamList(tokens);
                    //TODO: Smart errors if trying to redefine a macro with the same num of params.
                    return(new Just <IParamNode>(new MacroInvocationNode(this, head, param, scopes)));
                }

            case TokenType.IDENTIFIER:
                if (expandDefs && Definitions.ContainsKey(head.Content) && ExpandIdentifier(tokens, scopes))
                {
                    return(ParseParam(tokens, scopes, expandDefs));
                }
                else
                {
                    return(ParseAtom(tokens, scopes, expandDefs).Fmap((IAtomNode x) => (IParamNode)x.Simplify()));
                }

            default:
                return(ParseAtom(tokens, scopes, expandDefs).Fmap((IAtomNode x) => (IParamNode)x.Simplify()));
            }
        }
Beispiel #8
0
        /***
         *   Precondition: tokens.Current.Type == TokenType.IDENTIFIER || MAYBE_MACRO
         *   Postcondition: tokens.Current is fully reduced (i.e. not a macro, and not a definition)
         *   Returns: true iff tokens was actually expanded.
         */
        public bool ExpandIdentifier(MergeableGenerator <Token> tokens, ImmutableStack <Closure> scopes)
        {
            bool ret = false;

            //Macros and Definitions.
            if (tokens.Current.Type == TokenType.MAYBE_MACRO && Macros.ContainsName(tokens.Current.Content))
            {
                Token head = tokens.Current;
                tokens.MoveNext();
                IList <IList <Token> > parameters = ParseMacroParamList(tokens);
                if (Macros.HasMacro(head.Content, parameters.Count))
                {
                    tokens.PrependEnumerator(Macros.GetMacro(head.Content, parameters.Count).ApplyMacro(head, parameters, scopes).GetEnumerator());
                }
                else
                {
                    Error(head.Location, System.String.Format("No overload of {0} with {1} parameters.", head.Content, parameters.Count));
                }
                return(true);
            }
            else if (tokens.Current.Type == TokenType.MAYBE_MACRO)
            {
                Token head = tokens.Current;
                tokens.MoveNext();
                tokens.PutBack(new Token(TokenType.IDENTIFIER, head.Location, head.Content));
                return(true);
            }
            else if (Definitions.ContainsKey(tokens.Current.Content))
            {
                Token head = tokens.Current;
                tokens.MoveNext();
                tokens.PrependEnumerator(Definitions[head.Content].ApplyDefinition(head).GetEnumerator());
                return(true);
            }

            return(ret);
        }
Beispiel #9
0
        private Maybe <ILineNode> ParsePreprocessor(MergeableGenerator <Token> tokens, ImmutableStack <Closure> scopes)
        {
            head = tokens.Current;
            tokens.MoveNext();
            //Note: Not a ParseParamList because no commas.
            IList <IParamNode> paramList = ParsePreprocParamList(tokens, scopes);
            Maybe <ILineNode>  retVal    = directiveHandler.HandleDirective(this, head, paramList, tokens);

            if (!retVal.IsNothing)
            {
                CheckDataWrite(retVal.FromJust.Size);
                CurrentOffset += retVal.FromJust.Size;
            }
            return(retVal);
        }
Beispiel #10
0
        public IList <IList <Token> > ParseMacroParamList(MergeableGenerator <Token> tokens)
        {
            IList <IList <Token> > parameters = new List <IList <Token> >();
            int parenNestings = 0;

            do
            {
                tokens.MoveNext();
                List <Token> currentParam = new List <Token>();
                while (
                    !(parenNestings == 0 && (tokens.Current.Type == TokenType.CLOSE_PAREN || tokens.Current.Type == TokenType.COMMA)) &&
                    tokens.Current.Type != TokenType.NEWLINE)
                {
                    if (tokens.Current.Type == TokenType.CLOSE_PAREN)
                    {
                        parenNestings--;
                    }
                    else if (tokens.Current.Type == TokenType.OPEN_PAREN)
                    {
                        parenNestings++;
                    }
                    currentParam.Add(tokens.Current);
                    tokens.MoveNext();
                }
                parameters.Add(currentParam);
            } while (tokens.Current.Type != TokenType.CLOSE_PAREN && tokens.Current.Type != TokenType.NEWLINE);
            if (tokens.Current.Type != TokenType.CLOSE_PAREN || parenNestings != 0)
            {
                Error(tokens.Current.Location, "Unmatched open parenthesis.");
            }
            else
            {
                tokens.MoveNext();
            }
            return(parameters);
        }
Beispiel #11
0
        private IList <IParamNode> ParseParamList(MergeableGenerator <Token> tokens, ImmutableStack <Closure> scopes, bool expandFirstDef = true)
        {
            IList <IParamNode> paramList = new List <IParamNode>();
            bool first = true;

            while (tokens.Current.Type != TokenType.NEWLINE && tokens.Current.Type != TokenType.SEMICOLON && !tokens.EOS)
            {
                Token head = tokens.Current;
                ParseParam(tokens, scopes, expandFirstDef || !first).IfJust(
                    (IParamNode n) => paramList.Add(n),
                    () => Error(head.Location, "Expected parameter."));
                first = false;
            }
            if (tokens.Current.Type == TokenType.SEMICOLON)
            {
                tokens.MoveNext();
            }
            return(paramList);
        }
Beispiel #12
0
        public Maybe <ILineNode> ParseLine(MergeableGenerator <Token> tokens, ImmutableStack <Closure> scopes)
        {
            if (IsIncluding)
            {
                if (tokens.Current.Type == TokenType.NEWLINE || tokens.Current.Type == TokenType.SEMICOLON)
                {
                    tokens.MoveNext();
                    return(new Nothing <ILineNode>());
                }
                head = tokens.Current;
                switch (head.Type)
                {
                case TokenType.IDENTIFIER:
                case TokenType.MAYBE_MACRO:
                    if (ExpandIdentifier(tokens, scopes))
                    {
                        return(ParseLine(tokens, scopes));
                    }
                    else
                    {
                        tokens.MoveNext();
                        if (tokens.Current.Type == TokenType.COLON)
                        {
                            tokens.MoveNext();
                            if (scopes.Head.HasLocalLabel(head.Content))
                            {
                                Warning(head.Location, "Label already in scope, ignoring: " + head.Content);    //replacing: " + head.Content);
                            }
                            else if (!IsValidLabelName(head.Content))
                            {
                                Error(head.Location, "Invalid label name " + head.Content + '.');
                            }
                            else
                            {
                                scopes.Head.AddLabel(head.Content, CurrentOffset);
                            }

                            return(new Nothing <ILineNode>());
                        }
                        else
                        {
                            tokens.PutBack(head);
                            return(ParseStatement(tokens, scopes));
                        }
                    }

                case TokenType.OPEN_BRACE:
                    return(new Just <ILineNode>(ParseBlock(tokens, new ImmutableStack <Closure>(new Closure(), scopes))));

                case TokenType.PREPROCESSOR_DIRECTIVE:
                    return(ParsePreprocessor(tokens, scopes));

                case TokenType.OPEN_BRACKET:
                    Error(head.Location, "Unexpected list literal.");
                    IgnoreRestOfLine(tokens);
                    break;

                case TokenType.NUMBER:
                case TokenType.OPEN_PAREN:
                    Error(head.Location, "Unexpected mathematical expression.");
                    IgnoreRestOfLine(tokens);
                    break;

                default:
                    tokens.MoveNext();
                    Error(head.Location, System.String.Format("Unexpected token: {0}: {1}", head.Type, head.Content));
                    IgnoreRestOfLine(tokens);
                    break;
                }
                return(new Nothing <ILineNode>());
            }
            else
            {
                bool hasNext = true;
                while (tokens.Current.Type != TokenType.PREPROCESSOR_DIRECTIVE && (hasNext = tokens.MoveNext()))
                {
                    ;
                }
                if (hasNext)
                {
                    return(ParsePreprocessor(tokens, scopes));
                }
                else
                {
                    Error(null, System.String.Format("Missing {0} endif(s).", Inclusion.Count));
                    return(new Nothing <ILineNode>());
                }
            }
        }
Beispiel #13
0
        private Maybe <IAtomNode> ParseAtom(MergeableGenerator <Token> tokens, ImmutableStack <Closure> scopes, bool expandDefs = true)
        {
            //Use Shift Reduce Parsing
            Token head = tokens.Current;
            Stack <Either <IAtomNode, Token> > grammarSymbols = new Stack <Either <IAtomNode, Token> >();
            bool ended = false;

            while (!ended)
            {
                bool  shift = false, lookingForAtom = grammarSymbols.Count == 0 || grammarSymbols.Peek().IsRight;
                Token lookAhead = tokens.Current;

                if (!ended && !lookingForAtom) //Is already a complete node. Needs an operator of matching precedence and a node of matching prec to reduce.
                {
                    //Verify next symbol to be an operator.
                    switch (lookAhead.Type)
                    {
                    case TokenType.MUL_OP:
                    case TokenType.DIV_OP:
                    case TokenType.MOD_OP:
                    case TokenType.ADD_OP:
                    case TokenType.SUB_OP:
                    case TokenType.LSHIFT_OP:
                    case TokenType.RSHIFT_OP:
                    case TokenType.SIGNED_RSHIFT_OP:
                    case TokenType.AND_OP:
                    case TokenType.XOR_OP:
                    case TokenType.OR_OP:
                        if (precedences.ContainsKey(lookAhead.Type))
                        {
                            Reduce(grammarSymbols, precedences[lookAhead.Type]);
                        }
                        shift = true;
                        break;

                    default:
                        ended = true;
                        break;
                    }
                }
                else if (!ended) //Is just an operator. Error if two operators in a row.
                {
                    //Error if two operators in a row.
                    switch (lookAhead.Type)
                    {
                    case TokenType.IDENTIFIER:
                    case TokenType.MAYBE_MACRO:
                    case TokenType.NUMBER:
                        shift = true;
                        break;

                    case TokenType.OPEN_PAREN:
                    {
                        tokens.MoveNext();
                        Maybe <IAtomNode> interior = ParseAtom(tokens, scopes);
                        if (tokens.Current.Type != TokenType.CLOSE_PAREN)
                        {
                            Error(tokens.Current.Location, "Unmatched open parenthesis (currently at " + tokens.Current.Type + ").");
                            return(new Nothing <IAtomNode>());
                        }
                        else if (interior.IsNothing)
                        {
                            Error(lookAhead.Location, "Expected expression inside paretheses. ");
                            return(new Nothing <IAtomNode>());
                        }
                        else
                        {
                            grammarSymbols.Push(new Left <IAtomNode, Token>(interior.FromJust));
                            tokens.MoveNext();
                            break;
                        }
                    }

                    case TokenType.SUB_OP:
                    {
                        //Assume unary negation.
                        tokens.MoveNext();
                        Maybe <IAtomNode> interior = ParseAtom(tokens, scopes);
                        if (interior.IsNothing)
                        {
                            Error(lookAhead.Location, "Expected expression after negation. ");
                            return(new Nothing <IAtomNode>());
                        }
                        grammarSymbols.Push(new Left <IAtomNode, Token>(new NegationNode(lookAhead, interior.FromJust)));
                        break;
                    }

                    case TokenType.COMMA:
                        Error(lookAhead.Location, "Unexpected comma (perhaps unrecognized macro invocation?).");
                        IgnoreRestOfStatement(tokens);
                        return(new Nothing <IAtomNode>());

                    case TokenType.MUL_OP:
                    case TokenType.DIV_OP:
                    case TokenType.MOD_OP:
                    case TokenType.ADD_OP:
                    case TokenType.LSHIFT_OP:
                    case TokenType.RSHIFT_OP:
                    case TokenType.SIGNED_RSHIFT_OP:
                    case TokenType.AND_OP:
                    case TokenType.XOR_OP:
                    case TokenType.OR_OP:
                    default:
                        Error(lookAhead.Location, "Expected identifier or literal, got " + lookAhead.Type + ": " + lookAhead.Content + '.');
                        IgnoreRestOfStatement(tokens);
                        return(new Nothing <IAtomNode>());
                    }
                }

                if (shift)
                {
                    if (lookAhead.Type == TokenType.IDENTIFIER)
                    {
                        if (expandDefs && ExpandIdentifier(tokens, scopes))
                        {
                            continue;
                        }
                        if (lookAhead.Content.ToUpper() == "CURRENTOFFSET")
                        {
                            grammarSymbols.Push(new Left <IAtomNode, Token>(new NumberNode(lookAhead, CurrentOffset)));
                        }
                        else
                        {
                            grammarSymbols.Push(new Left <IAtomNode, Token>(new IdentifierNode(lookAhead, scopes)));
                        }
                    }
                    else if (lookAhead.Type == TokenType.MAYBE_MACRO)
                    {
                        ExpandIdentifier(tokens, scopes);
                        continue;
                    }
                    else if (lookAhead.Type == TokenType.NUMBER)
                    {
                        grammarSymbols.Push(new Left <IAtomNode, Token>(new NumberNode(lookAhead)));
                    }
                    else if (lookAhead.Type == TokenType.ERROR)
                    {
                        Error(lookAhead.Location, System.String.Format("Unexpected token: {0}", lookAhead.Content));
                        tokens.MoveNext();
                        return(new Nothing <IAtomNode>());
                    }
                    else
                    {
                        grammarSymbols.Push(new Right <IAtomNode, Token>(lookAhead));
                    }
                    tokens.MoveNext();
                    continue;
                }
            }
            while (grammarSymbols.Count > 1)
            {
                Reduce(grammarSymbols, 11);
            }
            if (grammarSymbols.Peek().IsRight)
            {
                Error(grammarSymbols.Peek().GetRight.Location, "Unexpected token: " + grammarSymbols.Peek().GetRight.Type);
            }
            return(new Just <IAtomNode>(grammarSymbols.Peek().GetLeft));
        }
Beispiel #14
0
        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>());
            }
        }