Skip to content

Instantly share code, notes, and snippets.

@nikomatsakis
Last active February 19, 2020 00:58
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save nikomatsakis/5fa3bd8291841b853144 to your computer and use it in GitHub Desktop.
Save nikomatsakis/5fa3bd8291841b853144 to your computer and use it in GitHub Desktop.
use compiler::parser::tok::{self, Tok};
use compiler::ast::*;
grammar<'input>["LALR(1)"];
extern {
type Location = usize;
type Error = tok::Error;
enum Tok<'input> {
"if" => Tok::If,
"else" => Tok::Else,
"var" => Tok::Var,
"true" => Tok::True,
"false" => Tok::False,
"(" => Tok::LeftParen,
")" => Tok::RightParen,
"{" => Tok::LeftParen,
"}" => Tok::RightParen,
"<" => Tok::LessThan,
">" => Tok::GreaterThan,
"<=" => Tok::LessThanEqual,
">=" => Tok::GreaterThanEqual,
"=" => Tok::Equals,
"==" => Tok::EqualsEquals,
"!" => Tok::Bang,
"!=" => Tok::BangEquals,
"+" => Tok::Plus,
"-" => Tok::Minus,
"*" => Tok::Star,
"/" => Tok::Slash,
"%" => Tok::Percent,
"," => Tok::Comma,
"Number" => Tok::Number(<f64>),
"String" => Tok::String(<&'input str>),
"Ident" => Tok::Ident(<&'input str>),
}
}
pub Program: Program = {
<lo:@L> <exprs:Expression*> <hi:@R> => Program { span: span(lo, hi), exprs: exprs }
};
Node<T>: Node<T> = <lo:@L> <inner:T> <hi:@R> => node(span(lo, hi), inner);
Expression = ExpressionRestr<"I">; // include ifs by default
ExpressionRestr<I> = Node<ExpressionType1<I>>;
ExpressionType1<I>: ExpressionType = {
"var" <name:Ident> <value:("=" <ExpressionRestr<I>>)?> => ExpressionType::Decl { name: name, value: value.map(Box::new) },
"(" <Expression> ")" => ExpressionType::Paren { body: Box::new(<>) },
"{" <Expression*> "}" => ExpressionType::Block { body: <> },
"if" "(" <cond:Expression> ")" <result:ExpressionRestr<"I">> if I != "" =>
ExpressionType::If { cond: Box::new(cond), result: Box::new(result), else_: Box::new(None) },
"if" "(" <cond:Expression> ")" <result:ExpressionRestr<"">> <else_:("else" <ExpressionRestr<I>>)> =>
ExpressionType::If { cond: Box::new(cond), result: Box::new(result), else_: else_.map(Some).map(Box::new) },
<Ident> => ExpressionType::Variable { name: <> },
<Literal> => ExpressionType::Literal { lit: <> },
};
Literal = Node<LiteralType>;
LiteralType: LiteralType = {
<num:"Number"> => LiteralType::Number(num),
"true" => LiteralType::Boolean(true),
"false" => LiteralType::Boolean(true),
<str:"String"> => LiteralType::String(str.to_owned()),
};
Ident = Node<String>;
String: String = <"Ident"> => <>.to_owned();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment