summaryrefslogtreecommitdiff
path: root/src/zisp/io
diff options
context:
space:
mode:
Diffstat (limited to 'src/zisp/io')
-rw-r--r--src/zisp/io/Parser.zig85
1 files changed, 33 insertions, 52 deletions
diff --git a/src/zisp/io/Parser.zig b/src/zisp/io/Parser.zig
index ed55a36..dbcd6ad 100644
--- a/src/zisp/io/Parser.zig
+++ b/src/zisp/io/Parser.zig
@@ -1,55 +1,36 @@
-// === Syntax ===
-//
-// See docs/parser.md and spec/syntax.bnf to understand the syntax.
-//
-//
-// === Trampolining strategy ===
-//
-// Instead of using recursion directly, the parser is written in a "trampoline"
-// style, which ensures that parse depth is not limited by stack size.
-//
-// All state and context is passed around via a struct pointer. The parser has
-// a main loop, which calls a function as dictated by parser.context.next, and
-// the function may update the state to have another function called next.
-//
-// If a function wants to call a recursive subroutine, it pushes some of the
-// current context onto a stack, including what function the subroutine should
-// return to, and then updates the state to instruct the main loop to call one
-// of the entry point subroutines.
-//
-// If a function wants to make the parser return, either from a subroutine or
-// from the main loop, it sets the .result field, and tries to pop the saved
-// context. If the context stack was empty, the main loop returns.
-//
-//
-// === Buffering ===
-//
-// For efficiency, call the parser on an input stream with implicit buffering.
-//
-// The parser does not use its own buffer, beyond one character that may be
-// written back into the unread_char field, which is checked at the end to
-// ensure it's nothing other than a trailing blank or comment.
-//
-// This lack of buffering is to ensure that the parser never reads more bytes
-// from the input than what it needs to parse a datum. Consider the input:
-//
-// (a b c) (x y z)
-//
-// If we used proper buffering, like reading up to 4K bytes per read, then the
-// whole stream would be consumed at once before it's parsed. Then, the parser
-// would return the first datum, and the rest of the stream would be lost. The
-// parser would need some way to reset the input stream's read head to the end
-// of the first datum, but not all stream types may support this.
-//
-// Although in a scenario like this it would be wise to create a single Parser
-// instance to call multiple times (in which case it could continue using its
-// internal buffer from where it left), this may not always be practical.
-//
-// One could even have an input stream with Zisp s-expressions and other data
-// intertwined, in which case this lack of buffering is also crucial, since one
-// needs to alternate between calling the Zisp parser and some other parser on
-// the same input stream.
-//
+//!
+//! === Syntax ===
+//!
+//! See docs/c1/1-parse.md to understand the implemented syntax.
+//!
+//!
+//! === Trampolining strategy ===
+//!
+//! Instead of using recursion directly, the parser is written in a "trampoline"
+//! style, which ensures that parse depth is not limited by stack size.
+//!
+//! All state and context is passed around via a struct pointer. The parser has
+//! a main loop, which calls a function as dictated by parser.context.next, and
+//! the function may update the state to have another function called next.
+//!
+//! If a function wants to call a recursive subroutine, it pushes some of the
+//! current context onto a stack, including what function the subroutine should
+//! return to, and then updates the state to instruct the main loop to call one
+//! of the entry point subroutines.
+//!
+//! If a function wants to make the parser return, either from a subroutine or
+//! from the main loop, it sets the .result field, and tries to pop the saved
+//! context. If the context stack was empty, the main loop returns.
+//!
+//!
+//! === Buffering ===
+//!
+//! For efficiency, call the parser on an input stream with implicit buffering.
+//!
+//! The parser does not use its own buffer, beyond one character that may be
+//! written back into the unread_char field, which is checked at the end to
+//! ensure it's nothing other than a trailing blank or comment.
+//!
const builtin = @import("builtin");
const std = @import("std");