I have a g-code written in Fanuc g-code format including Macro-B (more info here), for example

#101 = 2.0 (first variable)
#102 = 0.1 (second variable)
#103 = [#101 + #102 * 3] (third variable using simple arithmetic)
G01 X#101 Y#103 F0.1

which should be converted to:

G01 X1.0 Y2.3 F0.1

more elaborate examples here and here.

things to be changed:

  1. all instances of a variable slot should be replace with its value:

(#\d+)\s*=\s*(-?\d*\.\d+|\d+\.\d*)

  1. arithmetic +, -, * and / inside the [...] need to be calculated:

(#\d+)\s*=\s*\[(#\d+|(-?\d*\.\d+|\d+\.\d*))(\s*[+\-*/]\s*(#\d+|(-?\d*\.\d+|\d+\.\d*|\d+)))*\]

  1. comments (...) could be ignored or removed.

I would appreciate if you could help me know how i can do this in Python and if the regex I have above is correct. Thanks for your support in advance.

P.S.1. Unfortunately I can't find the syntax highlighting for fenced code blocks for g-code

P.S.2. when changing floats to strings one should consider the issue with Python floating point handeling. I made this function to solve that:

def f32str(inputFloat):
    """
    This function converts a Python float to a string with 3 decimals
    """
    return str(f"{inputFloat:.3f}")

1 Answers

0
Foad On

OK I scrapped a piece of code which does the job. Assuming gcode is a multiline string read from a Fanuc G-code:

import re
import os

def f32str(inputFloat):
    return str(f"{inputFloat:.3f}")

gcode = re.sub(r"\(.*?\)", "", gcode)

flag = len(re.findall(r"#\d+", gcode))

while 0 < flag:
    cases = re.findall(r"((#\d+)\s*=\s*([-+]?\s*(\d*\.\d+|\d+\.?\d*)))", gcode)
    for case in cases:
        gcode = gcode.replace(case[0], "")
        gcode = gcode.replace(case[0], case[1])
    cases = re.findall(r"(\[(\s*[+-]?\s*(\d+(\.\d*)?|\d*\.\d+)(\s*[-+*\/]\s*[+-]?\s*(\d+(\.\d*)?|\d*\.\d+)\s*)*)\])", gcode)
    for case in cases:
        gcode = gcode.replace(case[0], f32str(eval(case[1])))
    flag = len(re.findall(r"#\d+", gcode))

gcode = os.linesep.join([s for s in gcode.splitlines() if s.strip()])

this is probably the worst way to do this and there should be more efficient implementations. I will leave the rest to the Python experts.