homer512

Flex scanner for binary numbers

Apr 29th, 2013
211
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 2.77 KB | None | 0 0
  1. /*
  2.  * Copyright 2013 Florian Philipp
  3.  *
  4.  * Licensed under the Apache License, Version 2.0 (the "License");
  5.  * you may not use this file except in compliance with the License.
  6.  * You may obtain a copy of the License at
  7.  *
  8.  * http://www.apache.org/licenses/LICENSE-2.0
  9.  *
  10.  * Unless required by applicable law or agreed to in writing, software
  11.  * distributed under the License is distributed on an "AS IS" BASIS,
  12.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13.  * See the License for the specific language governing permissions and
  14.  * limitations under the License.
  15.  */
  16. %option header-file="binaries.yy.hpp"
  17. %option outfile="binaries.yy.cpp"
  18. %option prefix="bin_"
  19. %option reentrant noyywrap nodefault
  20. %option extra-type="bin::scanner_t*"
  21.  
  22. %top {
  23. # include <cstdio>
  24. # include <vector>
  25.   namespace bin {
  26.     /**
  27.      * Parses the given file as a list of binary numbers or comments with ";"
  28.      * \param input a file opened for reading such as stdout. The read position
  29.      * after the function returns is either EOF or undefined in case of
  30.      * an error
  31.      * \param output a vector to which the binary numbers are appended.
  32.      * \throw std::domain_error in case of a parser failure
  33.      */
  34.     void parse(FILE* input, std::vector<unsigned long>* output);
  35.     class scanner_t;
  36.   }
  37. }
  38. %{
  39. # include <cstdlib>
  40. # include <sstream>
  41. # include <stdexcept>
  42.   namespace bin {
  43.     struct scanner_t
  44.     {
  45.       std::vector<unsigned long>* output;
  46.       int line;
  47.       yyscan_t lex;
  48.       scanner_t(std::vector<unsigned long>* output);
  49.       void parse(FILE* input);
  50.       ~scanner_t();
  51.     };
  52.   }
  53. %}
  54. %%
  55. [ \t]+ /* skip whitespace */
  56. ;.* /* skip comments */
  57. [01]+ { /* convert binary number */
  58.   yyextra->output->push_back(std::strtoul(yytext, NULL /*end*/, 2 /*base*/));
  59. }
  60. \r?\n yyextra->line += 1; /* linebreak */
  61. . {
  62.   std::ostringstream err;
  63.   err << "Unrecognized character '" << yytext <<"' in line " << yyextra->line;
  64.   throw std::domain_error(err.str());
  65. }
  66. <<EOF>> return 0;
  67. %%
  68. namespace bin {
  69.   scanner_t::scanner_t(std::vector<unsigned long>* output):
  70.         output(output), line(1)
  71.   {
  72.     bin_lex_init_extra(this, &lex);
  73.   }
  74.   void scanner_t::parse(FILE* input)
  75.   {
  76.     bin_set_in(input, lex);
  77.     bin_lex(lex);
  78.   }
  79.   void parse(FILE* input, std::vector<unsigned long>* output)
  80.   {
  81.     scanner_t scanner(output);
  82.     scanner.parse(input);
  83.   }
  84.   scanner_t::~scanner_t() { yylex_destroy(lex); }
  85. }
  86. int main(void)
  87. {
  88.   std::vector<unsigned long> out;
  89.   try {
  90.     bin::parse(stdin, &out);
  91.   } catch(std::domain_error& err) {
  92.     fprintf(stderr, "Parser error: %s\n", err.what());
  93.   }
  94.   for(std::vector<unsigned long>::iterator i = out.begin(); i != out.end(); ++i)
  95.     std::fprintf(stdout, "%lu\n", *i);
  96.   return 0;
  97. }
Advertisement
Add Comment
Please, Sign In to add comment