Line data Source code
1 : /* Copyright (C) 2006-2008 The PARI group.
2 :
3 : This file is part of the PARI package.
4 :
5 : PARI/GP is free software; you can redistribute it and/or modify it under the
6 : terms of the GNU General Public License as published by the Free Software
7 : Foundation; either version 2 of the License, or (at your option) any later
8 : version. It is distributed in the hope that it will be useful, but WITHOUT
9 : ANY WARRANTY WHATSOEVER.
10 :
11 : Check the License for details. You should have received a copy of it, along
12 : with the package; see the file 'COPYING'. If not, write to the Free Software
13 : Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
14 :
15 : #include "pari.h"
16 : #include "paripriv.h"
17 : BEGINEXTERN
18 : #include "parse.h"
19 : ENDEXTERN
20 : #include "anal.h"
21 : #include "tree.h"
22 :
23 : static THREAD int pari_once;
24 : static THREAD long pari_discarded;
25 : static THREAD const char *pari_lex_start;
26 : static THREAD GEN pari_lasterror;
27 :
28 : static void
29 119 : pari_error(PARI_LTYPE *yylloc, char **lex, const char *s)
30 : {
31 : (void) yylloc; (void) lex;
32 119 : if (pari_lasterror) cgiv(pari_lasterror);
33 119 : pari_lasterror=strtoGENstr(s);
34 119 : }
35 :
36 : static THREAD pari_stack s_node;
37 : THREAD node *pari_tree;
38 :
39 : void
40 378351 : pari_init_parser(void)
41 : {
42 : long i;
43 378351 : const char *opname[]={"_||_", "_&&_", "_===_", "_==_", "_!=_", "_>=_", "_>_", "_<=_", "_<_", "_-_","_+_","_<<_", "_>>_", "_%_", "_\\/_", "_\\_", "_/_", "_*_","_^_","__","_--","_++","_-=_", "_+=_", "_<<=_", "_>>=_", "_%=_", "_\\/=_", "_\\=_", "_/=_", "_*=_","+_","-_","!_","_!","_#","_'_","_~","[_.._]","[_|_<-_,_]","[_|_<-_,_;_]","[_|_=_,_]","[_|_=_,_;_]","%","%#","#_",""};
44 :
45 378351 : pari_stack_init(&s_node,sizeof(*pari_tree),(void **)&pari_tree);
46 378384 : pari_stack_alloc(&s_node,OPnboperator);
47 378423 : parsestate_reset();
48 17753127 : for (i=0;i<OPnboperator;i++)
49 : {
50 17374658 : pari_tree[i].f = Fconst;
51 17374658 : pari_tree[i].x = CSTentry;
52 17374658 : pari_tree[i].y = -1;
53 17374658 : pari_tree[i].str = opname[i];
54 17374658 : pari_tree[i].len = strlen(opname[i]);
55 17374658 : pari_tree[i].flags= 0;
56 : }
57 378469 : }
58 : void
59 356467 : pari_close_parser(void) { pari_stack_delete(&s_node); }
60 :
61 : void
62 56 : compile_err(const char *msg, const char *str)
63 : {
64 56 : pari_err(e_SYNTAX, msg, str, pari_lex_start);
65 0 : }
66 :
67 : void
68 35 : compile_varerr(const char *str)
69 : {
70 35 : pari_err(e_SYNTAX, "variable name expected", str, pari_lex_start);
71 0 : }
72 :
73 : void
74 378865 : parsestate_reset(void)
75 : {
76 378865 : s_node.n = OPnboperator;
77 378865 : pari_lex_start = NULL;
78 378865 : pari_once=1;
79 378865 : pari_discarded=0;
80 378865 : pari_lasterror=NULL;
81 378865 : }
82 : void
83 1084366 : parsestate_save(struct pari_parsestate *state)
84 : {
85 1084366 : state->node = s_node.n;
86 1084366 : state->lex_start = pari_lex_start;
87 1084366 : state->once = pari_once;
88 1084366 : state->discarded = pari_discarded;
89 1084366 : state->lasterror = pari_lasterror;
90 1084366 : }
91 : void
92 950625 : parsestate_restore(struct pari_parsestate *state)
93 : {
94 950625 : s_node.n = state->node;
95 950625 : pari_lex_start = state->lex_start;
96 950625 : pari_once = state->once;
97 950625 : pari_discarded = state->discarded;
98 950625 : pari_lasterror = state->lasterror;
99 950625 : }
100 :
101 : GEN
102 937551 : pari_compile_str(const char *lex)
103 : {
104 937551 : pari_sp ltop=avma;
105 : GEN code;
106 : struct pari_parsestate state;
107 937551 : parsestate_save(&state);
108 937551 : pari_lex_start = lex;
109 937551 : pari_once=1;
110 937551 : pari_discarded=0;
111 937551 : pari_lasterror=NULL;
112 937551 : if (pari_parse((char**)&lex) || pari_discarded)
113 : {
114 7 : if (pari_lasterror)
115 7 : compile_err(GSTR(pari_lasterror),lex-1);
116 : else /* should not happen */
117 0 : compile_err("syntax error",lex-1);
118 : }
119 937544 : set_avma(ltop);
120 937544 : optimizenode(s_node.n-1);
121 937509 : code=gp_closure(s_node.n-1);
122 937460 : parsestate_restore(&state);
123 937460 : return code;
124 : }
125 :
126 : static long
127 99046225 : newnode(Ffunc f, long x, long y, struct node_loc *loc)
128 : {
129 99046225 : long n=pari_stack_new(&s_node);
130 99046225 : pari_tree[n].f=f;
131 99046225 : pari_tree[n].x=x;
132 99046225 : pari_tree[n].y=y;
133 99046225 : pari_tree[n].str=loc->start;
134 99046225 : pari_tree[n].len=loc->end-loc->start;
135 99046225 : pari_tree[n].flags=0;
136 99046225 : return n;
137 : }
138 :
139 : static long
140 5364548 : newconst(long x, struct node_loc *loc)
141 : {
142 5364548 : return newnode(Fconst,x,-1,loc);
143 : }
144 :
145 : static long
146 10567449 : newopcall(OPerator op, long x, long y, struct node_loc *loc)
147 : {
148 10567449 : if (y==-1)
149 9411226 : return newnode(Ffunction,op,x,loc);
150 : else
151 1156223 : return newnode(Ffunction,op,newnode(Flistarg,x,y,loc),loc);
152 : }
153 :
154 : static long
155 189 : newopcall3(OPerator op, long x, long y, long z, struct node_loc *loc)
156 : {
157 189 : return newopcall(op,newnode(Flistarg,x,y,loc),z,loc);
158 : }
159 :
160 : static long
161 977 : countarg(long n)
162 : {
163 : long i;
164 3120 : for(i=1; pari_tree[n].f==Flistarg; i++)
165 2143 : n = pari_tree[n].x;
166 977 : return i;
167 : }
168 :
169 : static long
170 872 : addcurrexpr(long n, long currexpr, struct node_loc *loc)
171 : {
172 872 : long y, m = n;
173 977 : while (pari_tree[m].x==OPcomprc || pari_tree[m].x==OPcompreqc)
174 : {
175 105 : y = pari_tree[m].y; if (countarg(y)==4) y = pari_tree[y].x;
176 105 : m = pari_tree[y].y;
177 : }
178 872 : y = pari_tree[m].y; if (countarg(y)==4) y = pari_tree[y].x;
179 872 : pari_tree[y].y = currexpr;
180 872 : pari_tree[n].str=loc->start;
181 872 : pari_tree[n].len=loc->end-loc->start;
182 872 : return n;
183 : }
184 :
185 : static long
186 31517577 : newintnode(struct node_loc *loc)
187 : {
188 31517577 : if (loc->end-loc->start<=(long)(1+LOG10_2*BITS_IN_LONG))
189 : {
190 30605540 : pari_sp ltop=avma;
191 30605540 : GEN g=strtoi(loc->start);
192 30605540 : long s = itos_or_0(g), sg = signe(g);
193 30605540 : set_avma(ltop);
194 30605540 : if (sg==0 || s) return newnode(Fsmall,s,-1,loc);
195 : }
196 943222 : return newconst(CSTint,loc);
197 : }
198 :
199 : static long
200 3898 : newfunc(CSTtype t, struct node_loc *func, long args, long code,
201 : struct node_loc *loc)
202 : {
203 3898 : long name=newnode(Fentry,newconst(t,func),-1,func);
204 3898 : return newnode(Fassign,name,newnode(Flambda,args,code,loc),loc);
205 : }
206 :
207 :
|