static void EndRow(TParseTables* Tables) { /* add sentinel marker to token ID array */ IntAdd(&Tables->LLColumns, EolSymbol->Value); /* add dummy spacer to LLRows, to keep it same size as LLColumns */ IntAdd(&Tables->LLRows, 0); }
/* SelectAdd() - add a new rule/token pair to the table. * * Given a table (array) of TSelect structures, we either * discover that the rule already exists in the table and * add this token to its Tokens (symbol list), or else we * add this rule to the table and then do the same. * * The caller is responsible for making sure the table is * big enough that a new rule can be added to the end. */ static int SelectAdd(TSelect* Table, int Size, int Rule, TSymbol* Token) { int iSelect; int NewSize = Size; for(iSelect=0; iSelect < Size; ++iSelect) if(Table[iSelect].Rule == Rule) break; if(iSelect >= Size) { Table[iSelect].Rule = Rule; ++NewSize; } IntAdd(&Table[iSelect].Tokens, Token->Value); return NewSize; }
Point InfoShape::getMinSize() const { Font font=cfg.font.get(); Coord dx=0; Coord dy=0; for(ulen index=0,count=info->getLineCount(); index<count ;index++) { TextSize ts=font->text(info->getLine(index)); IntGuard( !ts.overflow ); Replace_max(dx,ts.full_dx); dy=IntAdd(dy,ts.dy); } return 2*(+cfg.space)+Point(dx,dy); }
void InfoShape::draw(const DrawBuf &buf) const { if( !pane ) return; Smooth::DrawArt art(buf); VColor text=enable?+cfg.text:+cfg.inactive; Point space=+cfg.space; // decor { MPane p(pane); MCoord width=+cfg.width; MCoord dx=Fraction(space.x)-width; MCoord dy=Fraction(space.y)-width; if( focus ) { FigureBox fig(p.shrink(Fraction(space.x)/2,Fraction(space.y)/2)); fig.loop(art,width,+cfg.focus); } if( xoff>0 ) { FigureLeftMark fig(p,dx); fig.solid(art,text); } if( xoff<xoffMax ) { FigureRightMark fig(p,dx); fig.solid(art,text); } if( yoff>0 ) { FigureUpMark fig(p,dy); fig.solid(art,text); } if( yoff<yoffMax ) { FigureDownMark fig(p,dy); fig.solid(art,text); } } // text { Pane inner=pane.shrink(space); if( !inner ) return; ulen count=info->getLineCount(); ulen index=yoff; Font font=cfg.font.get(); FontSize fs=font->getSize(); DrawBuf tbuf=buf.cutRebase(inner); Pane row(-xoff,0,IntAdd(xoff,inner.dx),fs.dy); for(; index<count && row.y+row.dy<=inner.dy ;index++,row.y+=row.dy) { font->text(tbuf,row,TextPlace(AlignX_Left,AlignY_Top),info->getLine(index),text); } } }
void ScrollListShape::draw(const DrawBuf &buf) const { if( !pane ) return; SmoothDrawArt art(buf.cut(pane)); art.block(pane,+cfg.back); VColor text = enable? +cfg.text : +cfg.inactive ; VColor title = enable? +cfg.title : +cfg.inactive ; VColor gray=+cfg.gray; VColor snow=+cfg.snow; Point space=+cfg.space; // decor { MPane p(pane); MCoord width=+cfg.width; MPoint s(space); FigureTopBorder fig_top(p,width); fig_top.solid(art,gray); FigureBottomBorder fig_bottom(p,width); fig_bottom.solid(art,snow); if( focus ) { FigureBox fig(p.shrink(s/2)); fig.loop(art,width,+cfg.focus); } MCoord dx=s.x-width; MCoord dy=s.y-width; if( xoff>0 ) { FigureLeftMark fig(p,dx); fig.solid(art,text); } if( xoff<xoffMax ) { FigureRightMark fig(p,dx); fig.solid(art,text); } if( yoff>0 ) { FigureUpMark fig(p,dy); fig.solid(art,text); } if( yoff<yoffMax ) { FigureDownMark fig(p,dy); fig.solid(art,text); } } // text { Pane inner=pane.shrink(space); if( !inner ) return; ulen count=info->getLineCount(); ulen index=yoff; Font font=cfg.font.get(); FontSize fs=font->getSize(); DrawBuf tbuf=buf.cut(inner); SmoothDrawArt tart(tbuf); Pane row=inner; row.dy=fs.dy; Coord pos_x=fs.dx0-xoff; Coord lim=inner.y+inner.dy; VColor titleTop=+cfg.titleTop; VColor titleBottom=+cfg.titleBottom; Coord off=fs.dy; for(; index<count && IntAdd(row.y,row.dy)<=lim ;index++,row.y+=row.dy) { if( enable && index==select ) tbuf.erase(row,+cfg.select); ComboInfoItem item=info->getLine(index); switch( item.type ) { case ComboInfoText : { font->text(tbuf,row,TextPlace(pos_x,AlignY_Top),item.text,text); } break; case ComboInfoTitle : { MPane p(row); TwoField field(p.getTopLeft(),titleTop,p.getBottomLeft(),titleBottom); FigureBox(p).solid(tart,field); font->text(tbuf,row,TextPlace(pos_x+off,AlignY_Top),item.text,title); } break; default: // case ComboInfoSeparator : { MPane p(row); MCoord delta=2*(p.dy/5); p=p.shrinkY(delta); TwoField field(p.getTopLeft(),snow,p.getBottomLeft(),gray); FigureBox(p).solid(tart,field); } } } } }
TParseTables* GenerateParseTables(void) { size_t IP, IPStart; int NNonTerms, NSymbols; int iRule, iTerminal; SymIt NonTerm; TSymbol* Symbol; TParseTables* Tables; SYMBOLS LLNonTerms; int Reduced; int TerminalsEmitted; printf("GenerateParseTables() begins\n"); Tables = NEW(TParseTables); assert(Tables != NULL); Tables->LLNonTerms = LLNonTerms = GetLLNonTerms(); /* get list of only nonterminals we care about */ /* assign integers to any undefined tokens */ DefineTokens(Tables); IP = BLC_HDR_SIZE; /* skip over initial header containing 5 two-byte table sizes */ NNonTerms = SymbolListCount(LLNonTerms); /* generate terminal symbol table */ IPStart = IP; TerminalsEmitted = 0; for(iTerminal=Tables->MinTokenVal; iTerminal <= Tables->MaxTokenVal; ++iTerminal) { Symbol = SymbolFromValue(iTerminal); if(Symbol) { /* store token ID, followed by its null-terminated string */ IP = Store8(Tables, IP, iTerminal); IP = StoreStr(Tables, IP, SymbolStr(Symbol)); ++TerminalsEmitted; } } IP = Store8(Tables, IP, 0); /* sentinel byte */ Store16(Tables, BLC_HDR_TERMSYMTAB_SIZE, IP - IPStart); /* generate nonterminal symbol table */ IPStart = IP; NonTerm = SymItNew(LLNonTerms); while(SymbolIterate(&NonTerm)) { IP = StoreStr(Tables, IP, SymbolStr(NonTerm.Symbol)); } IP = Store8(Tables, IP, 0); /* sentinel byte */ Store16(Tables, BLC_HDR_NONTERMSYMTAB_SIZE, IP - IPStart); /* for each production of <start>, add an entry point */ IPStart = IP; Symbol = SymbolStart(); assert(Symbol != NULL); for(iRule = 0; iRule < RuleCount(Symbol); ++iRule) { /* actual value will have to be backpatched */ MarkPatch(IP, AddRule(Tables, Symbol->Rules[iRule], Symbol)); IP = Store16(Tables, IP, 0); } Store16(Tables, BLC_HDR_ENTRYTABLE_SIZE, IP - IPStart); /* for each nonterminal, generate its SELECT body*/ IPStart = IP; Tables->SelSectOfs = IPStart; NonTerm = SymItNew(LLNonTerms); while(SymbolIterate(&NonTerm)) IP = GenerateSelect(Tables, IP, NonTerm.Symbol); Store16(Tables, BLC_HDR_SELECTTABLE_SIZE, IP - IPStart); Dump("Generate opcodes for each unique rule\n"); /* generate opcodes for each unique rule */ IPStart = IP; Tables->RuleSectOfs = IPStart; for(iRule = 0; iRule < Tables->NRules; ++iRule) { int iProdItem; TRule* Rule = Tables->Rules[iRule]; IntAdd(&Tables->RuleOffsets, IP); Reduced = FALSE; /* have not performed a reduction for this rule yet */ NSymbols = SymbolListCount(Rule->Symbols); fprintf(stdout, "-> "); SymbolListDump(stdout, Rule->Symbols, " "); fprintf(stdout, "\n"); for(iProdItem = 0; iProdItem < NSymbols; ++iProdItem) { TSymbol* Symbol = SymbolListGet(Rule->Symbols, iProdItem); if(SymbolGetBit(Symbol, SYM_TERMINAL)) { IP = Store8(Tables, IP, BLCOP_MATCH); IP = Store8(Tables, IP, Symbol->Value); if(Symbol == SymbolFind(EOFToken)) { IP = Store8(Tables, IP, BLCOP_HALT); Reduced = TRUE; } } else if(SymbolIsAction(Symbol)) { int FinalAction, ArgCount; assert(Rule->RuleId < 255); assert(iProdItem < 255); FinalAction = FALSE; if(iProdItem == NSymbols-1) FinalAction = TRUE; else if(Rule->TailRecursive && iProdItem == NSymbols-2) FinalAction = TRUE; ArgCount = iProdItem; if(Rule->TailRecursive == 2) ++ArgCount; fprintf(stdout, "iProdItem=%d, NSymbols=%d,TailRecursive=%d,FinalAction=%d\n", iProdItem, NSymbols, Rule->TailRecursive, FinalAction); IP = Store8(Tables, IP, FinalAction?BLCOP_ACTRED:BLCOP_ACTION8); IP = Store8(Tables, IP, Symbol->Action->Number); IP = Store8(Tables, IP, ArgCount); Symbol->Action->ArgCount = ArgCount; if(FinalAction) Reduced = TRUE; } else if(SymbolListContains(LLNonTerms, Symbol)) /* non-terminal */ { int iSymbol = SymbolListContains(LLNonTerms, Symbol); if(RuleCount(Symbol) > 1) { if(Symbol->Name.Text[0] == '`') /* if a tail recursive rule... */ { IP = Store8(Tables, IP, BLCOP_TAILSELECT); IP = Store8(Tables, IP, iProdItem); Reduced = TRUE; /* TAILSELECT opcode must do the reducing to shuffle stack correctly */ } else IP = Store8(Tables, IP, BLCOP_LLSELECT); IP = Store16(Tables, IP, Symbol->SelectOffset); } /* else, only 1 rule to choose from, so just transfer control to that rule! */ else { int iRule = AddRule(Tables, Symbol->Rules[0], Symbol); IP = Store8(Tables, IP, BLCOP_CALL); IP = MarkPatch(IP, iRule); } assert(iSymbol>0); /* ???TODO why is this???*/ } else // else, it's an operator trigger { assert(Symbol->LR0 != NULL); fprintf(stderr, "watch out: we don't handle LR(0) yet!\n"); } } if(!Reduced) { IP = Store8(Tables, IP, BLCOP_REDUCE); IP = Store8(Tables, IP, NSymbols); } } Store16(Tables, BLC_HDR_RULEOPCODE_SIZE, IP - IPStart); DumpVerbose("Backpatch opcode addresses.\n"); for(iRule = 0; iRule < Tables->NRules; ++iRule) BackPatch(Tables, iRule, Tables->RuleOffsets.v[iRule] - IPStart); DumpVerbose("Backpatching complete.\n"); assert(IP < (1024*64)); // Opcodes = realloc(Opcodes, IP * sizeof(Opcodes[0])); Tables->NOpcodes = IP; Dump("GenerateParseTables() returns after %d opcodes\n", Tables->NOpcodes); return Tables; }
static void StartRow(TParseTables* Tables) { /* record offset of where next variable-length row starts */ IntAdd(&Tables->LLRowStarts, Tables->LLRows.Size); }