Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 : #include "parser.hxx"
21 : #include "iosys.hxx"
22 : #include <boost/scoped_ptr.hpp>
23 :
24 : // test if there's an I/O channel
25 :
26 15 : bool SbiParser::Channel( bool bAlways )
27 : {
28 15 : bool bRes = false;
29 15 : Peek();
30 15 : if( IsHash() )
31 : {
32 15 : SbiExpression aExpr( this );
33 44 : while( Peek() == COMMA || Peek() == SEMICOLON )
34 14 : Next();
35 15 : aExpr.Gen();
36 15 : aGen.Gen( _CHANNEL );
37 15 : bRes = true;
38 : }
39 0 : else if( bAlways )
40 0 : Error( SbERR_EXPECTED, "#" );
41 15 : return bRes;
42 : }
43 :
44 : // it's tried that at object variables the Default-
45 : // Property is addressed for PRINT and WRITE
46 :
47 15 : void SbiParser::Print()
48 : {
49 15 : bool bChan = Channel();
50 :
51 30 : while( !bAbort )
52 : {
53 15 : if( !IsEoln( Peek() ) )
54 : {
55 14 : boost::scoped_ptr<SbiExpression> pExpr(new SbiExpression( this ));
56 14 : pExpr->Gen();
57 14 : pExpr.reset();
58 14 : Peek();
59 14 : aGen.Gen( eCurTok == COMMA ? _PRINTF : _BPRINT );
60 : }
61 15 : if( eCurTok == COMMA || eCurTok == SEMICOLON )
62 : {
63 0 : Next();
64 0 : if( IsEoln( Peek() ) ) break;
65 : }
66 : else
67 : {
68 15 : aGen.Gen( _PRCHAR, '\n' );
69 15 : break;
70 : }
71 : }
72 15 : if( bChan )
73 15 : aGen.Gen( _CHAN0 );
74 15 : }
75 :
76 : // WRITE #chan, expr, ...
77 :
78 0 : void SbiParser::Write()
79 : {
80 0 : bool bChan = Channel();
81 :
82 0 : while( !bAbort )
83 : {
84 0 : boost::scoped_ptr<SbiExpression> pExpr(new SbiExpression( this ));
85 0 : pExpr->Gen();
86 0 : pExpr.reset();
87 0 : aGen.Gen( _BWRITE );
88 0 : if( Peek() == COMMA )
89 : {
90 0 : aGen.Gen( _PRCHAR, ',' );
91 0 : Next();
92 0 : if( IsEoln( Peek() ) ) break;
93 : }
94 : else
95 : {
96 0 : aGen.Gen( _PRCHAR, '\n' );
97 0 : break;
98 : }
99 0 : }
100 0 : if( bChan )
101 0 : aGen.Gen( _CHAN0 );
102 0 : }
103 :
104 :
105 : // #i92642 Handle LINE keyword outside ::Next()
106 0 : void SbiParser::Line()
107 : {
108 : // #i92642: Special handling to allow name as symbol
109 0 : if( Peek() == INPUT )
110 : {
111 0 : Next();
112 0 : LineInput();
113 : }
114 : else
115 : {
116 0 : aGen.Statement();
117 :
118 0 : KeywordSymbolInfo aInfo;
119 0 : aInfo.m_aKeywordSymbol = "line";
120 0 : aInfo.m_eSbxDataType = GetType();
121 0 : aInfo.m_eTok = SYMBOL;
122 :
123 0 : Symbol( &aInfo );
124 : }
125 0 : }
126 :
127 :
128 : // LINE INPUT [prompt], var$
129 :
130 0 : void SbiParser::LineInput()
131 : {
132 0 : Channel( true );
133 0 : boost::scoped_ptr<SbiExpression> pExpr(new SbiExpression( this, SbOPERAND ));
134 0 : if( !pExpr->IsVariable() )
135 0 : Error( SbERR_VAR_EXPECTED );
136 0 : if( pExpr->GetType() != SbxVARIANT && pExpr->GetType() != SbxSTRING )
137 0 : Error( SbERR_CONVERSION );
138 0 : pExpr->Gen();
139 0 : aGen.Gen( _LINPUT );
140 0 : pExpr.reset();
141 0 : aGen.Gen( _CHAN0 ); // ResetChannel() not in StepLINPUT() anymore
142 0 : }
143 :
144 : // INPUT
145 :
146 0 : void SbiParser::Input()
147 : {
148 0 : aGen.Gen( _RESTART );
149 0 : Channel( true );
150 0 : boost::scoped_ptr<SbiExpression> pExpr(new SbiExpression( this, SbOPERAND ));
151 0 : while( !bAbort )
152 : {
153 0 : if( !pExpr->IsVariable() )
154 0 : Error( SbERR_VAR_EXPECTED );
155 0 : pExpr->Gen();
156 0 : aGen.Gen( _INPUT );
157 0 : if( Peek() == COMMA )
158 : {
159 0 : Next();
160 0 : pExpr.reset(new SbiExpression( this, SbOPERAND ));
161 : }
162 0 : else break;
163 : }
164 0 : pExpr.reset();
165 0 : aGen.Gen( _CHAN0 );
166 0 : }
167 :
168 : // OPEN stringexpr FOR mode ACCCESS access mode AS Channel [Len=n]
169 :
170 1 : void SbiParser::Open()
171 : {
172 1 : bInStatement = true;
173 1 : SbiExpression aFileName( this );
174 : SbiToken eTok;
175 1 : TestToken( FOR );
176 1 : StreamMode nMode = StreamMode::NONE;
177 1 : short nFlags = 0;
178 1 : switch( Next() )
179 : {
180 : case INPUT:
181 0 : nMode = StreamMode::READ; nFlags |= SBSTRM_INPUT; break;
182 : case OUTPUT:
183 1 : nMode = StreamMode::WRITE | StreamMode::TRUNC; nFlags |= SBSTRM_OUTPUT; break;
184 : case APPEND:
185 0 : nMode = StreamMode::WRITE; nFlags |= SBSTRM_APPEND; break;
186 : case RANDOM:
187 0 : nMode = StreamMode::READ | StreamMode::WRITE; nFlags |= SBSTRM_RANDOM; break;
188 : case BINARY:
189 0 : nMode = StreamMode::READ | StreamMode::WRITE; nFlags |= SBSTRM_BINARY; break;
190 : default:
191 0 : Error( SbERR_SYNTAX );
192 : }
193 1 : if( Peek() == ACCESS )
194 : {
195 0 : Next();
196 0 : eTok = Next();
197 : // influence only READ,WRITE-Flags in nMode
198 0 : nMode &= ~StreamMode(StreamMode::READ | StreamMode::WRITE); // delete
199 0 : if( eTok == READ )
200 : {
201 0 : if( Peek() == WRITE )
202 : {
203 0 : Next();
204 0 : nMode |= (StreamMode::READ | StreamMode::WRITE);
205 : }
206 : else
207 0 : nMode |= StreamMode::READ;
208 : }
209 0 : else if( eTok == WRITE )
210 0 : nMode |= StreamMode::WRITE;
211 : else
212 0 : Error( SbERR_SYNTAX );
213 : }
214 1 : switch( Peek() )
215 : {
216 : #ifdef SHARED
217 : #undef SHARED
218 : #define tmpSHARED
219 : #endif
220 : case SHARED:
221 0 : Next(); nMode |= StreamMode::SHARE_DENYNONE; break;
222 : #ifdef tmpSHARED
223 : #define SHARED
224 : #undef tmpSHARED
225 : #endif
226 : case LOCK:
227 0 : Next();
228 0 : eTok = Next();
229 0 : if( eTok == READ )
230 : {
231 0 : if( Peek() == WRITE ) Next(), nMode |= StreamMode::SHARE_DENYALL;
232 0 : else nMode |= StreamMode::SHARE_DENYREAD;
233 : }
234 0 : else if( eTok == WRITE )
235 0 : nMode |= StreamMode::SHARE_DENYWRITE;
236 : else
237 0 : Error( SbERR_SYNTAX );
238 0 : break;
239 1 : default: break;
240 : }
241 1 : TestToken( AS );
242 : // channel number
243 1 : boost::scoped_ptr<SbiExpression> pChan(new SbiExpression( this ));
244 1 : if( !pChan )
245 0 : Error( SbERR_SYNTAX );
246 2 : boost::scoped_ptr<SbiExpression> pLen;
247 1 : if( Peek() == SYMBOL )
248 : {
249 0 : Next();
250 0 : if( aSym.equalsIgnoreAsciiCase("LEN") )
251 : {
252 0 : TestToken( EQ );
253 0 : pLen.reset(new SbiExpression( this ));
254 : }
255 : }
256 1 : if( !pLen ) pLen.reset(new SbiExpression( this, 128, SbxINTEGER ));
257 : // the stack for the OPEN command looks as follows:
258 : // block length
259 : // channel number
260 : // file name
261 1 : pLen->Gen();
262 1 : if( pChan )
263 1 : pChan->Gen();
264 1 : aFileName.Gen();
265 1 : aGen.Gen( _OPEN, static_cast<sal_uInt32>(nMode), nFlags );
266 2 : bInStatement = false;
267 1 : }
268 :
269 : // NAME file AS file
270 :
271 0 : void SbiParser::Name()
272 : {
273 : // #i92642: Special handling to allow name as symbol
274 0 : if( Peek() == EQ )
275 : {
276 0 : aGen.Statement();
277 :
278 0 : KeywordSymbolInfo aInfo;
279 0 : aInfo.m_aKeywordSymbol = "name";
280 0 : aInfo.m_eSbxDataType = GetType();
281 0 : aInfo.m_eTok = SYMBOL;
282 :
283 0 : Symbol( &aInfo );
284 0 : return;
285 : }
286 0 : SbiExpression aExpr1( this );
287 0 : TestToken( AS );
288 0 : SbiExpression aExpr2( this );
289 0 : aExpr1.Gen();
290 0 : aExpr2.Gen();
291 0 : aGen.Gen( _RENAME );
292 : }
293 :
294 : // CLOSE [n,...]
295 :
296 16 : void SbiParser::Close()
297 : {
298 16 : Peek();
299 16 : if( IsEoln( eCurTok ) )
300 0 : aGen.Gen( _CLOSE, 0 );
301 : else
302 : for( ;; )
303 : {
304 16 : SbiExpression aExpr( this );
305 32 : while( Peek() == COMMA || Peek() == SEMICOLON )
306 0 : Next();
307 16 : aExpr.Gen();
308 16 : aGen.Gen( _CHANNEL );
309 16 : aGen.Gen( _CLOSE, 1 );
310 :
311 16 : if( IsEoln( Peek() ) )
312 16 : break;
313 0 : }
314 16 : }
315 :
316 :
317 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|