tiny.smt.smtlib.parse.term
Defined in smtlib.parse.
Reads one SMT-LIB term and builds it in a Context.
API (1)
Actions
Public operations.
parse: Reads one term at the parser's position, builds it in the parser'sContextand returns it.
Source
Source: lib/smt/src/smtlib/parse/root.zig:13
zig
pub const term = @import("term.zig");Source: lib/smt/src/smtlib/parse/term.zig
zig
//! Reads one SMT-LIB term and builds it in a `Context`. A script's formulas use the operators of//! different theories, so the reader has to map each operator name to the term it builds. A table//! maps each supported SMT-LIB operator name to its term kind. Every two-operand operator takes//! exactly two operands, so a chained `(= a b c)` fails. The reader refuses `let`, `ite`, `xor`,//! `-`, `bvneg`, the `#b` and `#x` literals and quoted symbols. It descends one call per//! parenthesis, with no depth bound.const std = @import("std");const smt = @import("../../root.zig");const errors = @import("error.zig");const state = @import("state.zig");const token = @import("token.zig");const Error = errors.Error;const ParseError = errors.ParseError;const Parser = state.Parser;const term = smt.term;const ExprTag = std.meta.Tag(term.Expr);const Operation = union(enum) { unary: ExprTag, binary: ExprTag, ternary: ExprTag, nary: ExprTag,};const OperationEntry = struct { name: []const u8, operation: Operation,};const operations = [_]OperationEntry{ .{ .name = "not", .operation = .{ .unary = .not } }, .{ .name = "=>", .operation = .{ .binary = .implies } }, .{ .name = "=", .operation = .{ .binary = .eq } }, .{ .name = "<=", .operation = .{ .binary = .le } }, .{ .name = "<", .operation = .{ .binary = .lt } }, .{ .name = ">=", .operation = .{ .binary = .ge } }, .{ .name = ">", .operation = .{ .binary = .gt } }, .{ .name = "bvule", .operation = .{ .binary = .bvule } }, .{ .name = "bvult", .operation = .{ .binary = .bvult } }, .{ .name = "bvsle", .operation = .{ .binary = .bvsle } }, .{ .name = "bvslt", .operation = .{ .binary = .bvslt } }, .{ .name = "bvuaddo", .operation = .{ .binary = .bvuaddo } }, .{ .name = "bvsaddo", .operation = .{ .binary = .bvsaddo } }, .{ .name = "bvssubo", .operation = .{ .binary = .bvssubo } }, .{ .name = "bvumulo", .operation = .{ .binary = .bvumulo } }, .{ .name = "bvsmulo", .operation = .{ .binary = .bvsmulo } }, .{ .name = "bvnot", .operation = .{ .unary = .bvnot } }, .{ .name = "bvand", .operation = .{ .binary = .bvand } }, .{ .name = "bvor", .operation = .{ .binary = .bvor } }, .{ .name = "bvxor", .operation = .{ .binary = .bvxor } }, .{ .name = "bvshl", .operation = .{ .binary = .bvshl } }, .{ .name = "bvlshr", .operation = .{ .binary = .bvlshr } }, .{ .name = "bvashr", .operation = .{ .binary = .bvashr } }, .{ .name = "bvudiv", .operation = .{ .binary = .bvudiv } }, .{ .name = "bvurem", .operation = .{ .binary = .bvurem } }, .{ .name = "bvsdiv", .operation = .{ .binary = .bvsdiv } }, .{ .name = "bvsrem", .operation = .{ .binary = .bvsrem } }, .{ .name = "bvsmod", .operation = .{ .binary = .bvsmod } }, .{ .name = "select", .operation = .{ .binary = .array_select } }, .{ .name = "store", .operation = .{ .ternary = .array_store } }, .{ .name = "concat", .operation = .{ .binary = .bvconcat } }, .{ .name = "bvadd", .operation = .{ .binary = .bvadd } }, .{ .name = "bvsub", .operation = .{ .binary = .bvsub } }, .{ .name = "bvmul", .operation = .{ .binary = .bvmul } }, .{ .name = "and", .operation = .{ .nary = .and_ } }, .{ .name = "or", .operation = .{ .nary = .or_ } }, .{ .name = "distinct", .operation = .{ .nary = .distinct } }, .{ .name = "+", .operation = .{ .nary = .add } }, .{ .name = "*", .operation = .{ .nary = .mul } },};/// Reads one term at the parser's position, builds it in the parser's `Context` and returns it. The/// command reader calls it for the term of each `assert`. An atom is `true`, `false`, an integer,/// the name of a function with no arguments, or the name of a declared constant. An integer is a/// decimal numeral with an optional leading `-`. A list is `(_ bvV W)` for a bit-vector constant,/// an indexed operator such as `((_ extract high low) x)`, a supported operator applied to its/// operands, or a declared function applied to its arguments. It returns `UnknownSymbol` for an/// undeclared name, `UnsupportedTerm` for an unsupported operator, `InvalidNumber` for a malformed/// number, and the errors of the `Context` builders, such as `FunctionArityMismatch`. It checks no/// sorts except the arguments of a function application.pub fn parse(parser: *Parser) Error!term.Term { if (!token.peekLeft(parser)) { const item = try token.atom(parser); if (std.mem.eql(u8, item, "true")) return try parser.ctx.boolValue(true); if (std.mem.eql(u8, item, "false")) return try parser.ctx.boolValue(false); if (parseInteger(item)) |value| return try parser.ctx.intValue(value); if (parser.functions.get(item)) |function_id| return try parser.ctx.apply(function_id, &.{}); return parser.symbols.get(item) orelse ParseError.UnknownSymbol; } try token.expectLeft(parser); if (token.peekLeft(parser)) return try parseIndexed(parser); const op = try token.atom(parser); if (std.mem.eql(u8, op, "_")) { const value_atom = try token.atom(parser); if (!std.mem.startsWith(u8, value_atom, "bv")) return ParseError.UnsupportedTerm; const value = std.fmt.parseInt(u128, value_atom[2..], 10) catch return ParseError.InvalidNumber; const width = std.fmt.parseInt(u32, try token.atom(parser), 10) catch return ParseError.InvalidNumber; try token.expectRight(parser); return try parser.ctx.bitvecValue(value, width); } inline for (operations) |entry| { if (std.mem.eql(u8, op, entry.name)) return try parseOperation(parser, entry.operation); } if (parser.functions.get(op)) |function_id| return try parseApply(parser, function_id); return ParseError.UnsupportedTerm;}fn parseOperation(parser: *Parser, comptime operation: Operation) Error!term.Term { return switch (operation) { .unary => |tag| try parseUnary(parser, tag), .binary => |tag| try parseBinary(parser, tag), .ternary => |tag| try parseTernary(parser, tag), .nary => |tag| try parseNary(parser, tag), };}fn parseIndexed(parser: *Parser) Error!term.Term { try token.expectLeft(parser); const underscore = try token.atom(parser); if (!std.mem.eql(u8, underscore, "_")) return ParseError.UnsupportedTerm; const op = try token.atom(parser); if (std.mem.eql(u8, op, "extract")) { const high = std.fmt.parseInt(u32, try token.atom(parser), 10) catch return ParseError.InvalidNumber; const low = std.fmt.parseInt(u32, try token.atom(parser), 10) catch return ParseError.InvalidNumber; try token.expectRight(parser); const operand = try parse(parser); try token.expectRight(parser); return try parser.ctx.bvextract(operand, high, low); } if (std.mem.eql(u8, op, "zero_extend")) { const extra = std.fmt.parseInt(u32, try token.atom(parser), 10) catch return ParseError.InvalidNumber; try token.expectRight(parser); const operand = try parse(parser); try token.expectRight(parser); return try parser.ctx.bvzeroext(operand, extra); } if (std.mem.eql(u8, op, "sign_extend")) { const extra = std.fmt.parseInt(u32, try token.atom(parser), 10) catch return ParseError.InvalidNumber; try token.expectRight(parser); const operand = try parse(parser); try token.expectRight(parser); return try parser.ctx.bvsignext(operand, extra); } if (std.mem.eql(u8, op, "rotate_left")) { const amount = std.fmt.parseInt(u32, try token.atom(parser), 10) catch return ParseError.InvalidNumber; try token.expectRight(parser); const operand = try parse(parser); try token.expectRight(parser); return try parser.ctx.bvrotl(operand, amount); } if (std.mem.eql(u8, op, "rotate_right")) { const amount = std.fmt.parseInt(u32, try token.atom(parser), 10) catch return ParseError.InvalidNumber; try token.expectRight(parser); const operand = try parse(parser); try token.expectRight(parser); return try parser.ctx.bvrotr(operand, amount); } return ParseError.UnsupportedTerm;}fn parseUnary(parser: *Parser, comptime tag: std.meta.Tag(term.Expr)) Error!term.Term { const operand = try parse(parser); try token.expectRight(parser); return switch (tag) { .not => try parser.ctx.not(operand), .bvnot => try parser.ctx.bvnot(operand), else => unreachable, };}fn parseBinary(parser: *Parser, comptime tag: std.meta.Tag(term.Expr)) Error!term.Term { const lhs = try parse(parser); const rhs = try parse(parser); try token.expectRight(parser); return try parser.ctx.binary(tag, lhs, rhs);}fn parseTernary(parser: *Parser, comptime tag: std.meta.Tag(term.Expr)) Error!term.Term { const first = try parse(parser); const second = try parse(parser); const third = try parse(parser); try token.expectRight(parser); return switch (tag) { .array_store => try parser.ctx.arrayStore(first, second, third), else => unreachable, };}fn parseNary(parser: *Parser, comptime tag: std.meta.Tag(term.Expr)) Error!term.Term { var operands: std.ArrayList(term.Term) = .empty; defer operands.deinit(parser.ctx.allocator); while (!token.peekRight(parser)) { try operands.append(parser.ctx.allocator, try parse(parser)); } try token.expectRight(parser); return switch (tag) { .and_ => try parser.ctx.and_(operands.items), .or_ => try parser.ctx.or_(operands.items), .distinct => try parser.ctx.distinct(operands.items), .add => try parser.ctx.add(operands.items), .mul => try parser.ctx.mul(operands.items), else => unreachable, };}fn parseApply(parser: *Parser, function: term.Function) Error!term.Term { var operands: std.ArrayList(term.Term) = .empty; defer operands.deinit(parser.ctx.allocator); while (!token.peekRight(parser)) { try operands.append(parser.ctx.allocator, try parse(parser)); } try token.expectRight(parser); return try parser.ctx.apply(function, operands.items);}fn parseInteger(text: []const u8) ?i128 { if (text.len == 0) return null; if (text[0] == '-' and text.len == 1) return null; if (text[0] != '-' and (text[0] < '0' or text[0] > '9')) return null; return std.fmt.parseInt(i128, text, 10) catch null;}Complete call list for smtlib.parse.term.parse
8 direct calls.
lib.smt.src.smtlib.parse.term.parseApply[function] — private source atlib/smt/src/smtlib/parse/term.zig:208in nearest public ownertiny.smt.smtlib.parse.termlib.smt.src.smtlib.parse.term.parseIndexed[function] — private source atlib/smt/src/smtlib/parse/term.zig:119in nearest public ownertiny.smt.smtlib.parse.termlib.smt.src.smtlib.parse.term.parseInteger[function] — private source atlib/smt/src/smtlib/parse/term.zig:218in nearest public ownertiny.smt.smtlib.parse.termlib.smt.src.smtlib.parse.term.parseOperation[function] — private source atlib/smt/src/smtlib/parse/term.zig:110in nearest public ownertiny.smt.smtlib.parse.termtiny.smt.smtlib.parse.token.atom[function] atlib/smt/src/smtlib/parse/token.zig:59tiny.smt.smtlib.parse.token.expectLeft[function] atlib/smt/src/smtlib/parse/token.zig:43tiny.smt.smtlib.parse.token.expectRight[function] atlib/smt/src/smtlib/parse/token.zig:50tiny.smt.smtlib.parse.token.peekLeft[function] atlib/smt/src/smtlib/parse/token.zig:29
Audit
| Definitions | 2 |
|---|---|
| Public names | 2 |
| Members | 0 |
| Version | 26.7.0 |
| Revision | daab053ee433 |