nk 1.0.0
C++ Numerical Computing Runtime
Loading...
Searching...
No Matches
parser.hpp
1#pragma once
2
3#include <nk/core/ast.hpp>
4#include <nk/core/lexer.hpp>
5#include <nk/core/stack_guard.hpp>
6#include <initializer_list>
7#include <stdexcept>
8#include <string>
9#include <vector>
10
11namespace nk {
12
13class Parser
14{
15public:
16 explicit Parser(const std::vector<Token> &tokens);
17 ASTNodePtr parse();
18
19private:
20 std::vector<Token> tokens_;
21 size_t pos_ = 0;
22 size_t nestingDepth_ = 0;
23 static constexpr size_t MAX_NESTING_DEPTH = 200;
24
25 struct NestingGuard
26 {
27 Parser &p;
28 explicit NestingGuard(Parser &parser)
29 : p(parser)
30 {
31 // Watermark before the depth limit: on small-stack hosts (WASM
32 // workers) the descent can exhaust the stack before the fixed
33 // 200-level limit fires — refuse with a diagnostic either way.
34 StackGuard::check("parser");
35 if (++p.nestingDepth_ > MAX_NESTING_DEPTH) {
36 throw std::runtime_error("Parse error at line " + std::to_string(p.current().line)
37 + " col " + std::to_string(p.current().col)
38 + ": Expression or block nesting exceeds maximum supported depth ("
39 + std::to_string(MAX_NESTING_DEPTH) + ")");
40 }
41 }
42 ~NestingGuard() { --p.nestingDepth_; }
43 };
44
45 // — Позиция в исходнике —
46 struct SourceLoc
47 {
48 int line;
49 int col;
50 };
51 SourceLoc loc() const;
52
53 // — Утилиты навигации по токенам —
54 const Token &current() const;
55 const Token &peekToken(int off = 0) const;
56 bool isAtEnd() const;
57 bool check(TokenType t) const;
58 bool match(TokenType t);
59 Token consume(TokenType t, const std::string &msg = "");
60 void skipNewlines();
61 void skipTerminators();
62 // Consume a statement-terminating SEMICOLON or COMMA token (if
63 // present), recording its position into node.endLine / node.endCol
64 // so downstream tools (the graph viewer's sourceText slicer) can
65 // bound the statement's source range precisely. Returns true iff
66 // a SEMICOLON was consumed (i.e. suppress-output is set); COMMA
67 // returns false (it terminates the stmt but doesn't suppress).
68 bool consumeStmtTerminator(ASTNode &node);
69
70 // Single chokepoint for token-position changes. After moving pos_
71 // forward, skips past any COMMENT tokens so the parser never has
72 // to deal with them — COMMENT is purely lexical metadata for
73 // downstream tools (script-graph viewer, formatters, doc
74 // extractors). All `pos_++` sites in parser.cpp go through this
75 // helper, plus the constructor invokes skipPastComments() once
76 // to handle a leading comment.
77 void advance();
78 void skipPastComments();
79
80 // — Проверка терминаторов —
81 bool isTerminator(std::initializer_list<TokenType> terminators) const;
82
83 // — Безопасный парсинг числа —
84 static double parseDouble(const std::string &text, int line, int col);
85
86 // — Command-style calls (clear all, grid on, cd dir, etc.) —
87 bool isCommandStyleCall() const;
88 ASTNodePtr parseCommandStyleCall();
89
90 // — Statements —
91 ASTNodePtr parseStatement();
92 ASTNodePtr parseExpressionStatement();
93 ASTNodePtr tryMultiAssign();
94 ASTNodePtr parseIf();
95 ASTNodePtr parseFor();
96 ASTNodePtr parseWhile();
97 ASTNodePtr parseSwitch();
98 ASTNodePtr parseFunctionDef();
99 ASTNodePtr parseClassDef();
100 ASTNodePtr parseTryCatch();
101 ASTNodePtr parseGlobalPersistent();
102 ASTNodePtr parseBlock(std::initializer_list<TokenType> terminators);
103
104 // — Expressions (MATLAB precedence, low to high) —
105 ASTNodePtr parseExpression();
106 ASTNodePtr parseShortCircuitOr(); // ||
107 ASTNodePtr parseShortCircuitAnd(); // &&
108 ASTNodePtr parseElementOr(); // |
109 ASTNodePtr parseElementAnd(); // &
110 ASTNodePtr parseComparison(); // == ~= < > <= >=
111 ASTNodePtr parseColon(); // :
112 ASTNodePtr parseAddSub(); // + -
113 ASTNodePtr parseMulDiv(); // * / .* ./
114 ASTNodePtr parseUnary(); // - ~ +
115 ASTNodePtr parsePower(); // ^ .^
116 ASTNodePtr parsePostfix(); // () {} . ' .'
117 ASTNodePtr parsePrimary();
118
119 // — Литералы —
120 ASTNodePtr parseArrayLiteral(TokenType open, TokenType close, NodeType nodeType);
121 ASTNodePtr parseMatrixLiteral();
122 ASTNodePtr parseCellLiteral();
123 ASTNodePtr parseAnonFunc();
124 // Reconstruct anonymous-function source from the token span [from, to)
125 // (for func2str). MATLAB-style: no inter-token whitespace, literals re-quoted.
126 std::string reconstructAnonSource(size_t from, size_t to) const;
127
128 // — Lookahead для function def —
129 bool probeHasOutputSignature() const;
130};
131
132} // namespace nk