// See the file "COPYING" in the main distribution directory for copyright. #include "pac_context.h" #include "pac_analyzer.h" #include "pac_exception.h" #include "pac_exttype.h" #include "pac_flow.h" #include "pac_id.h" #include "pac_output.h" #include "pac_param.h" #include "pac_paramtype.h" #include "pac_type.h" #include "pac_utils.h" ContextField::ContextField(ID* id, Type* type) : Field(CONTEXT_FIELD, TYPE_NOT_TO_BE_PARSED | CLASS_MEMBER | PUBLIC_READABLE, id, type) {} AnalyzerContextDecl* AnalyzerContextDecl::current_analyzer_context_ = nullptr; namespace { ParamList* ContextFieldsToParams(ContextFieldList* context_fields) { // Convert context fields to parameters ParamList* params = new ParamList(); foreach (i, ContextFieldList, context_fields) { ContextField* f = *i; params->push_back(new Param(f->id()->clone(), f->type())); } return params; } } // namespace AnalyzerContextDecl::AnalyzerContextDecl(ID* id, ContextFieldList* context_fields) : TypeDecl(new ID(strfmt("Context%s", id->Name())), ContextFieldsToParams(context_fields), new DummyType()) { context_name_id_ = id; if ( current_analyzer_context_ != nullptr ) { throw Exception(this, strfmt("multiple declaration of analyzer context; " "the previous one is `%s'", current_analyzer_context_->id()->Name())); } else current_analyzer_context_ = this; context_fields_ = context_fields; param_type_ = new ParameterizedType(id_->clone(), nullptr); flow_buffer_added_ = false; DEBUG_MSG("Context type: %s\n", param_type()->class_name().c_str()); } AnalyzerContextDecl::~AnalyzerContextDecl() { delete context_name_id_; delete param_type_; delete_list(ContextFieldList, context_fields_); } void AnalyzerContextDecl::GenForwardDeclaration(Output* out_h) { GenNamespaceBegin(out_h); TypeDecl::GenForwardDeclaration(out_h); } void AnalyzerContextDecl::GenCode(Output* out_h, Output* out_cc) { GenNamespaceBegin(out_h); GenNamespaceBegin(out_cc); TypeDecl::GenCode(out_h, out_cc); } void AnalyzerContextDecl::GenNamespaceBegin(Output* out) const { out->println("namespace %s {", context_name_id()->Name()); } void AnalyzerContextDecl::GenNamespaceEnd(Output* out) const { out->println("} // namespace %s", context_name_id()->Name()); } void AnalyzerContextDecl::AddFlowBuffer() { if ( flow_buffer_added_ ) return; AddParam(new Param(new ID(kFlowBufferVar), FlowDecl::flow_buffer_type()->Clone())); flow_buffer_added_ = true; } string AnalyzerContextDecl::mb_buffer(Env* env) { // A hack. The orthodox way would be to build an Expr of // context.flow_buffer_var, and then EvalExpr. return strfmt("%s->%s()", env->RValue(analyzer_context_id), kFlowBufferVar); } Type* DummyType::DoClone() const { // Fields will be copied in Type::Clone(). return new DummyType(); }