Ablexpr.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466
  1. //===========================================================================//
  2. // Copyright (C) Microsoft Corporation. All rights reserved. //
  3. //===========================================================================//
  4. //***************************************************************************
  5. //
  6. // ABLEXPR.CPP
  7. //
  8. //***************************************************************************
  9. #include <string.h>
  10. #include <stdio.h>
  11. #include <stdlib.h>
  12. #ifndef ABLGEN_H
  13. #include "ablgen.h"
  14. #endif
  15. #ifndef ABLERR_H
  16. #include "ablerr.h"
  17. #endif
  18. #ifndef ABLSCAN_H
  19. #include "ablscan.h"
  20. #endif
  21. #ifndef ABLSYMT_H
  22. #include "ablsymt.h"
  23. #endif
  24. #ifndef ABLPARSE_H
  25. #include "ablparse.h"
  26. #endif
  27. #ifndef ABLEXEC_H
  28. #include "ablexec.h"
  29. #endif
  30. #ifndef ABLENV_H
  31. #include "ablenv.h"
  32. #endif
  33. //***************************************************************************
  34. extern TokenCodeType curToken;
  35. extern char tokenString[];
  36. extern char wordString[];
  37. extern Literal curLiteral;
  38. extern SymTableNodePtr SymTableDisplay[];
  39. extern long level;
  40. extern TypePtr IntegerTypePtr, CharTypePtr, RealTypePtr, BooleanTypePtr;
  41. extern Type DummyType;
  42. extern TokenCodeType statementEndList[];
  43. extern bool EnterStateSymbol;
  44. extern ABLModulePtr CurFSM;
  45. SymTableNodePtr forwardState (char* stateName);
  46. extern SymTableNodePtr CurModuleIdPtr;
  47. //***************************************************************************
  48. TokenCodeType relationalOperatorList[] = {
  49. TKN_LT,
  50. TKN_LE,
  51. TKN_EQUALEQUAL,
  52. TKN_NE,
  53. TKN_GE,
  54. TKN_GT,
  55. TKN_NONE
  56. };
  57. TokenCodeType addOperatorList[] = {
  58. TKN_PLUS,
  59. TKN_MINUS,
  60. TKN_OR,
  61. TKN_NONE
  62. };
  63. TokenCodeType multiplyOperatorList[] = {
  64. TKN_STAR,
  65. TKN_FSLASH,
  66. TKN_DIV, // we'll probably want to make this covered with FSLASH
  67. TKN_MOD,
  68. TKN_AND,
  69. TKN_NONE
  70. };
  71. //***************************************************************************
  72. // MISC
  73. //***************************************************************************
  74. inline bool integerOperands (TypePtr type1, TypePtr type2) {
  75. return((type1 == IntegerTypePtr) && (type2 == IntegerTypePtr));
  76. }
  77. //***************************************************************************
  78. inline bool realOperands (TypePtr type1, TypePtr type2) {
  79. if (type1 == RealTypePtr)
  80. return((type2 == RealTypePtr) || (type2 == IntegerTypePtr));
  81. else if (type2 == RealTypePtr)
  82. return(type1 == IntegerTypePtr);
  83. else
  84. return(false);
  85. }
  86. //***************************************************************************
  87. inline bool booleanOperands (TypePtr type1, TypePtr type2) {
  88. return((type1 == BooleanTypePtr) && (type2 == BooleanTypePtr));
  89. }
  90. //***************************************************************************
  91. void checkRelationalOpTypes (TypePtr type1, TypePtr type2) {
  92. if (type1 && type2) {
  93. if ((type1 == type2) && ((type1->form == FRM_SCALAR) || (type1->form == FRM_ENUM)))
  94. return;
  95. if (((type1 == IntegerTypePtr) && (type2 == RealTypePtr)) ||
  96. ((type2 == IntegerTypePtr) && (type1 == RealTypePtr)))
  97. return;
  98. if ((type1->form == FRM_ARRAY) && (type2->form == FRM_ARRAY) &&
  99. (type1->info.array.elementTypePtr == CharTypePtr) && (type2->info.array.elementTypePtr == CharTypePtr) &&
  100. (type1->info.array.elementCount == type2->info.array.elementCount))
  101. return;
  102. }
  103. syntaxError(ABL_ERR_SYNTAX_INCOMPATIBLE_TYPES);
  104. }
  105. //***************************************************************************
  106. long isAssignTypeCompatible (TypePtr type1, TypePtr type2) {
  107. if (type1 == type2)
  108. return(1);
  109. if ((type1 == RealTypePtr) && (type2 == IntegerTypePtr))
  110. return(1);
  111. if ((type1->form == FRM_ARRAY) && (type2->form == FRM_ARRAY) &&
  112. (type1->info.array.elementTypePtr == CharTypePtr) && (type2->info.array.elementTypePtr == CharTypePtr) &&
  113. (type1->info.array.elementCount >= type2->info.array.elementCount))
  114. return(1);
  115. return(0);
  116. }
  117. //***************************************************************************
  118. // EXPRESSION routines
  119. //***************************************************************************
  120. TypePtr variable (SymTableNodePtr variableIdPtr) {
  121. TypePtr typePtr = (TypePtr)(variableIdPtr->typePtr);
  122. DefinitionType defnKey = variableIdPtr->defn.key;
  123. crunchSymTableNodePtr(variableIdPtr);
  124. switch (defnKey) {
  125. case DFN_VAR:
  126. case DFN_VALPARAM:
  127. case DFN_REFPARAM:
  128. case DFN_FUNCTION:
  129. case DFN_UNDEFINED:
  130. break;
  131. default:
  132. typePtr = &DummyType;
  133. syntaxError(ABL_ERR_SYNTAX_INVALID_IDENTIFIER_USAGE);
  134. }
  135. getToken();
  136. //---------------------------------------------------------------------
  137. // There should not be a parameter list. However, if there is, parse it
  138. // for error recovery...
  139. if (curToken == TKN_LPAREN) {
  140. syntaxError(ABL_ERR_SYNTAX_UNEXPECTED_TOKEN);
  141. actualParamList(variableIdPtr, 0);
  142. return(typePtr);
  143. }
  144. //-----------
  145. // Subscripts
  146. while (curToken == TKN_LBRACKET) {
  147. if (curToken == TKN_LBRACKET)
  148. typePtr = arraySubscriptList(typePtr);
  149. }
  150. return(typePtr);
  151. }
  152. //***************************************************************************
  153. TypePtr arraySubscriptList (TypePtr typePtr) {
  154. TypePtr indexTypePtr = NULL;
  155. TypePtr elementTypePtr = NULL;
  156. TypePtr subscriptTypePtr = NULL;
  157. do {
  158. if (typePtr->form == FRM_ARRAY) {
  159. indexTypePtr = typePtr->info.array.indexTypePtr;
  160. elementTypePtr = typePtr->info.array.elementTypePtr;
  161. getToken();
  162. subscriptTypePtr = expression();
  163. //-------------------------------------------------------------
  164. // If the subscript expression isn't assignment type compatible
  165. // with its corresponding subscript type, we're screwed...
  166. if (!isAssignTypeCompatible(indexTypePtr, subscriptTypePtr))
  167. syntaxError(ABL_ERR_SYNTAX_INCOMPATIBLE_TYPES);
  168. typePtr = elementTypePtr;
  169. }
  170. else {
  171. syntaxError(ABL_ERR_SYNTAX_TOO_MANY_SUBSCRIPTS);
  172. while ((curToken != TKN_RBRACKET) && !tokenIn(statementEndList))
  173. getToken();
  174. }
  175. } while (curToken == TKN_COMMA);
  176. ifTokenGetElseError(TKN_RBRACKET, ABL_ERR_SYNTAX_MISSING_RBRACKET);
  177. return(typePtr);
  178. }
  179. //***************************************************************************
  180. TypePtr factor (void) {
  181. TypePtr thisType = NULL;
  182. switch (curToken) {
  183. case TKN_IDENTIFIER: {
  184. SymTableNodePtr IdPtr = NULL;
  185. searchAndFindAllSymTables(IdPtr);
  186. switch (IdPtr->defn.key) {
  187. case DFN_FUNCTION:
  188. crunchSymTableNodePtr(IdPtr);
  189. getToken();
  190. thisType = routineCall(IdPtr, 1);
  191. break;
  192. case DFN_CONST:
  193. crunchSymTableNodePtr(IdPtr);
  194. getToken();
  195. thisType = (TypePtr)(IdPtr->typePtr);
  196. break;
  197. default:
  198. thisType = (TypePtr)variable(IdPtr);
  199. break;
  200. }
  201. }
  202. break;
  203. case TKN_NUMBER: {
  204. SymTableNodePtr thisNode = searchSymTable(tokenString, SymTableDisplay[1]);
  205. if (!thisNode)
  206. thisNode = enterSymTable(tokenString, &SymTableDisplay[1]);
  207. if (curLiteral.type == LIT_INTEGER) {
  208. thisNode->typePtr = IntegerTypePtr;
  209. thisType = (TypePtr)(thisNode->typePtr);
  210. thisNode->defn.info.constant.value.integer = curLiteral.value.integer;
  211. }
  212. else {
  213. thisNode->typePtr = RealTypePtr;
  214. thisType = (TypePtr)(thisNode->typePtr);
  215. thisNode->defn.info.constant.value.real = curLiteral.value.real;
  216. }
  217. crunchSymTableNodePtr(thisNode);
  218. getToken();
  219. }
  220. break;
  221. case TKN_STRING: {
  222. long length = strlen(curLiteral.value.string);
  223. if (EnterStateSymbol) {
  224. SymTableNodePtr stateSymbol = searchSymTableForState(curLiteral.value.string, SymTableDisplay[1]);
  225. if (!stateSymbol)
  226. forwardState(curLiteral.value.string);
  227. }
  228. SymTableNodePtr thisNode = searchSymTableForString(tokenString, SymTableDisplay[1]);
  229. if (!thisNode)// {
  230. thisNode = enterSymTable(tokenString, &SymTableDisplay[1]);
  231. if (length == 1) {
  232. thisNode->defn.info.constant.value.character = curLiteral.value.string[0];
  233. thisType = CharTypePtr;
  234. }
  235. else {
  236. thisNode->typePtr = thisType = makeStringType(length);
  237. thisNode->info = (char*)ABLSymbolMallocCallback(length + 1);
  238. if (!thisNode->info)
  239. ABL_Fatal(0, " ABL: Unable to AblSymTableHeap->malloc string literal ");
  240. strcpy(thisNode->info, curLiteral.value.string);
  241. }
  242. //}
  243. crunchSymTableNodePtr(thisNode);
  244. getToken();
  245. }
  246. break;
  247. case TKN_NOT:
  248. getToken();
  249. thisType = factor();
  250. break;
  251. case TKN_LPAREN:
  252. getToken();
  253. thisType = expression();
  254. ifTokenGetElseError(TKN_RPAREN, ABL_ERR_SYNTAX_MISSING_RPAREN);
  255. break;
  256. default:
  257. syntaxError(ABL_ERR_SYNTAX_INVALID_EXPRESSION);
  258. thisType = &DummyType;
  259. break;
  260. }
  261. return(thisType);
  262. }
  263. //***************************************************************************
  264. TypePtr term (void) {
  265. //-------------------------
  266. // Grab the first factor...
  267. TypePtr resultType = factor();
  268. //------------------------------------------------------------------
  269. // Now, continue grabbing factors separated by multiply operators...
  270. while (tokenIn(multiplyOperatorList)) {
  271. TokenCodeType op = curToken;
  272. getToken();
  273. TypePtr secondType = factor();
  274. switch (op) {
  275. case TKN_STAR:
  276. if (integerOperands(resultType, secondType)) {
  277. //---------------------------------------------------
  278. // Both operands are integer, so result is integer...
  279. resultType = IntegerTypePtr;
  280. }
  281. else if (realOperands(resultType, secondType)) {
  282. //----------------------------------------------------
  283. // Both real operands, or mixed (real and integer)...
  284. resultType = RealTypePtr;
  285. }
  286. else {
  287. syntaxError(ABL_ERR_SYNTAX_INCOMPATIBLE_TYPES);
  288. resultType = &DummyType;
  289. }
  290. break;
  291. case TKN_FSLASH:
  292. if (integerOperands(resultType, secondType)) {
  293. //---------------------------------------------------
  294. // Both operands are integer, so result is integer...
  295. resultType = IntegerTypePtr;
  296. }
  297. else if (realOperands(resultType, secondType)) {
  298. //----------------------------------------------------
  299. // Both real operands, or mixed (real and integer)...
  300. resultType = RealTypePtr;
  301. }
  302. else {
  303. syntaxError(ABL_ERR_SYNTAX_INCOMPATIBLE_TYPES);
  304. resultType = &DummyType;
  305. }
  306. break;
  307. case TKN_DIV:
  308. case TKN_MOD:
  309. //----------------------------------------------------------
  310. // Both operands should be integer, and result is integer...
  311. if (!integerOperands(resultType, secondType))
  312. syntaxError(ABL_ERR_SYNTAX_INCOMPATIBLE_TYPES);
  313. resultType = IntegerTypePtr;
  314. break;
  315. case TKN_AND:
  316. if (!booleanOperands(resultType, secondType))
  317. syntaxError(ABL_ERR_SYNTAX_INCOMPATIBLE_TYPES);
  318. resultType = BooleanTypePtr;
  319. break;
  320. }
  321. }
  322. return(resultType);
  323. }
  324. //***************************************************************************
  325. TypePtr simpleExpression (void) {
  326. bool usedUnaryOp = false;
  327. TokenCodeType unaryOp = TKN_PLUS;
  328. if ((curToken == TKN_PLUS) || (curToken == TKN_MINUS)) {
  329. unaryOp = curToken;
  330. usedUnaryOp = true;
  331. getToken();
  332. }
  333. //------------------------------------------------
  334. // Grab the first term in the simple expression...
  335. TypePtr resultType = term();
  336. if (usedUnaryOp && (resultType != IntegerTypePtr) && (resultType != RealTypePtr))
  337. syntaxError(ABL_ERR_SYNTAX_INCOMPATIBLE_TYPES);
  338. //---------------------------------------------------
  339. // Continue to process all terms in the expression...
  340. while (tokenIn(addOperatorList)) {
  341. TokenCodeType op = curToken;
  342. getToken();
  343. TypePtr secondType = term();
  344. switch (op) {
  345. case TKN_PLUS:
  346. case TKN_MINUS:
  347. if (integerOperands(resultType, secondType)) {
  348. //---------------------------------------------------
  349. // Both operands are integer, so result is integer...
  350. resultType = IntegerTypePtr;
  351. }
  352. else if (realOperands(resultType, secondType)) {
  353. //----------------------------------------------------
  354. // Both real operands, or mixed (real and integer)...
  355. resultType = RealTypePtr;
  356. }
  357. else {
  358. syntaxError(ABL_ERR_SYNTAX_INCOMPATIBLE_TYPES);
  359. resultType = &DummyType;
  360. }
  361. break;
  362. case TKN_OR:
  363. if (!booleanOperands(resultType, secondType))
  364. syntaxError(ABL_ERR_SYNTAX_INCOMPATIBLE_TYPES);
  365. resultType = BooleanTypePtr;
  366. break;
  367. }
  368. }
  369. return(resultType);
  370. }
  371. //***************************************************************************
  372. TypePtr expression (void) {
  373. //------------------------------------
  374. // Grab the first simple expression...
  375. TypePtr resultType = simpleExpression();
  376. if (tokenIn(relationalOperatorList)) {
  377. //---------------------------------------
  378. // Snatch the second simple expression...
  379. getToken();
  380. TypePtr secondType = simpleExpression();
  381. checkRelationalOpTypes(resultType, secondType);
  382. resultType = BooleanTypePtr;
  383. }
  384. return(resultType);
  385. }
  386. //***************************************************************************