grammar.lalrpop 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. use crate::ast::*;
  2. use crate::lexer::*;
  3. grammar<'input>(ast: &mut ASTArena, file: FileRef);
  4. extern {
  5. type Location = usize;
  6. type Error = LexerError;
  7. enum Token<'input> {
  8. "<" => Token::LAngle,
  9. ">" => Token::RAngle,
  10. "(" => Token::LPar,
  11. ")" => Token::RPar,
  12. "{" => Token::LCurl,
  13. "}" => Token::RCurl,
  14. "[" => Token::LBrac,
  15. "]" => Token::RBrac,
  16. "|" => Token::Pipe,
  17. ":" => Token::Colon,
  18. "," => Token::Comma,
  19. ";" => Token::Semi,
  20. "." => Token::Dot,
  21. "_" => Token::Underscore,
  22. ".." => Token::DotDot,
  23. "=>" => Token::Arrow,
  24. ":=" => Token::Assn,
  25. "::=" => Token::LitAssn,
  26. "puts" => Token::Puts,
  27. "case" => Token::Case,
  28. "let" => Token::Let,
  29. "in" => Token::In,
  30. "fix" => Token::Fix,
  31. "var" => Token::Var(<&'input str>),
  32. "atom" => Token::Atom(<&'input str>),
  33. "num" => Token::Num(<i64>),
  34. "str" => Token::Str(<String>)
  35. }
  36. }
  37. pub Stmts: Vec<Stmt> = {
  38. <mut stmts:(<Stmt> ";")*> <stmt:Stmt?> => match stmt {
  39. None => stmts,
  40. Some(stmt) => {
  41. stmts.push(stmt);
  42. stmts
  43. }
  44. },
  45. };
  46. pub Stmt: Stmt = {
  47. "puts" <Located<Expr>> => Stmt::Puts(<>),
  48. <fixed:"fix"?> <name:Name> ":=" <expr:Located<Expr>> => Stmt::Assn(fixed.is_some(), name, expr),
  49. <fixed:"fix"?> <name:Name> "::=" <strs:(<Located<AtomLit>>)*> =>
  50. Stmt::LitAssn(
  51. fixed.is_some(),
  52. name,
  53. strs,
  54. ),
  55. "fix" <Name> => Stmt::Fix(<>),
  56. };
  57. pub AtomLit: string_interner::DefaultSymbol = {
  58. "var" => ast.add_string(<>),
  59. "atom" => ast.add_string(<>),
  60. };
  61. pub Name: Name = {
  62. <start: @L> <str:"var"> <end: @R> =>
  63. Located::new(ast.add_string(str), file, Span { start: start as u32, end: end as u32 }),
  64. };
  65. pub ExprRef = Located<Expr>;
  66. pub Expr: ExprId = {
  67. <mut ts:(<Choice> "|")*> <t:Choice> => {
  68. if ts.len() == 0 {
  69. t.value.item
  70. } else {
  71. ts.push(t);
  72. ast.add_expr(Expr::Chc(ts))
  73. }
  74. }
  75. };
  76. pub Choice: Choice = {
  77. <weight:"num"> ":" <value:Located<Term>> => Choice {
  78. weight: Some(weight),
  79. value
  80. },
  81. <value:Located<Term>> => Choice {
  82. weight: None,
  83. value
  84. }
  85. };
  86. pub Term: ExprId = {
  87. <mut bs:(<Located<Branch>>)*> => {
  88. match bs.len() {
  89. 0 => ast.expr_nil(),
  90. 1 => bs.pop().unwrap().item,
  91. _ => ast.add_expr(Expr::Cat(<>)),
  92. }
  93. }
  94. };
  95. pub Branch: ExprId = {
  96. // <l:Located<Branch>> "." <r:Located<Subbranch>> => ast.add_expr(Expr::Ap(l, r)),
  97. <l:Located<Branch>> "[" <mut rs:Located<(<Expr> ",")>*> <r:Located<Expr>> "]" => {
  98. rs.push(r);
  99. ast.add_expr(Expr::Ap(l, rs))
  100. },
  101. <Subbranch> => <>,
  102. };
  103. pub Subbranch: ExprId = {
  104. <l:Located<Subbranch>> ".." <r:Located<Leaf>> => ast.add_expr(Expr::Range(l, r)),
  105. <Leaf> => <>,
  106. }
  107. pub Leaf: ExprId = {
  108. <Literal> => ast.add_expr(Expr::Lit(<>)),
  109. <Name> => ast.add_expr(Expr::Var(<>)),
  110. "<" <mut es:(<Located<Expr>> ",")*> <e:Located<Expr>> ">" => {
  111. if es.len() == 0 && e.item.nil() {
  112. ast.add_expr(Expr::Tup(Vec::new()))
  113. } else {
  114. es.push(e);
  115. ast.add_expr(Expr::Tup(es))
  116. }
  117. },
  118. "let" <fixed:"fix"?> <name:Name> ":=" <e1:Located<Expr>> "in" "{" <e2:Located<Expr>> "}" =>
  119. ast.add_expr(Expr::Let(fixed.is_some(), name, e1, e2)),
  120. "{" <cs:FunCases> "}" =>
  121. ast.add_expr(Expr::Fun(cs)),
  122. "case" <e:Located<Expr>> "in" "{" <cs:Cases> "}" =>
  123. ast.add_expr(Expr::Case(e, cs)),
  124. "(" <e:Expr> ")" => e,
  125. };
  126. pub Cases: Vec<Case> = {
  127. <mut cs:(<Case> ";")*> <c:Case> => {
  128. cs.push(c);
  129. cs
  130. }
  131. };
  132. pub Case: Case = {
  133. <pat:Pat> "=>" <expr:Located<Expr>> =>
  134. Case { pats: vec![pat], expr }
  135. };
  136. pub FunCases: Vec<Case> = {
  137. <mut cs:(<FunCase> ";")*> <c:FunCase> => {
  138. cs.push(c);
  139. cs
  140. }
  141. };
  142. pub FunCase: Case = {
  143. "[" <mut pats:(<Pat> ",")*> <pat:Pat> "]" "=>" <expr:Located<Expr>> => {
  144. pats.push(pat);
  145. Case { pats, expr }
  146. }
  147. };
  148. pub Pat: Pat = {
  149. "_" => Pat::Wildcard,
  150. <Literal> => Pat::Lit(<>),
  151. <Name> => Pat::Var(<>),
  152. "<" ">" => Pat::Tup(Vec::new()),
  153. "<" <mut ps:(<Pat> ",")*> <p:Pat> ">" => {
  154. ps.push(p);
  155. Pat::Tup(ps)
  156. },
  157. };
  158. pub Literal: Literal = {
  159. "num" => Literal::Num(<>),
  160. "str" => Literal::Str(<>),
  161. <atom:Located<"atom">> => Literal::Atom(atom.map(|x| ast.add_string(x))),
  162. };
  163. #[inline]
  164. Located<T>: Located<T> = {
  165. <start: @L> <data: T> <end: @R> =>
  166. Located::new(data, file, Span { start: start as u32, end: end as u32 }),
  167. };