You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

692 lines
21 KiB

  1. //==============================================================================
  2. //
  3. // Copyright (c) 2015-
  4. // Authors:
  5. // * Joachim Klein <klein@tcs.inf.tu-dresden.de>
  6. // * David Mueller <david.mueller@tcs.inf.tu-dresden.de>
  7. //
  8. //------------------------------------------------------------------------------
  9. //
  10. // This file is part of the cpphoafparser library,
  11. // http://automata.tools/hoa/cpphoafparser/
  12. //
  13. // The cpphoafparser library is free software; you can redistribute it and/or
  14. // modify it under the terms of the GNU Lesser General Public
  15. // License as published by the Free Software Foundation; either
  16. // version 2.1 of the License, or (at your option) any later version.
  17. //
  18. // The cpphoafparser library is distributed in the hope that it will be useful,
  19. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  20. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  21. // Lesser General Public License for more details.
  22. //
  23. // You should have received a copy of the GNU Lesser General Public
  24. // License along with this library; if not, write to the Free Software
  25. // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  26. //
  27. //==============================================================================
  28. #ifndef CPPHOAFPARSER_HOAPARSER_H
  29. #define CPPHOAFPARSER_HOAPARSER_H
  30. #include <set>
  31. #include <string>
  32. #include <sstream>
  33. #include "cpphoafparser/parser/hoa_lexer.hh"
  34. #include "cpphoafparser/consumer/hoa_consumer.hh"
  35. #include "cpphoafparser/consumer/hoa_intermediate_check_validity.hh"
  36. #include "cpphoafparser/consumer/hoa_intermediate_resolve_aliases.hh"
  37. #include "cpphoafparser/parser/hoa_parser_exception.hh"
  38. /** @mainpage cpphoafparser API documentation
  39. *
  40. * API documentation for the <a href="http://automata.tools/hoa/cpphoafparser/">cpphoafparser</a> library.
  41. */
  42. /** @namespace cpphoafparser
  43. * The `cpphoafparser` namespace contains all the classes of the
  44. * cpphoafparser library.
  45. */
  46. namespace cpphoafparser {
  47. /**
  48. * Parser class for parsing HOA files.
  49. *
  50. * Provides a static function for parsing a HOA automaton from an input stream,
  51. * calling into a HOAConsumer for every syntax element encountered during the parse.
  52. *
  53. * The parser is implemented as a simple, hand-written recursive-descent parser,
  54. * with functions corresponding to grammar rules.
  55. **/
  56. class HOAParser {
  57. public:
  58. /**
  59. * Function for parsing a single HOA automaton.
  60. *
  61. * On error, will throw HOAParserException, the consumers will generally throw
  62. * HOAConsumerException.
  63. *
  64. * @param in std::istream from which the automaton will be read
  65. * @param consumer a shared_ptr to the HOAConsumer whose functions will
  66. * be called for each element of the HOA automaton
  67. * @param check_validity Should the validity of the HOA be checked?
  68. * These are checks beyond the basic syntactic well-formedness guaranteed by the grammar.
  69. **/
  70. static void parse(std::istream& in, HOAConsumer::ptr consumer, bool check_validity=true) {
  71. if (consumer->parserResolvesAliases()) {
  72. consumer.reset(new HOAIntermediateResolveAliases(consumer));
  73. }
  74. if (check_validity) {
  75. consumer.reset(new HOAIntermediateCheckValidity(consumer));
  76. }
  77. HOAParser parser(in, consumer);
  78. parser.nextToken();
  79. parser.Automaton();
  80. }
  81. private:
  82. /** The registered consumer */
  83. HOAConsumer::ptr consumer;
  84. /** The lexer for tokenizing the input stream */
  85. HOALexer lexer;
  86. /** The current token */
  87. HOALexer::Token token;
  88. /** true if we are currently in a State: definition */
  89. bool inState;
  90. /** the index of the current state*/
  91. unsigned int currentState;
  92. /** true if the current state has state labeling */
  93. bool currentStateHasStateLabel;
  94. /** Private constructor. */
  95. HOAParser(std::istream& in, HOAConsumer::ptr consumer) :
  96. consumer(consumer), lexer(in), inState(false), currentState(0), currentStateHasStateLabel(false) {
  97. }
  98. /** Advance to the next token. Handles TOKEN_ABORT */
  99. void nextToken() {
  100. token = lexer.nextToken();
  101. if (token.kind == HOALexer::TOKEN_ABORT) {
  102. consumer->notifyAbort();
  103. throw "aborted";
  104. }
  105. }
  106. /** Advances to the next token if it is of the expected kind, otherwise throw an error. */
  107. void expect(HOALexer::TokenType kind, const std::string& context="") {
  108. if (token.kind != kind) {
  109. throw error(HOALexer::Token::forErrorMessage(kind), context);
  110. }
  111. // eat token
  112. nextToken();
  113. }
  114. /**
  115. * Constructs a HOAParserExeption for a syntax error.
  116. * @param expectedTokenTypes a string detailing which token types were expected
  117. * @param context optionally, some context for the error message */
  118. HOAParserException error(const std::string& expectedTokenTypes, const std::string& context="") {
  119. std::stringstream ss;
  120. ss << "Syntax error";
  121. if (context != "") {
  122. ss << " (while reading " << context << ")";
  123. }
  124. ss << ": Expected " << expectedTokenTypes;
  125. ss << ", got " << HOALexer::Token::forErrorMessage(token);
  126. ss << " (line " << std::to_string(token.line) << ", col " << std::to_string(token.col) << ")";
  127. return HOAParserException(ss.str(), token.line, token.col);
  128. }
  129. /** Grammar rule for the whole Automaton */
  130. void Automaton() {
  131. Header();
  132. expect(HOALexer::TOKEN_BODY);
  133. consumer->notifyBodyStart();
  134. Body();
  135. expect(HOALexer::TOKEN_END);
  136. if (inState) {
  137. consumer->notifyEndOfState(currentState);
  138. }
  139. consumer->notifyEnd();
  140. }
  141. /** Grammar rule for the HOA header */
  142. void Header() {
  143. Format();
  144. HeaderItems();
  145. }
  146. /** Grammar rule for the HOA: header */
  147. void Format() {
  148. expect(HOALexer::TOKEN_HOA);
  149. std::string version = Identifier("version");
  150. // TODO: check format version
  151. consumer->notifyHeaderStart(version);
  152. }
  153. /** Grammar rule for the remaining header items, returns if there are not more headers */
  154. void HeaderItems() {
  155. while (true) {
  156. switch (token.kind) {
  157. case HOALexer::TOKEN_STATES: HeaderItemStates(); break;
  158. case HOALexer::TOKEN_START: HeaderItemStart(); break;
  159. case HOALexer::TOKEN_AP: HeaderItemAP(); break;
  160. case HOALexer::TOKEN_ALIAS: HeaderItemAlias(); break;
  161. case HOALexer::TOKEN_ACCEPTANCE: HeaderItemAcceptance(); break;
  162. case HOALexer::TOKEN_ACCNAME: HeaderItemAccName(); break;
  163. case HOALexer::TOKEN_TOOL: HeaderItemTool(); break;
  164. case HOALexer::TOKEN_NAME: HeaderItemName(); break;
  165. case HOALexer::TOKEN_PROPERTIES: HeaderItemProperties(); break;
  166. case HOALexer::TOKEN_HEADER_NAME: HeaderMiscItem(); break;
  167. default:
  168. // not a header, return
  169. return;
  170. }
  171. }
  172. }
  173. /** Grammar rule for the States-header */
  174. void HeaderItemStates() {
  175. expect(HOALexer::TOKEN_STATES);
  176. unsigned int states = Integer("number of states in States-header");
  177. consumer->setNumberOfStates(states);
  178. }
  179. /** Grammar rule for the Start-header */
  180. void HeaderItemStart() {
  181. expect(HOALexer::TOKEN_START);
  182. std::vector<unsigned int> stateConjunction;
  183. unsigned int state = Integer("Start: index of start state");
  184. stateConjunction.push_back(state);
  185. while (token.kind == HOALexer::TOKEN_AND) {
  186. expect(HOALexer::TOKEN_AND);
  187. state = Integer("Start: index of start state in conjunction");
  188. stateConjunction.push_back(state);
  189. }
  190. consumer->addStartStates(stateConjunction);
  191. }
  192. /** Grammar rule for the AP-header */
  193. void HeaderItemAP() {
  194. expect(HOALexer::TOKEN_AP);
  195. unsigned int apCount = Integer("AP: number of atomic propositions");
  196. std::vector<std::string> apList;
  197. std::set<std::string> aps;
  198. while (token.kind == HOALexer::TOKEN_STRING) {
  199. std::string ap = QuotedString();
  200. if (aps.find(ap) != aps.end()) {
  201. throw HOAConsumerException("Atomic proposition \""+ap+"\" is a duplicate!");
  202. }
  203. aps.insert(ap);
  204. apList.push_back(ap);
  205. }
  206. if (apList.size() != apCount) {
  207. throw HOAConsumerException("Number of provided APs (" + std::to_string(apList.size()) + ") does not match number of APs that was specified (" + std::to_string(apCount) + ")");
  208. }
  209. consumer->setAPs(apList);
  210. }
  211. /** Grammar rule for the Alias-header */
  212. void HeaderItemAlias() {
  213. expect(HOALexer::TOKEN_ALIAS);
  214. std::string aliasName = AliasName();
  215. HOAConsumer::label_expr::ptr labelExpr = LabelExpr();
  216. consumer->addAlias(aliasName, labelExpr);
  217. }
  218. /** Grammar rule for the Acceptance-header */
  219. void HeaderItemAcceptance() {
  220. expect(HOALexer::TOKEN_ACCEPTANCE);
  221. unsigned int numberOfSets = Integer("Acceptance: number of acceptance sets");
  222. HOAConsumer::acceptance_expr::ptr accExpr = AcceptanceCondition();
  223. consumer->setAcceptanceCondition(numberOfSets, accExpr);
  224. }
  225. /** Grammar rule for the acc-name-header */
  226. void HeaderItemAccName() {
  227. expect(HOALexer::TOKEN_ACCNAME);
  228. std::string accName = Identifier("acceptance name");
  229. std::vector<IntOrString> extraInfo;
  230. while (true) {
  231. if (token.kind == HOALexer::TOKEN_IDENT) {
  232. extraInfo.push_back(IntOrString(Identifier()));
  233. } else if (token.kind == HOALexer::TOKEN_INT) {
  234. extraInfo.push_back(IntOrString(Integer()));
  235. } else if (token.kind == HOALexer::TOKEN_TRUE) {
  236. extraInfo.push_back(IntOrString("t"));
  237. expect(HOALexer::TOKEN_TRUE); // munch
  238. } else if (token.kind == HOALexer::TOKEN_FALSE) {
  239. extraInfo.push_back(IntOrString("f"));
  240. expect(HOALexer::TOKEN_FALSE); // munch
  241. } else {
  242. break;
  243. }
  244. // TODO
  245. // if (settings == null || !settings.getFlagIgnoreAccName()) {
  246. // consumer.provideAcceptanceName(accName, extraInfo);
  247. //}
  248. }
  249. consumer->provideAcceptanceName(accName, extraInfo);
  250. }
  251. /** Grammar rule for the tool-header */
  252. void HeaderItemTool() {
  253. expect(HOALexer::TOKEN_TOOL);
  254. std::string tool = QuotedString();
  255. std::shared_ptr<std::string> version;
  256. if (token.kind == HOALexer::TOKEN_STRING) {
  257. version.reset(new std::string(QuotedString()));
  258. }
  259. consumer->setTool(tool, version);
  260. }
  261. /** Grammar rule for the name-header */
  262. void HeaderItemName() {
  263. expect(HOALexer::TOKEN_NAME);
  264. std::string name = QuotedString();
  265. consumer->setName(name);
  266. }
  267. /** Grammar rule for the properties-header */
  268. void HeaderItemProperties() {
  269. expect(HOALexer::TOKEN_PROPERTIES);
  270. std::vector<std::string> properties;
  271. while (true) {
  272. if (token.kind == HOALexer::TOKEN_IDENT) {
  273. std::string property = Identifier();
  274. properties.push_back(property);
  275. } else if (token.kind == HOALexer::TOKEN_TRUE) {
  276. // t does not have the special boolean meaning here, back to string
  277. properties.push_back("t");
  278. expect(HOALexer::TOKEN_TRUE); // eat
  279. } else if (token.kind == HOALexer::TOKEN_FALSE) {
  280. // f does not have the special boolean meaning here, back to string
  281. properties.push_back("f");
  282. expect(HOALexer::TOKEN_FALSE); // eat
  283. } else {
  284. // no more properties...
  285. break;
  286. }
  287. }
  288. consumer->addProperties(properties);
  289. }
  290. /** Grammar rule for a misc header (not known from the format specification) */
  291. void HeaderMiscItem() {
  292. std::string headerName = token.vString;
  293. headerName = headerName.substr(0, headerName.length()-1);
  294. expect(HOALexer::TOKEN_HEADER_NAME);
  295. std::vector<IntOrString> content;
  296. while (true) {
  297. if (token.kind == HOALexer::TOKEN_INT) {
  298. content.push_back(Integer());
  299. } else if (token.kind == HOALexer::TOKEN_IDENT) {
  300. content.push_back(Identifier());
  301. } else if (token.kind == HOALexer::TOKEN_STRING) {
  302. content.push_back(IntOrString(QuotedString(), true));
  303. } else if (token.kind == HOALexer::TOKEN_TRUE) {
  304. // t does not have the special boolean meaning here, back to string
  305. content.push_back(IntOrString("t", false));
  306. expect(HOALexer::TOKEN_TRUE); // eat
  307. } else if (token.kind == HOALexer::TOKEN_FALSE) {
  308. // f does not have the special boolean meaning here, back to string
  309. content.push_back(IntOrString("f", false));
  310. expect(HOALexer::TOKEN_FALSE); // eat
  311. } else {
  312. break;
  313. }
  314. }
  315. consumer->addMiscHeader(headerName, content);
  316. }
  317. /** Grammar rule for the automaton body */
  318. void Body() {
  319. while (true) {
  320. switch (token.kind) {
  321. case HOALexer::TOKEN_STATE:
  322. StateName();
  323. break;
  324. case HOALexer::TOKEN_END:
  325. return;
  326. case HOALexer::TOKEN_EOF:
  327. return;
  328. default:
  329. if (inState) {
  330. Edge();
  331. } else {
  332. throw error("either State: or --END--");
  333. }
  334. }
  335. }
  336. }
  337. /** Grammar rule for the State definition */
  338. void StateName() {
  339. expect(HOALexer::TOKEN_STATE);
  340. HOAConsumer::label_expr::ptr labelExpr;
  341. std::shared_ptr<std::string> stateComment;
  342. std::shared_ptr<HOAConsumer::int_list> accSignature;
  343. if (token.kind == HOALexer::TOKEN_LBRACKET) {
  344. labelExpr = Label();
  345. }
  346. unsigned int state = Integer(); // name of the state
  347. if (token.kind == HOALexer::TOKEN_STRING) {
  348. stateComment.reset(new std::string(QuotedString())); // state comment
  349. }
  350. if (token.kind == HOALexer::TOKEN_LCURLY) {
  351. accSignature = AcceptanceSignature();
  352. }
  353. if (inState) {
  354. consumer->notifyEndOfState(currentState);
  355. }
  356. consumer->addState(state, stateComment, labelExpr, accSignature);
  357. // store global information:
  358. inState = true;
  359. currentState = state;
  360. currentStateHasStateLabel = (bool)(labelExpr);
  361. }
  362. /** Grammar rule for an automaton edge */
  363. void Edge() {
  364. HOAConsumer::label_expr::ptr labelExpr;
  365. std::shared_ptr<HOAConsumer::int_list> conjStates;
  366. std::shared_ptr<HOAConsumer::int_list> accSignature;
  367. if (token.kind == HOALexer::TOKEN_LBRACKET) {
  368. labelExpr = Label();
  369. }
  370. conjStates = StateConjunction("edge");
  371. if (token.kind == HOALexer::TOKEN_LCURLY) {
  372. accSignature = AcceptanceSignature();
  373. }
  374. if (labelExpr || currentStateHasStateLabel) {
  375. consumer->addEdgeWithLabel(currentState, labelExpr, *conjStates, accSignature);
  376. } else {
  377. consumer->addEdgeImplicit(currentState, *conjStates, accSignature);
  378. }
  379. }
  380. /**
  381. * Grammar rule for a state conjunction
  382. * @param context contextual information for error messages
  383. */
  384. std::shared_ptr<HOAConsumer::int_list> StateConjunction(const std::string& context) {
  385. std::shared_ptr<HOAConsumer::int_list> stateConjunction (new HOAConsumer::int_list());
  386. unsigned int state = Integer(context);
  387. stateConjunction->push_back(state);
  388. while (token.kind == HOALexer::TOKEN_AND) {
  389. expect(HOALexer::TOKEN_AND);
  390. state = Integer(context);
  391. stateConjunction->push_back(state);
  392. }
  393. return stateConjunction;
  394. }
  395. /** Grammar rule for a [label-expr] */
  396. HOAConsumer::label_expr::ptr Label() {
  397. HOAConsumer::label_expr::ptr result;
  398. expect(HOALexer::TOKEN_LBRACKET);
  399. result = LabelExpr();
  400. expect(HOALexer::TOKEN_RBRACKET);
  401. return result;
  402. }
  403. /** Grammar rule for an acceptance signature */
  404. std::shared_ptr<HOAConsumer::int_list> AcceptanceSignature() {
  405. std::shared_ptr<HOAConsumer::int_list> result(new HOAConsumer::int_list());
  406. expect(HOALexer::TOKEN_LCURLY);
  407. while (token.kind == HOALexer::TOKEN_INT) {
  408. unsigned int accSet = Integer();
  409. result->push_back(accSet);
  410. }
  411. expect(HOALexer::TOKEN_RCURLY);
  412. return result;
  413. }
  414. /** Grammar rule for an acceptance condition expression (handle disjunction)*/
  415. HOAConsumer::acceptance_expr::ptr AcceptanceCondition() {
  416. HOAConsumer::acceptance_expr::ptr left = AcceptanceConditionAnd();
  417. while (token.kind == HOALexer::TOKEN_OR) {
  418. expect(HOALexer::TOKEN_OR);
  419. HOAConsumer::acceptance_expr::ptr right = AcceptanceConditionAnd();
  420. left = left | right;
  421. }
  422. return left;
  423. }
  424. /** Grammar rule for conjunction in an acceptance condition */
  425. HOAConsumer::acceptance_expr::ptr AcceptanceConditionAnd() {
  426. HOAConsumer::acceptance_expr::ptr left = AcceptanceConditionAtom();
  427. while (token.kind == HOALexer::TOKEN_AND) {
  428. expect(HOALexer::TOKEN_AND);
  429. HOAConsumer::acceptance_expr::ptr right = AcceptanceConditionAtom();
  430. left = left & right;
  431. }
  432. return left;
  433. }
  434. /** Grammar rule for the atoms in an acceptance condition */
  435. HOAConsumer::acceptance_expr::ptr AcceptanceConditionAtom() {
  436. HOAConsumer::acceptance_expr::ptr result;
  437. switch (token.kind) {
  438. case HOALexer::TOKEN_LPARENTH:
  439. expect(HOALexer::TOKEN_LPARENTH);
  440. result = AcceptanceCondition();
  441. expect(HOALexer::TOKEN_RPARENTH);
  442. return result;
  443. case HOALexer::TOKEN_TRUE:
  444. expect(HOALexer::TOKEN_TRUE);
  445. result.reset(new HOAConsumer::acceptance_expr(true));
  446. return result;
  447. case HOALexer::TOKEN_FALSE:
  448. expect(HOALexer::TOKEN_FALSE);
  449. result.reset(new HOAConsumer::acceptance_expr(false));
  450. return result;
  451. case HOALexer::TOKEN_IDENT:
  452. result.reset(new HOAConsumer::acceptance_expr(AcceptanceConditionTemporalOperator()));
  453. return result;
  454. default:
  455. throw error("acceptance condition");
  456. }
  457. }
  458. /** Grammar rule for a temporal operator (Fin/Inf) in an acceptance condition */
  459. AtomAcceptance::ptr AcceptanceConditionTemporalOperator() {
  460. AtomAcceptance::AtomType atomType = AtomAcceptance::TEMPORAL_FIN;
  461. bool negated = false;
  462. unsigned int accSetIndex;
  463. std::string temporalOperator = Identifier();
  464. if (temporalOperator == "Fin") {
  465. atomType = AtomAcceptance::TEMPORAL_FIN;
  466. } else if (temporalOperator == "Inf") {
  467. atomType = AtomAcceptance::TEMPORAL_INF;
  468. } else {
  469. throw error("either 'Fin' or 'Inf'", "acceptance condition");
  470. }
  471. expect(HOALexer::TOKEN_LPARENTH, "acceptance condition");
  472. if (token.kind == HOALexer::TOKEN_NOT) {
  473. expect(HOALexer::TOKEN_NOT);
  474. negated = true;
  475. }
  476. accSetIndex = Integer("acceptance set index");
  477. expect(HOALexer::TOKEN_RPARENTH, "acceptance condition");
  478. return AtomAcceptance::ptr(new AtomAcceptance(atomType, accSetIndex, negated));
  479. }
  480. /** Grammar rule for a label expression (handle disjunction) */
  481. HOAConsumer::label_expr::ptr LabelExpr() {
  482. HOAConsumer::label_expr::ptr left = LabelExprAnd();
  483. while (token.kind == HOALexer::TOKEN_OR) {
  484. expect(HOALexer::TOKEN_OR);
  485. HOAConsumer::label_expr::ptr right = LabelExprAnd();
  486. left = left | right;
  487. }
  488. return left;
  489. }
  490. /** Grammar rule for a label expression (handle conjunction) */
  491. HOAConsumer::label_expr::ptr LabelExprAnd() {
  492. HOAConsumer::label_expr::ptr left = LabelExprAtom();
  493. while (token.kind == HOALexer::TOKEN_AND) {
  494. expect(HOALexer::TOKEN_AND);
  495. HOAConsumer::label_expr::ptr right = LabelExprAtom();
  496. left = left & right;
  497. }
  498. return left;
  499. }
  500. /** Grammar rule for a label expression (handle atoms) */
  501. HOAConsumer::label_expr::ptr LabelExprAtom() {
  502. HOAConsumer::label_expr::ptr result;
  503. switch (token.kind) {
  504. case HOALexer::TOKEN_LPARENTH:
  505. expect(HOALexer::TOKEN_LPARENTH);
  506. result = LabelExpr();
  507. expect(HOALexer::TOKEN_RPARENTH);
  508. return result;
  509. case HOALexer::TOKEN_TRUE:
  510. expect(HOALexer::TOKEN_TRUE);
  511. result.reset(new HOAConsumer::label_expr(true));
  512. return result;
  513. case HOALexer::TOKEN_FALSE:
  514. expect(HOALexer::TOKEN_FALSE);
  515. result.reset(new HOAConsumer::label_expr(false));
  516. return result;
  517. case HOALexer::TOKEN_NOT:
  518. expect(HOALexer::TOKEN_NOT);
  519. result = LabelExprAtom();
  520. return !result;
  521. case HOALexer::TOKEN_INT: {
  522. unsigned int apIndex = Integer();
  523. result.reset(new HOAConsumer::label_expr(AtomLabel::createAPIndex(apIndex)));
  524. return result;
  525. }
  526. case HOALexer::TOKEN_ALIAS_NAME: {
  527. std::string aliasName = AliasName();
  528. result.reset(new HOAConsumer::label_expr(AtomLabel::createAlias(aliasName)));
  529. return result;
  530. }
  531. default:
  532. throw error("label expression");
  533. }
  534. }
  535. /** Grammar rule for a quoted string */
  536. std::string QuotedString(const std::string& context="") {
  537. if (token.kind != HOALexer::TOKEN_STRING) {
  538. expect(HOALexer::TOKEN_STRING, context);
  539. }
  540. std::string result = token.vString;
  541. // eat token
  542. nextToken();
  543. result = HOAParserHelper::unquote(result);
  544. return result;
  545. }
  546. /** Grammar rule for a HOA identifier */
  547. std::string Identifier(const std::string& context="") {
  548. if (token.kind != HOALexer::TOKEN_IDENT) {
  549. expect(HOALexer::TOKEN_IDENT, context);
  550. }
  551. std::string result = token.vString;
  552. // eat token
  553. nextToken();
  554. return result;
  555. }
  556. /** Grammar rule for an @@alias-name. Returns the name without the leading @@. */
  557. std::string AliasName() {
  558. if (token.kind != HOALexer::TOKEN_ALIAS_NAME) {
  559. expect(HOALexer::TOKEN_ALIAS_NAME);
  560. }
  561. std::string result = token.vString;
  562. // eat token
  563. nextToken();
  564. // eat @
  565. result = result.substr(1);
  566. return result;
  567. }
  568. /** Grammar rule for an unsigned integer */
  569. unsigned int Integer(const std::string& context="") {
  570. if (token.kind != HOALexer::TOKEN_INT) {
  571. expect(HOALexer::TOKEN_INT, context);
  572. }
  573. unsigned int result = token.vInteger;
  574. // eat token
  575. nextToken();
  576. return result;
  577. }
  578. };
  579. }
  580. #endif