Skip to content
Snippets Groups Projects
Commit 314ca19b authored by Sander Mathijs van Veen's avatar Sander Mathijs van Veen
Browse files

Added debug information to bison generated parser.

parent 7dd1e1a8
No related branches found
No related tags found
No related merge requests found
......@@ -7,3 +7,4 @@
*.pdf
*.toc
*.synctex.gz
/build
BUILD=build/
# Fix pdflatex search path
......@@ -9,21 +8,29 @@ TEXGREP := grep -i ".*:[0-9]*:.*\|warning"
TGT_DIR :=
TGT_DOC :=
# Default target is 'all'. The 'build' target is defined here so that all
# sub rules.mk can add prerequisites to the 'build' target.
all:
build:
d := docs/
include base.mk
include $(d)/rules.mk
.PHONY: docs
d := external/
include base.mk
include $(d)/rules.mk
d := tests/
include base.mk
include $(d)/rules.mk
.PHONY: doc
all: docs
all: doc build
clean:
rm -rf $(CLEAN)
docs: $(TGT_DOC)
$(TGT_DIR):
mkdir -p $(TGT_DIR)
$(b)%.pdf: $(d)%.tex $(TGT_DIR)
pdflatex $(TEXFLAGS) -output-directory `dirname $@` $< | ${TEXGREP} || true
.PHONY: docs
TGT_DOC += $(b)proposal.pdf
doc: $(TGT_DOC)
$(b)%.pdf: $(d)%.tex $(TGT_DIR)
pdflatex $(TEXFLAGS) -output-directory `dirname $@` $< | ${TEXGREP} || true
pybison @ 9c01c2ce
Subproject commit a8765c6130a70855967527f61e527b13ce5143f5
Subproject commit 9c01c2cea1d39f5334c9e987eb40dfb25788862e
TGT_DIR += $(b)pybison
PYBISON_INC := -Iexternal/pybison/src/c -I/usr/include/python2.7
build: $(b)pybison/bison_.so $(b)pybison/bison.py
$(b)pybison/bison_.so: $(b)pybison/bison_.o $(b)pybison/bisondynlib-linux.o
$(CC) -g -O0 -pipe -Wall -Wextra -shared -pthread -o $@ $^
$(b)pybison/bison.py: $(d)pybison/src/python/bison.py | $(b)pybison
ln -s `realpath $<` $@
$(b)pybison/bisondynlib-linux.o $(b)pybison/bison_.o: | $(b)pybison
$(CC) -g -O0 -pipe -Wall -Wextra -o $@ -c $< -pthread -fPIC $(PYBISON_INC)
$(b)pybison/bisondynlib-linux.o: $(d)pybison/src/c/bisondynlib-linux.c
$(b)pybison/bison_.o: $(b)pybison/bison_.c
$(b)pybison/%.c: $(d)pybison/src/pyrex/%.pyx
pyrexc -o $@ $<
#!/usr/bin/env python
"""
A simple pybison parser program implementing a calculator
"""
import os.path
PYBISON_BUILD = os.path.realpath('build/external/pybison')
PYBISON_PYREX = os.path.realpath('external/pybison/src/pyrex')
import sys
sys.path.insert(0, PYBISON_BUILD)
sys.path.insert(1, PYBISON_PYREX)
from bison import BisonParser, BisonNode
class Parser(BisonParser):
"""
Implements the calculator parser. Grammar rules are defined in the method
docstrings. Scanner rules are in the 'lexscript' attribute.
"""
# Output directory of generated pybison files, including a trailing slash.
buildDirectory = PYBISON_BUILD + '/'
# ----------------------------------------------------------------
# lexer tokens - these must match those in your lex script (below)
# ----------------------------------------------------------------
tokens = ['NUMBER',
'PLUS', 'MINUS', 'TIMES', 'DIVIDE', 'POW',
'LPAREN', 'RPAREN',
'NEWLINE', 'QUIT']
# ------------------------------
# precedences
# ------------------------------
precedences = (
('left', ('MINUS', 'PLUS')),
('left', ('TIMES', 'DIVIDE')),
('left', ('NEG', )),
('right', ('POW', )),
)
# ------------------------------------------------------------------
# override default read method with a version that prompts for input
# ------------------------------------------------------------------
def read(self, nbytes):
try:
return raw_input("> ") + "\n"
except EOFError:
return ''
# ---------------------------------------------------------------
# These methods are the python handlers for the bison targets.
# (which get called by the bison code each time the corresponding
# parse target is unambiguously reached)
#
# WARNING - don't touch the method docstrings unless you know what
# you are doing - they are in bison rule syntax, and are passed
# verbatim to bison to build the parser engine library.
# ---------------------------------------------------------------
# Declare the start target here (by name)
start = "input"
def on_input(self, target, option, names, values):
"""
input :
| input line
"""
return
def on_line(self, target, option, names, values):
"""
line : NEWLINE
| exp NEWLINE
"""
if option == 1:
print 'option:', option
#print 'on_line:', values[0]
def on_exp(self, target, option, names, values):
"""
exp : NUMBER
| exp PLUS exp
| exp MINUS exp
| exp TIMES exp
| exp DIVIDE exp
| MINUS exp %prec NEG
| exp POW exp
| LPAREN exp RPAREN
"""
print 'on_exp: got %s %s %s %s' % (target, option, names, values)
if option == 0:
return
#return float(values[0])
elif option == 1:
return
#return values[0] + values[2]
elif option == 2:
return values[0] - values[2]
elif option == 3:
return values[0] * values[2]
elif option == 4:
return values[0] / values[2]
elif option == 5:
return - values[1]
elif option == 6:
return values[0] ** values[2]
elif option == 7:
return values[1]
# -----------------------------------------
# raw lex script, verbatim here
# -----------------------------------------
lexscript = r"""
%{
//int yylineno = 0;
#include <stdio.h>
#include <string.h>
#include "Python.h"
#define YYSTYPE void *
#include "tokens.h"
extern void *py_parser;
extern void (*py_input)(PyObject *parser, char *buf, int *result, int max_size);
#define returntoken(tok) yylval = PyString_FromString(strdup(yytext)); return (tok);
#define YY_INPUT(buf,result,max_size) { (*py_input)(py_parser, buf, &result, max_size); }
%}
%%
[0-9]+ { returntoken(NUMBER); }
"(" { returntoken(LPAREN); }
")" { returntoken(RPAREN); }
"+" { returntoken(PLUS); }
"-" { returntoken(MINUS); }
"*" { returntoken(TIMES); }
"**" { returntoken(POW); }
"/" { returntoken(DIVIDE); }
"quit" { printf("lex: got QUIT\n"); yyterminate(); returntoken(QUIT); }
[ \t\v\f] {}
[\n] {yylineno++; returntoken(NEWLINE); }
. { printf("unknown char %c ignored, yytext=0x%lx\n", yytext[0], yytext); /* ignore bad chars */}
%%
yywrap() { return(1); }
"""
if __name__ == '__main__':
p = Parser(verbose=0, keepfiles=1)
p.run(debug=1)
import logging
import logging.config
import sys
import config
import default_config as default
try:
logging.basicConfig(level=logging.DEBUG,
format=getattr(config, 'LOG_FORMAT', default.LOG_FORMAT),
filename=getattr(config, 'LOG_FILE', default.LOG_FILE),
filemode='a')
except IOError as e: # pragma: no cover
print >>sys.stderr, 'warning: IOError raised: "%s"' % str(e)
def logger(name):
return logging.getLogger(name)
from testrunner import main
import sys
main(sys.argv[1:])
TESTS=$(wildcard tests/test_*.py)
COVERAGE_OUTPUT_DIR := coverage
OMIT := --omit /usr/share/pyshared/*,/usr/lib64/portage/*
ifeq ($(findstring python-coverage,$(wildcard /usr/bin/*)), python-coverage)
COVERAGE=/usr/bin/python-coverage
else
COVERAGE=/usr/bin/coverage
endif
.PHONY: test coverage $(TESTS)
test: $(TESTS) build
coverage: ${COVERAGE}
mkdir ${COVERAGE_OUTPUT_DIR} 2>/dev/null || true
${COVERAGE} erase
for t in ${TESTS}; do \
echo $$t; \
${COVERAGE} ${OMIT} -x test.py $$t; \
${COVERAGE} ${OMIT} -c; \
done
${COVERAGE} html ${OMIT} --dir ${COVERAGE_OUTPUT_DIR}
${COVERAGE}:
@echo "Install package 'python-coverage' to generate a coverage report."
@echo "On Debian/Ubuntu use: sudo apt-get install python-coverage"; false
$(TESTS): ; @python -m testrunner $@
import unittest
class TestCalc(unittest.TestCase):
def setUp(self):
pass
def tearDown(self):
pass
def test_true(self):
assert True
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment