/* * parser.c * * Created on: 10.04.2018 * Author: julian */ #include "parser.h" #include 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"); }