Source code

Revision control

Copy as Markdown

Other Tools

/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef _MDB_
# include "mdb.h"
#endif
#ifndef _MORK_
# include "mork.h"
#endif
#ifndef _MORKNODE_
# include "morkNode.h"
#endif
#ifndef _MORKMAP_
# include "morkMap.h"
#endif
#ifndef _MORKENV_
# include "morkEnv.h"
#endif
#ifndef _MORKPARSER_
# include "morkParser.h"
#endif
#ifndef _MORKBUILDER_
# include "morkBuilder.h"
#endif
#ifndef _MORKCELL_
# include "morkCell.h"
#endif
#ifndef _MORKSTORE_
# include "morkStore.h"
#endif
#ifndef _MORKTABLE_
# include "morkTable.h"
#endif
#ifndef _MORKROW_
# include "morkRow.h"
#endif
#ifndef _MORKCELL_
# include "morkCell.h"
#endif
#ifndef _MORKATOM_
# include "morkAtom.h"
#endif
#ifndef _MORKATOMSPACE_
# include "morkAtomSpace.h"
#endif
#ifndef _MORKROWSPACE_
# include "morkRowSpace.h"
#endif
// 456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
// ````` ````` ````` ````` `````
// { ===== begin morkNode interface =====
/*public virtual*/ void morkBuilder::CloseMorkNode(
morkEnv* ev) // CloseBuilder() only if open
{
if (this->IsOpenNode()) {
this->MarkClosing();
this->CloseBuilder(ev);
this->MarkShut();
}
}
/*public virtual*/
morkBuilder::~morkBuilder() // assert CloseBuilder() executed earlier
{
MORK_ASSERT(mBuilder_Store == 0);
MORK_ASSERT(mBuilder_Row == 0);
MORK_ASSERT(mBuilder_Table == 0);
MORK_ASSERT(mBuilder_Cell == 0);
MORK_ASSERT(mBuilder_RowSpace == 0);
MORK_ASSERT(mBuilder_AtomSpace == 0);
}
/*public non-poly*/
morkBuilder::morkBuilder(morkEnv* ev, const morkUsage& inUsage,
nsIMdbHeap* ioHeap, morkStream* ioStream,
mdb_count inBytesPerParseSegment,
nsIMdbHeap* ioSlotHeap, morkStore* ioStore)
: morkParser(ev, inUsage, ioHeap, ioStream, inBytesPerParseSegment,
ioSlotHeap)
,
mBuilder_Store(0)
,
mBuilder_Table(0),
mBuilder_Row(0),
mBuilder_Cell(0)
,
mBuilder_RowSpace(0),
mBuilder_AtomSpace(0)
,
mBuilder_OidAtomSpace(0),
mBuilder_ScopeAtomSpace(0)
,
mBuilder_PortForm(0),
mBuilder_PortRowScope((mork_scope)'r'),
mBuilder_PortAtomScope((mork_scope)'v')
,
mBuilder_TableForm(0),
mBuilder_TableRowScope((mork_scope)'r'),
mBuilder_TableAtomScope((mork_scope)'v'),
mBuilder_TableKind(0)
,
mBuilder_TablePriority(morkPriority_kLo),
mBuilder_TableIsUnique(morkBool_kFalse),
mBuilder_TableIsVerbose(morkBool_kFalse),
mBuilder_TablePadByte(0)
,
mBuilder_RowForm(0),
mBuilder_RowRowScope((mork_scope)'r'),
mBuilder_RowAtomScope((mork_scope)'v')
,
mBuilder_CellForm(0),
mBuilder_CellAtomScope((mork_scope)'v')
,
mBuilder_DictForm(0),
mBuilder_DictAtomScope((mork_scope)'v')
,
mBuilder_MetaTokenSlot(0)
,
mBuilder_DoCutRow(morkBool_kFalse),
mBuilder_DoCutCell(morkBool_kFalse),
mBuilder_CellsVecFill(0) {
if (ev->Good()) {
if (ioStore) {
morkStore::SlotWeakStore(ioStore, ev, &mBuilder_Store);
if (ev->Good()) mNode_Derived = morkDerived_kBuilder;
} else
ev->NilPointerError();
}
}
/*public non-poly*/ void morkBuilder::CloseBuilder(
morkEnv* ev) // called by CloseMorkNode();
{
if (this->IsNode()) {
mBuilder_Row = 0;
mBuilder_Cell = 0;
mBuilder_MetaTokenSlot = 0;
morkTable::SlotStrongTable((morkTable*)0, ev, &mBuilder_Table);
morkStore::SlotWeakStore((morkStore*)0, ev, &mBuilder_Store);
morkRowSpace::SlotStrongRowSpace((morkRowSpace*)0, ev, &mBuilder_RowSpace);
morkAtomSpace::SlotStrongAtomSpace((morkAtomSpace*)0, ev,
&mBuilder_AtomSpace);
morkAtomSpace::SlotStrongAtomSpace((morkAtomSpace*)0, ev,
&mBuilder_OidAtomSpace);
morkAtomSpace::SlotStrongAtomSpace((morkAtomSpace*)0, ev,
&mBuilder_ScopeAtomSpace);
this->CloseParser(ev);
this->MarkShut();
} else
this->NonNodeError(ev);
}
// } ===== end morkNode methods =====
// ````` ````` ````` ````` `````
/*static*/ void morkBuilder::NonBuilderTypeError(morkEnv* ev) {
ev->NewError("non morkBuilder");
}
/*static*/ void morkBuilder::NilBuilderCellError(morkEnv* ev) {
ev->NewError("nil mBuilder_Cell");
}
/*static*/ void morkBuilder::NilBuilderRowError(morkEnv* ev) {
ev->NewError("nil mBuilder_Row");
}
/*static*/ void morkBuilder::NilBuilderTableError(morkEnv* ev) {
ev->NewError("nil mBuilder_Table");
}
/*static*/ void morkBuilder::NonColumnSpaceScopeError(morkEnv* ev) {
ev->NewError("column space != 'c'");
}
void morkBuilder::LogGlitch(morkEnv* ev, const morkGlitch& inGlitch,
const char* inKind) {
MORK_USED_2(inGlitch, inKind);
ev->NewWarning("parsing glitch");
}
/*virtual*/ void morkBuilder::MidToYarn(
morkEnv* ev,
const morkMid& inMid, // typically an alias to concat with strings
mdbYarn* outYarn)
// The parser might ask that some aliases be turned into yarns, so they
// can be concatenated into longer blobs under some circumstances. This
// is an alternative to using a long and complex callback for many parts
// for a single cell value.
{
mBuilder_Store->MidToYarn(ev, inMid, outYarn);
}
/*virtual*/ void morkBuilder::OnNewPort(morkEnv* ev, const morkPlace& inPlace)
// mp:Start ::= OnNewPort mp:PortItem* OnPortEnd
// mp:PortItem ::= mp:Content | mp:Group | OnPortGlitch
// mp:Content ::= mp:PortRow | mp:Dict | mp:Table | mp:Row
{
MORK_USED_2(ev, inPlace);
// mParser_InPort = morkBool_kTrue;
mBuilder_PortForm = 0;
mBuilder_PortRowScope = (mork_scope)'r';
mBuilder_PortAtomScope = (mork_scope)'v';
}
/*virtual*/ void morkBuilder::OnPortGlitch(morkEnv* ev,
const morkGlitch& inGlitch) {
this->LogGlitch(ev, inGlitch, "port");
}
/*virtual*/ void morkBuilder::OnPortEnd(morkEnv* ev, const morkSpan& inSpan)
// mp:Start ::= OnNewPort mp:PortItem* OnPortEnd
{
MORK_USED_2(ev, inSpan);
// ev->StubMethodOnlyError();
// nothing to do?
// mParser_InPort = morkBool_kFalse;
}
/*virtual*/ void morkBuilder::OnNewGroup(morkEnv* ev, const morkPlace& inPlace,
mork_gid inGid) {
MORK_USED_1(inPlace);
mParser_InGroup = morkBool_kTrue;
mork_pos startPos = inPlace.mPlace_Pos;
morkStore* store = mBuilder_Store;
if (store) {
if (inGid >= store->mStore_CommitGroupIdentity)
store->mStore_CommitGroupIdentity = inGid + 1;
if (!store->mStore_FirstCommitGroupPos)
store->mStore_FirstCommitGroupPos = startPos;
else if (!store->mStore_SecondCommitGroupPos)
store->mStore_SecondCommitGroupPos = startPos;
}
}
/*virtual*/ void morkBuilder::OnGroupGlitch(morkEnv* ev,
const morkGlitch& inGlitch) {
this->LogGlitch(ev, inGlitch, "group");
}
/*virtual*/ void morkBuilder::OnGroupCommitEnd(morkEnv* ev,
const morkSpan& inSpan) {
MORK_USED_2(ev, inSpan);
// mParser_InGroup = morkBool_kFalse;
// ev->StubMethodOnlyError();
}
/*virtual*/ void morkBuilder::OnGroupAbortEnd(morkEnv* ev,
const morkSpan& inSpan) {
MORK_USED_1(inSpan);
// mParser_InGroup = morkBool_kFalse;
ev->StubMethodOnlyError();
}
/*virtual*/ void morkBuilder::OnNewPortRow(morkEnv* ev,
const morkPlace& inPlace,
const morkMid& inMid,
mork_change inChange) {
MORK_USED_3(inMid, inPlace, inChange);
// mParser_InPortRow = morkBool_kTrue;
ev->StubMethodOnlyError();
}
/*virtual*/ void morkBuilder::OnPortRowGlitch(morkEnv* ev,
const morkGlitch& inGlitch) {
this->LogGlitch(ev, inGlitch, "port row");
}
/*virtual*/ void morkBuilder::OnPortRowEnd(morkEnv* ev,
const morkSpan& inSpan) {
MORK_USED_1(inSpan);
// mParser_InPortRow = morkBool_kFalse;
ev->StubMethodOnlyError();
}
/*virtual*/ void morkBuilder::OnNewTable(morkEnv* ev, const morkPlace& inPlace,
const morkMid& inMid,
mork_bool inCutAllRows)
// mp:Table ::= OnNewTable mp:TableItem* OnTableEnd
// mp:TableItem ::= mp:Row | mp:MetaTable | OnTableGlitch
// mp:MetaTable ::= OnNewMeta mp:MetaItem* mp:Row OnMetaEnd
// mp:Meta ::= OnNewMeta mp:MetaItem* OnMetaEnd
// mp:MetaItem ::= mp:Cell | OnMetaGlitch
{
MORK_USED_1(inPlace);
// mParser_InTable = morkBool_kTrue;
mBuilder_TableForm = mBuilder_PortForm;
mBuilder_TableRowScope = mBuilder_PortRowScope;
mBuilder_TableAtomScope = mBuilder_PortAtomScope;
mBuilder_TableKind = morkStore_kNoneToken;
mBuilder_TablePriority = morkPriority_kLo;
mBuilder_TableIsUnique = morkBool_kFalse;
mBuilder_TableIsVerbose = morkBool_kFalse;
morkTable* table = mBuilder_Store->MidToTable(ev, inMid);
morkTable::SlotStrongTable(table, ev, &mBuilder_Table);
if (table) {
if (table->mTable_RowSpace)
mBuilder_TableRowScope = table->mTable_RowSpace->SpaceScope();
if (inCutAllRows) table->CutAllRows(ev);
}
}
/*virtual*/ void morkBuilder::OnTableGlitch(morkEnv* ev,
const morkGlitch& inGlitch) {
this->LogGlitch(ev, inGlitch, "table");
}
/*virtual*/ void morkBuilder::OnTableEnd(morkEnv* ev, const morkSpan& inSpan)
// mp:Table ::= OnNewTable mp:TableItem* OnTableEnd
{
MORK_USED_1(inSpan);
// mParser_InTable = morkBool_kFalse;
if (mBuilder_Table) {
mBuilder_Table->mTable_Priority = mBuilder_TablePriority;
if (mBuilder_TableIsUnique) mBuilder_Table->SetTableUnique();
if (mBuilder_TableIsVerbose) mBuilder_Table->SetTableVerbose();
morkTable::SlotStrongTable((morkTable*)0, ev, &mBuilder_Table);
} else
this->NilBuilderTableError(ev);
mBuilder_Row = 0;
mBuilder_Cell = 0;
mBuilder_TablePriority = morkPriority_kLo;
mBuilder_TableIsUnique = morkBool_kFalse;
mBuilder_TableIsVerbose = morkBool_kFalse;
if (mBuilder_TableKind == morkStore_kNoneToken)
ev->NewError("missing table kind");
mBuilder_CellAtomScope = mBuilder_RowAtomScope = mBuilder_TableAtomScope =
mBuilder_PortAtomScope;
mBuilder_DoCutCell = morkBool_kFalse;
mBuilder_DoCutRow = morkBool_kFalse;
}
/*virtual*/ void morkBuilder::OnNewMeta(morkEnv* ev, const morkPlace& inPlace)
// mp:Meta ::= OnNewMeta mp:MetaItem* OnMetaEnd
// mp:MetaItem ::= mp:Cell | OnMetaGlitch
// mp:Cell ::= OnMinusCell? OnNewCell mp:CellItem? OnCellEnd
// mp:CellItem ::= mp:Slot | OnCellForm | OnCellGlitch
// mp:Slot ::= OnValue | OnValueMid | OnRowMid | OnTableMid
{
MORK_USED_2(ev, inPlace);
// mParser_InMeta = morkBool_kTrue;
}
/*virtual*/ void morkBuilder::OnMetaGlitch(morkEnv* ev,
const morkGlitch& inGlitch) {
this->LogGlitch(ev, inGlitch, "meta");
}
/*virtual*/ void morkBuilder::OnMetaEnd(morkEnv* ev, const morkSpan& inSpan)
// mp:Meta ::= OnNewMeta mp:MetaItem* OnMetaEnd
{
MORK_USED_2(ev, inSpan);
// mParser_InMeta = morkBool_kFalse;
}
/*virtual*/ void morkBuilder::OnMinusRow(morkEnv* ev) {
MORK_USED_1(ev);
mBuilder_DoCutRow = morkBool_kTrue;
}
/*virtual*/ void morkBuilder::OnNewRow(morkEnv* ev, const morkPlace& inPlace,
const morkMid& inMid,
mork_bool inCutAllCols)
// mp:Table ::= OnNewTable mp:TableItem* OnTableEnd
// mp:TableItem ::= mp:Row | mp:MetaTable | OnTableGlitch
// mp:MetaTable ::= OnNewMeta mp:MetaItem* mp:Row OnMetaEnd
// mp:Row ::= OnMinusRow? OnNewRow mp:RowItem* OnRowEnd
// mp:RowItem ::= mp:Cell | mp:Meta | OnRowGlitch
// mp:Cell ::= OnMinusCell? OnNewCell mp:CellItem? OnCellEnd
// mp:CellItem ::= mp:Slot | OnCellForm | OnCellGlitch
// mp:Slot ::= OnValue | OnValueMid | OnRowMid | OnTableMid
{
MORK_USED_1(inPlace);
// mParser_InRow = morkBool_kTrue;
mBuilder_CellForm = mBuilder_RowForm = mBuilder_TableForm;
mBuilder_CellAtomScope = mBuilder_RowAtomScope = mBuilder_TableAtomScope;
mBuilder_RowRowScope = mBuilder_TableRowScope;
morkStore* store = mBuilder_Store;
if (!inMid.mMid_Buf && !inMid.mMid_Oid.mOid_Scope) {
morkMid mid(inMid);
mid.mMid_Oid.mOid_Scope = mBuilder_RowRowScope;
mBuilder_Row = store->MidToRow(ev, mid);
} else {
mBuilder_Row = store->MidToRow(ev, inMid);
}
morkRow* row = mBuilder_Row;
if (row && inCutAllCols) {
row->CutAllColumns(ev);
}
morkTable* table = mBuilder_Table;
if (table) {
if (row) {
if (mParser_InMeta) {
morkRow* metaRow = table->mTable_MetaRow;
if (!metaRow) {
table->mTable_MetaRow = row;
table->mTable_MetaRowOid = row->mRow_Oid;
row->AddRowGcUse(ev);
} else if (metaRow != row) // not identical?
ev->NewError("duplicate table meta row");
} else {
if (mBuilder_DoCutRow)
table->CutRow(ev, row);
else
table->AddRow(ev, row);
}
}
}
// else // it is now okay to have rows outside a table:
// this->NilBuilderTableError(ev);
mBuilder_DoCutRow = morkBool_kFalse;
}
/*virtual*/ void morkBuilder::OnRowPos(morkEnv* ev, mork_pos inRowPos) {
if (mBuilder_Row && mBuilder_Table && !mParser_InMeta) {
mork_pos hintFromPos = 0; // best hint when we don't know position
mBuilder_Table->MoveRow(ev, mBuilder_Row, hintFromPos, inRowPos);
}
}
/*virtual*/ void morkBuilder::OnRowGlitch(morkEnv* ev,
const morkGlitch& inGlitch) {
this->LogGlitch(ev, inGlitch, "row");
}
void morkBuilder::FlushBuilderCells(morkEnv* ev) {
if (mBuilder_Row) {
morkPool* pool = mBuilder_Store->StorePool();
morkCell* cells = mBuilder_CellsVec;
mork_fill fill = mBuilder_CellsVecFill;
mBuilder_Row->TakeCells(ev, cells, fill, mBuilder_Store);
morkCell* end = cells + fill;
--cells; // prepare for preincrement
while (++cells < end) {
if (cells->mCell_Atom) cells->SetAtom(ev, (morkAtom*)0, pool);
}
mBuilder_CellsVecFill = 0;
} else
this->NilBuilderRowError(ev);
}
/*virtual*/ void morkBuilder::OnRowEnd(morkEnv* ev, const morkSpan& inSpan)
// mp:Row ::= OnMinusRow? OnNewRow mp:RowItem* OnRowEnd
{
MORK_USED_1(inSpan);
// mParser_InRow = morkBool_kFalse;
if (mBuilder_Row) {
this->FlushBuilderCells(ev);
} else
this->NilBuilderRowError(ev);
mBuilder_Row = 0;
mBuilder_Cell = 0;
mBuilder_DoCutCell = morkBool_kFalse;
mBuilder_DoCutRow = morkBool_kFalse;
}
/*virtual*/ void morkBuilder::OnNewDict(morkEnv* ev, const morkPlace& inPlace)
// mp:Dict ::= OnNewDict mp:DictItem* OnDictEnd
// mp:DictItem ::= OnAlias | OnAliasGlitch | mp:Meta | OnDictGlitch
{
MORK_USED_2(ev, inPlace);
// mParser_InDict = morkBool_kTrue;
mBuilder_CellForm = mBuilder_DictForm = mBuilder_PortForm;
mBuilder_CellAtomScope = mBuilder_DictAtomScope = mBuilder_PortAtomScope;
}
/*virtual*/ void morkBuilder::OnDictGlitch(morkEnv* ev,
const morkGlitch& inGlitch) {
this->LogGlitch(ev, inGlitch, "dict");
}
/*virtual*/ void morkBuilder::OnDictEnd(morkEnv* ev, const morkSpan& inSpan)
// mp:Dict ::= OnNewDict mp:DictItem* OnDictEnd
{
MORK_USED_2(ev, inSpan);
// mParser_InDict = morkBool_kFalse;
mBuilder_DictForm = 0;
mBuilder_DictAtomScope = 0;
}
/*virtual*/ void morkBuilder::OnAlias(morkEnv* ev, const morkSpan& inSpan,
const morkMid& inMid) {
MORK_USED_1(inSpan);
if (mParser_InDict) {
morkMid mid = inMid; // local copy for modification
mid.mMid_Oid.mOid_Scope = mBuilder_DictAtomScope;
mBuilder_Store->AddAlias(ev, mid, mBuilder_DictForm);
} else
ev->NewError("alias not in dict");
}
/*virtual*/ void morkBuilder::OnAliasGlitch(morkEnv* ev,
const morkGlitch& inGlitch) {
this->LogGlitch(ev, inGlitch, "alias");
}
morkCell* morkBuilder::AddBuilderCell(morkEnv* ev, const morkMid& inMid,
mork_change inChange) {
morkCell* outCell = 0;
mork_column column = inMid.mMid_Oid.mOid_Id;
if (ev->Good()) {
if (mBuilder_CellsVecFill >= morkBuilder_kCellsVecSize)
this->FlushBuilderCells(ev);
if (ev->Good()) {
if (mBuilder_CellsVecFill < morkBuilder_kCellsVecSize) {
mork_fill indx = mBuilder_CellsVecFill++;
outCell = mBuilder_CellsVec + indx;
outCell->SetColumnAndChange(column, inChange);
outCell->mCell_Atom = 0;
} else
ev->NewError("out of builder cells");
}
}
return outCell;
}
/*virtual*/ void morkBuilder::OnMinusCell(morkEnv* ev) {
MORK_USED_1(ev);
mBuilder_DoCutCell = morkBool_kTrue;
}
/*virtual*/ void morkBuilder::OnNewCell(morkEnv* ev, const morkPlace& inPlace,
const morkMid* inMid,
const morkBuf* inBuf)
// Exactly one of inMid and inBuf is nil, and the other is non-nil.
// When hex ID syntax is used for a column, then inMid is not nil, and
// when a naked string names a column, then inBuf is not nil.
// mp:Cell ::= OnMinusCell? OnNewCell mp:CellItem? OnCellEnd
// mp:CellItem ::= mp:Slot | OnCellForm | OnCellGlitch
// mp:Slot ::= OnValue | OnValueMid | OnRowMid | OnTableMid
{
MORK_USED_1(inPlace);
// mParser_InCell = morkBool_kTrue;
mork_change cellChange =
(mBuilder_DoCutCell) ? morkChange_kCut : morkChange_kAdd;
mBuilder_DoCutCell = morkBool_kFalse;
mBuilder_CellAtomScope = mBuilder_RowAtomScope;
mBuilder_Cell = 0; // nil until determined for a row
morkStore* store = mBuilder_Store;
mork_scope scope = morkStore_kColumnSpaceScope;
morkMid tempMid; // space for local and modifiable cell mid
morkMid* cellMid = &tempMid; // default to local if inMid==0
if (inMid) // mid parameter is actually provided?
{
*cellMid = *inMid; // bitwise copy for modifiable local mid
if (!cellMid->mMid_Oid.mOid_Scope) {
if (cellMid->mMid_Buf) {
scope = store->BufToToken(ev, cellMid->mMid_Buf);
cellMid->mMid_Buf = 0; // don't do scope lookup again
ev->NewWarning("column mids need column scope");
}
cellMid->mMid_Oid.mOid_Scope = scope;
}
} else if (inBuf) // buf points to naked column string name?
{
cellMid->ClearMid();
cellMid->mMid_Oid.mOid_Id = store->BufToToken(ev, inBuf);
cellMid->mMid_Oid.mOid_Scope = scope; // kColumnSpaceScope
} else
ev->NilPointerError(); // either inMid or inBuf must be non-nil
mork_column column = cellMid->mMid_Oid.mOid_Id;
if (mBuilder_Row && ev->Good()) // this cell must be inside a row
{
// mBuilder_Cell = this->AddBuilderCell(ev, *cellMid, cellChange);
if (mBuilder_CellsVecFill >= morkBuilder_kCellsVecSize)
this->FlushBuilderCells(ev);
if (ev->Good()) {
if (mBuilder_CellsVecFill < morkBuilder_kCellsVecSize) {
mork_fill ix = mBuilder_CellsVecFill++;
morkCell* cell = mBuilder_CellsVec + ix;
cell->SetColumnAndChange(column, cellChange);
cell->mCell_Atom = 0;
mBuilder_Cell = cell;
} else
ev->NewError("out of builder cells");
}
}
else if (mParser_InMeta && ev->Good()) // cell is in metainfo structure?
{
if (scope == morkStore_kColumnSpaceScope) {
if (mParser_InTable) // metainfo for table?
{
if (column == morkStore_kKindColumn)
mBuilder_MetaTokenSlot = &mBuilder_TableKind;
else if (column == morkStore_kStatusColumn)
mBuilder_MetaTokenSlot = &mBuilder_TableStatus;
else if (column == morkStore_kRowScopeColumn)
mBuilder_MetaTokenSlot = &mBuilder_TableRowScope;
else if (column == morkStore_kAtomScopeColumn)
mBuilder_MetaTokenSlot = &mBuilder_TableAtomScope;
else if (column == morkStore_kFormColumn)
mBuilder_MetaTokenSlot = &mBuilder_TableForm;
} else if (mParser_InDict) // metainfo for dict?
{
if (column == morkStore_kAtomScopeColumn)
mBuilder_MetaTokenSlot = &mBuilder_DictAtomScope;
else if (column == morkStore_kFormColumn)
mBuilder_MetaTokenSlot = &mBuilder_DictForm;
} else if (mParser_InRow) // metainfo for row?
{
if (column == morkStore_kAtomScopeColumn)
mBuilder_MetaTokenSlot = &mBuilder_RowAtomScope;
else if (column == morkStore_kRowScopeColumn)
mBuilder_MetaTokenSlot = &mBuilder_RowRowScope;
else if (column == morkStore_kFormColumn)
mBuilder_MetaTokenSlot = &mBuilder_RowForm;
}
} else
ev->NewWarning("expected column scope");
}
}
/*virtual*/ void morkBuilder::OnCellGlitch(morkEnv* ev,
const morkGlitch& inGlitch) {
this->LogGlitch(ev, inGlitch, "cell");
}
/*virtual*/ void morkBuilder::OnCellForm(morkEnv* ev,
mork_cscode inCharsetFormat) {
morkCell* cell = mBuilder_Cell;
if (cell) {
mBuilder_CellForm = inCharsetFormat;
} else
this->NilBuilderCellError(ev);
}
/*virtual*/ void morkBuilder::OnCellEnd(morkEnv* ev, const morkSpan& inSpan)
// mp:Cell ::= OnMinusCell? OnNewCell mp:CellItem? OnCellEnd
{
MORK_USED_2(ev, inSpan);
// mParser_InCell = morkBool_kFalse;
mBuilder_MetaTokenSlot = 0;
mBuilder_CellAtomScope = mBuilder_RowAtomScope;
}
/*virtual*/ void morkBuilder::OnValue(morkEnv* ev, const morkSpan& inSpan,
const morkBuf& inBuf)
// mp:CellItem ::= mp:Slot | OnCellForm | OnCellGlitch
// mp:Slot ::= OnValue | OnValueMid | OnRowMid | OnTableMid
{
MORK_USED_1(inSpan);
morkStore* store = mBuilder_Store;
morkCell* cell = mBuilder_Cell;
if (cell) {
mdbYarn yarn;
yarn.mYarn_Buf = inBuf.mBuf_Body;
yarn.mYarn_Fill = yarn.mYarn_Size = inBuf.mBuf_Fill;
yarn.mYarn_More = 0;
yarn.mYarn_Form = mBuilder_CellForm;
yarn.mYarn_Grow = 0;
morkAtom* atom = store->YarnToAtom(ev, &yarn, true /* create */);
cell->SetAtom(ev, atom, store->StorePool());
} else if (mParser_InMeta) {
mork_token* metaSlot = mBuilder_MetaTokenSlot;
if (metaSlot) {
if (metaSlot == &mBuilder_TableStatus) // table status?
{
if (mParser_InTable && mBuilder_Table) {
const char* body = (const char*)inBuf.mBuf_Body;
mork_fill bufFill = inBuf.mBuf_Fill;
if (body && bufFill) {
const char* bodyEnd = body + bufFill;
while (body < bodyEnd) {
int c = *body++;
switch (c) {
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
mBuilder_TablePriority = (mork_priority)(c - '0');
break;
case 'u':
case 'U':
mBuilder_TableIsUnique = morkBool_kTrue;
break;
case 'v':
case 'V':
mBuilder_TableIsVerbose = morkBool_kTrue;
break;
}
}
}
}
} else {
mork_token token = store->BufToToken(ev, &inBuf);
if (token) {
*metaSlot = token;
if (metaSlot == &mBuilder_TableKind) // table kind?
{
if (mParser_InTable && mBuilder_Table)
mBuilder_Table->mTable_Kind = token;
}
}
}
}
} else
this->NilBuilderCellError(ev);
}
/*virtual*/ void morkBuilder::OnValueMid(morkEnv* ev, const morkSpan& inSpan,
const morkMid& inMid)
// mp:CellItem ::= mp:Slot | OnCellForm | OnCellGlitch
// mp:Slot ::= OnValue | OnValueMid | OnRowMid | OnTableMid
{
MORK_USED_1(inSpan);
morkStore* store = mBuilder_Store;
morkCell* cell = mBuilder_Cell;
morkMid valMid; // local mid for modifications
mdbOid* valOid = &valMid.mMid_Oid; // ref to oid inside mid
*valOid = inMid.mMid_Oid; // bitwise copy inMid's oid
if (inMid.mMid_Buf) {
if (!valOid->mOid_Scope) store->MidToOid(ev, inMid, valOid);
} else if (!valOid->mOid_Scope)
valOid->mOid_Scope = mBuilder_CellAtomScope;
if (cell) {
morkBookAtom* atom = store->MidToAtom(ev, valMid);
if (atom)
cell->SetAtom(ev, atom, store->StorePool());
else
ev->NewError("undefined cell value alias");
} else if (mParser_InMeta) {
mork_token* metaSlot = mBuilder_MetaTokenSlot;
if (metaSlot) {
mork_scope valScope = valOid->mOid_Scope;
if (!valScope || valScope == morkStore_kColumnSpaceScope) {
if (ev->Good() && valMid.HasSomeId()) {
*metaSlot = valOid->mOid_Id;
if (metaSlot == &mBuilder_TableKind) // table kind?
{
if (mParser_InTable && mBuilder_Table) {
mBuilder_Table->mTable_Kind = valOid->mOid_Id;
} else
ev->NewWarning("mBuilder_TableKind not in table");
} else if (metaSlot == &mBuilder_TableStatus) // table status?
{
if (mParser_InTable && mBuilder_Table) {
// $$ what here??
} else
ev->NewWarning("mBuilder_TableStatus not in table");
}
}
} else
this->NonColumnSpaceScopeError(ev);
}
} else
this->NilBuilderCellError(ev);
}
/*virtual*/ void morkBuilder::OnRowMid(morkEnv* ev, const morkSpan& inSpan,
const morkMid& inMid)
// mp:CellItem ::= mp:Slot | OnCellForm | OnCellGlitch
// mp:Slot ::= OnValue | OnValueMid | OnRowMid | OnTableMid
{
MORK_USED_1(inSpan);
morkStore* store = mBuilder_Store;
morkCell* cell = mBuilder_Cell;
if (cell) {
mdbOid rowOid = inMid.mMid_Oid;
if (inMid.mMid_Buf) {
if (!rowOid.mOid_Scope) store->MidToOid(ev, inMid, &rowOid);
} else if (!rowOid.mOid_Scope)
rowOid.mOid_Scope = mBuilder_RowRowScope;
if (ev->Good()) {
morkPool* pool = store->StorePool();
morkAtom* atom = pool->NewRowOidAtom(ev, rowOid, &store->mStore_Zone);
if (atom) {
cell->SetAtom(ev, atom, pool);
morkRow* row = store->OidToRow(ev, &rowOid);
if (row) // found or created such a row?
row->AddRowGcUse(ev);
}
}
} else
this->NilBuilderCellError(ev);
}
/*virtual*/ void morkBuilder::OnTableMid(morkEnv* ev, const morkSpan& inSpan,
const morkMid& inMid)
// mp:CellItem ::= mp:Slot | OnCellForm | OnCellGlitch
// mp:Slot ::= OnValue | OnValueMid | OnRowMid | OnTableMid
{
MORK_USED_1(inSpan);
morkStore* store = mBuilder_Store;
morkCell* cell = mBuilder_Cell;
if (cell) {
mdbOid tableOid = inMid.mMid_Oid;
if (inMid.mMid_Buf) {
if (!tableOid.mOid_Scope) store->MidToOid(ev, inMid, &tableOid);
} else if (!tableOid.mOid_Scope)
tableOid.mOid_Scope = mBuilder_RowRowScope;
if (ev->Good()) {
morkPool* pool = store->StorePool();
morkAtom* atom = pool->NewTableOidAtom(ev, tableOid, &store->mStore_Zone);
if (atom) {
cell->SetAtom(ev, atom, pool);
morkTable* table = store->OidToTable(ev, &tableOid,
/*optionalMetaRowOid*/ (mdbOid*)0);
if (table) // found or created such a table?
table->AddTableGcUse(ev);
}
}
} else
this->NilBuilderCellError(ev);
}
// 456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789