diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/boot/bemol.cc | 60 | ||||
-rw-r--r-- | src/include/InputFragment.h | 90 | ||||
-rw-r--r-- | src/include/token.H | 42 | ||||
-rw-r--r-- | src/utils/Makefile.am | 1 | ||||
-rw-r--r-- | src/utils/Makefile.in | 35 |
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 |