parser.rs 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678
  1. use std::{iter::Peekable, str::Chars};
  2. use fxhash::FxBuildHasher;
  3. use indexmap::IndexMap;
  4. use itertools::Itertools;
  5. use super::{
  6. ast::{
  7. Constant, Constants, Statement, StatementType, Statements, UnparsedConstants,
  8. UnparsedWitnesses, Variable, Witness, Witnesses,
  9. },
  10. error::ErrorEmitter,
  11. lexer::{Token, TokenType},
  12. opcode::Opcode,
  13. types::Type,
  14. };
  15. pub struct Parser {
  16. tokens: Vec<Token>,
  17. error: ErrorEmitter,
  18. }
  19. impl Parser {
  20. pub fn new(filename: &str, source: Chars, tokens: Vec<Token>) -> Self {
  21. // For nice error reporting, we'll load everything into a string
  22. // vector so we have references to lines.
  23. let lines: Vec<String> = source.as_str().lines().map(|x| x.to_string()).collect();
  24. let error = ErrorEmitter::new("Parser", filename, lines);
  25. Parser { tokens, error }
  26. }
  27. pub fn parse(self) -> (Constants, Witnesses, Statements) {
  28. // We use these to keep state when iterating
  29. let mut declaring_constant = false;
  30. let mut declaring_contract = false;
  31. let mut declaring_circuit = false;
  32. let mut constant_tokens = vec![];
  33. let mut contract_tokens = vec![];
  34. let mut circuit_tokens = vec![];
  35. // Single statement in the circuit
  36. let mut circuit_statement = vec![];
  37. // All the circuit statements
  38. let mut circuit_statements = vec![];
  39. let mut ast = IndexMap::with_hasher(FxBuildHasher::default());
  40. let mut namespace = String::new();
  41. let mut ast_inner = IndexMap::new();
  42. let mut namespace_found = false; // Nasty
  43. let mut iter = self.tokens.iter();
  44. while let Some(t) = iter.next() {
  45. // Start by declaring a section
  46. if !declaring_constant && !declaring_contract && !declaring_circuit {
  47. if t.token_type != TokenType::Symbol {
  48. // TODO: Revisit
  49. // TODO: Visit this again when we are allowing imports
  50. unimplemented!();
  51. }
  52. // The sections we must be declaring in our source code
  53. match t.token.as_str() {
  54. "constant" => {
  55. declaring_constant = true;
  56. // Eat all the tokens within the `constant` section
  57. for inner in iter.by_ref() {
  58. constant_tokens.push(inner.clone());
  59. if inner.token_type == TokenType::RightBrace {
  60. break
  61. }
  62. }
  63. }
  64. "contract" => {
  65. declaring_contract = true;
  66. // Eat all the tokens within the `contract` section
  67. for inner in iter.by_ref() {
  68. contract_tokens.push(inner.clone());
  69. if inner.token_type == TokenType::RightBrace {
  70. break
  71. }
  72. }
  73. }
  74. "circuit" => {
  75. declaring_circuit = true;
  76. // Eat all the tokens within the `circuit` section
  77. // TODO: Revisit when we support if/else and loops
  78. for inner in iter.by_ref() {
  79. circuit_tokens.push(inner.clone());
  80. if inner.token_type == TokenType::RightBrace {
  81. break
  82. }
  83. }
  84. }
  85. x => {
  86. self.error.emit(format!("Unknown `{}` proof section", x), t.line, t.column)
  87. }
  88. }
  89. }
  90. // We shouldn't be reaching these states
  91. if declaring_constant && (declaring_contract || declaring_circuit) {
  92. unreachable!()
  93. }
  94. if declaring_contract && (declaring_constant || declaring_circuit) {
  95. unreachable!()
  96. }
  97. if declaring_circuit && (declaring_constant || declaring_contract) {
  98. unreachable!()
  99. }
  100. // Now go through the token vectors and work it through
  101. if declaring_constant {
  102. self.check_section_structure("constant", constant_tokens.clone());
  103. // TODO: Do we need this?
  104. if namespace_found && namespace != constant_tokens[0].token {
  105. self.error.emit(
  106. format!(
  107. "Found `{}` namespace. Expected `{}`.",
  108. constant_tokens[0].token, namespace
  109. ),
  110. constant_tokens[0].line,
  111. constant_tokens[0].column,
  112. );
  113. } else {
  114. namespace = constant_tokens[0].token.clone();
  115. namespace_found = true;
  116. }
  117. let constants_cloned = constant_tokens.clone();
  118. let mut constants_map = IndexMap::new();
  119. // This is everything between the braces: { .. }
  120. let mut constants_inner = constants_cloned[2..constant_tokens.len() - 1].iter();
  121. while let Some((typ, name, comma)) = constants_inner.next_tuple() {
  122. if comma.token_type != TokenType::Comma {
  123. self.error.emit(
  124. "Separator is not a comma".to_string(),
  125. comma.line,
  126. comma.column,
  127. );
  128. }
  129. if constants_map.contains_key(name.token.as_str()) {
  130. self.error.emit(
  131. format!(
  132. "Section `constant` already contains the token `{}`.",
  133. &name.token
  134. ),
  135. name.line,
  136. name.column,
  137. );
  138. }
  139. constants_map.insert(name.token.clone(), (name.clone(), typ.clone()));
  140. }
  141. ast_inner.insert("constant".to_string(), constants_map);
  142. declaring_constant = false;
  143. }
  144. if declaring_contract {
  145. self.check_section_structure("contract", contract_tokens.clone());
  146. // TODO: Do we need this?
  147. if namespace_found && namespace != contract_tokens[0].token {
  148. self.error.emit(
  149. format!(
  150. "Found `{}` namespace. Expected `{}`.",
  151. contract_tokens[0].token, namespace
  152. ),
  153. contract_tokens[0].line,
  154. contract_tokens[0].column,
  155. );
  156. } else {
  157. namespace = contract_tokens[0].token.clone();
  158. namespace_found = true;
  159. }
  160. let contract_cloned = contract_tokens.clone();
  161. let mut contract_map = IndexMap::new();
  162. // This is everything between the braces: { .. }
  163. let mut contract_inner = contract_cloned[2..contract_tokens.len() - 1].iter();
  164. while let Some((typ, name, comma)) = contract_inner.next_tuple() {
  165. if comma.token_type != TokenType::Comma {
  166. self.error.emit(
  167. "Separator is not a comma".to_string(),
  168. comma.line,
  169. comma.column,
  170. );
  171. }
  172. if contract_map.contains_key(name.token.as_str()) {
  173. self.error.emit(
  174. format!(
  175. "Section `contract` already contains the token `{}`.",
  176. &name.token
  177. ),
  178. name.line,
  179. name.column,
  180. );
  181. }
  182. contract_map.insert(name.token.clone(), (name.clone(), typ.clone()));
  183. }
  184. ast_inner.insert("contract".to_string(), contract_map);
  185. declaring_contract = false;
  186. }
  187. if declaring_circuit {
  188. self.check_section_structure("circuit", contract_tokens.clone());
  189. if circuit_tokens[circuit_tokens.len() - 2].token_type != TokenType::Semicolon {
  190. self.error.emit(
  191. "Circuit section does not end with a semicolon. Would never finish parsing.".to_string(),
  192. circuit_tokens[circuit_tokens.len()-2].line,
  193. circuit_tokens[circuit_tokens.len()-2].column
  194. );
  195. }
  196. // TODO: Do we need this?
  197. if namespace_found && namespace != circuit_tokens[0].token {
  198. self.error.emit(
  199. format!(
  200. "Found `{}` namespace. Expected `{}`.",
  201. circuit_tokens[0].token, namespace
  202. ),
  203. circuit_tokens[0].line,
  204. circuit_tokens[0].column,
  205. );
  206. } else {
  207. namespace = circuit_tokens[0].token.clone();
  208. namespace_found = true;
  209. }
  210. for i in circuit_tokens.clone()[2..circuit_tokens.len() - 1].iter() {
  211. if i.token_type == TokenType::Semicolon {
  212. circuit_statements.push(circuit_statement.clone());
  213. // println!("{:?}", circuit_statement);
  214. circuit_statement = vec![];
  215. continue
  216. }
  217. circuit_statement.push(i.clone());
  218. }
  219. declaring_circuit = false;
  220. }
  221. }
  222. ast.insert(namespace.clone(), ast_inner);
  223. // TODO: Verify there are both constant/contract sections
  224. // TODO: Verify there is a circuit section
  225. // TODO: Check that there are no duplicate names in constants, contract
  226. // and circuit assignments
  227. // Clean up the `constant` section
  228. let c = ast.get(&namespace).unwrap().get("constant").unwrap();
  229. let constants = self.parse_ast_constants(c);
  230. // Clean up the `contract` section
  231. let c = ast.get(&namespace).unwrap().get("contract").unwrap();
  232. let witnesses = self.parse_ast_contract(c);
  233. // Clean up the `circuit` section
  234. let stmt = self.parse_ast_circuit(circuit_statements);
  235. (constants, witnesses, stmt)
  236. }
  237. fn check_section_structure(&self, section: &str, tokens: Vec<Token>) {
  238. if tokens[0].token_type != TokenType::String {
  239. self.error.emit(
  240. format!("{} section declaration must start with a naming string.", section),
  241. tokens[0].line,
  242. tokens[0].column,
  243. );
  244. }
  245. if tokens[1].token_type != TokenType::LeftBrace {
  246. self.error.emit(
  247. format!(
  248. "{} section opening is not correct. Must be opened with a left brace `{{`",
  249. section
  250. ),
  251. tokens[0].line,
  252. tokens[0].column,
  253. );
  254. }
  255. if tokens[tokens.len() - 1].token_type != TokenType::RightBrace {
  256. self.error.emit(
  257. format!(
  258. "{} section closing is not correct. Must be closed with a right brace `}}`",
  259. section
  260. ),
  261. tokens[0].line,
  262. tokens[0].column,
  263. );
  264. }
  265. if (section == "constant" || section == "contract") &&
  266. tokens[2..tokens.len() - 1].len() % 3 != 0
  267. {
  268. self.error.emit(
  269. format!(
  270. "Invalid number of elements in `{}` section. Must be pairs of `type:name` separated with a comma `,`",
  271. section
  272. ),
  273. tokens[0].line,
  274. tokens[0].column,
  275. );
  276. }
  277. }
  278. fn parse_ast_constants(&self, ast: &UnparsedConstants) -> Constants {
  279. let mut ret = vec![];
  280. for (k, v) in ast {
  281. if &v.0.token != k {
  282. self.error.emit(
  283. format!("Constant name `{}` doesn't match token `{}`.", v.0.token, k),
  284. v.0.line,
  285. v.0.column,
  286. );
  287. }
  288. if v.0.token_type != TokenType::Symbol {
  289. self.error.emit(
  290. format!("Constant name `{}` is not a symbol.", v.0.token),
  291. v.0.line,
  292. v.0.column,
  293. );
  294. }
  295. if v.1.token_type != TokenType::Symbol {
  296. self.error.emit(
  297. format!("Constant type `{}` is not a symbol.", v.1.token),
  298. v.1.line,
  299. v.1.column,
  300. );
  301. }
  302. match v.1.token.as_str() {
  303. "EcFixedPoint" => {
  304. ret.push(Constant {
  305. name: k.to_string(),
  306. typ: Type::EcFixedPoint,
  307. line: v.0.line,
  308. column: v.0.column,
  309. });
  310. }
  311. "EcFixedPointShort" => {
  312. ret.push(Constant {
  313. name: k.to_string(),
  314. typ: Type::EcFixedPointShort,
  315. line: v.0.line,
  316. column: v.0.column,
  317. });
  318. }
  319. "EcFixedPointBase" => {
  320. ret.push(Constant {
  321. name: k.to_string(),
  322. typ: Type::EcFixedPointBase,
  323. line: v.0.line,
  324. column: v.0.column,
  325. });
  326. }
  327. x => {
  328. self.error.emit(
  329. format!("`{}` is an illegal constant type", x),
  330. v.1.line,
  331. v.1.column,
  332. );
  333. }
  334. }
  335. }
  336. ret
  337. }
  338. fn parse_ast_contract(&self, ast: &UnparsedWitnesses) -> Witnesses {
  339. let mut ret = vec![];
  340. for (k, v) in ast {
  341. if &v.0.token != k {
  342. self.error.emit(
  343. format!("Witness name `{}` doesn't match token `{}`.", v.0.token, k),
  344. v.0.line,
  345. v.0.column,
  346. );
  347. }
  348. if v.0.token_type != TokenType::Symbol {
  349. self.error.emit(
  350. format!("Witness name `{}` is not a symbol.", v.0.token),
  351. v.0.line,
  352. v.0.column,
  353. );
  354. }
  355. if v.1.token_type != TokenType::Symbol {
  356. self.error.emit(
  357. format!("Witness type `{}` is not a symbol.", v.1.token),
  358. v.1.line,
  359. v.1.column,
  360. );
  361. }
  362. match v.1.token.as_str() {
  363. "Base" => {
  364. ret.push(Witness {
  365. name: k.to_string(),
  366. typ: Type::Base,
  367. line: v.0.line,
  368. column: v.0.column,
  369. });
  370. }
  371. "Scalar" => {
  372. ret.push(Witness {
  373. name: k.to_string(),
  374. typ: Type::Scalar,
  375. line: v.0.line,
  376. column: v.0.column,
  377. });
  378. }
  379. "MerklePath" => {
  380. ret.push(Witness {
  381. name: k.to_string(),
  382. typ: Type::MerklePath,
  383. line: v.0.line,
  384. column: v.0.column,
  385. });
  386. }
  387. "Uint32" => {
  388. ret.push(Witness {
  389. name: k.to_string(),
  390. typ: Type::Uint32,
  391. line: v.0.line,
  392. column: v.0.column,
  393. });
  394. }
  395. "Uint64" => {
  396. ret.push(Witness {
  397. name: k.to_string(),
  398. typ: Type::Uint64,
  399. line: v.0.line,
  400. column: v.0.column,
  401. });
  402. }
  403. x => {
  404. self.error.emit(
  405. format!("`{}` is an illegal witness type", x),
  406. v.1.line,
  407. v.1.column,
  408. );
  409. }
  410. }
  411. }
  412. ret
  413. }
  414. fn parse_ast_circuit(&self, statements: Vec<Vec<Token>>) -> Vec<Statement> {
  415. let mut stmts = vec![];
  416. for statement in statements {
  417. let (mut left_paren, mut right_paren) = (0, 0);
  418. for i in &statement {
  419. match i.token.as_str() {
  420. "(" => left_paren += 1,
  421. ")" => right_paren += 1,
  422. _ => {}
  423. }
  424. }
  425. if left_paren != right_paren {
  426. self.error.emit(
  427. "Incorrect number of left and right parenthesis for statement.".to_string(),
  428. statement[0].line,
  429. statement[0].column,
  430. );
  431. }
  432. // C = poseidon_hash(pub_x, pub_y, value, token, serial, coin_blind)
  433. // | | | |
  434. // V V V V
  435. // variable opcode args
  436. // assign
  437. // constrain_instance(C)
  438. // | |
  439. // V V
  440. // opcode args
  441. let mut iter = statement.iter().peekable();
  442. let mut stmt = Statement::default();
  443. let mut parsing = false;
  444. while let Some(token) = iter.next() {
  445. if !parsing {
  446. if let Some(next_token) = iter.peek() {
  447. if next_token.token_type == TokenType::Assign {
  448. stmt.typ = StatementType::Assignment;
  449. stmt.variable = Some(Variable {
  450. name: token.token.clone(),
  451. typ: Type::Dummy,
  452. line: token.line,
  453. column: token.column,
  454. });
  455. // Skip over the `=` token.
  456. iter.next();
  457. parsing = true;
  458. continue
  459. }
  460. if next_token.token_type == TokenType::LeftParen {
  461. stmt.typ = StatementType::Call;
  462. stmt.variable = None;
  463. parsing = true;
  464. }
  465. if !parsing {
  466. self.error.emit(
  467. format!("Illegal token `{}`", next_token.token),
  468. next_token.line,
  469. next_token.column,
  470. );
  471. }
  472. }
  473. }
  474. // This matching could be moved over into the semantic analyzer.
  475. // We could just parse any kind of symbol here, and then do lookup
  476. // from the analyzer, to see if the calls actually exist and are
  477. // supported.
  478. // But for now, we'll just leave it here and expand later.
  479. let func_name = token.token.as_str();
  480. macro_rules! parse_func {
  481. ($opcode: expr) => {
  482. stmt.args = self.parse_function_call(token, &mut iter);
  483. stmt.opcode = $opcode;
  484. stmt.line = token.line;
  485. stmts.push(stmt.clone());
  486. parsing = false;
  487. continue
  488. };
  489. }
  490. match func_name {
  491. "poseidon_hash" => {
  492. parse_func!(Opcode::PoseidonHash);
  493. }
  494. "constrain_instance" => {
  495. parse_func!(Opcode::ConstrainInstance);
  496. }
  497. "calculate_merkle_root" => {
  498. parse_func!(Opcode::CalculateMerkleRoot);
  499. }
  500. "ec_mul_short" => {
  501. parse_func!(Opcode::EcMulShort);
  502. }
  503. "ec_mul_base" => {
  504. parse_func!(Opcode::EcMulBase);
  505. }
  506. "ec_mul" => {
  507. parse_func!(Opcode::EcMul);
  508. }
  509. "ec_get_x" => {
  510. parse_func!(Opcode::EcGetX);
  511. }
  512. "ec_get_y" => {
  513. parse_func!(Opcode::EcGetY);
  514. }
  515. "ec_add" => {
  516. parse_func!(Opcode::EcAdd);
  517. }
  518. "base_add" => {
  519. parse_func!(Opcode::BaseAdd);
  520. }
  521. "base_mul" => {
  522. parse_func!(Opcode::BaseMul);
  523. }
  524. "base_sub" => {
  525. parse_func!(Opcode::BaseSub);
  526. }
  527. "greater_than" => {
  528. parse_func!(Opcode::GreaterThan);
  529. }
  530. x => {
  531. self.error.emit(
  532. format!("Unimplemented function call `{}`", x),
  533. token.line,
  534. token.column,
  535. );
  536. }
  537. }
  538. }
  539. }
  540. // println!("{:#?}", stmts);
  541. stmts
  542. }
  543. fn parse_function_call(
  544. &self,
  545. token: &Token,
  546. iter: &mut Peekable<std::slice::Iter<'_, Token>>,
  547. ) -> Vec<Variable> {
  548. if let Some(next_token) = iter.peek() {
  549. if next_token.token_type != TokenType::LeftParen {
  550. self.error.emit(
  551. "Invalid function call opening. Must start with a `(`".to_string(),
  552. next_token.line,
  553. next_token.column,
  554. );
  555. }
  556. // Skip the opening parenthesis
  557. iter.next();
  558. } else {
  559. self.error.emit("Premature ending of statement".to_string(), token.line, token.column);
  560. }
  561. // Eat up function arguments
  562. let mut args = vec![];
  563. while let Some((arg, sep)) = iter.next_tuple() {
  564. args.push(Variable {
  565. name: arg.token.clone(),
  566. typ: Type::Dummy,
  567. line: arg.line,
  568. column: arg.column,
  569. });
  570. if sep.token_type == TokenType::RightParen {
  571. // Reached end of args
  572. break
  573. }
  574. if sep.token_type != TokenType::Comma {
  575. self.error.emit(
  576. "Argument separator is not a comma (`,`)".to_string(),
  577. sep.line,
  578. sep.column,
  579. );
  580. }
  581. }
  582. args
  583. }
  584. }