aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/boot/bemol.cc60
-rw-r--r--src/include/InputFragment.h90
-rw-r--r--src/include/token.H42
-rw-r--r--src/utils/Makefile.am1
-rw-r--r--src/utils/Makefile.in35
5 files changed, 157 insertions, 71 deletions
diff --git a/src/boot/bemol.cc b/src/boot/bemol.cc
index 34870e13..b36b174d 100644
--- a/src/boot/bemol.cc
+++ b/src/boot/bemol.cc
@@ -35,7 +35,7 @@
// --% Description:
#include <open-axiom/diagnostics>
-#include <open-axiom/token>
+#include <open-axiom/InputFragment>
#include <iostream>
#include <fstream>
#include <vector>
@@ -50,59 +50,11 @@ using namespace OpenAxiom;
// -- Reading input source files --
//
-// A physical line is just raw text, with coupled with location
-// information such as line and indentation column.
-struct Line : std::string {
- LineNumber number;
- ColumnIndex indent;
- Line() : number(), indent() { }
-
- std::string sub_string(ColumnIndex s, ColumnIndex e) const {
- return substr(s, e - s);
- }
-};
-
-// A program fragment is a logical line, composed of possibly
-// several physical lines subject to the off-side rule. As a
-// special case, a line ending with the underbar character
-// continues to the next next with disregard to the off-side rule.
-struct Fragment : std::vector<Line> {
- explicit operator bool() const { return not empty(); }
- bool line_continuation() const {
- return not empty() and back().back() == '_';
- }
- ColumnIndex last_indent() const {
- return empty() ? 0 : back().indent;
- }
- using std::vector<Line>::operator[];
- const Line& operator()(const OpenAxiom::FragmentCursor& pos) const {
- return (*this)[pos.line];
- }
- uint8_t operator[](const OpenAxiom::FragmentCursor& pos) const {
- return (*this)[pos.line][pos.column];
- }
- uint8_t advance(OpenAxiom::FragmentCursor& pos) const {
- return (*this)[pos.line][pos.column++];
- }
-
- bool covering(const OpenAxiom::FragmentCursor& pos) const {
- return pos.column < (*this)[pos.line].size();
- }
-};
-
-// Formatting program fragments.
-static std::ostream&
-operator<<(std::ostream& os, const Fragment& f) {
- std::copy(f.begin(), f.end(),
- std::ostream_iterator<std::string>(std::cout, "\n"));
- return os;
-}
-
-
// A source input transform a character stream into a program fragment
// stream, delivering a fragment one at a time.
struct SourceInput {
SourceInput(std::istream& is) : input(is) { }
+ // Return the next program fragment from this input source.
Fragment get();
private:
@@ -235,6 +187,14 @@ using TokenSequence = OpenAxiom::TokenStream<BemolToken>;
// --
+namespace {
+ struct Parser {
+ TokenSequence* tokens;
+ };
+}
+
+// --
+
static void
translate_source_file(SourceInput& src, std::ostream& out, const char* path) {
while (auto f = src.get()) {
diff --git a/src/include/InputFragment.h b/src/include/InputFragment.h
new file mode 100644
index 00000000..7f317973
--- /dev/null
+++ b/src/include/InputFragment.h
@@ -0,0 +1,90 @@
+// -*- C++ -*-
+// Copyright (C) 2014, Gabriel Dos Reis.
+// All rights reserved.
+// Written by Gabriel Dos Reis.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// - Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// - Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in
+// the documentation and/or other materials provided with the
+// distribution.
+//
+// - Neither the name of OpenAxiom. nor the names of its contributors
+// may be used to endorse or promote products derived from this
+// software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+// PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+// OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// --% Author: Gabriel Dos Reis
+
+#ifndef OPENAXIOM_INPUTFRAGMENT_included
+#define OPENAXIOM_INPUTFRAGMENT_included
+
+#include <open-axiom/token>
+
+namespace OpenAxiom {
+ // A physical line is just raw text, coupled with location
+ // information such as line and indentation column.
+ struct Line : std::string {
+ LineNumber number;
+ ColumnIndex indent;
+ Line() : number(), indent() { }
+
+ std::string sub_string(ColumnIndex s, ColumnIndex e) const {
+ return substr(s, e - s);
+ }
+ };
+
+ // A program fragment is a logical line, composed of possibly
+ // several physical lines subject to the off-side rule. As a
+ // special case, a line ending with the underbar character
+ // continues to the next line with disregard to the off-side rule.
+ struct Fragment : std::vector<Line> {
+ explicit operator bool() const { return not empty(); }
+ // Holds if the last physical line ends with line continuation marker.
+ bool line_continuation() const {
+ return not empty() and back().back() == '_';
+ }
+ // Return the indentation of the last physical line of this fragment.
+ ColumnIndex last_indent() const {
+ return empty() ? 0 : back().indent;
+ }
+ using std::vector<Line>::operator[];
+ // Reference a line given by a position into this fragment.
+ const Line& operator()(const OpenAxiom::FragmentCursor& pos) const {
+ return (*this)[pos.line];
+ }
+ // Reference a character code unit at the position into this fragment.
+ uint8_t operator[](const OpenAxiom::FragmentCursor& pos) const {
+ return (*this)[pos.line][pos.column];
+ }
+ // Advance the cursor position to the next character code unit.
+ uint8_t advance(OpenAxiom::FragmentCursor& pos) const {
+ return (*this)[pos.line][pos.column++];
+ }
+ // This predicate holds if this fragment covers the cursor position.
+ bool covering(const OpenAxiom::FragmentCursor& pos) const {
+ return pos.column < (*this)[pos.line].size();
+ }
+ };
+
+ std::ostream& operator<<(std::ostream&, const Fragment&);
+}
+
+#endif // OPENAXIOM_INPUTFRAGMENT_included
diff --git a/src/include/token.H b/src/include/token.H
index 719f6e5f..71d6cb10 100644
--- a/src/include/token.H
+++ b/src/include/token.H
@@ -75,6 +75,10 @@ namespace OpenAxiom {
std::ostream& operator<<(std::ostream&, TokenValue);
+ // Datatypes for locating lines and columns.
+ using LineNumber = std::size_t;
+ using ColumnIndex = std::size_t;
+
// Given a symbolic or alphabetic token, retrieve its category
// and associated abstract value.
struct TokenClassification {
@@ -88,31 +92,33 @@ namespace OpenAxiom {
TokenClassification classify(const std::string&);
- // Datatypes for locating lines and columns.
- using LineNumber = std::size_t;
- using ColumnIndex = std::size_t;
-
// Cursor into a fragment.
struct FragmentCursor {
std::size_t line; // index of a line in a fragment
std::size_t column; // column number at line.
- };
- inline FragmentCursor& operator++(FragmentCursor& p) {
- ++p.column;
- return p;
- }
+ inline FragmentCursor& operator++() {
+ ++column;
+ return *this;
+ }
- inline FragmentCursor operator++(FragmentCursor& p, int) {
- auto q = p;
- ++p;
- return q;
- }
+ inline FragmentCursor operator++(int) {
+ auto tmp = *this;
+ ++*this;
+ return tmp;
+ }
- inline FragmentCursor& operator--(FragmentCursor& p) {
- --p.column;
- return p;
- }
+ inline FragmentCursor& operator--() {
+ --column;
+ return *this;
+ }
+
+ inline FragmentCursor operator--(int) {
+ auto tmp = *this;
+ --*this;
+ return tmp;
+ }
+ };
// -- Exception types
struct EndOfStringUnseen {
diff --git a/src/utils/Makefile.am b/src/utils/Makefile.am
index 8c0bec65..0febb681 100644
--- a/src/utils/Makefile.am
+++ b/src/utils/Makefile.am
@@ -40,6 +40,7 @@ libOpenAxiom_a_SOURCES = \
filesystem.cc \
../io/Input.cc \
../io/std-streams.cc \
+ ../io/InputFragment.cxx \
../syntax/token.cc \
../syntax/sexpr.cc \
../rt/vm.cc \
diff --git a/src/utils/Makefile.in b/src/utils/Makefile.in
index 4600bb81..97cd1a0b 100644
--- a/src/utils/Makefile.in
+++ b/src/utils/Makefile.in
@@ -139,9 +139,10 @@ libOpenAxiom_a_LIBADD =
am__dirstamp = $(am__leading_dot)dirstamp
am_libOpenAxiom_a_OBJECTS = storage.$(OBJEXT) string-pool.$(OBJEXT) \
command.$(OBJEXT) filesystem.$(OBJEXT) ../io/Input.$(OBJEXT) \
- ../io/std-streams.$(OBJEXT) ../syntax/token.$(OBJEXT) \
- ../syntax/sexpr.$(OBJEXT) ../rt/vm.$(OBJEXT) \
- ../rt/Lisp.$(OBJEXT) ../rt/Database.$(OBJEXT)
+ ../io/std-streams.$(OBJEXT) ../io/InputFragment.$(OBJEXT) \
+ ../syntax/token.$(OBJEXT) ../syntax/sexpr.$(OBJEXT) \
+ ../rt/vm.$(OBJEXT) ../rt/Lisp.$(OBJEXT) \
+ ../rt/Database.$(OBJEXT)
libOpenAxiom_a_OBJECTS = $(am_libOpenAxiom_a_OBJECTS)
PROGRAMS = $(noinst_PROGRAMS)
am_hammer_OBJECTS = hammer.$(OBJEXT)
@@ -412,6 +413,7 @@ libOpenAxiom_a_SOURCES = \
filesystem.cc \
../io/Input.cc \
../io/std-streams.cc \
+ ../io/InputFragment.cxx \
../syntax/token.cc \
../syntax/sexpr.cc \
../rt/vm.cc \
@@ -475,6 +477,8 @@ clean-noinstLIBRARIES:
../io/$(DEPDIR)/$(am__dirstamp)
../io/std-streams.$(OBJEXT): ../io/$(am__dirstamp) \
../io/$(DEPDIR)/$(am__dirstamp)
+../io/InputFragment.$(OBJEXT): ../io/$(am__dirstamp) \
+ ../io/$(DEPDIR)/$(am__dirstamp)
../syntax/$(am__dirstamp):
@$(MKDIR_P) ../syntax
@: > ../syntax/$(am__dirstamp)
@@ -526,6 +530,7 @@ distclean-compile:
-rm -f *.tab.c
@AMDEP_TRUE@@am__include@ @am__quote@../io/$(DEPDIR)/Input.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@../io/$(DEPDIR)/InputFragment.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@../io/$(DEPDIR)/std-streams.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@../rt/$(DEPDIR)/Database.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@../rt/$(DEPDIR)/Lisp.Po@am__quote@
@@ -562,6 +567,30 @@ distclean-compile:
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LTCXXCOMPILE) -c -o $@ $<
+.cxx.o:
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\
+@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
+@am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ $<
+
+.cxx.obj:
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\
+@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\
+@am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
+
+.cxx.lo:
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\
+@am__fastdepCXX_TRUE@ $(LTCXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
+@am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LTCXXCOMPILE) -c -o $@ $<
+
mostlyclean-libtool:
-rm -f *.lo