grammar.lalrpop 4.2 KB

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