diff options
author | Ian Jauslin <ian.jauslin@roma1.infn.it> | 2016-05-24 13:39:23 +0000 |
---|---|---|
committer | Ian Jauslin <ian.jauslin@roma1.infn.it> | 2016-05-24 13:39:23 +0000 |
commit | fa9b6f2b9bcb80778e63ef2aa4e17c7573de0015 (patch) | |
tree | 92b740d0736c9ed6f5bda051c224c8bb7196bb03 /src/parser.c |
Diffstat (limited to 'src/parser.c')
-rw-r--r-- | src/parser.c | 274 |
1 files changed, 274 insertions, 0 deletions
diff --git a/src/parser.c b/src/parser.c new file mode 100644 index 0000000..9c4801a --- /dev/null +++ b/src/parser.c @@ -0,0 +1,274 @@ +/* +Copyright 2016 Ian Jauslin + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +#include "parser.h" +#include <stdlib.h> +#include <stdio.h> +#include <stdarg.h> +// define MPFR_USE_VA_LIST to enable the use of mpfr_inits and mpfr_clears +#define MPFR_USE_VA_LIST +#include <mpfr.h> + +// read parameter string +#define P_VAR_T1 1 +#define P_VAR_T2 2 +#define P_VAR_LAMBDA 3 +#define P_VAR_OMEGA 4 +#define P_VAR_SINPHI 5 +#define P_VAR_W 6 +#define P_VAR_PHI 7 +int read_params(hh_params* params, char* str){ + char* ptr; + char* buffer; + char* buffer_ptr; + int ret; + int var_flag=0; + unsigned int reset_W=0; + unsigned int set_phi=0; + unsigned int set_sinphi=0; + mpfr_t tmp, tmp2; + + buffer=calloc(str_len(str), sizeof(char)); + buffer_ptr=buffer; + *buffer_ptr='\0'; + + + for(ptr=str; *ptr!='\0'; ptr++){ + switch(*ptr){ + // left side of equation + case '=': + if(str_cmp(buffer, "t1")==1){ + var_flag=P_VAR_T1; + } + else if(str_cmp(buffer, "t2")==1){ + var_flag=P_VAR_T2; + } + else if(str_cmp(buffer, "lambda")==1){ + var_flag=P_VAR_LAMBDA; + } + else if(str_cmp(buffer, "omega")==1){ + var_flag=P_VAR_OMEGA; + } + else if(str_cmp(buffer, "sinphi")==1){ + var_flag=P_VAR_SINPHI; + // reset W to -3*omega*sqrt(3)*sin(phi) provided W is not set explicitly + if(reset_W==0){ + reset_W=1; + } + // do not allow setting both sinphi and phi + set_sinphi=1; + } + else if(str_cmp(buffer, "phi")==1){ + var_flag=P_VAR_PHI; + // reset W to -3*omega*sqrt(3)*sin(phi) provided W is not set explicitly + if(reset_W==0){ + reset_W=1; + } + // do not allow setting both sinphi and phi + set_phi=1; + } + else if(str_cmp(buffer, "W")==1){ + var_flag=P_VAR_W; + // do not reset W + reset_W=2; + } + else{ + fprintf(stderr, "parsing error: unrecognized token '%s'\n", buffer); + free(buffer); + return(-1); + } + + // reset buffer + buffer_ptr=buffer; + *buffer_ptr='\0'; + break; + + // assign value + case ';': + if(var_flag==P_VAR_T1){ + ret=mpfr_set_str(params->t1, buffer, 10, MPFR_RNDN); + if(ret<0){ + fprintf(stderr, "parsing error: t1 must be assigned to an MPFR floating point number\n got '%s'\n", buffer); + free(buffer); + return(-1); + } + } + else if(var_flag==P_VAR_T2){ + ret=mpfr_set_str(params->t2, buffer, 10, MPFR_RNDN); + if(ret<0){ + fprintf(stderr, "parsing error: t2 must be assigned to an MPFR floating point number\n got '%s'\n", buffer); + free(buffer); + return(-1); + } + } + else if(var_flag==P_VAR_LAMBDA){ + ret=mpfr_set_str(params->lambda, buffer, 10, MPFR_RNDN); + if(ret<0){ + fprintf(stderr, "parsing error: lambda must be assigned to an MPFR floating point number\n got '%s'\n", buffer); + free(buffer); + return(-1); + } + } + else if(var_flag==P_VAR_SINPHI){ + if(set_phi==1){ + fprintf(stderr, "error: cannot set both phi and sinphi\n"); + free(buffer); + return(-1); + } + + ret=mpfr_set_str(params->sinphi, buffer, 10, MPFR_RNDN); + if(ret<0){ + fprintf(stderr, "parsing error: sinphi must be assigned to an MPFR floating point number\n got '%s'\n", buffer); + free(buffer); + return(-1); + } + // check value + if(mpfr_cmp_ui(params->sinphi,1)>0 || mpfr_cmp_si(params->sinphi,-1)<0){ + fprintf(stderr, "error: sinphi must be in [-1,1]\n"); + free(buffer); + return(-1); + } + // set phi + mpfr_asin(params->phi, params->sinphi, MPFR_RNDN); + } + else if(var_flag==P_VAR_PHI){ + if(set_sinphi==1){ + fprintf(stderr, "error: cannot set both phi and sinphi\n"); + free(buffer); + return(-1); + } + + ret=mpfr_set_str(params->phi, buffer, 10, MPFR_RNDN); + if(ret<0){ + fprintf(stderr, "parsing error: phi must be assigned to an MPFR floating point number\n got '%s'\n", buffer); + free(buffer); + return(-1); + } + // set sinphi + mpfr_sin(params->sinphi, params->phi, MPFR_RNDN); + } + else if(var_flag==P_VAR_W){ + ret=mpfr_set_str(params->W, buffer, 10, MPFR_RNDN); + if(ret<0){ + fprintf(stderr, "parsing error: W must be assigned to an MPFR floating point number\n got '%s'\n", buffer); + free(buffer); + return(-1); + } + } + else if(var_flag==P_VAR_OMEGA){ + ret=sscanf(buffer, "%d", &(params->omega)); + if(ret!=1){ + fprintf(stderr, "parsing error: omega must be assigned to an integer\n got '%s'\n", buffer); + free(buffer); + return(-1); + } + // check value + if(params->omega!=1 && params->omega!=-1){ + fprintf(stderr, "error: omega must be either +1 or -1\n"); + return(-1); + } + } + else{ + fprintf(stderr, "parsing error: read right side of equation, but the matching token was not found\n"); + free(buffer); + return(-1); + } + + var_flag=0; + + // reset buffer + buffer_ptr=buffer; + *buffer_ptr='\0'; + break; + + // add to buffer + default: + buffer_ptr=str_addchar(buffer_ptr, *ptr); + break; + } + } + + // check that all variables were read + if(*buffer_ptr!='\0'){ + fprintf(stderr, "parsing error: trailing characters: '%s'\n", buffer); + free(buffer); + return(-1); + } + if(var_flag!=0){ + fprintf(stderr, "parsing error: empty assignment at the end of the string\n"); + free(buffer); + return(-1); + } + + // check that 3*abs(t2)<abs(t1) + mpfr_inits(tmp, tmp2, NULL); + mpfr_abs(tmp, params->t2, MPFR_RNDN); + mpfr_mul_ui(tmp, tmp, 3, MPFR_RNDN); + mpfr_abs(tmp2, params->t1, MPFR_RNDN); + if(mpfr_cmp(tmp, tmp2)>0){ + fprintf(stderr, "error: |t2| must be smaller than |t1|/3\n"); + return(-1); + } + + // if W was not set, reset its default to -3*omega*sqrt(3)*t2*sin(phi) + if(reset_W==1){ + mpfr_sqrt_ui(params->W, 3, MPFR_RNDN); + mpfr_mul_ui(params->W, params->W, 3, MPFR_RNDN); + mpfr_mul(params->W, params->W, params->sinphi, MPFR_RNDN); + mpfr_mul(params->W, params->W, params->t2, MPFR_RNDN); + if(params->omega==1){ + mpfr_neg(params->W, params->W, MPFR_RNDN); + } + } + + mpfr_clears(tmp, tmp2, NULL); + free(buffer); + return(0); +} + + +// length of a string +int str_len(char* str){ + char* ptr=str; + int ret=0; + while(*ptr!='\0'){ret++;ptr++;} + return(ret); +} + +// compare strings +int str_cmp(char* str1, char* str2){ + char* ptr1=str1; + char* ptr2=str2; + while(*ptr1==*ptr2 && *ptr1!='\0' && *ptr2!='\0'){ + ptr1++; + ptr2++; + } + if(*ptr1=='\0' && *ptr2=='\0'){ + return(1); + } + else{ + return(0); + } +} + +// append a character to the end of a string at the location pointed at by 'ptr' +char* str_addchar(char* ptr, const char c){ + *ptr=c; + ptr++; + *ptr='\0'; + return(ptr); +} + |