summaryrefslogtreecommitdiffstats
path: root/kommander/widget/parser.h
blob: 6dc66258f4f39638e034444b739c4d8ae9c37cf3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
/***************************************************************************
                    parser.h - Internal parser
                             -------------------
    copyright          : (C) 2004      Michal Rudolf <[email protected]>
    
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 ***************************************************************************/

#ifndef _HAVE_PARSER_H_
#define _HAVE_PARSER_H_

#include "kommander_export.h"
#include "parsenode.h"

#include <qvaluevector.h>
#include <qstringlist.h>
#include <qmap.h>

class KommanderWidget;
class ParserData;

class Parser
{
public:
  Parser(ParserData* data);
  Parser(ParserData* data, const QString& expr);
  // set string to parse
  bool setString(const QString& s);
  // set Kommander widget associated with parser
  void setWidget(KommanderWidget* w);

  // parse generic expression
  QString expression(Parse::Mode mode = Parse::Execute);
  // execute single command; return true if ok
  bool command(Parse::Mode mode = Parse::Execute);
  // special class method to execute single parser function without creating parser object
  static QString function(ParserData* data, const QString& name, const QStringList& params);
  // execute whole block; return true if ok
  bool parse(Parse::Mode mode = Parse::Execute);
  // return line of errorneous node
  int errorLine() const;
  // return error message
  QString errorMessage() const;

  // check if this is a name of standard variable
  bool isVariable(const QString& name) const;
  // set variable value
  void setVariable(const QString& name, ParseNode value);
  // unset variable
  void unsetVariable(const QString& key);
  // get variable value
  ParseNode variable(const QString& name) const;
  // access associative array 
  const QMap<QString, ParseNode>& array(const QString& name) const;
  // check if this is a name of an array
  bool isArray(const QString& name) const;
  // set array key
  void setArray(const QString& name, const QString& key, ParseNode value);
  // unset array key or whole array
  void unsetArray(const QString& name, const QString& key = QString::null);
  // array value 
  ParseNode arrayValue(const QString& name, const QString& key) const;
  // get associated widget
  KommanderWidget* currentWidget() const;

private:
  // parsing function - top-down approach

  // parse const
  ParseNode parseConstant(Parse::Mode mode = Parse::Execute);
  // parse value (literal or variable)
  ParseNode parseValue(Parse::Mode mode = Parse::Execute);
  // parse multiplication, division and mod (x*y, x/y, x%y)
  ParseNode parseMultiply(Parse::Mode mode = Parse::Execute);
  // parse sum (x+y, x-y)
  ParseNode parseAdd(Parse::Mode mode = Parse::Execute);
  // parse signed numeric (+x, -x)
  ParseNode parseSignedNumber(Parse::Mode mode = Parse::Execute);

  /*  
  // parse string expression
  ParseNode parseStringValue(Parse::Mode mode = Parse::Execute);
  // parse string concatenation (x+y)
  ParseNode parseConcatenation(Parse::Mode mode = Parse::Execute);
  */

  // parse comparisons (x==y, x<y, x>y, x!=y, x<>y, x<=y, x>=y
  ParseNode parseComparison(Parse::Mode mode = Parse::Execute);
  // parse boolean not (!x, not x)
  ParseNode parseNot(Parse::Mode mode = Parse::Execute);
  // parse boolean and (x&&y, x and y)
  ParseNode parseAnd(Parse::Mode mode = Parse::Execute);
  // parse boolean or (x||y, x or y)
  ParseNode parseOr(Parse::Mode mode = Parse::Execute);
  // parse generic condition
  ParseNode parseCondition(Parse::Mode mode = Parse::Execute);

  // parse (x) expression
  ParseNode parseParenthesis(Parse::Mode mode = Parse::Execute);
  // parse generic expression
  ParseNode parseExpression(Parse::Mode mode = Parse::Execute);
  // parse parameters
  ParseNode parseFunction(Parse::Mode mode = Parse::Execute);
  // parse widget function
  ParseNode parseWidget(Parse::Mode mode = Parse::Execute, const QString &widgetName = QString::null);

  // parse assignment
  ParseNode parseAssignment(Parse::Mode mode = Parse::Execute);
  // parse conditional
  Parse::Flow parseIf(Parse::Mode mode = Parse::Execute);
  // parse assignment
  Parse::Flow parseCommand(Parse::Mode mode = Parse::Execute);
  // parse while loop
  Parse::Flow parseWhile(Parse::Mode mode = Parse::Execute);
  // parse for loop
  Parse::Flow parseFor(Parse::Mode mode = Parse::Execute);
  // parse foreach loop
  Parse::Flow parseForeach(Parse::Mode mode = Parse::Execute);
  // parse switch block
  void parseSwitch(Parse::Mode mode = Parse::Execute);
  // parse whole block
  Parse::Flow parseBlock(Parse::Mode mode = Parse::Execute);

  // insert next node
  void insertNode(ParseNode p, int line);
  // next item to be parsed
  ParseNode next() const;
  // check if next item is keyword k, if so - go further, if no, set error
  bool tryKeyword(Parse::Keyword k, Parse::Mode mode = Parse::Execute);
  // check if next item is a variable, if so, return its name
  bool tryVariable(Parse::Mode mode = Parse::Execute);

  // get the name of the next node treated as variable
  QString nextVariable(Parse::Mode mode = Parse::Execute);
  // check whether variable/array name is global (preceded with _)
  bool isGlobal(const QString& name) const;
  // check if next item is a function
  bool isFunction() const;
  // check if next item is a widget
  bool isWidget() const;

  // reset to default state
  void reset();
  // set error state if no error was set before; err is expected symbol that wasn't found
  void setError(const QString& msg);
  void setError(const QString& msg, int pos);
  // check whether parsing was successful
  bool isError() const;

  // parsing data
  ParserData* m_data;
  // current parsing position
  uint m_start;
  // current error message
  QString m_error;
  // in case of error, this keeps position of first error
  uint m_errorPosition;
  // parsing nodes
  QValueVector<ParseNode> m_parts;
  // variables
  QMap<QString, ParseNode> m_variables;
  // arrays
  QMap<QString, QMap<QString, ParseNode> > m_arrays;
  // Kommander 
  KommanderWidget* m_widget;
  // global variables
  static QMap<QString, ParseNode> m_globalVariables;
  // global arrays
  static QMap<QString, QMap<QString, ParseNode> > m_globalArrays;
};

#endif