1 /* -*- mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- */
2 
3 /*
4  *  Main authors:
5  *     Guido Tack <guido.tack@monash.edu>
6  */
7 
8 /* This Source Code Form is subject to the terms of the Mozilla Public
9  * License, v. 2.0. If a copy of the MPL was not distributed with this
10  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
11 
12 #pragma once
13 
14 // This is a workaround for a bug in flex that only shows up
15 // with the Microsoft C++ compiler
16 #if defined(_MSC_VER)
17 #define YY_NO_UNISTD_H
18 #ifdef __cplusplus
19 extern "C" int isatty(int);
20 #endif
21 #endif
22 
23 // The Microsoft C++ compiler marks certain functions as deprecated,
24 // so let's take the alternative definitions
25 #if defined(_MSC_VER)
26 #define strdup _strdup
27 #define fileno _fileno
28 #endif
29 
30 #if defined(_MSC_VER)
31 #pragma warning(disable : 4065)
32 #endif
33 
34 namespace MiniZinc {
35 class ParserLocation;
36 }
37 #define YYLTYPE MiniZinc::ParserLocation
38 #define YYLTYPE_IS_DECLARED 1
39 #define YYLTYPE_IS_TRIVIAL 0
40 
41 #include <minizinc/astexception.hh>
42 #include <minizinc/file_utils.hh>
43 #include <minizinc/model.hh>
44 #include <minizinc/parser.tab.hh>
45 
46 #include <algorithm>
47 #include <cstdlib>
48 #include <cstring>
49 #include <iostream>
50 #include <map>
51 #include <string>
52 #include <utility>
53 #include <vector>
54 
55 namespace MiniZinc {
56 
57 struct ParseWorkItem {
58   Model* m;
59   IncludeI* ii;
60   std::string dirName;
61   std::string fileName;
62   bool isSTDLib;
63   bool isModelString;
ParseWorkItemMiniZinc::ParseWorkItem64   ParseWorkItem(Model* m0, IncludeI* ii0, std::string dirName0, std::string fileName0,
65                 bool isSTDLib0 = false, bool isModelString0 = false)
66       : m(m0),
67         ii(ii0),
68         dirName(std::move(dirName0)),
69         fileName(std::move(fileName0)),
70         isSTDLib(isSTDLib0),
71         isModelString(isModelString0) {}
72 };
73 
74 /// %State of the %MiniZinc parser
75 class ParserState {
76 public:
ParserState(const std::string & f,const std::string & b,std::ostream & err0,const std::vector<std::string> & includePaths0,std::vector<ParseWorkItem> & files0,std::map<std::string,Model * > & seenModels0,MiniZinc::Model * model0,bool isDatafile0,bool isFlatZinc0,bool isSTDLib0,bool parseDocComments0)77   ParserState(const std::string& f, const std::string& b, std::ostream& err0,
78               const std::vector<std::string>& includePaths0, std::vector<ParseWorkItem>& files0,
79               std::map<std::string, Model*>& seenModels0, MiniZinc::Model* model0, bool isDatafile0,
80               bool isFlatZinc0, bool isSTDLib0, bool parseDocComments0)
81       : filename(f.c_str()),
82         buf(b.c_str()),
83         pos(0),
84         length(static_cast<unsigned int>(b.size())),
85         lineStartPos(0),
86         nTokenNextStart(1),
87         hadNewline(false),
88         includePaths(includePaths0),
89         files(files0),
90         seenModels(seenModels0),
91         model(model0),
92         isDatafile(isDatafile0),
93         isFlatZinc(isFlatZinc0),
94         isSTDLib(isSTDLib0),
95         parseDocComments(parseDocComments0),
96         hadError(false),
97         err(err0) {}
98 
99   const char* filename;
100 
101   void* yyscanner;
102   const char* buf;
103   unsigned int pos, length;
104 
105   int lineStartPos;
106   int nTokenNextStart;
107   bool hadNewline;
108 
109   const std::vector<std::string>& includePaths;
110   std::vector<ParseWorkItem>& files;
111   std::map<std::string, Model*>& seenModels;
112   MiniZinc::Model* model;
113 
114   bool isDatafile;
115   bool isFlatZinc;
116   bool isSTDLib;
117   bool parseDocComments;
118   bool hadError;
119   std::vector<SyntaxError> syntaxErrors;
120   std::ostream& err;
121 
122   std::string stringBuffer;
123 
printCurrentLine(int firstCol,int lastCol)124   void printCurrentLine(int firstCol, int lastCol) {
125     const char* eol_c = strchr(buf + lineStartPos, '\n');
126     if (eol_c != nullptr) {
127       if (eol_c == buf + lineStartPos) {
128         return;
129       }
130       err << std::string(buf + lineStartPos, eol_c - (buf + lineStartPos));
131     } else {
132       err << buf + lineStartPos;
133     }
134     err << std::endl;
135     for (int i = 0; i < firstCol - 1; i++) {
136       err << " ";
137     }
138     for (int i = firstCol; i <= lastCol; i++) {
139       err << "^";
140     }
141     err << std::endl;
142   }
143 
fillBuffer(char * lexBuf,unsigned int lexBufSize)144   int fillBuffer(char* lexBuf, unsigned int lexBufSize) {
145     if (pos >= length) {
146       return 0;
147     }
148     int num = std::min(length - pos, lexBufSize);
149     memcpy(lexBuf, buf + pos, num);
150     pos += num;
151     return num;
152   }
153 
154   std::string canonicalFilename(const std::string& f) const;
155 };
156 
157 Model* parse(Env& env, const std::vector<std::string>& filename,
158              const std::vector<std::string>& datafiles, const std::string& textModel,
159              const std::string& textModelName, const std::vector<std::string>& includePaths,
160              bool isFlatZinc, bool ignoreStdlib, bool parseDocComments, bool verbose,
161              std::ostream& err);
162 
163 Model* parse_from_string(Env& env, const std::string& text, const std::string& filename,
164                          const std::vector<std::string>& includePaths, bool isFlatZinc,
165                          bool ignoreStdlib, bool parseDocComments, bool verbose, std::ostream& err,
166                          std::vector<SyntaxError>& syntaxErrors);
167 
168 Model* parse_data(Env& env, Model* m, const std::vector<std::string>& datafiles,
169                   const std::vector<std::string>& includePaths, bool isFlatZinc, bool ignoreStdlib,
170                   bool parseDocComments, bool verbose, std::ostream& err);
171 
172 }  // namespace MiniZinc
173