/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is part of the LibreOffice project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* This file incorporates work covered by the following license notice:
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed
* with this work for additional information regarding copyright
* ownership. The ASF licenses this file to you under the Apache
* License, Version 2.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
#pragma once
#include <memory>
#include "opcodes.hxx"
#include "token.hxx"
#include <vector>
class SbiExprNode;
class SbiExpression;
class SbiExprList;
class SbiParser;
class SbiCodeGen;
class SbiSymDef;
typedef std::unique_ptr<SbiExprList> SbiExprListPtr;
typedef std::vector<SbiExprListPtr> SbiExprListVector;
struct SbVar {
SbiExprNode* pNext;
// next element (for structures)
SbiSymDef* pDef;
// symbol definition
SbiExprList* pPar;
// optional parameters (is deleted)
SbiExprListVector* pvMorePar;
// Array of arrays foo(pPar)(avMorePar[0])(avMorePar[1])...
};
struct KeywordSymbolInfo
{
OUString m_aKeywordSymbol;
SbxDataType m_eSbxDataType;
};
enum SbiExprType {
// expression types:
SbSTDEXPR,
// normal expression
SbLVALUE,
// any lValue
SbSYMBOL,
// any composite symbol
SbOPERAND
// variable/function
};
enum SbiExprMode {
// Expression context:
EXPRMODE_STANDARD,
// default
EXPRMODE_STANDALONE,
// a param1, param2 OR a( param1, param2 ) = 42
EXPRMODE_LPAREN_PENDING,
// start of parameter list with bracket, special handling
EXPRMODE_LPAREN_NOT_NEEDED,
// pending LPAREN has not been used
EXPRMODE_ARRAY_OR_OBJECT,
// '=' or '(' or '.' found after ')' on ParenLevel 0, stopping
// expression, assuming array syntax a(...)[(...)] = ?
// or a(...).b(...)
EXPRMODE_EMPTY_PAREN
// It turned out that the paren don't contain anything: a()
};
enum SbiNodeType {
SbxNUMVAL,
// nVal = value
SbxSTRVAL,
// aStrVal = value, before #i59791/#i45570: nStringId = value
SbxVARVAL,
// aVar = value
SbxTYPEOF,
// TypeOf ObjExpr Is Type
SbxNODE,
// Node
SbxNEW,
// new <type> expression
SbxDUMMY
};
enum RecursiveMode
{
UNDEFINED,
FORCE_CALL,
PREVENT_CALL
};
class SbiExprList final {
// class for parameters and dims
std::vector<std::unique_ptr<SbiExpression>> aData;
short nDim;
bool bError;
bool bBracket;
public:
SbiExprList();
~SbiExprList();
static SbiExprListPtr ParseParameters(SbiParser*,
bool bStandaloneExpression =
false,
bool bPar =
true);
static SbiExprListPtr ParseDimList( SbiParser* );
bool IsBracket()
const {
return bBracket; }
bool IsValid()
const {
return !bError; }
short GetSize()
const {
return aData.size(); }
short GetDims()
const {
return nDim; }
SbiExpression* Get( size_t );
void Gen( SbiCodeGen& rGen);
// code generation
void addExpression( std::unique_ptr<SbiExpression>&& pExpr );
};
class SbiExprNode final {
// operators (and operands)
friend class SbiExpression;
friend class SbiConstExpression;
union {
sal_uInt16 nTypeStrId;
// pooled String-ID, #i59791/#i45570 Now only for TypeOf
double nVal;
// numeric value
SbVar aVar;
// or variable
};
OUString aStrVal;
// #i59791/#i45570 Store string directly
std::unique_ptr<SbiExprNode> pLeft;
// left branch
std::unique_ptr<SbiExprNode> pRight;
// right branch (NULL for unary ops)
SbiExprNode* pWithParent;
// node, whose member is "this per with"
SbiNodeType eNodeType;
SbxDataType eType;
SbiToken eTok;
bool bError;
// true: error
void FoldConstants(SbiParser*);
void FoldConstantsBinaryNode(SbiParser*);
void FoldConstantsUnaryNode(SbiParser*);
void CollectBits();
// converting numbers to strings
bool IsOperand()
const
{
return eNodeType != SbxNODE && eNodeType != SbxTYPEOF && eNodeType != SbxNEW; }
bool IsNumber()
const;
bool IsLvalue()
const;
// true, if usable as Lvalue
void GenElement( SbiCodeGen&, SbiOpcode );
public:
SbiExprNode();
SbiExprNode(
double, SbxDataType );
SbiExprNode( OUString );
SbiExprNode(
const SbiSymDef&, SbxDataType, SbiExprListPtr = nullptr );
SbiExprNode( std::unique_ptr<SbiExprNode>, SbiToken, std::unique_ptr<SbiExprNode> );
SbiExprNode( std::unique_ptr<SbiExprNode>, sal_uInt16 );
// #120061 TypeOf
SbiExprNode( sal_uInt16 );
// new <type>
~SbiExprNode();
bool IsValid()
const {
return !bError; }
bool IsConstant()
const // true: constant operand
{
return eNodeType == SbxSTRVAL || eNodeType == SbxNUMVAL; }
void ConvertToIntConstIfPossible();
bool IsVariable()
const;
void SetWithParent( SbiExprNode* p ) { pWithParent = p; }
SbxDataType GetType()
const {
return eType; }
void SetType( SbxDataType eTp ) { eType = eTp; }
SbiNodeType GetNodeType()
const {
return eNodeType; }
SbiSymDef* GetVar();
SbiSymDef* GetRealVar();
// last variable in x.y.z
SbiExprNode* GetRealNode();
// last node in x.y.z
const OUString& GetString()
const {
return aStrVal; }
short GetNumber()
const {
return static_cast<
short>(nVal); }
SbiExprList* GetParameters() {
return aVar.pPar; }
void Optimize(SbiParser*);
// tree matching
void Gen( SbiCodeGen& rGen, RecursiveMode eRecMode = UNDEFINED );
// giving out a node
};
class SbiExpression {
friend class SbiExprList;
protected:
OUString aArgName;
SbiParser* pParser;
std::unique_ptr<SbiExprNode> pExpr;
// expression tree
SbiExprType eCurExpr;
// type of expression
SbiExprMode m_eMode;
// expression context
bool bBased =
false;
// true: easy DIM-part (+BASE)
bool bError =
false;
bool bByVal =
false;
// true: ByVal-Parameter
bool bBracket =
false;
// true: Parameter list with brackets
sal_uInt16 nParenLevel = 0;
std::unique_ptr<SbiExprNode> Term(
const KeywordSymbolInfo* pKeywordSymbolInfo = nullptr
);
std::unique_ptr<SbiExprNode> ObjTerm( SbiSymDef& );
std::unique_ptr<SbiExprNode> Operand( bool bUsedForTypeOf = false );
std::unique_ptr<SbiExprNode> Unary();
std::unique_ptr<SbiExprNode> Exp();
std::unique_ptr<SbiExprNode> MulDiv();
std::unique_ptr<SbiExprNode> IntDiv();
std::unique_ptr<SbiExprNode> Mod();
std::unique_ptr<SbiExprNode> AddSub();
std::unique_ptr<SbiExprNode> Cat();
std::unique_ptr<SbiExprNode> Like();
std::unique_ptr<SbiExprNode> VBA_Not();
std::unique_ptr<SbiExprNode> Comp();
std::unique_ptr<SbiExprNode> Boolean();
public:
SbiExpression( SbiParser*, SbiExprType = SbSTDEXPR,
SbiExprMode eMode = EXPRMODE_STANDARD, const KeywordSymbolInfo* pKeywordSymbolInfo = nullptr ); // parsing Ctor
SbiExpression( SbiParser*, double, SbxDataType );
SbiExpression( SbiParser*, const SbiSymDef&, SbiExprListPtr = nullptr );
~SbiExpression();
OUString& GetName() { return aArgName; }
void SetBased() { bBased = true; }
bool IsBased() const { return bBased; }
void SetByVal() { bByVal = true; }
bool IsBracket() const { return bBracket; }
bool IsValid() const { return pExpr->IsValid(); }
bool IsVariable() const { return pExpr->IsVariable(); }
bool IsLvalue() const { return pExpr->IsLvalue(); }
void ConvertToIntConstIfPossible() { pExpr->ConvertToIntConstIfPossible(); }
const OUString& GetString() const { return pExpr->GetString(); }
SbiSymDef* GetRealVar() { return pExpr->GetRealVar(); }
SbiExprNode* GetExprNode() { return pExpr.get(); }
SbxDataType GetType() const { return pExpr->GetType(); }
void Gen( RecursiveMode eRecMode = UNDEFINED );
};
class SbiConstExpression : public SbiExpression {
double nVal;
OUString aVal;
SbxDataType eType;
public: // numeric constant
SbiConstExpression( SbiParser* );
SbxDataType GetType() const { return eType; }
const OUString& GetString() const { return aVal; }
double GetValue() const { return nVal; }
short GetShortValue();
};
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */