gcode_interpreter/parser.c

199 lines
3.1 KiB
C

/*
* parser.c
*
* Created on: 10.04.2018
* Author: julian
*/
#include "parser.h"
#include <stdio.h>
int isWhite(char c) {
return c == ' ' || c == '\t' || c == '\r' || c == '\n';
}
int isNumber(char c) {
return c >= '0' && c <= '9';
}
// point that splits real numbers
int isPoint(char c) {
return c == '.' || c == ',';
}
char toLower(char in) {
if (in >= 'A' && in <= 'Z') {
return in - 'A' + 'a';
}
return in;
}
char toUpper(char in) {
if (in >= 'a' && in <= 'z') {
return in - 'a' + 'A';
}
return in;
}
void skipWhite(const char ** start, const char * end) {
if (!start) return;
while(*start < end && isWhite(**start)) {
++*start;
}
}
// returns 1 on success
int asInt(int * result, const char ** start, const char * end) {
if (!result || !start) return 0;
skipWhite(start, end);
if (*start == end) { return 0; }
int inv = 0;
unsigned int count = 0;
switch(**start) {
case '-':
inv = 1;
case '+':
++*start;
break;
}
*result = 0;
for(;*start != end && isNumber(**start); ++*start, count++) {
*result *= 10;
*result += **start - '0';
}
if (inv) {
*result = -*result;
}
return count > 0;
}
int asFloat(float *result, const char **start, const char * end) {
if (!result || !start ) return 0;
skipWhite(start, end);
if (*start == end) return 0;
int nominator = 0;
float denomiator = 0.f;
if (!asInt(&nominator, start, end)) return 0;
if (isPoint(**start)) {
const char * denom_end = *start +1;
while(denom_end < end && isNumber(*denom_end))
denom_end++;
while(--denom_end > *start) {
denomiator += *denom_end - '0';
denomiator /= 10.f;
}
}
*result = (float)(nominator) + denomiator;
return 1;
}
int nextArgument(argument_t* result, const char ** start, const char * end) {
if (!start | !result) return 0;
skipWhite(start, end);
if (*start == end) return 0;
result->c = **start;
++*start;
asFloat(&result->num, start, end);
return 1;
}
volatile int notok;
void gcode(const char * start, const char * end) {
int code;
skipWhite(&start, end);
if (start == end || !asInt(&code, &start, end)) {
error("expected number after G\n");
return;
}
switch(code) {
case 0:
case 1:
// move
move(start, end);
break;
case 28:
// home;
home(start, end);
break;
case 90:
set_move_absolute();
break;
case 91:
set_move_relative();
break;
default:
error("unknown gcode: %d\n",code);
}
}
void mcode(const char * start, const char * end) {
int code;
skipWhite(&start, end);
if (start == end || !asInt(&code, &start, end)) {
printf("expected number after M\n");
return;
}
switch(code) {
case 500:
// save config data
printf("save config data\n");
break;
case 502:
printf("restore default config\n");
break;
default:
error("no Mcode: %d\n", code);
}
}
void parse(const char * start, const char * end) {
notok = 0;
skipWhite(&start, end);
if (start == end) return;
switch (toLower(*start)) {
case 'g':
gcode(++start, end);
break;
case 'm':
mcode(++start, end);
break;
case '?':
state(++start, end);
return;
default:
error("expected g or m codes\n");
}
if (notok) { return; }
printf("ok\n");
}