#[macro_use]
use corollary_support::*;
pub mod builtin;
pub mod lexer;
pub mod parser;
pub mod tokens;
use std::mem;
use std::rc::Rc;
use std::boxed::FnBox;
use std::iter::FromIterator;
use std::collections::HashSet;
use either::Either;
pub use parser::parser::Parser;
use parser::parser::translUnitP;
use parser::builtin::*;
use parser::tokens::{CToken, CTokEof, movePosLenOfTok};
use syntax::ast::*;
use data::name::{Name, NameSupply, new_name_supply};
use data::ident::Ident;
use data::r_list::{Reversed, RList, snoc};
use data::node::{NodeInfo, CNode};
use data::position::{Position, Pos};
use data::input_stream::InputStream;
#[derive(Debug)]
pub struct ParseError(pub (Vec<String>, Position));
impl ParseError {
pub fn new(pos: Position, msgs: Vec<String>) -> ParseError {
ParseError((msgs, pos))
}
}
pub struct PState {
curPos: Position,
curInput: InputStream,
prevToken: Option<CToken>,
savedToken: Option<CToken>,
nameSupply: NameSupply,
tyidents: HashSet<Ident>,
scopes: Vec<HashSet<Ident>>,
}
pub fn execParser<F, T>(input: InputStream, pos: Position, builtins: Vec<Ident>, names: NameSupply,
do_parse: F) -> Result<(T, NameSupply), ParseError>
where F: FnOnce(&mut Parser) -> Result<T, ParseError>
{
let initial_state = PState {
curPos: pos,
curInput: input,
prevToken: None,
savedToken: None,
nameSupply: names,
tyidents: HashSet::from_iter(builtins),
scopes: vec![],
};
let (state, res) = Parser::exec(initial_state, do_parse)?;
Ok((res, state.nameSupply))
}
impl Parser {
pub fn getNewName(&mut self) -> Name {
self.user.nameSupply.next().unwrap()
}
pub fn setPos(&mut self, pos: Position) {
self.user.curPos = pos;
}
pub fn getPos(&self) -> Position { self.user.curPos.clone()
}
pub fn addTypedef(&mut self, ident: Ident) {
self.user.tyidents.insert(ident);
}
pub fn shadowTypedef(&mut self, ident: &Ident) {
self.user.tyidents.remove(ident);
}
pub fn isTypeIdent(&self, ident: &Ident) -> bool {
self.user.tyidents.contains(ident)
}
pub fn enterScope(&mut self) {
self.user.scopes.insert(0, self.user.tyidents.clone());
}
pub fn leaveScope(&mut self) {
assert!(!self.user.scopes.is_empty(), "leaveScope: already in global scope");
self.user.tyidents = self.user.scopes.remove(0);
}
pub fn getInput(&self) -> InputStream { self.user.curInput.clone()
}
pub fn setInput(&mut self, i: InputStream) {
self.user.curInput = i;
}
pub fn getLastToken(&self) -> CToken { self.user.prevToken.clone().expect("touched undefined token")
}
pub fn getSavedToken(&self) -> CToken { self.user.savedToken.clone().expect("touched undefined token")
}
pub fn setLastToken(&mut self, tk: CToken) {
match tk {
CTokEof => {
self.user.savedToken = self.user.prevToken.clone();
}
tok => {
self.user.savedToken = mem::replace(&mut self.user.prevToken,
Some(tok));
}
}
}
pub fn handleEofToken(&mut self) -> () {
self.user.savedToken = self.user.prevToken.clone();
}
pub fn doDeclIdent(&mut self, declspecs: &[CDeclSpec], declr: CDeclrR) {
let is_typedef = |declspec: &CDeclSpec| match *declspec {
CStorageSpec(CTypedef(_)) => true,
_ => false,
};
match declr.ident {
None => (),
Some(ident) => {
if declspecs.iter().any(is_typedef) {
self.addTypedef(ident)
} else {
self.shadowTypedef(&ident)
}
},
}
}
pub fn doFuncParamDeclIdent(&mut self, decl: &CDeclr) {
if decl.1.is_empty() {
return;
}
if let CFunDeclr(Either::Right((ref params, _)), _, _) = decl.1[0] {
for param in params {
if let CDecl(_, ref dle, _) = *param {
for dl in dle {
if let (Some(ref declr), _, _,) = *dl {
if let Some(ref ident) = declr.0 {
self.shadowTypedef(ident);
}
}
}
}
}
}
}
pub fn withNodeInfo<T: 'static, N: Pos>(&mut self, node: N, mkAttrNode: Box<FnBox(NodeInfo) -> T>)
-> Result<T, ParseError> {
let name = self.getNewName();
let lastTok = self.getSavedToken();
let firstPos = node.into_pos();
let attrs = NodeInfo::new(firstPos, movePosLenOfTok(lastTok), name);
Ok(mkAttrNode(attrs))
}
pub fn withLength<T: Clone + 'static>(&mut self, nodeinfo: NodeInfo,
mkAttrNode: Box<FnBox(NodeInfo) -> T>) -> Result<T, ParseError> {
let lastTok = self.getSavedToken();
let firstPos = nodeinfo.pos().clone();
let attrs = NodeInfo::new(firstPos, movePosLenOfTok(lastTok),
nodeinfo.name().unwrap_or_else(|| panic!("nameOfNode")));
Ok(mkAttrNode(attrs))
}
pub fn withAttribute<N: Pos>(&mut self, node: N, cattrs: Vec<CAttribute<NodeInfo>>,
mkDeclrNode: Box<FnBox(NodeInfo) -> CDeclrR>) -> Result<CDeclrR, ParseError> {
let name = self.getNewName();
let attrs = NodeInfo::with_pos_name(node.into_pos(), name);
let newDeclr = mkDeclrNode(attrs).appendAttrs(cattrs);
Ok(newDeclr)
}
pub fn withAttributePF<N: Pos + 'static>(&mut self, node: N, cattrs: Vec<CAttribute<NodeInfo>>,
mkDeclrCtor: Box<Fn(NodeInfo, CDeclrR) -> CDeclrR>)
-> Result<Rc<Box<Fn(CDeclrR) -> CDeclrR>>, ParseError>
{
let mkDeclrCtor = Rc::new(mkDeclrCtor);
let name = self.getNewName();
let attrs = NodeInfo::with_pos_name(node.into_pos(), name);
let newDeclr: Rc<Box<Fn(CDeclrR) -> CDeclrR>> = Rc::new(box move |_0| {
mkDeclrCtor(attrs.clone(), _0).appendAttrs(cattrs.clone())
});
Ok(newDeclr)
}
}
#[derive(Clone)]
pub struct CDeclrR {
ident: Option<Ident>,
inner: Reversed<Vec<CDerivedDeclr>>,
asmname: Option<CStringLiteral<NodeInfo>>,
cattrs: Vec<CAttribute<NodeInfo>>,
at: NodeInfo,
}
impl CNode for CDeclrR {
fn node_info(&self) -> &NodeInfo {
&self.at
}
fn into_node_info(self) -> NodeInfo {
self.at
}
}
impl CDeclrR {
pub fn empty() -> CDeclrR {
CDeclrR { ident: None, inner: RList::empty(), asmname: None, cattrs: vec![],
at: NodeInfo::undef() }
}
pub fn from_var(ident: Ident, ni: NodeInfo) -> CDeclrR {
CDeclrR { ident: Some(ident), inner: RList::empty(), asmname: None, cattrs: vec![], at: ni }
}
pub fn setAsmName(mut self, mAsmName: Option<CStringLiteral<NodeInfo>>) -> Result<CDeclrR, ParseError> {
if self.asmname.is_none() {
self.asmname = mAsmName;
Ok(self)
} else if mAsmName.is_none() {
Ok(self)
} else {
let newname = mAsmName.unwrap();
let oldname = self.asmname.as_ref().unwrap();
Err(ParseError::new(
newname.pos().clone(),
vec!["Duplicate assembler name: ".to_string(),
oldname.0.to_string(), newname.0.to_string()]))
}
}
pub fn withAsmNameAttrs(self, (mAsmName, newAttrs): (Option<CStringLiteral<NodeInfo>>,
Vec<CAttribute<NodeInfo>>))
-> Result<CDeclrR, ParseError> {
self.appendObjAttrs(newAttrs).setAsmName(mAsmName)
}
pub fn funDeclr(mut self, params: Either<Vec<Ident>, (Vec<CDecl>, bool)>,
cattrs: Vec<CAttribute<NodeInfo>>, at: NodeInfo) -> CDeclrR {
self.inner = snoc(self.inner, CFunDeclr(params, cattrs, at));
self
}
pub fn arrDeclr(mut self, tyquals: Vec<CTypeQual>, var_sized: bool, static_size: bool,
size_expr_opt: Option<CExpr>, at: NodeInfo) -> CDeclrR {
let arr_sz = match size_expr_opt {
Some(e) => CArrSize(static_size, e),
None => CNoArrSize(var_sized)
};
self.inner = snoc(self.inner, CArrDeclr(tyquals, arr_sz, at));
self
}
pub fn appendAttrs(mut self, mut newAttrs: Vec<CAttribute<NodeInfo>>) -> Self {
match RList::get_mut(&mut self.inner, 0) {
None => self.cattrs.append(&mut newAttrs),
Some(&mut CPtrDeclr(ref mut typeQuals, _)) => {
typeQuals.extend(newAttrs.into_iter().map(CAttrQual))
}
Some(&mut CArrDeclr(ref mut typeQuals, _, _)) => {
typeQuals.extend(newAttrs.into_iter().map(CAttrQual))
}
Some(&mut CFunDeclr(_, ref mut cattrs, _)) => {
cattrs.append(&mut newAttrs)
}
}
self
}
pub fn appendObjAttrs(mut self, mut newAttrs: Vec<CAttribute<NodeInfo>>) -> CDeclrR {
self.cattrs.append(&mut newAttrs);
self
}
pub fn reverse(self) -> CDeclarator<NodeInfo> {
let CDeclrR { ident, inner: reversedDDs, asmname, cattrs, at } = self;
CDeclarator(ident, RList::reverse(reversedDDs), asmname, cattrs, at)
}
}
pub fn ptrDeclr(mut slf: CDeclrR, tyquals: Vec<CTypeQual>, at: NodeInfo) -> CDeclrR {
slf.inner = snoc(slf.inner, CPtrDeclr(tyquals, at));
slf
}
pub fn parseC(input: InputStream, initialPosition: Position) -> Result<CTranslUnit, ParseError> {
execParser(input, initialPosition, builtinTypeNames(), new_name_supply(), translUnitP).map(|x| x.0)
}
pub fn execParser_<T, F>(do_parse: F, input: InputStream, pos: Position) -> Result<T, ParseError>
where T: 'static, F: Fn(&mut Parser) -> Result<T, ParseError>
{
execParser(input, pos, builtinTypeNames(), new_name_supply(), do_parse).map(|x| x.0)
}