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 105 : static void pari_error(PARI_LTYPE *yylloc, char **lex, const char *s)
29 : {
30 : (void) yylloc; (void) lex;
31 105 : if (pari_lasterror) cgiv(pari_lasterror);
32 105 : pari_lasterror=strtoGENstr(s);
33 105 : }
34 :
35 : static THREAD pari_stack s_node;
36 : THREAD node *pari_tree;
37 :
38 : void
39 326352 : pari_init_parser(void)
40 : {
41 : long i;
42 326352 : const char *opname[]={"_||_", "_&&_", "_===_", "_==_", "_!=_", "_>=_", "_>_", "_<=_", "_<_", "_-_","_+_","_<<_", "_>>_", "_%_", "_\\/_", "_\\_", "_/_", "_*_","_^_","__","_--","_++","_-=_", "_+=_", "_<<=_", "_>>=_", "_%=_", "_\\/=_", "_\\=_", "_/=_", "_*=_","+_","-_","!_","_!","_#","_'_","_~","[_.._]","[_|_<-_,_]","[_|_<-_,_;_]","%","%#","#_",""};
43 :
44 326352 : pari_stack_init(&s_node,sizeof(*pari_tree),(void **)&pari_tree);
45 326328 : pari_stack_alloc(&s_node,OPnboperator);
46 326311 : parsestate_reset();
47 14629217 : for (i=0;i<OPnboperator;i++)
48 : {
49 14302945 : pari_tree[i].f = Fconst;
50 14302945 : pari_tree[i].x = CSTentry;
51 14302945 : pari_tree[i].y = -1;
52 14302945 : pari_tree[i].str = opname[i];
53 14302945 : pari_tree[i].len = strlen(opname[i]);
54 14302945 : pari_tree[i].flags= 0;
55 : }
56 326272 : }
57 : void
58 321333 : pari_close_parser(void) { pari_stack_delete(&s_node); }
59 :
60 : void
61 49 : compile_err(const char *msg, const char *str)
62 : {
63 49 : pari_err(e_SYNTAX, msg, str, pari_lex_start);
64 0 : }
65 :
66 : void
67 28 : compile_varerr(const char *str)
68 : {
69 28 : pari_err(e_SYNTAX, "variable name expected", str, pari_lex_start);
70 0 : }
71 :
72 : void
73 326745 : parsestate_reset(void)
74 : {
75 326745 : s_node.n = OPnboperator;
76 326745 : pari_lex_start = NULL;
77 326745 : pari_once=1;
78 326745 : pari_discarded=0;
79 326745 : pari_lasterror=NULL;
80 326745 : }
81 : void
82 1073013 : parsestate_save(struct pari_parsestate *state)
83 : {
84 1073013 : state->node = s_node.n;
85 1073013 : state->lex_start = pari_lex_start;
86 1073013 : state->once = pari_once;
87 1073013 : state->discarded = pari_discarded;
88 1073013 : state->lasterror = pari_lasterror;
89 1073013 : }
90 : void
91 944827 : parsestate_restore(struct pari_parsestate *state)
92 : {
93 944827 : s_node.n = state->node;
94 944827 : pari_lex_start = state->lex_start;
95 944827 : pari_once = state->once;
96 944827 : pari_discarded = state->discarded;
97 944827 : pari_lasterror = state->lasterror;
98 944827 : }
99 :
100 : GEN
101 932095 : pari_compile_str(const char *lex)
102 : {
103 932095 : pari_sp ltop=avma;
104 : GEN code;
105 : struct pari_parsestate state;
106 932095 : parsestate_save(&state);
107 932095 : pari_lex_start = lex;
108 932095 : pari_once=1;
109 932095 : pari_discarded=0;
110 932095 : pari_lasterror=NULL;
111 932095 : if (pari_parse((char**)&lex) || pari_discarded)
112 : {
113 0 : if (pari_lasterror)
114 0 : compile_err(GSTR(pari_lasterror),lex-1);
115 : else /* should not happen */
116 0 : compile_err("syntax error",lex-1);
117 : }
118 932095 : set_avma(ltop);
119 932095 : optimizenode(s_node.n-1);
120 932060 : code=gp_closure(s_node.n-1);
121 932018 : parsestate_restore(&state);
122 932018 : return code;
123 : }
124 :
125 : static long
126 35609829 : newnode(Ffunc f, long x, long y, struct node_loc *loc)
127 : {
128 35609829 : long n=pari_stack_new(&s_node);
129 35609829 : pari_tree[n].f=f;
130 35609829 : pari_tree[n].x=x;
131 35609829 : pari_tree[n].y=y;
132 35609829 : pari_tree[n].str=loc->start;
133 35609829 : pari_tree[n].len=loc->end-loc->start;
134 35609829 : pari_tree[n].flags=0;
135 35609829 : return n;
136 : }
137 :
138 : static long
139 2291811 : newconst(long x, struct node_loc *loc)
140 : {
141 2291811 : return newnode(Fconst,x,-1,loc);
142 : }
143 :
144 : static long
145 4474488 : newopcall(OPerator op, long x, long y, struct node_loc *loc)
146 : {
147 4474488 : if (y==-1)
148 4120658 : return newnode(Ffunction,op,x,loc);
149 : else
150 353830 : return newnode(Ffunction,op,newnode(Flistarg,x,y,loc),loc);
151 : }
152 :
153 : static long
154 161 : newopcall3(OPerator op, long x, long y, long z, struct node_loc *loc)
155 : {
156 161 : return newopcall(op,newnode(Flistarg,x,y,loc),z,loc);
157 : }
158 :
159 : static long
160 921 : countarg(long n)
161 : {
162 : long i;
163 2924 : for(i=1; pari_tree[n].f==Flistarg; i++)
164 2003 : n = pari_tree[n].x;
165 921 : return i;
166 : }
167 :
168 : static long
169 823 : addcurrexpr(long n, long currexpr, struct node_loc *loc)
170 : {
171 823 : long y, m = n;
172 921 : while (pari_tree[m].x==OPcomprc)
173 : {
174 98 : y = pari_tree[m].y; if (countarg(y)==4) y = pari_tree[y].x;
175 98 : m = pari_tree[y].y;
176 : }
177 823 : y = pari_tree[m].y; if (countarg(y)==4) y = pari_tree[y].x;
178 823 : pari_tree[y].y = currexpr;
179 823 : pari_tree[n].str=loc->start;
180 823 : pari_tree[n].len=loc->end-loc->start;
181 823 : return n;
182 : }
183 :
184 : static long
185 11949859 : newintnode(struct node_loc *loc)
186 : {
187 11949859 : if (loc->end-loc->start<=(long)(1+LOG10_2*BITS_IN_LONG))
188 : {
189 11122960 : pari_sp ltop=avma;
190 11122960 : GEN g=strtoi(loc->start);
191 11122960 : long s = itos_or_0(g), sg = signe(g);
192 11122960 : set_avma(ltop);
193 11122960 : if (sg==0 || s) return newnode(Fsmall,s,-1,loc);
194 : }
195 840276 : return newconst(CSTint,loc);
196 : }
197 :
198 : static long
199 3667 : newfunc(CSTtype t, struct node_loc *func, long args, long code,
200 : struct node_loc *loc)
201 : {
202 3667 : long name=newnode(Fentry,newconst(t,func),-1,func);
203 3667 : return newnode(Fassign,name,newnode(Flambda,args,code,loc),loc);
204 : }
205 :
206 :
|