parser.rs 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887
  1. /* This file is part of DarkFi (https://dark.fi)
  2. *
  3. * Copyright (C) 2020-2023 Dyne.org foundation
  4. *
  5. * This program is free software: you can redistribute it and/or modify
  6. * it under the terms of the GNU Affero General Public License as
  7. * published by the Free Software Foundation, either version 3 of the
  8. * License, or (at your option) any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU Affero General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU Affero General Public License
  16. * along with this program. If not, see <https://www.gnu.org/licenses/>.
  17. */
  18. use std::{iter::Peekable, str::Chars};
  19. use indexmap::IndexMap;
  20. use itertools::Itertools;
  21. use super::{
  22. ast::{Arg, Constant, Literal, Statement, StatementType, Variable, Witness},
  23. error::ErrorEmitter,
  24. lexer::{Token, TokenType},
  25. LitType, Opcode, VarType,
  26. };
  27. /// zkas language builtin keywords.
  28. /// These can not be used anywhere except where they are expected.
  29. const KEYWORDS: [&str; 3] = ["constant", "witness", "circuit"];
  30. /// Forbidden namespaces
  31. const NOPE_NS: [&str; 4] = [".constant", ".literal", ".witness", ".circuit"];
  32. /// Valid EcFixedPoint constant names supported by the VM.
  33. const VALID_ECFIXEDPOINT: [&str; 1] = ["VALUE_COMMIT_RANDOM"];
  34. /// Valid EcFixedPointShort constant names supported by the VM.
  35. const VALID_ECFIXEDPOINTSHORT: [&str; 1] = ["VALUE_COMMIT_VALUE"];
  36. /// Valid EcFixedPointBase constant names supported by the VM.
  37. const VALID_ECFIXEDPOINTBASE: [&str; 1] = ["NULLIFIER_K"];
  38. pub struct Parser {
  39. tokens: Vec<Token>,
  40. error: ErrorEmitter,
  41. }
  42. impl Parser {
  43. pub fn new(filename: &str, source: Chars, tokens: Vec<Token>) -> Self {
  44. // For nice error reporting, we'll load everything into a string
  45. // vector so we have references to lines.
  46. let lines: Vec<String> = source.as_str().lines().map(|x| x.to_string()).collect();
  47. let error = ErrorEmitter::new("Parser", filename, lines);
  48. Self { tokens, error }
  49. }
  50. pub fn parse(&self) -> (String, Vec<Constant>, Vec<Witness>, Vec<Statement>) {
  51. // We use these to keep state while parsing.
  52. let mut namespace = None;
  53. let (mut declaring_constant, mut declared_constant) = (false, false);
  54. let (mut declaring_witness, mut declared_witness) = (false, false);
  55. let (mut declaring_circuit, mut declared_circuit) = (false, false);
  56. // The tokens gathered from each of the sections
  57. let mut constant_tokens = vec![];
  58. let mut witness_tokens = vec![];
  59. let mut circuit_tokens = vec![];
  60. // Tokens belonging to the current statement
  61. let mut circuit_stmt = vec![];
  62. // All completed statements are pushed here
  63. let mut circuit_stmts = vec![];
  64. // Contains constant and witness sections
  65. let mut ast_inner = IndexMap::new();
  66. let mut ast = IndexMap::new();
  67. if self.tokens[0].token_type != TokenType::Symbol {
  68. self.error.abort(
  69. "Source file does not start with a section. Expected `constant/witness/circuit`.",
  70. 0,
  71. 0,
  72. );
  73. }
  74. let mut iter = self.tokens.iter();
  75. while let Some(t) = iter.next() {
  76. // Sections "constant", "witness", and "circuit" are
  77. // the sections we must be declaring in our source code.
  78. // When we find one, we'll take all the tokens found in
  79. // the section and place them in their respective vec.
  80. // NOTE: Currently this logic depends on the fact that
  81. // the sections are closed off with braces. This should
  82. // be revisited later when we decide to add other lang
  83. // functionality that also depends on using braces.
  84. if !declaring_constant && !declaring_witness && !declaring_circuit {
  85. //
  86. // We use this macro to avoid code repetition in the following
  87. // match statement for soaking up the section tokens.
  88. macro_rules! absorb_inner_tokens {
  89. ($v:ident) => {
  90. for inner in iter.by_ref() {
  91. if KEYWORDS.contains(&inner.token.as_str()) &&
  92. inner.token_type == TokenType::Symbol
  93. {
  94. self.error.abort(
  95. &format!("Keyword '{}' used in improper place.", inner.token),
  96. inner.line,
  97. inner.column,
  98. );
  99. }
  100. $v.push(inner.clone());
  101. if inner.token_type == TokenType::RightBrace {
  102. break
  103. }
  104. }
  105. };
  106. }
  107. match t.token.as_str() {
  108. "constant" => {
  109. declaring_constant = true;
  110. absorb_inner_tokens!(constant_tokens);
  111. }
  112. "witness" => {
  113. declaring_witness = true;
  114. absorb_inner_tokens!(witness_tokens);
  115. }
  116. "circuit" => {
  117. declaring_circuit = true;
  118. absorb_inner_tokens!(circuit_tokens);
  119. }
  120. x => self.error.abort(
  121. &format!("Section `{}` is not a valid section", x),
  122. t.line,
  123. t.column,
  124. ),
  125. }
  126. }
  127. // We use this macro to set or check that the namespace of all sections
  128. // is the same and no stray strings appeared.
  129. macro_rules! check_namespace {
  130. ($t:ident) => {
  131. if let Some(ns) = namespace.clone() {
  132. if ns != $t[0].token {
  133. self.error.abort(
  134. &format!("Found '{}' namespace, expected '{}'.", $t[0].token, ns),
  135. $t[0].line,
  136. $t[0].column,
  137. );
  138. }
  139. } else {
  140. if NOPE_NS.contains(&$t[0].token.as_str()) {
  141. self.error.abort(
  142. &format!("'{}' cannot be a namespace.", $t[0].token),
  143. $t[0].line,
  144. $t[0].column,
  145. );
  146. }
  147. namespace = Some($t[0].token.clone());
  148. }
  149. };
  150. }
  151. // Parse the constant section into the AST.
  152. if declaring_constant {
  153. if declared_constant {
  154. self.error.abort("Duplicate `constant` section found.", t.line, t.column);
  155. }
  156. self.check_section_structure("constant", constant_tokens.clone());
  157. check_namespace!(constant_tokens);
  158. let mut constants_map = IndexMap::new();
  159. // This is everything between the braces: { ... }
  160. let mut constant_inner = constant_tokens[2..constant_tokens.len() - 1].iter();
  161. while let Some((typ, name, comma)) = constant_inner.next_tuple() {
  162. if comma.token_type != TokenType::Comma {
  163. self.error.abort("Separator is not a comma.", comma.line, comma.column);
  164. }
  165. // No variable shadowing
  166. if constants_map.contains_key(name.token.as_str()) {
  167. self.error.abort(
  168. &format!(
  169. "Section `constant` already contains the token `{}`.",
  170. &name.token
  171. ),
  172. name.line,
  173. name.column,
  174. );
  175. }
  176. constants_map.insert(name.token.clone(), (name.clone(), typ.clone()));
  177. }
  178. if constant_inner.next().is_some() {
  179. self.error.abort("Internal error, leftovers in 'constant' iterator", 0, 0);
  180. }
  181. ast_inner.insert("constant".to_string(), constants_map);
  182. declaring_constant = false;
  183. declared_constant = true;
  184. }
  185. // Parse the witness section into the AST.
  186. if declaring_witness {
  187. if declared_witness {
  188. self.error.abort("Duplicate `witness` section found.", t.line, t.column);
  189. }
  190. self.check_section_structure("witness", witness_tokens.clone());
  191. check_namespace!(witness_tokens);
  192. let mut witnesses_map = IndexMap::new();
  193. // This is everything between the braces: { ... }
  194. let mut witness_inner = witness_tokens[2..witness_tokens.len() - 1].iter();
  195. while let Some((typ, name, comma)) = witness_inner.next_tuple() {
  196. if comma.token_type != TokenType::Comma {
  197. self.error.abort("Separator is not a comma.", comma.line, comma.column);
  198. }
  199. // No variable shadowing
  200. if witnesses_map.contains_key(name.token.as_str()) {
  201. self.error.abort(
  202. &format!(
  203. "Section `witness` already contains the token `{}`.",
  204. &name.token
  205. ),
  206. name.line,
  207. name.column,
  208. );
  209. }
  210. witnesses_map.insert(name.token.clone(), (name.clone(), typ.clone()));
  211. }
  212. if witness_inner.next().is_some() {
  213. self.error.abort("Internal error, leftovers in 'witness' iterator", 0, 0);
  214. }
  215. ast_inner.insert("witness".to_string(), witnesses_map);
  216. declaring_witness = false;
  217. declared_witness = true;
  218. }
  219. // Parse the circuit section into the AST.
  220. if declaring_circuit {
  221. if declared_circuit {
  222. self.error.abort("Duplicate `circuit` section found.", t.line, t.column);
  223. }
  224. self.check_section_structure("circuit", circuit_tokens.clone());
  225. check_namespace!(circuit_tokens);
  226. // Grab tokens for each statement
  227. for i in circuit_tokens[2..circuit_tokens.len() - 1].iter() {
  228. if i.token_type == TokenType::Semicolon {
  229. // Push completed statement to the heap
  230. circuit_stmts.push(circuit_stmt.clone());
  231. circuit_stmt = vec![];
  232. continue
  233. }
  234. circuit_stmt.push(i.clone());
  235. }
  236. declaring_circuit = false;
  237. declared_circuit = true;
  238. }
  239. }
  240. // Tokens have been processed and ast is complete
  241. let ns = namespace.unwrap();
  242. ast.insert(ns.clone(), ast_inner);
  243. let constants = {
  244. let c = match ast.get(&ns).unwrap().get("constant") {
  245. Some(c) => c,
  246. None => {
  247. self.error.abort("Missing `constant` section in .zk source.", 0, 0);
  248. unreachable!();
  249. }
  250. };
  251. self.parse_ast_constants(c)
  252. };
  253. let witnesses = {
  254. let c = match ast.get(&ns).unwrap().get("witness") {
  255. Some(c) => c,
  256. None => {
  257. self.error.abort("Missing `witness` section in .zk source.", 0, 0);
  258. unreachable!();
  259. }
  260. };
  261. self.parse_ast_witness(c)
  262. };
  263. let statements = self.parse_ast_circuit(circuit_stmts);
  264. if statements.is_empty() {
  265. self.error.abort("Circuit section is empty.", 0, 0);
  266. }
  267. (ns, constants, witnesses, statements)
  268. }
  269. /// Routine checks on section structure
  270. fn check_section_structure(&self, section: &str, tokens: Vec<Token>) {
  271. if tokens[0].token_type != TokenType::String {
  272. self.error.abort(
  273. "Section declaration must start with a naming string.",
  274. tokens[0].line,
  275. tokens[0].column,
  276. );
  277. }
  278. if tokens[1].token_type != TokenType::LeftBrace {
  279. self.error.abort(
  280. "Section must be opened with a left brace '{'",
  281. tokens[0].line,
  282. tokens[0].column,
  283. );
  284. }
  285. if tokens.last().unwrap().token_type != TokenType::RightBrace {
  286. self.error.abort(
  287. "Section must be closed with a right brace '}'",
  288. tokens[0].line,
  289. tokens[0].column,
  290. );
  291. }
  292. match section {
  293. "constant" | "witness" => {
  294. if tokens.len() == 3 {
  295. self.error.warn(&format!("{} section is empty.", section), 0, 0);
  296. }
  297. if tokens[2..tokens.len() - 1].len() % 3 != 0 {
  298. self.error.abort(
  299. &format!("Invalid number of elements in '{}' section. Must be pairs of '<Type> <name>' separated with a comma ','.", section),
  300. tokens[0].line,
  301. tokens[0].column
  302. );
  303. }
  304. }
  305. "circuit" => {
  306. if tokens.len() == 3 {
  307. self.error.abort("circuit section is empty.", 0, 0);
  308. }
  309. if tokens[tokens.len() - 2].token_type != TokenType::Semicolon {
  310. self.error.abort(
  311. "Circuit section does not end with a semicolon. Would never finish parsing.",
  312. tokens[tokens.len()-2].line,
  313. tokens[tokens.len()-2].column,
  314. );
  315. }
  316. }
  317. _ => unreachable!(),
  318. };
  319. }
  320. fn parse_ast_constants(&self, ast: &IndexMap<String, (Token, Token)>) -> Vec<Constant> {
  321. let mut ret = vec![];
  322. // k = name
  323. // v = (name, type)
  324. for (k, v) in ast {
  325. if &v.0.token != k {
  326. self.error.abort(
  327. &format!("Constant name `{}` doesn't match token `{}`.", v.0.token, k),
  328. v.0.line,
  329. v.0.column,
  330. );
  331. }
  332. if v.0.token_type != TokenType::Symbol {
  333. self.error.abort(
  334. &format!("Constant name `{}` is not a symbol.", v.0.token),
  335. v.0.line,
  336. v.0.column,
  337. );
  338. }
  339. if v.1.token_type != TokenType::Symbol {
  340. self.error.abort(
  341. &format!("Constant type `{}` is not a symbol.", v.1.token),
  342. v.1.line,
  343. v.1.column,
  344. );
  345. }
  346. // Valid constant types, these are the constants/generators supported
  347. // in `src/crypto/constants.rs` and `src/crypto/constants/`.
  348. match v.1.token.as_str() {
  349. "EcFixedPoint" => {
  350. if !VALID_ECFIXEDPOINT.contains(&v.0.token.as_str()) {
  351. self.error.abort(
  352. &format!(
  353. "`{}` is not a valid EcFixedPoint constant. Supported: {:?}",
  354. v.0.token.as_str(),
  355. VALID_ECFIXEDPOINT
  356. ),
  357. v.0.line,
  358. v.0.column,
  359. );
  360. }
  361. ret.push(Constant {
  362. name: k.to_string(),
  363. typ: VarType::EcFixedPoint,
  364. line: v.1.line,
  365. column: v.1.column,
  366. });
  367. }
  368. "EcFixedPointShort" => {
  369. if !VALID_ECFIXEDPOINTSHORT.contains(&v.0.token.as_str()) {
  370. self.error.abort(
  371. &format!(
  372. "`{}` is not a valid EcFixedPointShort constant. Supported: {:?}",
  373. v.0.token.as_str(),
  374. VALID_ECFIXEDPOINTSHORT
  375. ),
  376. v.0.line,
  377. v.0.column,
  378. );
  379. }
  380. ret.push(Constant {
  381. name: k.to_string(),
  382. typ: VarType::EcFixedPointShort,
  383. line: v.1.line,
  384. column: v.1.column,
  385. });
  386. }
  387. "EcFixedPointBase" => {
  388. if !VALID_ECFIXEDPOINTBASE.contains(&v.0.token.as_str()) {
  389. self.error.abort(
  390. &format!(
  391. "`{}` is not a valid EcFixedPointBase constant. Supported: {:?}",
  392. v.0.token.as_str(),
  393. VALID_ECFIXEDPOINTBASE
  394. ),
  395. v.0.line,
  396. v.0.column,
  397. );
  398. }
  399. ret.push(Constant {
  400. name: k.to_string(),
  401. typ: VarType::EcFixedPointBase,
  402. line: v.1.line,
  403. column: v.1.column,
  404. });
  405. }
  406. x => {
  407. self.error.abort(
  408. &format!("`{}` is an unsupported constant type.", x),
  409. v.1.line,
  410. v.1.column,
  411. );
  412. }
  413. }
  414. }
  415. ret
  416. }
  417. fn parse_ast_witness(&self, ast: &IndexMap<String, (Token, Token)>) -> Vec<Witness> {
  418. let mut ret = vec![];
  419. // k = name
  420. // v = (name, type)
  421. for (k, v) in ast {
  422. if &v.0.token != k {
  423. self.error.abort(
  424. &format!("Witness name `{}` doesn't match token `{}`.", v.0.token, k),
  425. v.0.line,
  426. v.0.column,
  427. );
  428. }
  429. if v.0.token_type != TokenType::Symbol {
  430. self.error.abort(
  431. &format!("Witness name `{}` is not a symbol.", v.0.token),
  432. v.0.line,
  433. v.0.column,
  434. );
  435. }
  436. if v.1.token_type != TokenType::Symbol {
  437. self.error.abort(
  438. &format!("Witness type `{}` is not a symbol.", v.1.token),
  439. v.1.line,
  440. v.1.column,
  441. );
  442. }
  443. // Valid witness types
  444. match v.1.token.as_str() {
  445. "EcPoint" => {
  446. ret.push(Witness {
  447. name: k.to_string(),
  448. typ: VarType::EcPoint,
  449. line: v.0.line,
  450. column: v.0.column,
  451. });
  452. }
  453. "EcNiPoint" => {
  454. ret.push(Witness {
  455. name: k.to_string(),
  456. typ: VarType::EcNiPoint,
  457. line: v.0.line,
  458. column: v.0.column,
  459. });
  460. }
  461. "Base" => {
  462. ret.push(Witness {
  463. name: k.to_string(),
  464. typ: VarType::Base,
  465. line: v.0.line,
  466. column: v.0.column,
  467. });
  468. }
  469. "Scalar" => {
  470. ret.push(Witness {
  471. name: k.to_string(),
  472. typ: VarType::Scalar,
  473. line: v.0.line,
  474. column: v.0.column,
  475. });
  476. }
  477. "MerklePath" => {
  478. ret.push(Witness {
  479. name: k.to_string(),
  480. typ: VarType::MerklePath,
  481. line: v.0.line,
  482. column: v.0.column,
  483. });
  484. }
  485. "Uint32" => {
  486. ret.push(Witness {
  487. name: k.to_string(),
  488. typ: VarType::Uint32,
  489. line: v.0.line,
  490. column: v.0.column,
  491. });
  492. }
  493. "Uint64" => {
  494. ret.push(Witness {
  495. name: k.to_string(),
  496. typ: VarType::Uint64,
  497. line: v.0.line,
  498. column: v.0.column,
  499. });
  500. }
  501. x => {
  502. self.error.abort(
  503. &format!("`{}` is an unsupported witness type.", x),
  504. v.1.line,
  505. v.1.column,
  506. );
  507. }
  508. }
  509. }
  510. ret
  511. }
  512. fn parse_ast_circuit(&self, statements: Vec<Vec<Token>>) -> Vec<Statement> {
  513. // The statement layouts/syntax in the language are as follows:
  514. //
  515. // C = poseidon_hash(pub_x, pub_y, value, token, serial, coin_blind);
  516. // | | | | |
  517. // V V V V V
  518. // variable opcode arg arg
  519. // assign
  520. //
  521. // constrain_instance(C);
  522. // | |
  523. // V V
  524. // opcode arg
  525. //
  526. // inner opcode arg
  527. // |
  528. // constrain_instance(ec_get_x(foo));
  529. // | |
  530. // V V
  531. // opcode arg as opcode
  532. //
  533. // In the latter, we want to support nested function calls, e.g.:
  534. //
  535. // constrain_instance(ec_get_x(token_commit));
  536. //
  537. // The inner call's result would still get pushed on the heap,
  538. // but it will not be accessible in any other scope.
  539. //
  540. // In certain opcodes, we also support literal types, and the
  541. // opcodes can return a variable type after running the operation.
  542. // e.g.
  543. // one = witness_base(1);
  544. // zero = witness_base(0);
  545. //
  546. // The literal type is used only in the function call's scope, but
  547. // the result is then accessible on the heap to be used by further
  548. // computation.
  549. //
  550. // Regarding multiple return values from opcodes, this is perhaps
  551. // not necessary for the current language scope, as this is a low
  552. // level representation. Note that it could be relatively easy to
  553. // modify the parsing logic to support that here. For now we'll
  554. // defer it, and if at some point we decide that the language is
  555. // too expressive and noisy, we'll consider having multiple return
  556. // types. It also very much depends on the type of functions/opcodes
  557. // that we want to support.
  558. // Vec of statements to return from this entire parsing operation.
  559. let mut ret = vec![];
  560. // Here, our statements tokens have been parsed and delimited by
  561. // semicolons (;) in the source file. This iterator contains each
  562. // of those statements as an array of tokens we then consume and
  563. // build the AST further.
  564. for statement in statements {
  565. if statement.is_empty() {
  566. continue
  567. }
  568. let (mut left_paren, mut right_paren) = (0, 0);
  569. for i in &statement {
  570. match i.token.as_str() {
  571. "(" => left_paren += 1,
  572. ")" => right_paren += 1,
  573. _ => {}
  574. }
  575. }
  576. if left_paren != right_paren || (left_paren == 0 || right_paren == 0) {
  577. self.error.abort(
  578. "Incorrect number of left and right parenthesis for statement.",
  579. statement[0].line,
  580. statement[0].column,
  581. );
  582. }
  583. // Peekable iterator so we can see tokens in advance
  584. // without consuming the iterator.
  585. let mut iter = statement.iter().peekable();
  586. // Dummy statement that we'll hopefully fill now.
  587. let mut stmt = Statement::default();
  588. let mut parsing = false;
  589. while let Some(token) = iter.next() {
  590. if !parsing {
  591. // TODO: MAKE SURE IT'S A SYMBOL
  592. // This logic must be changed if we want to support
  593. // multiple return values.
  594. if let Some(next_token) = iter.peek() {
  595. if next_token.token_type == TokenType::Assign {
  596. stmt.line = token.line;
  597. stmt.typ = StatementType::Assign;
  598. stmt.rhs = vec![];
  599. stmt.lhs = Some(Variable {
  600. name: token.token.clone(),
  601. typ: VarType::Dummy,
  602. line: token.line,
  603. column: token.column,
  604. });
  605. // Skip over the `=` token.
  606. iter.next();
  607. parsing = true;
  608. continue
  609. }
  610. if next_token.token_type == TokenType::LeftParen {
  611. stmt.line = token.line;
  612. stmt.typ = StatementType::Call;
  613. stmt.rhs = vec![];
  614. stmt.lhs = None;
  615. parsing = true;
  616. }
  617. if !parsing {
  618. self.error.abort(
  619. &format!("Illegal token `{}`.", next_token.token),
  620. next_token.line,
  621. next_token.column,
  622. );
  623. }
  624. }
  625. }
  626. // If parsing == true, we now know if we're making a variable
  627. // assignment or a function call without a return value.
  628. // Let's dig deeper to see what the statement's call is, and
  629. // what it contains as arguments. With this we'll fill `rhs`.
  630. // The arguments could be literal types, other variables, or
  631. // even nested function calls.
  632. // For now, we don't care if the params are valid, as this is
  633. // the job of the semantic analyzer which comes after the
  634. // parsing module.
  635. // The assumption here is that the current token is a function
  636. // call, so we check if it's legit and start digging.
  637. let func_name = token.token.as_str();
  638. // TODO: MAKE SURE IT'S A SYMBOL
  639. if let Some(op) = Opcode::from_name(func_name) {
  640. let rhs = self.parse_function_call(token, &mut iter);
  641. stmt.opcode = op;
  642. stmt.rhs = rhs;
  643. } else {
  644. self.error.abort(
  645. &format!("Unimplemented opcode `{}`.", func_name),
  646. token.line,
  647. token.column,
  648. );
  649. }
  650. ret.push(stmt);
  651. stmt = Statement::default();
  652. }
  653. }
  654. ret
  655. }
  656. fn parse_function_call(
  657. &self,
  658. token: &Token,
  659. iter: &mut Peekable<std::slice::Iter<'_, Token>>,
  660. ) -> Vec<Arg> {
  661. if let Some(next_token) = iter.peek() {
  662. if next_token.token_type != TokenType::LeftParen {
  663. self.error.abort(
  664. "Invalid function call opening. Must start with a '('.",
  665. next_token.line,
  666. next_token.column,
  667. );
  668. }
  669. // Skip the opening parenthesis
  670. iter.next();
  671. } else {
  672. self.error.abort("Premature ending of statement.", token.line, token.column);
  673. }
  674. let mut ret = vec![];
  675. // The next element in the iter now hopefully contains an opcode
  676. // argument. If it's another opcode, we'll recurse into this
  677. // function's logic.
  678. // Otherwise, we look for variable and literal types.
  679. while let Some(arg) = iter.next() {
  680. // ============================
  681. // Parse a nested function call
  682. // ============================
  683. if let Some(op_inner) = Opcode::from_name(&arg.token) {
  684. if let Some(paren) = iter.peek() {
  685. if paren.token_type != TokenType::LeftParen {
  686. self.error.abort(
  687. "Invalid function call opening. Must start with a '('.",
  688. paren.line,
  689. paren.column,
  690. );
  691. }
  692. // Recurse this function to get the params of the nested one.
  693. let args = self.parse_function_call(arg, iter);
  694. // Then we assign a "fake" variable that serves as a heap
  695. // reference.
  696. let var = Variable {
  697. name: format!("_op_inner_{}_{}", arg.line, arg.column),
  698. typ: VarType::Dummy,
  699. line: arg.line,
  700. column: arg.column,
  701. };
  702. let arg = Arg::Func(Statement {
  703. typ: StatementType::Assign,
  704. opcode: op_inner,
  705. lhs: Some(var),
  706. rhs: args,
  707. line: arg.line,
  708. });
  709. ret.push(arg);
  710. continue
  711. }
  712. self.error.abort(
  713. "Missing tokens in statement, there's a syntax error here.",
  714. arg.line,
  715. arg.column,
  716. );
  717. }
  718. // ==========================================
  719. // Parse normal argument, not a function call
  720. // ==========================================
  721. if let Some(sep) = iter.next() {
  722. // See if we have a variable or a literal type.
  723. match arg.token_type {
  724. TokenType::Symbol => ret.push(Arg::Var(Variable {
  725. name: arg.token.clone(),
  726. typ: VarType::Dummy,
  727. line: arg.line,
  728. column: arg.column,
  729. })),
  730. TokenType::Number => {
  731. // Check if we can actually convert this into a number.
  732. match arg.token.parse::<u64>() {
  733. Ok(_) => {}
  734. Err(e) => {
  735. self.error.abort(
  736. &format!("Failed to convert literal into u64: {}", e),
  737. arg.line,
  738. arg.column,
  739. );
  740. }
  741. };
  742. ret.push(Arg::Lit(Literal {
  743. name: arg.token.clone(),
  744. typ: LitType::Uint64,
  745. line: arg.line,
  746. column: arg.column,
  747. }))
  748. }
  749. TokenType::RightParen => {
  750. if let Some(comma) = iter.peek() {
  751. if comma.token_type == TokenType::Comma {
  752. iter.next();
  753. }
  754. }
  755. break
  756. }
  757. x => unimplemented!("{:#?}", x),
  758. };
  759. if sep.token_type == TokenType::RightParen {
  760. if let Some(comma) = iter.peek() {
  761. if comma.token_type == TokenType::Comma {
  762. iter.next();
  763. }
  764. }
  765. // Reached end of args
  766. break
  767. }
  768. if sep.token_type != TokenType::Comma {
  769. self.error.abort(
  770. "Argument separator is not a comma (`,`)",
  771. sep.line,
  772. sep.column,
  773. );
  774. }
  775. }
  776. }
  777. ret
  778. }
  779. }