Ejemplo n.º 1
0
        bool ParseToolScript( string s )
        {
            int linecounter = -1;

            try
            {

                //_toolpaths.Clear();
                //_rawElements.Clear();

                //_toolpaths.Clear();
                //_features.Clear();

                tabWidth = eval(tbTabWidth.Text);

                float fRotation = eval(tbRotateDegrees.Text);
                PointF pRotationCenter = evalPoint(tbRotateCenter.Text);

                Color currentColor = Color.Green;

                Feature currentFeature = new Feature( FeatureType.Reference );

                Dictionary<string, string> variables = new Dictionary<string, string>();

                PointF pOffset = new PointF(0, 0);
                float fScale = 1.0f;

                float.TryParse(tbScale.Text, out fScale);
                string[] offsets = tbOffset.Text.Split(new char[] { ',' });
                if (offsets.Length > 1)
                {
                    pOffset.X = float.Parse(offsets[0]);
                    pOffset.Y = float.Parse(offsets[1]);
                }

                // grab the text
                //string s = editor.Text;

                // comments: C++, C, perl

                // FIXME: deal with the c++ comment differently so we can match
                // up line numbers below (for errors)

                s = new Regex(@"/\*..*?\*/", RegexOptions.Singleline).Replace(s, "\r\n");
                s = new Regex(@"//.*$", RegexOptions.Multiline).Replace(s, "");
                s = new Regex(@"#.*$", RegexOptions.Multiline).Replace(s, "");

                // split into single lines... ?
                s = s.Replace("\r\n", "\n");
                string[] lines = s.Split(new char[] { '\n' });//, StringSplitOptions.RemoveEmptyEntries);

                foreach (string baseline in lines)
                {
                    linecounter++;

                    string line = baseline.Trim();
                    if (line.Equals("")) continue;

                    string keyword = new Regex(@"(?:\W|\s).*$", RegexOptions.Singleline).Replace(line, "").ToUpper();
                    string parmstring = new Regex(@"^\S+\s+", RegexOptions.Singleline).Replace( line + " ", "").ToUpper();

                    foreach (string key in variables.Keys)
                    {
                        parmstring = new Regex(@"(?<=^|\s|\W)\$" + key + @"(?=$|\s|\W)").Replace(parmstring, variables[key]);
                    }

                    bool handled = false;

                    if (keyword.Equals("SET"))
                    {
                        // problem: variable could be an expression.  either
                        // (1) evaluate before setting here; or (2) wrap in
                        // parens.  each is equally valid, should be no difference
                        // in effects because we replace variables _before_ this
                        // point.  if we were replacing variables _after_ this,
                        // then the parens would be a no brainer.

                        // CHANGEME? for now, eval.

                        string[] parms = parmstring.Split(new char[] { '=' });
                        parms[0] = parms[0].Trim().ToUpper();
                        float evar = eval(parms[1]);
                        if (variables.ContainsKey(parms[0])) variables[parms[0]] = evar.ToString();
                        else variables.Add(parms[0], evar.ToString());
                        logMessage(string.Format("Set {0} = {1:0.00}", parms[0], evar ));
                        handled = true;
                    }

                    if (!handled)
                    {
                        string[] parms = parmstring.Split(new char[] { ' ', '\t' }, StringSplitOptions.RemoveEmptyEntries);
                        for (int i = 0; i < parms.Length; i++) parms[i] = new Regex(@"\W").Replace(parms[i], "");

                        handled = true;
                        switch (keyword)
                        {
                            // feature definitions

                            case "PROFILE":
                                if (null != currentFeature && currentFeature.Count() > 0)
                                    _features.Add(currentFeature);
                                currentFeature = new Feature( FeatureType.Profile );
                                break;

                            case "POCKET":
                                if (null != currentFeature && currentFeature.Count() > 0)
                                    _features.Add(currentFeature);
                                currentFeature = new Feature( FeatureType.Pocket | FeatureType.Shadowfill );
                                break;

                            case "TRACE":
                                if (null != currentFeature && currentFeature.Count() > 0)
                                    _features.Add(currentFeature);
                                currentFeature = new Feature( FeatureType.Trace );
                                break;

                            case "REFERENCE":
                                if (null != currentFeature && currentFeature.Count() > 0)
                                    _features.Add(currentFeature);
                                currentFeature = new Feature( FeatureType.Reference );
                                break;

                            // option

                            case "COLOR": // feature color, just for painting

                                currentColor = System.Drawing.ColorTranslator.FromHtml(parms[0]);

                                break;

                            default:
                                handled = false;
                                break;
                        }

                        if (handled)
                        {
                            foreach (string p in parms)
                            {
                                if (p.Equals("DOUBLE")) currentFeature.featureType |= FeatureType.Double;
                                if (p.Equals("INSIDE")) currentFeature.featureType |= FeatureType.Inside;
                                if (p.Equals("DOGBONE") || p.Equals("BONE")) currentFeature.featureType |= FeatureType.Dogbone;
                                //if (p.Equals("SHADOWFILL") || p.Equals("SHADOW")) currentFeature.featureType |= FeatureType.Shadowfill;
                                if (p.Equals("POLYGONFILL") || p.Equals("POLYFILL")) currentFeature.featureType &= ~FeatureType.Shadowfill;
                                if (p.Equals("TAB") || p.Equals("TABS")) currentFeature.featureType |= FeatureType.Tabs;
                            }

                            //logMessage("Feature: " + currentFeature.featureType);
                        }

                    }

                    if (!handled)
                    {
                        string[] parms = parmstring.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);

                        // math ops on all parms [ FIXME: use named parms? ]

                        float[] fparms = new float[parms.Length];
                        for (int i = 0; i < parms.Length; i++)
                        {
                            //parms[i] = new DataTable().Compute(parms[i], null).ToString();
                            //fparms[i] = float.Parse(parms[i].Trim());
                            fparms[i] = eval(parms[i]);
                        }
                        int tabs = 0;

                        //ToolpathElement elt = null;
                        List<ToolpathElement> elts = new List<ToolpathElement>();

                        switch (keyword)
                        {
                            // global config options

                            case "OFFSET": // reset offset
                                pOffset = new PointF(fparms[0], fparms[1]);
                                break;

                            case "ROTATE": // rotation, degrees
                                fRotation = fparms[0];
                                break;

                            case "CENTER": // rotation center
                                pRotationCenter = new PointF(fparms[0], fparms[1]);
                                break;

                            case "SCALE": // reset scale
                                fScale = fparms[0];
                                break;

                            // feature options

                            case "DEPTH": // depth from top
                                currentFeature.Depth = fparms[0];
                                break;

                            case "START": // depth from top to _START_ cutting, if not default
                                currentFeature.Start = fparms[0];
                                break;

                            // basic types

                            case "ARC": // center.x, center.y, diameter, start, end
                                elts.Add(new Arc(new PointF(fparms[0], fparms[1]), fparms[2], -1, fparms[3], fparms[4]));
                                break;

                            case "ARC2": // center.x, center.y, diameter, diameter2, start, end
                                elts.Add(new Arc(new PointF(fparms[0], fparms[1]), fparms[2], fparms[3], fparms[4], fparms[5]));
                                break;

                            case "CIRCLE": // center.x, center.y, diameter

                                Arc circle = new Arc(new PointF(fparms[0], fparms[1]), fparms[2]);
                                //if (fparms.Length > 3) circle.Tab = true;
                                elts.Add(circle);
                                break;

                            case "LINE": // start.x, start.y, end.x, end.y
                                elts.Add(new Line(new PointF(fparms[0], fparms[1]), new PointF(fparms[2], fparms[3])));
                                break;

                                /*
                            case "TAB": // start.x, start.y, end.x, end.y
                                ToolpathElement elt = (new Line(new PointF(fparms[0], fparms[1]), new PointF(fparms[2], fparms[3])));
                                elt.Tab = true;
                                elts.Add(elt);
                                break;
                                */

                            // convenience types

                            case "RECT": // origin.x, origin.y, width, height, [tabs]

                                elts.Add(new Line(new PointF(fparms[0], fparms[1]), new PointF(fparms[0], fparms[1] + fparms[3])));
                                elts.Add(new Line(new PointF(fparms[0] + fparms[2], fparms[1]), new PointF(fparms[0] + fparms[2], fparms[1] + fparms[3])));
                                elts.Add(new Line(new PointF(fparms[0], fparms[1]), new PointF(fparms[0] + fparms[2], fparms[1])));
                                elts.Add(new Line(new PointF(fparms[0], fparms[1] + fparms[3]), new PointF(fparms[0] + fparms[2], fparms[1] + fparms[3])));

                                /*
                                if (fparms.Length > 4)
                                {
                                    int flags = (int)fparms[4];
                                    if ((flags & 0x01) != 0) elts[0].Tab = true;
                                    if ((flags & 0x02) != 0) elts[1].Tab = true;
                                    if ((flags & 0x04) != 0) elts[2].Tab = true;
                                    if ((flags & 0x08) != 0) elts[3].Tab = true;
                                }
                                */

                                break;

                            case "ROUNDRECT": // origin.x, origin.y, width, height, diameter, [tabs]

                                float r = fparms[4] / 2.0f;

                                // edges

                                elts.Add(new Line(new PointF(fparms[0], fparms[1] + r), new PointF(fparms[0], fparms[1] + fparms[3] - r)));
                                elts.Add(new Line(new PointF(fparms[0] + fparms[2], fparms[1] + r), new PointF(fparms[0] + fparms[2], fparms[1] + fparms[3] - r)));
                                elts.Add(new Line(new PointF(fparms[0] + r, fparms[1]), new PointF(fparms[0] + fparms[2] - r, fparms[1])));
                                elts.Add(new Line(new PointF(fparms[0] + r, fparms[1] + fparms[3]), new PointF(fparms[0] + fparms[2] - r, fparms[1] + fparms[3])));

                                // round corners

                                elts.Add(new Arc(new PointF(fparms[0] + r, fparms[1] + fparms[3] - r), fparms[4], -1, 180, 270));
                                elts.Add(new Arc(new PointF(fparms[0] + fparms[2] - r, fparms[1] + fparms[3] - r), fparms[4], -1, 270, 360));
                                elts.Add(new Arc(new PointF(fparms[0] + fparms[2] - r, fparms[1] + r), fparms[4], -1, 0, 90));
                                elts.Add(new Arc(new PointF(fparms[0] + r, fparms[1] + r), fparms[4], -1, 90, 180));

                                /*
                                if (fparms.Length > 5)
                                {
                                    int flags = (int)fparms[5];
                                    if ((flags & 0x01) != 0) elts[0].Tab = true;
                                    if ((flags & 0x02) != 0) elts[1].Tab = true;
                                    if ((flags & 0x04) != 0) elts[2].Tab = true;
                                    if ((flags & 0x08) != 0) elts[3].Tab = true;
                                }
                                */

                                break;
                        }

                        foreach (ToolpathElement elt in elts)
                        {
                            // add any translation/scale
                            ToolpathElement tp = elt.Clone();

                            // set color...
                            tp.color = currentColor;

                            if (fRotation != 0) tp = tp.Rotate(fRotation, pRotationCenter);
                            currentFeature.Add(tp.Scale(fScale).Offset(pOffset));
                            //logMessage("Path element: " + elt.elementType);
                        }

                    }
                }
                linecounter = -1;

                if (null != currentFeature && currentFeature.Count() > 0 ) _features.Add(currentFeature);

                int elementCount = 0;
                foreach (Feature feature in _features)
                {
                    elementCount += feature.Count();
                }

                Invoke( new Action<string>(( str ) => { statusMessage.Text = str; }), new object[]{
                    string.Format( "Parse OK: {0} element{1} in {2} feature{3}",
                        elementCount, elementCount == 1 ? "" : "s",
                        _features.Count(), _features.Count() == 1 ? "" : "s" )
                    });

            }
            catch (Exception e)
            {
                if (linecounter >= 0)
                {
                    logMessage("Parse error on script line " + linecounter);
                    Invoke(new Action<int>((line) => { highlightCodeError( line ); }), new object[] { linecounter });
                }
                logMessage(e.Message);
                logMessage(e.StackTrace);
                Invoke(new Action<string>((str) => { statusMessage.Text = str; ctc.SelectedIndex = 0;  }), new object[] { "Parse error, see log" });

                return false;
            }

            return true;
        }