199 lines
3.1 KiB
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");
|
|
}
|
|
|
|
|
|
|