1 %{
2 
3   /** @file ergo_input_processor.c Parses the input.
4       Uses bison code generator to generate the parses.
5   */
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include <math.h>
9 
10 #include "ergo_scripted.h"
11 #define YYERROR_VERBOSE
12 int yylex(void);
13 int yyerror(const char *s);
14 static const char *last_token = NULL;
15 
16 %}
17 
18 %union {
19   double num;     /* for returning numbers */
20   char str[256];  /* for returning strings */
21   struct variable *var; /* for returning lvalues */
22 }
23 
24 %token <num> NUMBER
25 %token DOT
26 %token <str> SYMBOL EQUAL STRING EOFTAG GETEXC GETPOL K_ALL HELP MOLTAG GHOSTTAG MOLDAL QUIT RUNTAG SYSTEM GHOST ANGSTROM PRECISION RANGE WARRANTY
27 %token LIST_DFT_FUNCS
28 %token IS_CHT_USED
29 %token SET_NTHREADS
30 %token	PLUS	MINUS	TIMES	DIVIDE	POWER
31 %token	LEFT_PARENTHESIS	RIGHT_PARENTHESIS
32 %token	EOL
33 
34 %type <num> Expression
35 %type <var> Lvalue
36 
37 %left	PLUS	MINUS
38 %left	TIMES	DIVIDE
39 %left	NEG
40 %right	POWER
41 
42 %start Input
43 %%
44 
45 Input:
46         |  Line
47 	|  Line EOL Input
48 	;
49 
50 Line:
51          /* Empty */
52 	| Assignment
53         | Command
54         | error { if(!ergo_scanner_reading_stdin) { yyerror("Aborted."); YYABORT; } }
55 	;
56 
57 Assignment:
58           Lvalue EQUAL Expression { es_assign_num($1, $3);}
59         | Lvalue EQUAL STRING     { es_assign_str($1, $3);}
60         ;
61 
62 Lvalue:
63           SYMBOL            { $$=es_find_var(NULL, $1);
64                               if(!$$) { last_token = $1;
65                                         yyerror("Unknown variable");YYERROR; }}
66         | Lvalue DOT SYMBOL { $$=es_find_var($1,   $3);
67                               if(!$$) { last_token = $3;
68                                         yyerror("Unknown variable");YYERROR;}}
69         ;
70 
71 Command:
72           MOLTAG EOL Molinput { es_mol_commit(); }
73         | MOLTAG ANGSTROM EOL Molinput { es_mol_commit(); }
74         | GHOSTTAG EOL Molinput { es_mol_commit(); }
75         | GHOSTTAG ANGSTROM EOL Molinput { es_mol_commit(); }
76         | HELP                { es_print_help(); }
77         | HELP Lvalue         { es_print_help_var($2); }
78         | LIST_DFT_FUNCS      { es_print_list_dft_funcs(); }
79         | IS_CHT_USED         { es_print_is_cht_used(); }
80         | PRECISION           { es_print_precision(); }
81         | MOLDAL STRING       { if(es_mol_read_molecule($2,MOL_MAIN)) {
82                               yyerror("Reading MOLECULE failed"); YYERROR;} }
83         | MOLDAL GHOST STRING { if(es_mol_read_molecule($3, MOL_GHOST)) {
84                               yyerror("Reading GHOST MOLECULE failed"); YYERROR;} }
85         | RUNTAG STRING     { if(es_run($2, 0)) {
86                               yyerror("RUN failed"); YYERROR;} }
87         | SET_NTHREADS LEFT_PARENTHESIS Expression RIGHT_PARENTHESIS {
88           if(es_set_nthreads($3)) { yyerror("setNThreads failed"); YYERROR;} }
89         | SET_NTHREADS LEFT_PARENTHESIS STRING RIGHT_PARENTHESIS {
90           if(es_set_nthreads_string($3)) { yyerror("setNThreads failed"); YYERROR;} }
91         | SYSTEM STRING { puts($2);
92                    if(system($2) != 0) {yyerror("system() failed"); YYERROR;} }
93         | WARRANTY { es_warranty(); }
94         | GETEXC STRING NUMBER { if(es_getexc($2, $3)) {
95                               yyerror("get_excited_state failed"); YYERROR;} }
96         | GETPOL STRING STRING NUMBER { if(es_get_polarisability($2, $3, $4)) {
97                               yyerror("get_polarisability failed"); YYERROR;} }
98         | GETPOL STRING K_ALL NUMBER { if(es_get_polarisability($2, NULL,$4)) {
99                               yyerror("get_polarisability failed"); YYERROR;} }
100         | QUIT { YYACCEPT; }
101         | RANGE NUMBER EQUAL NUMBER NUMBER STRING {
102                          if(!es_assign_range(MOL_MAIN,$2, $4, $5, $6)) {
103                             yyerror("Invalid main basis set range");YYERROR;}
104                          }
105         | RANGE GHOST NUMBER EQUAL NUMBER NUMBER STRING {
106                          if(!es_assign_range(MOL_GHOST,$3, $5, $6, $7)) {
107                             yyerror("Invalid ghost basis set range");YYERROR;}
108                          }
109         ;
110 
111 Molinput:
112         EOFTAG
113         | Molline Molinput
114         ;
115 
116 Molline:
117         SYMBOL NUMBER NUMBER NUMBER EOL { es_add_atom($1, $2, $3, $4); }
118         ;
119 
120 Expression:
121           NUMBER			{ $$=$1;  }
122         | Expression PLUS Expression	{ $$=$1+$3; }
123 	| Expression MINUS Expression	{ $$=$1-$3; }
124 	| Expression TIMES Expression	{ $$=$1*$3; }
125 	| Expression DIVIDE Expression	{ $$=$1/$3; }
126 	| MINUS Expression %prec NEG	{ $$=-$2; }
127 	| Expression POWER Expression	{ $$=pow($1,$3); }
128 	| LEFT_PARENTHESIS Expression RIGHT_PARENTHESIS	{ $$=$2; }
129 	;
130 
131 %%
132 
133 YYSTYPE yylval;
134 int ergo_scanner_lineno = 1;
135 int ergo_scanner_reading_stdin = 0;
136 
yyerror(const char * s)137 int yyerror(const char *s) {
138   if (last_token) {
139     printf("line %d: %s at '%s'\n",ergo_scanner_lineno, s, last_token);
140     last_token = NULL;
141   } else {
142     printf("line %d: %s\n",ergo_scanner_lineno, s);
143   }
144   return !ergo_scanner_reading_stdin;
145 }
146 
147 #ifdef SCANNER_TEST
main(void)148 int main(void) {
149   yyparse();
150 }
151 #endif
152