Skip to content

Commit 24000ae

Browse files
committed
Merge remote-tracking branch 'jbeard/master'
# Conflicts: # mc_lexer.l # mc_parser.yy # mc_scanner.hpp
2 parents 40b5d5a + be34ca6 commit 24000ae

13 files changed

+64294
-40
lines changed

.gitignore

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
*.swp
2+
*.o
3+
location.hh
4+
position.hh
5+
stack.hh
6+
mc_lexer.yy.cc
7+
mc_parser.output
8+
mc_parser.tab.cc
9+
mc_parser.tab.hh
10+
my_wc

.travis.yml

+65
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
## container build, no sudo
2+
sudo: false
3+
4+
language: cpp
5+
6+
compiler:
7+
- gcc
8+
- clang
9+
10+
os:
11+
- linux
12+
13+
cache:
14+
apt:
15+
ccache:
16+
directories:
17+
18+
env:
19+
global:
20+
- GCC_VERSION=5
21+
- CXXFLAGS=-std=c++11
22+
- CFLAGS=-std=c99
23+
24+
branches:
25+
only:
26+
- master
27+
28+
before_install:
29+
- if [ ${CC} != "clang" ]; then
30+
export CC=/usr/bin/gcc-${GCC_VERSION} CXX=/usr/bin/g++-${GCC_VERSION};
31+
C=gcc;
32+
fi
33+
34+
35+
addons:
36+
apt:
37+
sources:
38+
- ubuntu-toolchain-r-test
39+
- llvm-toolchain-precise
40+
packages:
41+
# ensure these match GCC_VERSION
42+
- gcc-5
43+
- g++-5
44+
- binutils
45+
- gawk
46+
- build-essential
47+
- wget
48+
- libtool
49+
- flex
50+
51+
52+
before_script:
53+
- echo $LANG
54+
- echo $LC_ALL
55+
- wget --no-check-certificate http://ftp.gnu.org/gnu/bison/bison-3.0.4.tar.gz
56+
- mkdir $HOME/bison
57+
- tar -xf bison-3.0.4.tar.gz; cd bison-3.0.4; ./configure --prefix=$HOME/bison; make -j 4 install; cd $PWD/..;
58+
- export PATH=$HOME/bison/bin:$PATH
59+
script:
60+
- ${CC} --version ; ${CXX} --version;
61+
- bison --version
62+
- pwd
63+
- ls -la $HOME
64+
- env
65+
- make all && make test

Makefile

+5-2
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@ CXXDEBUG = -g -Wall
1010
CSTD = -std=c99
1111
CXXSTD = -std=c++11
1212

13-
CFLAGS = -O0 $(CDEBUG) $(CSTD)
14-
CXXFLAGS = -O0 $(CXXDEBUG) $(CXXSTD)
13+
CFLAGS = -Wno-deprecated-register -O0 $(CDEBUG) $(CSTD)
14+
CXXFLAGS = -Wno-deprecated-register -O0 $(CXXDEBUG) $(CXXSTD)
1515

1616

1717
CPPOBJ = main mc_driver
@@ -44,6 +44,9 @@ lexer: mc_lexer.l
4444
flex --outfile=mc_lexer.yy.cc $<
4545
$(CXX) $(CXXFLAGS) -c mc_lexer.yy.cc -o lexer.o
4646

47+
.PHONY: test
48+
test:
49+
cd test && ./test0.pl
4750

4851
.PHONY: clean
4952
clean:

README.md

+15-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,17 @@
1-
simple_wc_example
1+
###Simple Word Count Parser Example
22
=================
33

4-
simple word count example using flex/bison parser
4+
###Build Status
5+
Tested on linux and OS X
6+
7+
[![Build Status](https://travis-ci.org/jonathan-beard/simple_wc_example.svg?branch=master)](https://travis-ci.org/jonathan-beard/simple_wc_example)
8+
9+
###About
10+
So this is a super simple parser example. The tutorial is located here:
11+
<a href="http://www.jonathanbeard.io/tutorials/FlexBisonC++.html" target="_blank">link</a>
12+
13+
Between the tutorial and the code you should be able to get started with more advanced projects using C++ and Flex/Bison. Admittedly the example itself is a bit contrived, however it's mean to be simple and get the point across. If there are changes in Flex/Bison that prevent the example from compiling or if you just have improvements, feel free to generate a pull request or just shoot me an e-mail.
14+
15+
To compile just download and run make, there's a super simple test harness to make sure it runs in the <tt>test</tt> dir.
16+
17+
Thanks!

main.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
#include "mc_driver.hpp"
55

66
int
7-
main(const int argc, const char **argv)
7+
main( const int argc, const char **argv )
88
{
99
if(argc != 2 )
1010
return ( EXIT_FAILURE );

mc_driver.cpp

+3-2
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,16 @@
44

55
#include "mc_driver.hpp"
66

7-
MC::MC_Driver::~MC_Driver(){
7+
MC::MC_Driver::~MC_Driver()
8+
{
89
delete(scanner);
910
scanner = nullptr;
1011
delete(parser);
1112
parser = nullptr;
1213
}
1314

1415
void
15-
MC::MC_Driver::parse( const char *filename )
16+
MC::MC_Driver::parse( const char * const filename )
1617
{
1718
assert( filename != nullptr );
1819
std::ifstream in_file( filename );

mc_driver.hpp

+9-14
Original file line numberDiff line numberDiff line change
@@ -2,20 +2,15 @@
22
#define __MCDRIVER_HPP__ 1
33

44
#include <string>
5+
#include <cstdint>
56
#include "mc_scanner.hpp"
67
#include "mc_parser.tab.hh"
78

89
namespace MC{
910

1011
class MC_Driver{
1112
public:
12-
MC_Driver() : chars(0),
13-
words(0),
14-
lines(0),
15-
uppercase(0),
16-
lowercase(0),
17-
parser( nullptr ),
18-
scanner( nullptr ){};
13+
MC_Driver() = default;
1914

2015
virtual ~MC_Driver();
2116

@@ -30,13 +25,13 @@ class MC_Driver{
3025

3126
std::ostream& print(std::ostream &stream);
3227
private:
33-
int chars;
34-
int words;
35-
int lines;
36-
int uppercase;
37-
int lowercase;
38-
MC::MC_Parser *parser;
39-
MC::MC_Scanner *scanner;
28+
int chars = 0;
29+
int words = 0;
30+
int lines = 0;
31+
int uppercase = 0;
32+
int lowercase = 0;
33+
MC::MC_Parser *parser = nullptr;
34+
MC::MC_Scanner *scanner = nullptr;
4035
};
4136

4237
} /* end namespace MC */

mc_lexer.l

+20-15
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
/* Implementation of yyFlexScanner */
66
#include "mc_scanner.hpp"
77
#undef YY_DECL
8-
#define YY_DECL int MC::MC_Scanner::yylex(MC::MC_Parser::semantic_type *lval)
8+
#define YY_DECL int MC::MC_Scanner::yylex(MC::MC_Parser::semantic_type * const lval, MC::MC_Parser::location_type *location)
99

1010
/* typedef to make the returns for the tokens shorter */
1111
typedef MC::MC_Parser::token token;
@@ -19,41 +19,46 @@ typedef MC::MC_Parser::token token;
1919
/* msvc2010 requires that we exclude this header file. */
2020
#define YY_NO_UNISTD_H
2121

22+
/* update location on matching */
23+
#define YY_USER_ACTION loc->step(); loc->columns(yyleng);
24+
2225
%}
2326

24-
%option debug
25-
%option nodefault
26-
%option yyclass="MC::MC_Scanner"
27-
%option noyywrap
27+
%option debug
28+
%option nodefault
29+
%option yyclass="MC::MC_Scanner"
30+
%option noyywrap
2831
%option c++
2932

3033
%%
3134
%{ // Code executed at the beginning of yylex
3235
yylval = lval;
3336
%}
3437

35-
[a-z] {
36-
return( token::LOWER );
38+
[a-z] {
39+
return( token::LOWER );
3740
}
3841

39-
[A-Z] {
40-
return( token::UPPER );
42+
[A-Z] {
43+
return( token::UPPER );
4144
}
4245

43-
[a-zA-Z]+ {
46+
[a-zA-Z]+ {
4447
// Section 10.1.5.1 of the 3.0.2 Bison Manual says the following should work
4548
// yylval.build( yytext );
4649
// But it doesn't.
4750
yylval->build<std::string>( yytext );
48-
return( token::WORD );
51+
return( token::WORD );
4952
}
5053

51-
\n {
52-
return( token::NEWLINE );
54+
\n {
55+
// Update line number
56+
loc->lines();
57+
return( token::NEWLINE );
5358
}
5459

55-
. {
56-
return( token::CHAR );
60+
. {
61+
return( token::CHAR );
5762
}
5863
%%
5964

mc_parser.yy

+3-2
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@
4747
%token NEWLINE
4848
%token CHAR
4949

50+
%locations
5051

5152
%%
5253

@@ -69,7 +70,7 @@ item
6970

7071

7172
void
72-
MC::MC_Parser::error( const std::string &err_message )
73+
MC::MC_Parser::error( const location_type &l, const std::string &err_message )
7374
{
74-
std::cerr << "Error: " << err_message << "\n";
75+
std::cerr << "Error: " << err_message << " at " << l << "\n";
7576
}

mc_scanner.hpp

+9-2
Original file line numberDiff line numberDiff line change
@@ -6,22 +6,29 @@
66
#endif
77

88
#include "mc_parser.tab.hh"
9+
#include "location.hh"
910

1011
namespace MC{
1112

1213
class MC_Scanner : public yyFlexLexer{
1314
public:
1415

1516
MC_Scanner(std::istream *in) : yyFlexLexer(in),
16-
yylval( nullptr ){};
17+
yylval( nullptr )
18+
{
19+
loc = new MC::MC_Parser::location_type();
20+
};
1721

18-
int yylex(MC::MC_Parser::semantic_type *lval);
22+
int yylex(MC::MC_Parser::semantic_type * const lval, MC::MC_Parser::location_type *location);
1923
// YY_DECL defined in mc_lexer.l
2024
// Method body created by flex in mc_lexer.yy.cc
2125

26+
2227
private:
2328
/* yyval ptr */
2429
MC::MC_Parser::semantic_type *yylval;
30+
/* location ptr */
31+
MC::MC_Parser::location_type *loc;
2532
};
2633

2734
} /* end namespace MC */

test/test0.pl

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
#!/usr/bin/env perl
2+
use strict;
3+
use warnings;
4+
5+
system( "../my_wc wordlist.txt > temp.txt" );
6+
my $diff = `diff temp.txt wordlist_out.txt`;
7+
chomp( $diff );
8+
if( $diff )
9+
{
10+
print STDERR $diff;
11+
unlink( "temp.txt" );
12+
exit( -1 );
13+
}
14+
print STDERR "***PASSED***\n";
15+
unlink( "temp.txt" );
16+
exit( 0 );

0 commit comments

Comments
 (0)