Beispiel #1
0
        /// <summary>
        /// Gets the precedence of operator codes.
        /// </summary>
        /// <param name="opcode">operater code</param>
        /// <returns>value indicating precedence</returns>
        private static int OperatorPrecedence(GerberOpcodes opcode)
        {
            switch (opcode)
            {
            case GerberOpcodes.Add:
            case GerberOpcodes.Subtract:
                return(1);

            case GerberOpcodes.Multiple:
            case GerberOpcodes.Divide:
                return(2);
            }

            return(0);
        }
Beispiel #2
0
        public static ApertureMacro ProcessApertureMacro(GerberLineReader reader)
        {
            const int         MathOperationStackSize = 2;
            ApertureMacro     apertureMacro          = new ApertureMacro();
            GerberInstruction instruction;

            GerberOpcodes[] mathOperations = new GerberOpcodes[MathOperationStackSize];
            char            characterRead;
            int             primitive          = 0;
            int             mathOperationIndex = 0;
            int             equate             = 0;
            bool            continueLoop       = true;
            bool            comma          = false; // Just read an operator (one of '*+X/)
            bool            isNegative     = false; // Negative numbers succeeding ','
            bool            foundPrimitive = false;
            int             length         = 0;

            // Get macro name
            apertureMacro.Name = reader.GetStringValue('*');
            characterRead      = reader.Read(); // skip '*'

            // The first instruction in all programs will be NOP.
            instruction        = new GerberInstruction();
            instruction.Opcode = GerberOpcodes.NOP;
            apertureMacro.InstructionList.Add(instruction);

            while (continueLoop && !reader.EndOfFile)
            {
                length        = 0;
                characterRead = reader.Read();
                switch (characterRead)
                {
                case '$':
                    if (foundPrimitive)
                    {
                        instruction        = new GerberInstruction();
                        instruction.Opcode = GerberOpcodes.PushParameter;
                        apertureMacro.InstructionList.Add(instruction);
                        apertureMacro.NufPushes++;
                        instruction.Data.IntValue = reader.GetIntegerValue(ref length);
                        comma = false;
                    }

                    else
                    {
                        equate = reader.GetIntegerValue(ref length);
                    }

                    break;

                case '*':
                    while (mathOperationIndex != 0)
                    {
                        instruction        = new GerberInstruction();
                        instruction.Opcode = mathOperations[--mathOperationIndex];
                        apertureMacro.InstructionList.Add(instruction);
                    }

                    // Check is due to some gerber files has spurious empty lines (eg EagleCad)
                    if (foundPrimitive)
                    {
                        instruction = new GerberInstruction();
                        if (equate > 0)
                        {
                            instruction.Opcode        = GerberOpcodes.PopParameter;
                            instruction.Data.IntValue = equate;
                        }

                        else
                        {
                            instruction.Opcode        = GerberOpcodes.Primative;
                            instruction.Data.IntValue = primitive;
                        }

                        apertureMacro.InstructionList.Add(instruction);

                        equate         = 0;
                        primitive      = 0;
                        foundPrimitive = false;
                    }
                    break;

                case '=':
                    if (equate > 0)
                    {
                        foundPrimitive = true;
                    }

                    break;

                case ',':
                    if (!foundPrimitive)
                    {
                        foundPrimitive = true;
                        break;
                    }

                    while (mathOperationIndex != 0)
                    {
                        instruction        = new GerberInstruction();
                        instruction.Opcode = mathOperations[--mathOperationIndex];
                        apertureMacro.InstructionList.Add(instruction);
                    }

                    comma = true;
                    break;

                case '+':
                    while ((mathOperationIndex != 0) &&
                           OperatorPrecedence((mathOperationIndex > 0) ? mathOperations[mathOperationIndex - 1] : GerberOpcodes.NOP) >=
                           (OperatorPrecedence(GerberOpcodes.Add)))
                    {
                        instruction        = new GerberInstruction();
                        instruction.Opcode = mathOperations[--mathOperationIndex];
                        apertureMacro.InstructionList.Add(instruction);
                    }

                    mathOperations[mathOperationIndex++] = GerberOpcodes.Add;
                    comma = true;
                    break;

                case '-':
                    if (comma)
                    {
                        isNegative = true;
                        comma      = false;
                        break;
                    }

                    while ((mathOperationIndex != 0) &&
                           OperatorPrecedence((mathOperationIndex > 0) ? mathOperations[mathOperationIndex - 1] : GerberOpcodes.NOP) >=
                           (OperatorPrecedence(GerberOpcodes.Subtract)))
                    {
                        instruction        = new GerberInstruction();
                        instruction.Opcode = mathOperations[--mathOperationIndex];
                        apertureMacro.InstructionList.Add(instruction);
                    }

                    mathOperations[mathOperationIndex++] = GerberOpcodes.Subtract;
                    break;

                case '/':
                    while ((mathOperationIndex != 0) &&
                           OperatorPrecedence((mathOperationIndex > 0) ? mathOperations[mathOperationIndex - 1] : GerberOpcodes.NOP) >=
                           (OperatorPrecedence(GerberOpcodes.Divide)))
                    {
                        instruction        = new GerberInstruction();
                        instruction.Opcode = mathOperations[--mathOperationIndex];
                        apertureMacro.InstructionList.Add(instruction);
                    }

                    mathOperations[mathOperationIndex++] = GerberOpcodes.Divide;
                    comma = true;
                    break;

                case 'X':
                case 'x':
                    while ((mathOperationIndex != 0) &&
                           OperatorPrecedence((mathOperationIndex > 0) ? mathOperations[mathOperationIndex - 1] : GerberOpcodes.NOP) >=
                           (OperatorPrecedence(GerberOpcodes.Multiple)))
                    {
                        instruction        = new GerberInstruction();
                        instruction.Opcode = mathOperations[--mathOperationIndex];
                        apertureMacro.InstructionList.Add(instruction);
                    }

                    mathOperations[mathOperationIndex++] = GerberOpcodes.Multiple;
                    comma = true;
                    break;

                case '0':
                case '1':
                case '2':
                case '3':
                case '4':
                case '5':
                case '6':
                case '7':
                case '8':
                case '9':
                case '.':
                    // Comments in aperture macros are a definition starting with zero and ends with a '*'
                    if ((characterRead == '0') && (!foundPrimitive) && (primitive == 0))
                    {
                        // Comment continues until next '*', just throw it away.
                        reader.GetStringValue('*');
                        characterRead = reader.Read();     // Read the '*'.
                        break;
                    }

                    // First number in an aperture macro describes the primitive as a numerical value
                    if (!foundPrimitive)
                    {
                        primitive = (primitive * 10) + (characterRead - '0');
                        break;
                    }

                    reader.Position--;
                    instruction        = new GerberInstruction();
                    instruction.Opcode = GerberOpcodes.Push;
                    apertureMacro.InstructionList.Add(instruction);
                    apertureMacro.NufPushes++;
                    instruction.Data.DoubleValue = reader.GetDoubleValue();
                    if (isNegative)
                    {
                        instruction.Data.DoubleValue = -(instruction.Data.DoubleValue);
                    }

                    isNegative = false;
                    comma      = false;
                    break;

                case '%':
                    reader.Position--;          // Must return with % first in string since the main parser needs it.
                    continueLoop = false;       // Reached the end of the macro.
                    break;

                default:
                    // Whitespace.
                    break;
                }
            }

            if (reader.EndOfFile)
            {
                return(null);
            }

            return(apertureMacro);
        }