grammar.js 10.0 KB

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