syntaxerror("Not an Integer: \"%s\"", str);
return atoi(str);
}
-int parseRawTwip(char*str)
+static double parseRawTwip(char*str)
{
char*dot;
int sign=1;
if(!dot) {
int l=strlen(str);
int t;
- return sign*parseInt(str)*20;
+ return sign*parseInt(str);
} else {
char* old = strdup(str);
int l=strlen(dot+1);
char*s;
*dot++ = 0;
- for(s=str;s<dot-1;s++)
- if(*s<'0' || *s>'9')
- {
- free(old);
- syntaxerror("Not a coordinate: \"%s\"", str);
+ for(s=str;s<dot-1;s++) {
+ if(*s<'0' || *s>'9')
+ {
+ free(old);
+ syntaxerror("Not a coordinate: \"%s\"", str);
+ }
}
- for(s=dot;*s;s++)
- if(*s<'0' || *s>'9')
- {
- free(old);
- syntaxerror("Not a coordinate: \"%s\"", str);
+ for(s=dot;*s;s++) {
+ if(*s<'0' || *s>'9')
+ {
+ free(old);
+ syntaxerror("Not a coordinate: \"%s\"", str);
+ }
}
if(l>2 || (l==2 && (dot[1]!='0' && dot[1]!='5'))) {
dot[1] = ((dot[1]-0x30)/5)*5 + 0x30;
}
free(old);
if(l==0)
- return sign*(atoi(str)*20);
+ return sign*(atoi(str));
if(l==1)
- return sign*(atoi(str)*20+atoi(dot)*2);
+ return sign*(atoi(str)+0.1*atoi(dot));
if(l==2)
- return sign*(atoi(str)*20+atoi(dot)/5);
+ return sign*(atoi(str)+0.01*atoi(dot));
}
return 0;
}
static int defines_initialized = 0;
static mem_t define_values;
-int parseTwip(char*str)
+static double parseNameOrTwip(char*s)
{
- /* TODO: make this a proper expression parser */
- char*p = str;
- int val = 0;
- char ex = 0;
- char*lastpos = 0;
- while(*p) {
- if(*p == '+' || *p == '-' || *p == '/' || *p == '*')
- ex = *p;
- else if(!lastpos)
- lastpos = p;
- p++;
- if((*p == '+' || *p == '-' || *p == '/' || *p == '*' || *p == 0) && lastpos) {
- char save = *p;
- *p = 0;
-
- int l = 0;
- int v = 0;
- if(defines_initialized) {
- l = (int)dictionary_lookup(&defines, lastpos);
- }
- if(l) {
- v = *(int*)&define_values.buffer[l-1];
- } else {
- v = parseRawTwip(lastpos);
- }
- *p = save;
- if(ex == '+')
- val += v;
- else if(ex == '-')
- val -= v;
- else if(ex == '/')
- val = (val*20) / v;
- else if(ex == '*')
- val = (val*v) / 20;
- else
- val += v;
- ex = 0;
- lastpos = 0;
- }
+ int l = 0;
+ double v;
+ if(defines_initialized) {
+ l = (int)dictionary_lookup(&defines, s);
}
- return val;
+ if(l) {
+ return *(int*)&define_values.buffer[l-1];
+ } else {
+ return parseRawTwip(s);
+ }
+}
+
+/* automatically generated by yiyiyacc, http://www.quiss.org/yiyiyacc/ */
+static double parseExpression(char*s)
+{
+ int chr2index[256];
+ memset(chr2index, -1, sizeof(chr2index));
+ chr2index['+'] = 0;
+ chr2index['-'] = 1;
+ chr2index['*'] = 2;
+ chr2index['/'] = 3;
+ chr2index['('] = 5;
+ chr2index[')'] = 6;
+ chr2index['\0'] = 7;
+
+ int stackpos = 1;
+ int stack[256];
+ double values[256];
+ stack[0]=0;
+ values[0]=0;
+ int accept = 18;
+ int left[10]={11,8,8,8,8,9,9,9,10,10}; //production left side
+ int plen[10]={1,3,2,3,1,3,3,1,1,3}; //production size
+ int table[18][12] = {
+ {0, 4, 0, 0, 5, 6, 0, 0, 1, 2, 3, 0},
+ {7, 8, 0, 0, 0, 0, 0, 18, 0, 0, 0, 0},
+ {-4, -4, 9, 10, 0, 0, -4, -4, 0, 0, 0, 0},
+ {-7, -7, -7, -7, 0, 0, -7, -7, 0, 0, 0, 0},
+ {0, 0, 0, 0, 5, 6, 0, 0, 0, 11, 3, 0},
+ {-8, -8, -8, -8, 0, 0, -8, -8, 0, 0, 0, 0},
+ {0, 4, 0, 0, 5, 6, 0, 0, 12, 2, 3, 0},
+ {0, 0, 0, 0, 5, 6, 0, 0, 0, 13, 3, 0},
+ {0, 0, 0, 0, 5, 6, 0, 0, 0, 14, 3, 0},
+ {0, 0, 0, 0, 5, 6, 0, 0, 0, 0, 15, 0},
+ {0, 0, 0, 0, 5, 6, 0, 0, 0, 0, 16, 0},
+ {-2, -2, 9, 10, 0, 0, -2, -2, 0, 0, 0, 0},
+ {7, 8, 0, 0, 0, 0, 17, 0, 0, 0, 0, 0},
+ {-1, -1, 9, 10, 0, 0, -1, -1, 0, 0, 0, 0},
+ {-3, -3, 9, 10, 0, 0, -3, -3, 0, 0, 0, 0},
+ {-5, -5, -5, -5, 0, 0, -5, -5, 0, 0, 0, 0},
+ {-6, -6, -6, -6, 0, 0, -6, -6, 0, 0, 0, 0},
+ {-9, -9, -9, -9, 0, 0, -9, -9, 0, 0, 0, 0}};
+
+ char*p = s;
+ while(1) {
+ char*pnext = p+1;
+ int action;
+ double value = 0;
+ if(!stackpos) {
+ fprintf(stderr, "Error in expression\n");
+ return 0.0;
+ }
+
+ if(chr2index[*p]<0) {
+ action = table[stack[stackpos-1]][4];
+ if(action>0) {
+ while(chr2index[*pnext]<0)
+ pnext++;
+ char save = *pnext;
+ *pnext = 0;
+ value = parseNameOrTwip(p);
+ *pnext = save;
+ }
+ } else {
+ action = table[stack[stackpos-1]][chr2index[*p]];
+ }
+
+ if(action == accept) {
+ return values[stack[stackpos-1]];
+ } else if(action>0) { // shift
+ if(stackpos>254) {
+ fprintf(stderr, "Stack overflow while parsing expression\n");
+ return 0.0;
+ }
+ values[stackpos]=value;
+ stack[stackpos++]=action;
+ p=pnext;
+ } else if(action<0) { // reduce
+ stackpos-=plen[-action];
+ stack[stackpos] = table[stack[stackpos-1]][left[-action]];
+ switch(-action) {
+ case 1:
+ values[stackpos] = values[stackpos+0] + values[stackpos+2];
+ break;
+ case 2:
+ values[stackpos] = 0 - values[stackpos+1];
+ break;
+ case 3:
+ values[stackpos] = values[stackpos+0] - values[stackpos+2];
+ break;
+ case 5:
+ values[stackpos] = values[stackpos+0] * values[stackpos+2];
+ break;
+ case 6:
+ values[stackpos] = values[stackpos+0] / values[stackpos+2];
+ break;
+ case 9:
+ values[stackpos] = values[stackpos+1];
+ break;
+ }
+ stackpos++;
+ } else {
+ fprintf(stderr, "Syntax error in expression\n");
+ return 0.0;
+ }
+ }
+}
+
+int parseTwip(char*str)
+{
+ int v = (int)(parseExpression(str)*20);
+ printf("%s = %.2f\n", str, v/20.0);
+ return v;
}
int parseArc(char* str)