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