C# Vraagje

Vragen die je boven niet kwijt kunt, kan je hier stellen.

Moderator: Moderators

Plaats reactie
hfjbuis
Donateur
Berichten: 3078
Lid geworden op: 13 feb 2017 00:26
Locatie: Hoensbroek

Re: C# Vraagje

Bericht door hfjbuis »

Arie Kabaalstra schreef: 12 feb 2023 12:57 Dus... G01 X20 Y20 Z20 is goed..
maar... Gosub Finish.. is niet goed
De vraag is hoe herken ik de Gxx met regex
De Gode die met een G beginnen worden gevolgd door 1tot 3 cijfers en optioneel een punt en nog 1tot 2cijfers.

Zo uit het hoofd:

Code: Selecteer alles

      public const string RegexMaskValue = @"G\d{1,3}(.\d{1,2})?";
De @ dient voor het gebruik van de \ in de string
De G is een literal, die moet voorkomene
\d is een decimaal
{1,3} die 1 tot 3 keer moet voorkomen
(....) is een groep
? de groep moet 0 of 1 keer voorkomen
. is een literal
\d is een decimaal
{1,2} die 1tot 2 keer moet voorkomen

Nu is de vraag wat achter de gcode komt. Als dat altijd een spatie moet zijn dan wordt het (spatie achter de ? die bij de groep hoort):

Code: Selecteer alles

      public const string RegexMaskValue = @"G\d{1,3}(.\d{1,2})? ";
There are only 2 limits, the sky and your imagination
hfjbuis
Donateur
Berichten: 3078
Lid geworden op: 13 feb 2017 00:26
Locatie: Hoensbroek

Re: C# Vraagje

Bericht door hfjbuis »

Ik gebruik regex veel, meestal is het copy/paste/ en een beetje aanpassen. Meestal moet ik het boekje erbij pakken.
Regular Expressions Pocket Reference van O'Reily
https://www.amazon.nl/s?k=978-059651427 ... nb_sb_noss
Letop, er zijn ook PDF en Kindle edities van
There are only 2 limits, the sky and your imagination
Gebruikersavatar
Arie Kabaalstra
Donateur
Berichten: 13495
Lid geworden op: 07 feb 2007 18:37
Locatie: Bakhuuz'n
Contacteer:

Re: C# Vraagje

Bericht door Arie Kabaalstra »

Code: Selecteer alles

@"G\d{1,3}(.\d{1,2})? "
Ja.. die werkt.. ik heb alleen die spatie weggehaald.. omdat met name Mcodes doorgaans zonder verdere aanduiding gebruikt worden..Ik heb zelf immers M100 en M101 aangemaakt in EdingCNC, M100 slaat de huidige coordinaten (machinecoordinaten) op, en M101 verplaatst in ijlgang naar deze coordinaten.. zo kun je een punt snel vastleggen, weg joggen en snel weer terugkeren naar dit punt. (op de draaibank reuze handig.. want je Jogt een eind van je werkstuk om gereedschappen te wisselen. dat punt leg je vast met M100, en als je gaat wisselen.. M101 en dan M6 T...easy as 355/113 :P

Nu alleen nog even uitvlooien hoe ik alles op een regel na een ; of tussen () in één kleur krijg..ongeacht wat er in die regel staat... of heeft dat mogelijkerwijs ook met de volgorde te maken?..
Gebruikersavatar
Arie Kabaalstra
Donateur
Berichten: 13495
Lid geworden op: 07 feb 2007 18:37
Locatie: Bakhuuz'n
Contacteer:

Re: C# Vraagje

Bericht door Arie Kabaalstra »

hfjbuis schreef: 12 feb 2023 14:25 Ik gebruik regex veel, meestal is het copy/paste/ en een beetje aanpassen. Meestal moet ik het boekje erbij pakken.
Regular Expressions Pocket Reference van O'Reily
https://www.amazon.nl/s?k=978-059651427 ... nb_sb_noss
Letop, er zijn ook PDF en Kindle edities van
een boek bladert altijd wel lekker.. ik heb em net in mijn mandje gemikt.. vrijdag zou ie er moeten zijn...
hfjbuis
Donateur
Berichten: 3078
Lid geworden op: 13 feb 2017 00:26
Locatie: Hoensbroek

Re: C# Vraagje

Bericht door hfjbuis »

Arie Kabaalstra schreef: 12 feb 2023 14:44 Nu alleen nog even uitvlooien hoe ik alles op een regel na een ; of tussen () in één kleur krijg..ongeacht wat er in die regel staat... of heeft dat mogelijkerwijs ook met de volgorde te maken?..

Code: Selecteer alles

 public const string RegexMaskValue = @";.*\r\n";
; is literal
. is elk karakter behalve cr lf
* match voorgaande 0 of meerdere keren
\r\n tot aan de cr lf
Voor de tekst tussen ()

Code: Selecteer alles

 public const string RegexMaskValue = @"\(.*)";
\( is een haakje openen

Nu zie ik dat de punt uit de vorige expressie \. had moeten zijn omdat . voor een willekeurig karakter staat en \'. staat voor een punt. Daarmee zou G91a1 ook goed zijn.

Code: Selecteer alles

      
      public const string RegexMaskValue = @"G\d{1,3}(\.\d{1,2})?";
There are only 2 limits, the sky and your imagination
Leeuwinga
Berichten: 2983
Lid geworden op: 29 apr 2007 15:00
Locatie: Roden
Contacteer:

Re: C# Vraagje

Bericht door Leeuwinga »

vraag het eens aan Chatgpt :lol:
hfjbuis
Donateur
Berichten: 3078
Lid geworden op: 13 feb 2017 00:26
Locatie: Hoensbroek

Re: C# Vraagje

Bericht door hfjbuis »

Ik heb het eens geprobeerd, hier het resultaat. Echt niet verkeerd behalve dat volgens deze regex de regel moet beginnen met een G.

Code: Selecteer alles

create c# regex for selecting text that starts with G, followed by 1 to 3 digits and optionally a dot and 1 to 2 digits

Regex: ^G\d{1,3}(\.\d{1,2})?
There are only 2 limits, the sky and your imagination
Gebruikersavatar
Arie Kabaalstra
Donateur
Berichten: 13495
Lid geworden op: 07 feb 2007 18:37
Locatie: Bakhuuz'n
Contacteer:

Re: C# Vraagje

Bericht door Arie Kabaalstra »

hfjbuis schreef: 12 feb 2023 17:40 Ik heb het eens geprobeerd, hier het resultaat. Echt niet verkeerd behalve dat volgens deze regex de regel moet beginnen met een G.

Code: Selecteer alles

create c# regex for selecting text that starts with G, followed by 1 to 3 digits and optionally a dot and 1 to 2 digits

Regex: ^G\d{1,3}(\.\d{1,2})?
Nou dat lijkt me niet verkeerd voor een G38.2 G59.1 of G92.1..
Als zodanig heb ik ze nu ook in de code staan.. ik weet niet of Mcodes ook met een punt kunnen... dat moet ik nog eens uitvlooien.. als ik er een toepassing voor kan verzinnen.. Wie weet wat ik er nog voor verzin.. iets met optionele operatoren..

(Volgens de Officiele specificaties is G Code, oftewel ISO9683 een Imperatieve, procedurele taal, officieel heeft het geen klassen.. maar wij weten inmiddels beter.. Object georienteerd is het ook niet.. maar ook daar hebben we een broertje dood aan.
Eigenlijk is het wel gaaf om op deze manier ook met de ontwikkeling van een taal bezig te zijn.. : 8)

Het enige waar ik nog mee zit is het "per ongeluk" gebruik van keywords die een andere kleur krijgen, in een commentaar regel... daar moet alles groen worden.. ongeacht de kleur van een keyword.. en dat doet ie dus nog nie...

nou moet ik toegeven dat het momenteel nog een beetje aanklooien is.. ik werk op een 12" laptopje.. en niet thuis op 3 19" schermen naast elkaar...
Gebruikersavatar
newhumanoid
Berichten: 102
Lid geworden op: 07 okt 2022 17:23
Locatie: Oekraïne, Nikolajev

Re: C# Vraagje

Bericht door newhumanoid »

If I understand the question correctly. There is a good prototype in the open source code of GRBL.
https://github.com/fra589/grbl-Mega-5X
There is a module gcode.c
It has the function of parsing the string G, M, F, S ... codes, digital part and coordinates.
It can be taken with minor modifications.
hfjbuis
Donateur
Berichten: 3078
Lid geworden op: 13 feb 2017 00:26
Locatie: Hoensbroek

Re: C# Vraagje

Bericht door hfjbuis »

I am pretty familiar with grbl (and compatibles). The grbl code is written for the arduino uno. Main goal was getting it to fit in the small arduino memory and run fast on an 8 bit processor. Therefore the code isn't easy to read or parce from C++ to C#.
There are only 2 limits, the sky and your imagination
Gebruikersavatar
newhumanoid
Berichten: 102
Lid geworden op: 07 okt 2022 17:23
Locatie: Oekraïne, Nikolajev

Re: C# Vraagje

Bericht door newhumanoid »

hfjbuis schreef: 12 feb 2023 23:18 Therefore the code isn't easy to read or parce from C++ to C#.
Here is a function for parsing numbers.
How does it differ PRINCIPALLY from C#?
Moreover, the code is commented.

Code: Selecteer alles

uint8_t read_float(char *line, uint8_t *char_counter, float *float_ptr)
{
  char *ptr = line + *char_counter;
  unsigned char c;

  // Grab first character and increment pointer. No spaces assumed in line.
  c = *ptr++;

  // Capture initial positive/minus character
  bool isnegative = false;
  if (c == '-') {
    isnegative = true;
    c = *ptr++;
  } else if (c == '+') {
    c = *ptr++;
  }

  // Extract number into fast integer. Track decimal in terms of exponent value.
  uint32_t intval = 0;
  int8_t exp = 0;
  uint8_t ndigit = 0;
  bool isdecimal = false;
  while(1) {
    c -= '0';
    if (c <= 9) {
      ndigit++;
      if (ndigit <= MAX_INT_DIGITS) {
        if (isdecimal) { exp--; }
        intval = (((intval << 2) + intval) << 1) + c; // intval*10 + c
      } else {
        if (!(isdecimal)) { exp++; }  // Drop overflow digits
      }
    } else if (c == (('.'-'0') & 0xff)  &&  !(isdecimal)) {
      isdecimal = true;
    } else {
      break;
    }
    c = *ptr++;
  }

  // Return if no digits have been read.
  if (!ndigit) { return(false); };

  // Convert integer into floating point.
  float fval;
  fval = (float)intval;

  // Apply decimal. Should perform no more than two floating point multiplications for the
  // expected range of E0 to E-4.
  if (fval != 0) {
    while (exp <= -2) {
      fval *= 0.01;
      exp += 2;
    }
    if (exp < 0) {
      fval *= 0.1;
    } else if (exp > 0) {
      do {
        fval *= 10.0;
      } while (--exp > 0);
    }
  }

  // Assign floating point value with correct sign.
  if (isnegative) {
    *float_ptr = -fval;
  } else {
    *float_ptr = fval;
  }

  *char_counter = ptr - line - 1; // Set char_counter to next statement

  return(true);
}

And a snippet of the parsing code.

Code: Selecteer alles

  /* -------------------------------------------------------------------------------------
     STEP 2: Import all g-code words in the block line. A g-code word is a letter followed by
     a number, which can either be a 'G'/'M' command or sets/assigns a command value. Also,
     perform initial error-checks for command word modal group violations, for any repeated
     words, and for negative values set for the value words F, N, P, T, and S. */

  uint32_t dword_bit; // Bit-value for assigning tracking variables
  uint8_t char_counter;
  char letter;
  float value;
  uint8_t int_value = 0;
  uint16_t mantissa = 0;
  if (gc_parser_flags & GC_PARSER_JOG_MOTION) { char_counter = 3; } // Start parsing after `$J=`
  else { char_counter = 0; }

  while (line[char_counter] != 0) { // Loop until no more g-code words in line.

    // Import the next g-code word, expecting a letter followed by a value. Otherwise, error out.
    letter = line[char_counter];
    if((letter < 'A') || (letter > 'Z')) { FAIL(STATUS_EXPECTED_COMMAND_LETTER); } // [Expected word letter]
    char_counter++;
    if (!read_float(line, &char_counter, &value)) { FAIL(STATUS_BAD_NUMBER_FORMAT); } // [Expected word value]

    // Convert values to smaller uint8 significand and mantissa values for parsing this word.
    // NOTE: Mantissa is multiplied by 100 to catch non-integer command values. This is more
    // accurate than the NIST gcode requirement of x10 when used for commands, but not quite
    // accurate enough for value words that require integers to within 0.0001. This should be
    // a good enough comprimise and catch most all non-integer errors. To make it compliant,
    // we would simply need to change the mantissa to int16, but this add compiled flash space.
    // Maybe update this later.
    int_value = trunc(value);
    mantissa =  round(100*(value - int_value)); // Compute mantissa for Gxx.x commands.
    // NOTE: Rounding must be used to catch small floating point errors.

    // Check if the g-code word is supported or errors due to modal group violations or has
    // been repeated in the g-code block. If ok, update the command or record its value.
    switch(letter) {

      /* 'G' and 'M' Command Words: Parse commands and check for modal group violations.
         NOTE: Modal group numbers are defined in Table 4 of NIST RS274-NGC v3, pg.20 */

      case 'G':
        // Determine 'G' command and its modal group
        switch(int_value) {
          case 10: case 28: case 30: case 92:
            // Check for G10/28/30/92 being called with G0/1/2/3/38 on same block.
            // * G43.1 is also an axis command but is not explicitly defined this way.
            if (mantissa == 0) { // Ignore G28.1, G30.1, and G92.1
              if (axis_command) { FAIL(STATUS_GCODE_AXIS_COMMAND_CONFLICT); } // [Axis word/command conflict]
              axis_command = AXIS_COMMAND_NON_MODAL;
            }
            // No break. Continues to next line.
          case 4: case 53:
            dword_bit = MODAL_GROUP_G0;
            gc_block.non_modal_command = int_value;
            if ((int_value == 28) || (int_value == 30) || (int_value == 92)) {
              if (!((mantissa == 0) || (mantissa == 10))) { FAIL(STATUS_GCODE_UNSUPPORTED_COMMAND); }
              gc_block.non_modal_command += mantissa;
              mantissa = 0; // Set to zero to indicate valid non-integer G command.
            }
            break;
          case 0: case 1: case 2: case 3: case 38:
            // Check for G0/1/2/3/38 being called with G10/28/30/92 on same block.
            // * G43.1 is also an axis command but is not explicitly defined this way.
            if (axis_command) { FAIL(STATUS_GCODE_AXIS_COMMAND_CONFLICT); } // [Axis word/command conflict]
            axis_command = AXIS_COMMAND_MOTION_MODE;
            // No break. Continues to next line.
          case 80:
            dword_bit = MODAL_GROUP_G1;
            gc_block.modal.motion = int_value;
            if (int_value == 38){
              if (!((mantissa == 20) || (mantissa == 30) || (mantissa == 40) || (mantissa == 50))) {
                FAIL(STATUS_GCODE_UNSUPPORTED_COMMAND); // [Unsupported G38.x command]
              }
              gc_block.modal.motion += (mantissa/10)+100;
              mantissa = 0; // Set to zero to indicate valid non-integer G command.
            }
            break;
          case 17: case 18: case 19:
            dword_bit = MODAL_GROUP_G2;
            gc_block.modal.plane_select = int_value - 17;
            break;
          case 90: case 91:
            if (mantissa == 0) {
              dword_bit = MODAL_GROUP_G3;
              gc_block.modal.distance = int_value - 90;
            } else {
              dword_bit = MODAL_GROUP_G4;
              if ((mantissa != 10) || (int_value == 90)) { FAIL(STATUS_GCODE_UNSUPPORTED_COMMAND); } // [G90.1 not supported]
              mantissa = 0; // Set to zero to indicate valid non-integer G command.
              // Otherwise, arc IJK incremental mode is default. G91.1 does nothing.
            }
            break;
          case 93: case 94:
            dword_bit = MODAL_GROUP_G5;
            gc_block.modal.feed_rate = 94 - int_value;
            break;
          case 20: case 21:
            dword_bit = MODAL_GROUP_G6;
            gc_block.modal.units = 21 - int_value;
            break;
          case 40:
            dword_bit = MODAL_GROUP_G7;
            // NOTE: Not required since cutter radius compensation is always disabled. Only here
            // to support G40 commands that often appear in g-code program headers to setup defaults.
            // gc_block.modal.cutter_comp = CUTTER_COMP_DISABLE; // G40
            break;
          case 43: case 49:
            dword_bit = MODAL_GROUP_G8;
            // NOTE: The NIST g-code standard vaguely states that when a tool length offset is changed,
            // there cannot be any axis motion or coordinate offsets updated. Meaning G43, G43.1, and G49
            // all are explicit axis commands, regardless if they require axis words or not.
            if (axis_command) { FAIL(STATUS_GCODE_AXIS_COMMAND_CONFLICT); } // [Axis word/command conflict] }
            axis_command = AXIS_COMMAND_TOOL_LENGTH_OFFSET;
            if (int_value == 49) { // G49
              gc_block.modal.tool_length = TOOL_LENGTH_OFFSET_CANCEL;
            } else if (mantissa == 10) { // G43.1
              gc_block.modal.tool_length = TOOL_LENGTH_OFFSET_ENABLE_DYNAMIC;
            } else { FAIL(STATUS_GCODE_UNSUPPORTED_COMMAND); } // [Unsupported G43.x command]
            mantissa = 0; // Set to zero to indicate valid non-integer G command.
            break;
          case 54: case 55: case 56: case 57: case 58: case 59:
            // NOTE: G59.x are not supported. (But their int_values would be 60, 61, and 62.)
            dword_bit = MODAL_GROUP_G12;
            gc_block.modal.coord_select = int_value - 54; // Shift to array indexing.
            break;
          case 61:
            dword_bit = MODAL_GROUP_G13;
            if (mantissa != 0) { FAIL(STATUS_GCODE_UNSUPPORTED_COMMAND); } // [G61.1 not supported]
            // gc_block.modal.control = CONTROL_MODE_EXACT_PATH; // G61
            break;
          default: FAIL(STATUS_GCODE_UNSUPPORTED_COMMAND); // [Unsupported G command]
        }
        if (mantissa > 0) { FAIL(STATUS_GCODE_COMMAND_VALUE_NOT_INTEGER); } // [Unsupported or invalid Gxx.x command]
        // Check for more than one command per modal group violations in the current block
        // NOTE: Variable 'dword_bit' is always assigned, if the command is valid.
        if ( bit_istrue(command_dwords,dwbit(dword_bit)) ) { FAIL(STATUS_GCODE_MODAL_GROUP_VIOLATION); }
        command_dwords |= dwbit(dword_bit);
        break;

      case 'M':

        // Determine 'M' command and its modal group
        if (mantissa > 0) { FAIL(STATUS_GCODE_COMMAND_VALUE_NOT_INTEGER); } // [No Mxx.x commands]
        switch(int_value) {
          case 0: case 1: case 2: case 30:
This is nothing more than my opinion. If something is wrong, I apologize.
MeMoRy
Berichten: 737
Lid geworden op: 17 okt 2022 09:40
Locatie: Utrecht

Re: C# Vraagje

Bericht door MeMoRy »

hfjbuis schreef: 12 feb 2023 14:17 Zo uit het hoofd:

Code: Selecteer alles

public const string RegexMaskValue =@"G\d{1,3}(.\d{1,2})?";
Nice! 8)
(edit :lol: )
Laatst gewijzigd door MeMoRy op 13 feb 2023 15:08, 1 keer totaal gewijzigd.
Gebruikersavatar
Arie Kabaalstra
Donateur
Berichten: 13495
Lid geworden op: 07 feb 2007 18:37
Locatie: Bakhuuz'n
Contacteer:

Re: C# Vraagje

Bericht door Arie Kabaalstra »

Ja.. wel nice, maar dit is nog de versie zonder \. en da's net niet goed..

@Newhumanoid, my challenge doesn't lie in parsing G-code statements, but in Syntaxis Marking.

For that i use FCTB (Fast Colored Text Box), which is written by your fellow countryman, Pavel Torgashov, he made an Nuget Package of it to easily import it into a C# Project..

My challenge is just that i want specific parts of the Syntaxis colored in a specific way..but if you use "SUB" in a Comment, that will show up in Bold Blue, for subroutine marking, instead of green, like a comment should be... the rest of the comment is green like it should be..
and... if you type "SUB" in a comment, there will also be a folder marking which is also not good.

But Maybe, i should change my RegEx for "SUB" a bit, so that SUB only becomes blue and gets a folding mark, if it occurs at the start of the line of code..
MeMoRy
Berichten: 737
Lid geworden op: 17 okt 2022 09:40
Locatie: Utrecht

Re: C# Vraagje

Bericht door MeMoRy »

newhumanoid schreef: 13 feb 2023 00:43
hfjbuis schreef: 12 feb 2023 23:18 Therefore the code isn't easy to read or parce from C++ to C#.
Here is a function for parsing numbers.
How does it differ PRINCIPALLY from C#?
Well, as a starter there's pointer arithmetic. While it is possible in C#, it's almost never done. C# is just not a low level language. And while C is mostly sticking to it's original 1970-80's imperative syntax and C++ has some progression introducing OO and generics, but also stays behind due to legacy, C# is an evolving language. With lambda's from early days, extension classes/methods and now pattern matching, modern code is written in a more functional programming kind of way. It's just a different language.
I mean, you would not even write that same function in C#, you would just do

Code: Selecteer alles

float.Parse(line);
done

By the way @hfjbuis this is definitely C, not C++.
Plaats reactie