tiny.smg.tree.runtime.lexer
Defined in tree.runtime.
API (12)
Actions
Public operations.
Lexer.advanceLexer.eofLexer.finishLexer.includedRangeStartLexer.initLexer.lookaheadLexer.markEndLexer.setResultLexer.start
Types and contracts
Public types and contracts.
Source
Source: tools/smg/src/tree/runtime/lexer.zig
zig
const std = @import("std");const runtime = @import("root.zig");const abi = runtime.abi;pub const Position = struct { byte: u32, point: abi.Point,};pub const Token = struct { symbol: abi.Symbol, start: Position, end: Position,};pub const Lexer = struct { abi: abi.Lexer, source: []const u8, current: Position, token_start: Position, token_end: Position, marked: bool, pub fn init(source: []const u8, initial: Position) Lexer { var self = Lexer{ .abi = .{ .lookahead = 0, .result_symbol = 0, .advance = advanceAbi, .mark_end = markEndAbi, .get_column = columnAbi, .is_at_included_range_start = rangeStartAbi, .eof = eofAbi, .log = null, }, .source = source, .current = initial, .token_start = initial, .token_end = initial, .marked = false, }; self.refresh(); return self; } pub fn start(self: *Lexer) void { self.token_start = self.current; self.token_end = self.current; self.marked = false; self.abi.result_symbol = 0; if (self.current.byte == 0 and self.abi.lookahead == 0xfeff) self.advance(true); } pub fn finish(self: *Lexer) Token { if (!self.marked) self.markEnd(); if (self.token_end.byte < self.token_start.byte) self.token_start = self.token_end; return .{ .symbol = self.abi.result_symbol, .start = self.token_start, .end = self.token_end, }; } pub fn lookahead(self: *const Lexer) i32 { return self.abi.lookahead; } pub fn setResult(self: *Lexer, symbol: abi.Symbol) void { self.abi.result_symbol = symbol; } pub fn advance(self: *Lexer, skip: bool) void { if (self.current.byte < self.source.len) { const length = codepointLength(self.source[self.current.byte..]); if (self.abi.lookahead == '\n') { self.current.point.row += 1; self.current.point.column = 0; } else { self.current.point.column += @intCast(length); } self.current.byte += @intCast(length); } if (skip) self.token_start = self.current; self.refresh(); } pub fn markEnd(self: *Lexer) void { self.token_end = self.current; self.marked = true; } pub fn includedRangeStart(_: *const Lexer) bool { return false; } pub fn eof(self: *const Lexer) bool { return self.current.byte == self.source.len; } fn refresh(self: *Lexer) void { if (self.eof()) { self.abi.lookahead = 0; return; } const remaining = self.source[self.current.byte..]; const length = codepointLength(remaining); if (length == 1 and remaining[0] >= 0x80) return self.setDecodeError(); self.abi.lookahead = @intCast(std.unicode.utf8Decode(remaining[0..length]) catch { return self.setDecodeError(); }); } fn setDecodeError(self: *Lexer) void { self.abi.lookahead = -1; } fn codepointLength(source: []const u8) usize { const length = std.unicode.utf8ByteSequenceLength(source[0]) catch return 1; if (length > source.len) return 1; _ = std.unicode.utf8Decode(source[0..length]) catch return 1; return length; } fn parent(pointer: anytype) if (@TypeOf(pointer) == *abi.Lexer) *Lexer else *const Lexer { return @fieldParentPtr("abi", pointer); } fn advanceAbi(pointer: *abi.Lexer, skip: bool) callconv(.c) void { parent(pointer).advance(skip); } fn markEndAbi(pointer: *abi.Lexer) callconv(.c) void { parent(pointer).markEnd(); } fn columnAbi(pointer: *abi.Lexer) callconv(.c) u32 { return parent(pointer).current.point.column; } fn rangeStartAbi(pointer: *const abi.Lexer) callconv(.c) bool { return parent(pointer).includedRangeStart(); } fn eofAbi(pointer: *const abi.Lexer) callconv(.c) bool { return parent(pointer).eof(); }};test "lexer exposes generated and native scanner semantics" { var value = Lexer.init("a\n\xe2\x82\xac", .{ .byte = 0, .point = .{ .row = 0, .column = 0 } }); value.start(); try std.testing.expectEqual(@as(i32, 'a'), value.lookahead()); value.advance(true); try std.testing.expectEqual(@as(u32, 1), value.token_start.byte); value.advance(false); try std.testing.expectEqual(@as(u32, 1), value.current.point.row); try std.testing.expectEqual(@as(i32, 0x20ac), value.lookahead()); value.setResult(7); value.advance(false); const token = value.finish(); try std.testing.expectEqual(@as(abi.Symbol, 7), token.symbol); try std.testing.expectEqual(@as(u32, 1), token.start.byte); try std.testing.expectEqual(@as(u32, 5), token.end.byte);}Source: tools/smg/src/tree/runtime/root.zig:3
zig
pub const lexer = @import("lexer.zig");Audit
| Definitions | 13 |
|---|---|
| Public names | 13 |
| Members | 11 |
| Version | 26.7.0 |
| Revision | daab053ee433 |