grammar.js 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236
  1. "use strict";
  2. var ContextAssignment = require("js/ContextAssignment.js");
  3. var ContextCase = require("js/ContextCase.js");
  4. var ContextDesignator = require("js/ContextDesignator.js");
  5. var ContextExpression = require("js/ContextExpression.js");
  6. var ContextIdentdef = require("js/ContextIdentdef.js");
  7. var ContextLoop = require("js/ContextLoop.js");
  8. var ContextModule = require("js/ContextModule.js");
  9. var ContextProcedure = require("js/ContextProcedure.js");
  10. var ContextType = require("js/ContextType.js");
  11. var Lexer = require("js/Lexer.js");
  12. var Parser = require("parser.js");
  13. var literal = Parser.literal;
  14. var point = Lexer.point;
  15. var and = Parser.and;
  16. var or = Parser.or;
  17. var optional = Parser.optional;
  18. var repeat = Parser.repeat;
  19. var context = Parser.context;
  20. var emit = Parser.emit;
  21. var required = Parser.required;
  22. var reservedWords = "ARRAY IMPORT THEN BEGIN IN TO BY IS TRUE CASE MOD TYPE CONST MODULE UNTIL DIV NIL VAR DO OF WHILE ELSE OR ELSIF POINTER END PROCEDURE FALSE RECORD FOR REPEAT IF RETURN";
  23. function make(makeIdentdef,
  24. makeDesignator,
  25. makeExpression,
  26. makeStrucType,
  27. makeStatement,
  28. makeProcedureHeading,
  29. makeProcedureDeclaration,
  30. makeFieldList,
  31. makeFieldListSequence,
  32. makeForInit,
  33. makeArrayDimensions,
  34. makeFormalArray,
  35. makeFormalResult,
  36. makeReturn,
  37. contexts,
  38. reservedWords
  39. ){
  40. var result = {};
  41. var ident = function(stream, context){
  42. return Lexer.ident(stream, context, reservedWords);
  43. };
  44. var qualident = context(and(optional(context(and(ident, "."), ContextIdentdef.QualifiedModule)), ident),
  45. ContextIdentdef.Qualified);
  46. var identdef = makeIdentdef(ident);
  47. var selector = or(and(point, ident)
  48. // break recursive declaration of expList
  49. , and("[", function(stream, context){return expList(stream, context);}, "]")
  50. , "^"
  51. , context(and("(", qualident, ")"), ContextDesignator.TypeCast)
  52. );
  53. var designator = makeDesignator(
  54. ident,
  55. qualident,
  56. selector,
  57. // break recursive declaration of actualParameters
  58. function(stream, context){return actualParameters(stream, context);}
  59. );
  60. var type = or(qualident,
  61. function(stream, context){return strucType(stream, context);} // break recursive declaration of strucType
  62. );
  63. var identList = and(identdef, repeat(and(",", identdef)));
  64. var variableDeclaration = context(and(identList, ":", type), contexts.variableDeclaration);
  65. var integer = context(Lexer.integer, ContextExpression.Integer);
  66. var real = context(Lexer.real, ContextExpression.Real);
  67. var number = or(real, integer);
  68. var string = context(Lexer.string, ContextExpression.Str);
  69. var factor = context(
  70. or(string,
  71. number,
  72. "NIL",
  73. "TRUE",
  74. "FALSE",
  75. function(stream, context){return set(stream, context);}, // break recursive declaration of set
  76. designator.factor,
  77. and("(", function(stream, context){return expression(stream, context);}
  78. , required(")", "no matched ')'")),
  79. and("~", function(stream, context){
  80. return factor(stream, context);}) // break recursive declaration of factor
  81. )
  82. , contexts.Factor);
  83. var addOperator = context(or("+", "-", "OR"), ContextExpression.AddOperator);
  84. var mulOperator = context(or("*", "/", "DIV", "MOD", "&"), ContextExpression.MulOperator);
  85. var term = context(and(factor, repeat(and(mulOperator, factor))), contexts.Term);
  86. var simpleExpression = context(
  87. and(optional(or("+", "-"))
  88. , term
  89. , repeat(and(addOperator, term)))
  90. , contexts.SimpleExpression);
  91. var relation = or("=", "#", "<=", "<", ">=", ">", "IN", "IS");
  92. var expression = makeExpression(and(simpleExpression, optional(and(relation, required(simpleExpression, "invalid operand")))));
  93. var constExpression = expression;
  94. var element = context(and(expression, optional(and("..", expression))), ContextExpression.SetElement);
  95. var set = and("{", context(optional(and(element, repeat(and(",", element)))), ContextExpression.Set)
  96. , "}");
  97. var expList = and(expression, repeat(and(",", expression)));
  98. var actualParameters = and("(", context(optional(expList), ContextDesignator.ActualParameters), ")");
  99. var assignment = and(context(or(":=", "="), ContextAssignment.Check),
  100. required(expression, "expression expected"));
  101. // break recursive declaration of statement
  102. var forwardStatement = function(stream, context){return statement(stream, context);};
  103. var statementSequence = and(forwardStatement, repeat(and(";", forwardStatement)));
  104. var ifStatement = and("IF", context(and(expression, required("THEN", "THEN expected"), statementSequence,
  105. repeat(and("ELSIF", expression, required("THEN", "THEN expected"), statementSequence)),
  106. optional(and("ELSE", statementSequence)),
  107. "END"),
  108. contexts.If));
  109. var label = or(integer, string, qualident);
  110. var labelRange = context(and(label, optional(and("..", label))), ContextCase.Range);
  111. var caseLabelList = context(and(labelRange, repeat(and(",", labelRange))), ContextCase.LabelList);
  112. var caseParser = optional(context(and(caseLabelList, ":", statementSequence), contexts.CaseLabel));
  113. var caseStatement = and("CASE", context(and(expression
  114. , "OF", caseParser, repeat(and("|", caseParser)), "END")
  115. , ContextCase.Type));
  116. var whileStatement = and("WHILE",
  117. context(and(expression, "DO", statementSequence,
  118. repeat(and("ELSIF", expression, "DO", statementSequence)),
  119. "END"),
  120. contexts.While));
  121. var repeatStatement = and("REPEAT",
  122. context(and(statementSequence,
  123. "UNTIL",
  124. context(expression, ContextLoop.Until)),
  125. contexts.Repeat));
  126. var forStatement = and("FOR",
  127. context(and(makeForInit(ident, expression, assignment), "TO", expression
  128. , optional(and("BY", constExpression))
  129. , emit("DO", ContextLoop.emitForBegin)
  130. , statementSequence, required("END", "END expected (FOR)"))
  131. , contexts.For));
  132. var statement = optional(
  133. makeStatement(or( emit(designator.assignmentOrProcedureCall(assignment, expression), ContextAssignment.emitEnd),
  134. ifStatement,
  135. caseStatement,
  136. whileStatement,
  137. repeatStatement,
  138. forStatement),
  139. statementSequence,
  140. ident,
  141. expression));
  142. var fieldList = makeFieldList(
  143. identdef,
  144. identList,
  145. type,
  146. function(stream, context){return formalParameters(stream, context);}
  147. );
  148. var fieldListSequence = makeFieldListSequence(and(fieldList, repeat(and(";", fieldList))));
  149. var arrayType = and("ARRAY",
  150. context(and(makeArrayDimensions(constExpression), "OF", type),
  151. contexts.ArrayDecl));
  152. var baseType = context(qualident, ContextType.RecordBase);
  153. var recordType = and("RECORD", context(and(optional(and("(", baseType, ")")), optional(fieldListSequence)
  154. , "END"), contexts.recordDecl));
  155. var pointerType = and("POINTER", "TO", context(type, ContextType.Pointer));
  156. var formalType = context(and(repeat(makeFormalArray()), qualident), contexts.FormalType);
  157. var fpSection = and(optional("VAR"), ident, repeat(and(",", ident)), ":", formalType);
  158. var formalParameters = and(
  159. "("
  160. , optional(context(and(fpSection, repeat(and(";", fpSection))), ContextProcedure.DefinedParameters))
  161. , required( ")" )
  162. , optional(makeFormalResult(and(":", qualident), ident, actualParameters)));
  163. var procedureType = and("PROCEDURE"
  164. , context(optional(formalParameters), contexts.FormalParameters)
  165. );
  166. var strucType = makeStrucType(or(arrayType, recordType, pointerType, procedureType), type);
  167. var typeDeclaration = context(and(identdef, "=", strucType), contexts.typeDeclaration);
  168. var constantDeclaration = context(and(identdef, "=", constExpression), contexts.constDeclaration);
  169. var imprt = and(ident, optional(and(":=", ident)));
  170. var importList = and("IMPORT", imprt, repeat(and(",", imprt)));
  171. result.expression = expression;
  172. result.statement = statement;
  173. result.typeDeclaration = typeDeclaration;
  174. result.variableDeclaration = variableDeclaration;
  175. var procedureHeading = makeProcedureHeading(ident, identdef, formalParameters);
  176. result.ident = ident;
  177. result.procedureDeclaration
  178. // break recursive declaration of procedureBody
  179. = makeProcedureDeclaration(
  180. ident,
  181. procedureHeading,
  182. function(stream, context){
  183. return result.procedureBody(stream, context);}
  184. );
  185. result.declarationSequence
  186. = and(optional(and("CONST", repeat(and(constantDeclaration, required(";"))))),
  187. optional(and("TYPE", context(repeat(and(typeDeclaration, required(";"))), ContextType.Section))),
  188. optional(and("VAR", repeat(and(variableDeclaration, required(";"))))),
  189. repeat(and(result.procedureDeclaration, ";")));
  190. result.procedureBody
  191. = and(result.declarationSequence,
  192. optional(and("BEGIN", statementSequence)),
  193. optional(context(makeReturn(and("RETURN", expression)), ContextProcedure.Return)),
  194. required("END", "END expected (PROCEDURE)"));
  195. result.module
  196. = context(and("MODULE", ident, ";",
  197. context(optional(and(importList, ";")), ContextModule.Import),
  198. result.declarationSequence,
  199. optional(and("BEGIN", statementSequence)),
  200. required("END", "END expected (MODULE)"), ident, point),
  201. contexts.ModuleDeclaration);
  202. return result;
  203. }
  204. exports.make = make;
  205. exports.reservedWords = reservedWords;