UNPKG

zignet

Version:

MCP server for Zig — AI-powered code analysis, validation, and documentation with fine-tuned LLM

816 lines (813 loc) 23.6 kB
const require_chunk = require('./chunk-DWy1uDak.cjs'); //#region src/lexer.js var require_lexer = /* @__PURE__ */ require_chunk.__commonJS({ "src/lexer.js": ((exports, module) => { /** * ZigNet Lexer * Tokenizes Zig source code */ const TokenType$1 = { FN: "FN", CONST: "CONST", VAR: "VAR", STRUCT: "STRUCT", UNION: "UNION", ENUM: "ENUM", IF: "IF", ELSE: "ELSE", WHILE: "WHILE", FOR: "FOR", RETURN: "RETURN", BREAK: "BREAK", CONTINUE: "CONTINUE", COMPTIME: "COMPTIME", INLINE: "INLINE", I32: "I32", I64: "I64", U32: "U32", F32: "F32", F64: "F64", BOOL: "BOOL", VOID: "VOID", NUMBER: "NUMBER", STRING: "STRING", IDENT: "IDENT", TRUE: "TRUE", FALSE: "FALSE", PLUS: "PLUS", MINUS: "MINUS", STAR: "STAR", SLASH: "SLASH", PERCENT: "PERCENT", EQ: "EQ", NEQ: "NEQ", LT: "LT", GT: "GT", LTE: "LTE", GTE: "GTE", ASSIGN: "ASSIGN", PLUS_ASSIGN: "PLUS_ASSIGN", AND: "AND", OR: "OR", NOT: "NOT", LPAREN: "LPAREN", RPAREN: "RPAREN", LBRACE: "LBRACE", RBRACE: "RBRACE", LBRACKET: "LBRACKET", RBRACKET: "RBRACKET", COLON: "COLON", SEMICOLON: "SEMICOLON", COMMA: "COMMA", DOT: "DOT", ARROW: "ARROW", FAT_ARROW: "FAT_ARROW", EOF: "EOF", ERROR: "ERROR" }; var Token = class { constructor(type, value, line, column) { this.type = type; this.value = value; this.line = line; this.column = column; } toString() { return `Token(${this.type}, "${this.value}", ${this.line}:${this.column})`; } }; var Lexer = class { constructor(source) { this.source = source; this.position = 0; this.line = 1; this.column = 1; this.tokens = []; } error(message) { return new Token(TokenType$1.ERROR, message, this.line, this.column); } peek(offset = 0) { const pos = this.position + offset; if (pos >= this.source.length) return "\0"; return this.source[pos]; } advance() { const char = this.source[this.position]; this.position++; if (char === "\n") { this.line++; this.column = 1; } else this.column++; return char; } skipWhitespace() { while (this.position < this.source.length && /\s/.test(this.peek())) this.advance(); } skipComment() { if (this.peek() === "/" && this.peek(1) === "/") { while (this.peek() !== "\n" && this.peek() !== "\0") this.advance(); return true; } return false; } readIdentifier() { let value = ""; while (/[a-zA-Z0-9_]/.test(this.peek())) value += this.advance(); return value; } readNumber() { let value = ""; while (/[0-9]/.test(this.peek())) value += this.advance(); if (this.peek() === "." && /[0-9]/.test(this.peek(1))) { value += this.advance(); while (/[0-9]/.test(this.peek())) value += this.advance(); } return value; } readString(quote) { let value = ""; this.advance(); while (this.peek() !== quote && this.peek() !== "\0") if (this.peek() === "\\") { this.advance(); const escaped = this.advance(); value += this.getEscapeSequence(escaped); } else value += this.advance(); if (this.peek() === quote) this.advance(); else return this.error("Unterminated string"); return value; } getEscapeSequence(char) { return { "n": "\n", "t": " ", "r": "\r", "\\": "\\", "\"": "\"", "'": "'" }[char] || char; } tokenize() { const keywords = { "fn": TokenType$1.FN, "const": TokenType$1.CONST, "var": TokenType$1.VAR, "struct": TokenType$1.STRUCT, "union": TokenType$1.UNION, "enum": TokenType$1.ENUM, "if": TokenType$1.IF, "else": TokenType$1.ELSE, "while": TokenType$1.WHILE, "for": TokenType$1.FOR, "return": TokenType$1.RETURN, "break": TokenType$1.BREAK, "continue": TokenType$1.CONTINUE, "comptime": TokenType$1.COMPTIME, "inline": TokenType$1.INLINE, "i32": TokenType$1.I32, "i64": TokenType$1.I64, "u32": TokenType$1.U32, "f32": TokenType$1.F32, "f64": TokenType$1.F64, "bool": TokenType$1.BOOL, "void": TokenType$1.VOID, "true": TokenType$1.TRUE, "false": TokenType$1.FALSE }; while (this.position < this.source.length) { this.skipWhitespace(); if (this.skipComment()) continue; const char = this.peek(); const line = this.line; const column = this.column; if (char === "\0") break; if (/[0-9]/.test(char)) { const value = this.readNumber(); this.tokens.push(new Token(TokenType$1.NUMBER, value, line, column)); continue; } if (char === "\"" || char === "'") { const value = this.readString(char); if (value instanceof Token) this.tokens.push(value); else this.tokens.push(new Token(TokenType$1.STRING, value, line, column)); continue; } if (/[a-zA-Z_]/.test(char)) { const value = this.readIdentifier(); const type = keywords[value] || TokenType$1.IDENT; this.tokens.push(new Token(type, value, line, column)); continue; } this.advance(); if (char === "+") if (this.peek() === "=") { this.advance(); this.tokens.push(new Token(TokenType$1.PLUS_ASSIGN, "+=", line, column)); } else this.tokens.push(new Token(TokenType$1.PLUS, "+", line, column)); else if (char === "-") if (this.peek() === ">") { this.advance(); this.tokens.push(new Token(TokenType$1.ARROW, "->", line, column)); } else this.tokens.push(new Token(TokenType$1.MINUS, "-", line, column)); else if (char === "*") this.tokens.push(new Token(TokenType$1.STAR, "*", line, column)); else if (char === "/") this.tokens.push(new Token(TokenType$1.SLASH, "/", line, column)); else if (char === "%") this.tokens.push(new Token(TokenType$1.PERCENT, "%", line, column)); else if (char === "=") if (this.peek() === "=") { this.advance(); this.tokens.push(new Token(TokenType$1.EQ, "==", line, column)); } else if (this.peek() === ">") { this.advance(); this.tokens.push(new Token(TokenType$1.FAT_ARROW, "=>", line, column)); } else this.tokens.push(new Token(TokenType$1.ASSIGN, "=", line, column)); else if (char === "!") if (this.peek() === "=") { this.advance(); this.tokens.push(new Token(TokenType$1.NEQ, "!=", line, column)); } else this.tokens.push(new Token(TokenType$1.NOT, "!", line, column)); else if (char === "<") if (this.peek() === "=") { this.advance(); this.tokens.push(new Token(TokenType$1.LTE, "<=", line, column)); } else this.tokens.push(new Token(TokenType$1.LT, "<", line, column)); else if (char === ">") if (this.peek() === "=") { this.advance(); this.tokens.push(new Token(TokenType$1.GTE, ">=", line, column)); } else this.tokens.push(new Token(TokenType$1.GT, ">", line, column)); else if (char === "&") if (this.peek() === "&") { this.advance(); this.tokens.push(new Token(TokenType$1.AND, "&&", line, column)); } else this.tokens.push(new Token(TokenType$1.ERROR, `Unexpected char: &`, line, column)); else if (char === "|") if (this.peek() === "|") { this.advance(); this.tokens.push(new Token(TokenType$1.OR, "||", line, column)); } else this.tokens.push(new Token(TokenType$1.ERROR, `Unexpected char: |`, line, column)); else if (char === "(") this.tokens.push(new Token(TokenType$1.LPAREN, "(", line, column)); else if (char === ")") this.tokens.push(new Token(TokenType$1.RPAREN, ")", line, column)); else if (char === "{") this.tokens.push(new Token(TokenType$1.LBRACE, "{", line, column)); else if (char === "}") this.tokens.push(new Token(TokenType$1.RBRACE, "}", line, column)); else if (char === "[") this.tokens.push(new Token(TokenType$1.LBRACKET, "[", line, column)); else if (char === "]") this.tokens.push(new Token(TokenType$1.RBRACKET, "]", line, column)); else if (char === ":") this.tokens.push(new Token(TokenType$1.COLON, ":", line, column)); else if (char === ";") this.tokens.push(new Token(TokenType$1.SEMICOLON, ";", line, column)); else if (char === ",") this.tokens.push(new Token(TokenType$1.COMMA, ",", line, column)); else if (char === ".") this.tokens.push(new Token(TokenType$1.DOT, ".", line, column)); else this.tokens.push(new Token(TokenType$1.ERROR, `Unexpected char: ${char}`, line, column)); } this.tokens.push(new Token(TokenType$1.EOF, "", this.line, this.column)); return this.tokens; } }; module.exports = { Lexer, Token, TokenType: TokenType$1 }; }) }); //#endregion //#region src/parser.ts var import_lexer = /* @__PURE__ */ require_chunk.__toESM(require_lexer(), 1); /** * Parser error class */ var ParseError = class extends Error { constructor(message, token) { super(message); this.token = token; this.name = "ParseError"; } toString() { return `${this.name} at ${this.token.line}:${this.token.column}: ${this.message}`; } }; /** * Parser class */ var Parser = class { position = 0; constructor(tokens) { this.tokens = tokens; } /** * Parse the entire program */ parse() { const body = []; while (!this.isAtEnd()) body.push(this.parseDeclaration()); return { type: "Program", body }; } /** * Parse a top-level declaration */ parseDeclaration() { const isInline = this.match(import_lexer.TokenType.INLINE); const isComptime = this.match(import_lexer.TokenType.COMPTIME); if (this.check(import_lexer.TokenType.FN)) return this.parseFunctionDeclaration(isInline, isComptime); if (this.check(import_lexer.TokenType.CONST) || this.check(import_lexer.TokenType.VAR)) { const decl = this.parseVariableDeclaration(); if (decl.initializer && decl.initializer.type === "Identifier" && (this.previous().type === import_lexer.TokenType.STRUCT || this.previous().type === import_lexer.TokenType.UNION || this.previous().type === import_lexer.TokenType.ENUM)) return decl; return decl; } throw this.error("Expected declaration"); } /** * Parse function declaration */ parseFunctionDeclaration(isInline = false, isComptime = false) { const fnToken = this.consume(import_lexer.TokenType.FN, "Expected 'fn'"); const name = this.consume(import_lexer.TokenType.IDENT, "Expected function name").value; this.consume(import_lexer.TokenType.LPAREN, "Expected '(' after function name"); const parameters = this.parseParameters(); this.consume(import_lexer.TokenType.RPAREN, "Expected ')' after parameters"); const errorUnion = this.match(import_lexer.TokenType.NOT); return { type: "FunctionDeclaration", name, parameters, returnType: this.parseTypeAnnotation(), body: this.parseBlockStatement(), isInline, isComptime, errorUnion, line: fnToken.line, column: fnToken.column }; } /** * Parse function parameters */ parseParameters() { const parameters = []; if (!this.check(import_lexer.TokenType.RPAREN)) do { const isComptime = this.match(import_lexer.TokenType.COMPTIME); const paramToken = this.consume(import_lexer.TokenType.IDENT, "Expected parameter name"); const name = paramToken.value; this.consume(import_lexer.TokenType.COLON, "Expected ':' after parameter name"); const typeAnnotation = this.parseTypeAnnotation(); parameters.push({ type: "Parameter", name, typeAnnotation, isComptime, line: paramToken.line, column: paramToken.column }); } while (this.match(import_lexer.TokenType.COMMA)); return parameters; } /** * Parse variable declaration */ parseVariableDeclaration() { const isConst = this.match(import_lexer.TokenType.CONST); if (!isConst) this.consume(import_lexer.TokenType.VAR, "Expected 'const' or 'var'"); const nameToken = this.consume(import_lexer.TokenType.IDENT, "Expected variable name"); const name = nameToken.value; let typeAnnotation; if (this.match(import_lexer.TokenType.COLON)) typeAnnotation = this.parseTypeAnnotation(); let initializer; if (this.match(import_lexer.TokenType.ASSIGN)) initializer = this.parseExpression(); this.consume(import_lexer.TokenType.SEMICOLON, "Expected ';' after variable declaration"); return { type: "VariableDeclaration", isConst, name, typeAnnotation, initializer, line: nameToken.line, column: nameToken.column }; } /** * Parse type annotation */ parseTypeAnnotation() { const token = this.current(); if (this.check(import_lexer.TokenType.I32) || this.check(import_lexer.TokenType.I64) || this.check(import_lexer.TokenType.U32) || this.check(import_lexer.TokenType.F32) || this.check(import_lexer.TokenType.F64) || this.check(import_lexer.TokenType.BOOL) || this.check(import_lexer.TokenType.VOID)) { this.advance(); return { type: "PrimitiveType", name: token.value, line: token.line, column: token.column }; } if (this.check(import_lexer.TokenType.IDENT)) return { type: "IdentifierType", name: this.advance().value, line: token.line, column: token.column }; throw this.error("Expected type annotation"); } /** * Parse block statement */ parseBlockStatement() { const lbrace = this.consume(import_lexer.TokenType.LBRACE, "Expected '{'"); const statements = []; while (!this.check(import_lexer.TokenType.RBRACE) && !this.isAtEnd()) statements.push(this.parseStatement()); this.consume(import_lexer.TokenType.RBRACE, "Expected '}'"); return { type: "BlockStatement", statements, line: lbrace.line, column: lbrace.column }; } /** * Parse statement */ parseStatement() { if (this.check(import_lexer.TokenType.RETURN)) return this.parseReturnStatement(); if (this.check(import_lexer.TokenType.IF)) return this.parseIfStatement(); if (this.check(import_lexer.TokenType.WHILE)) return this.parseWhileStatement(); if (this.check(import_lexer.TokenType.BREAK)) { const token = this.advance(); this.consume(import_lexer.TokenType.SEMICOLON, "Expected ';' after 'break'"); return { type: "BreakStatement", line: token.line, column: token.column }; } if (this.check(import_lexer.TokenType.CONTINUE)) { const token = this.advance(); this.consume(import_lexer.TokenType.SEMICOLON, "Expected ';' after 'continue'"); return { type: "ContinueStatement", line: token.line, column: token.column }; } if (this.check(import_lexer.TokenType.COMPTIME)) return this.parseComptimeStatement(); if (this.check(import_lexer.TokenType.CONST) || this.check(import_lexer.TokenType.VAR)) return this.parseVariableDeclaration(); if (this.check(import_lexer.TokenType.LBRACE)) return this.parseBlockStatement(); return this.parseExpressionStatement(); } /** * Parse return statement */ parseReturnStatement() { const returnToken = this.consume(import_lexer.TokenType.RETURN, "Expected 'return'"); let value; if (!this.check(import_lexer.TokenType.SEMICOLON)) value = this.parseExpression(); this.consume(import_lexer.TokenType.SEMICOLON, "Expected ';' after return statement"); return { type: "ReturnStatement", value, line: returnToken.line, column: returnToken.column }; } /** * Parse if statement */ parseIfStatement() { const ifToken = this.consume(import_lexer.TokenType.IF, "Expected 'if'"); this.consume(import_lexer.TokenType.LPAREN, "Expected '(' after 'if'"); const condition = this.parseExpression(); this.consume(import_lexer.TokenType.RPAREN, "Expected ')' after condition"); const consequent = this.parseStatement(); let alternate; if (this.match(import_lexer.TokenType.ELSE)) alternate = this.parseStatement(); return { type: "IfStatement", condition, consequent, alternate, line: ifToken.line, column: ifToken.column }; } /** * Parse while statement */ parseWhileStatement() { const whileToken = this.consume(import_lexer.TokenType.WHILE, "Expected 'while'"); this.consume(import_lexer.TokenType.LPAREN, "Expected '(' after 'while'"); const condition = this.parseExpression(); this.consume(import_lexer.TokenType.RPAREN, "Expected ')' after condition"); return { type: "WhileStatement", condition, body: this.parseStatement(), line: whileToken.line, column: whileToken.column }; } /** * Parse comptime statement */ parseComptimeStatement() { const comptimeToken = this.consume(import_lexer.TokenType.COMPTIME, "Expected 'comptime'"); return { type: "ComptimeStatement", body: this.parseBlockStatement(), line: comptimeToken.line, column: comptimeToken.column }; } /** * Parse expression statement */ parseExpressionStatement() { const expr = this.parseExpression(); this.consume(import_lexer.TokenType.SEMICOLON, "Expected ';' after expression"); return { type: "ExpressionStatement", expression: expr, line: expr.line, column: expr.column }; } /** * Parse expression (starting point for precedence climbing) */ parseExpression() { return this.parseAssignment(); } /** * Parse assignment expression */ parseAssignment() { const expr = this.parseLogicalOr(); if (this.match(import_lexer.TokenType.ASSIGN, import_lexer.TokenType.PLUS_ASSIGN)) return { type: "AssignmentExpression", operator: this.previous().value, left: expr, right: this.parseAssignment(), line: expr.line, column: expr.column }; return expr; } /** * Parse logical OR expression */ parseLogicalOr() { let left = this.parseLogicalAnd(); while (this.match(import_lexer.TokenType.OR)) { const operator = this.previous().value; const right = this.parseLogicalAnd(); left = { type: "BinaryExpression", operator, left, right, line: left.line, column: left.column }; } return left; } /** * Parse logical AND expression */ parseLogicalAnd() { let left = this.parseEquality(); while (this.match(import_lexer.TokenType.AND)) { const operator = this.previous().value; const right = this.parseEquality(); left = { type: "BinaryExpression", operator, left, right, line: left.line, column: left.column }; } return left; } /** * Parse equality expression (==, !=) */ parseEquality() { let left = this.parseComparison(); while (this.match(import_lexer.TokenType.EQ, import_lexer.TokenType.NEQ)) { const operator = this.previous().value; const right = this.parseComparison(); left = { type: "BinaryExpression", operator, left, right, line: left.line, column: left.column }; } return left; } /** * Parse comparison expression (<, >, <=, >=) */ parseComparison() { let left = this.parseAddition(); while (this.match(import_lexer.TokenType.LT, import_lexer.TokenType.GT, import_lexer.TokenType.LTE, import_lexer.TokenType.GTE)) { const operator = this.previous().value; const right = this.parseAddition(); left = { type: "BinaryExpression", operator, left, right, line: left.line, column: left.column }; } return left; } /** * Parse addition/subtraction expression */ parseAddition() { let left = this.parseMultiplication(); while (this.match(import_lexer.TokenType.PLUS, import_lexer.TokenType.MINUS)) { const operator = this.previous().value; const right = this.parseMultiplication(); left = { type: "BinaryExpression", operator, left, right, line: left.line, column: left.column }; } return left; } /** * Parse multiplication/division expression */ parseMultiplication() { let left = this.parseUnary(); while (this.match(import_lexer.TokenType.STAR, import_lexer.TokenType.SLASH, import_lexer.TokenType.PERCENT)) { const operator = this.previous().value; const right = this.parseUnary(); left = { type: "BinaryExpression", operator, left, right, line: left.line, column: left.column }; } return left; } /** * Parse unary expression (-, !) */ parseUnary() { if (this.match(import_lexer.TokenType.MINUS, import_lexer.TokenType.NOT)) { const operator = this.previous(); return { type: "UnaryExpression", operator: operator.value, operand: this.parseUnary(), line: operator.line, column: operator.column }; } return this.parsePostfix(); } /** * Parse postfix expression (call, member access, index) */ parsePostfix() { let expr = this.parsePrimary(); while (true) if (this.match(import_lexer.TokenType.LPAREN)) { const args = []; if (!this.check(import_lexer.TokenType.RPAREN)) do args.push(this.parseExpression()); while (this.match(import_lexer.TokenType.COMMA)); this.consume(import_lexer.TokenType.RPAREN, "Expected ')' after arguments"); expr = { type: "CallExpression", callee: expr, arguments: args, line: expr.line, column: expr.column }; } else if (this.match(import_lexer.TokenType.DOT)) { const property = this.consume(import_lexer.TokenType.IDENT, "Expected property name").value; expr = { type: "MemberExpression", object: expr, property, line: expr.line, column: expr.column }; } else if (this.match(import_lexer.TokenType.LBRACKET)) { const index = this.parseExpression(); this.consume(import_lexer.TokenType.RBRACKET, "Expected ']' after index"); expr = { type: "IndexExpression", object: expr, index, line: expr.line, column: expr.column }; } else break; return expr; } /** * Parse primary expression (literals, identifiers, grouped expressions) */ parsePrimary() { const token = this.current(); if (this.match(import_lexer.TokenType.NUMBER)) return { type: "NumberLiteral", value: parseFloat(this.previous().value), line: token.line, column: token.column }; if (this.match(import_lexer.TokenType.STRING)) return { type: "StringLiteral", value: this.previous().value, line: token.line, column: token.column }; if (this.match(import_lexer.TokenType.TRUE)) return { type: "BooleanLiteral", value: true, line: token.line, column: token.column }; if (this.match(import_lexer.TokenType.FALSE)) return { type: "BooleanLiteral", value: false, line: token.line, column: token.column }; if (this.match(import_lexer.TokenType.IDENT)) return { type: "Identifier", name: this.previous().value, line: token.line, column: token.column }; if (this.match(import_lexer.TokenType.LPAREN)) { const expr = this.parseExpression(); this.consume(import_lexer.TokenType.RPAREN, "Expected ')' after expression"); return expr; } throw this.error("Expected expression"); } /** * Check if current token matches any of the given types */ match(...types) { for (const type of types) if (this.check(type)) { this.advance(); return true; } return false; } /** * Check if current token is of given type */ check(type) { if (this.isAtEnd()) return false; return this.current().type === type; } /** * Consume current token if it matches expected type, otherwise throw error */ consume(type, message) { if (this.check(type)) return this.advance(); throw this.error(message); } /** * Advance to next token */ advance() { if (!this.isAtEnd()) this.position++; return this.previous(); } /** * Check if at end of token stream */ isAtEnd() { return this.current().type === import_lexer.TokenType.EOF; } /** * Get current token */ current() { return this.tokens[this.position]; } /** * Get previous token */ previous() { return this.tokens[this.position - 1]; } /** * Create a parse error */ error(message) { return new ParseError(message, this.current()); } }; //#endregion exports.ParseError = ParseError; exports.Parser = Parser; //# sourceMappingURL=parser.cjs.map