/////////////////////////////////////////////////////////////////////////////// // // GoLangGenerator.cc // ------------------ // GoLangGenerator implementation module // // Design and Implementation by Bjoern Lemke // // (C)opyright 2000-2018 Bjoern Lemke // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; either version 2, or (at your option) // any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; see the file COPYING. If not, write to // the Free Software Foundation, 59 Temple Place - Suite 330, // Boston, MA 02111-1307, USA. // // IMPLEMENTATION MODULE // // Class: GoLangGenerator // // Description: Implementation module for the dragon Go generator // /////////////////////////////////////////////////////////////////////////////// #include #include #include #include #include #include #define LOADCOUNT 50 #include "GoLangGenerator.h" #include "Worm.h" GoLangGenerator::GoLangGenerator(const Chain& parserName, ParserMode mode, bool dynamicTable) : Dragon(parserName, mode, dynamicTable) { } GoLangGenerator::~GoLangGenerator() { } void GoLangGenerator::generateCode() { Chain goLangFileName = _parserName + ".go"; File fout(goLangFileName); fout.open(File::WRITE); fout << "//\n"; fout << "// File: "<< _parserName << ".go\n"; fout << "// This code was produced by the dragon parser generator\n"; fout << "//\n"; fout << "package " << _parserName << "\n"; fout << "\n"; // fout << "import \"fmt\"\n"; // fout << "import \"os\"\n"; fout << "type ParserAction interface {\n"; Production *pProd = _productionSet.First(); while (pProd) { if ( pProd->getAction() ) { fout << " " << pProd->getAction() << "()\n"; } pProd = _productionSet.Next(); } fout << " SetTokenList(tokenList []string)\n"; fout << " IsReserved() bool\n"; fout << " GetAndResetReserved() Token\n"; fout << " NextChar() byte\n"; fout << " BackChar()\n"; fout << "}\n"; fout << "\n"; fout << "const (\n"; fout << " MAXTOKENLEN int = 100\n"; fout << ")\n"; fout << "\n"; fout << "type Symbol int\n"; fout << "\n"; fout << "const (\n"; fout << " Symbol_PROD Symbol = 0\n"; fout << " Symbol_TOKEN Symbol = 1\n"; fout << " Symbol_NONE Symbol = 2\n"; fout << ")\n"; fout << "\n"; fout << "type Token int\n"; fout << "\n"; fout << "const (\n"; int i = 0; Terminal *pTerm = _terminalSet.First(); while (pTerm) { // Token_x Token = 0 fout << " Token_" << pTerm->getName() << " Token = " << i << "\n"; pTerm = _terminalSet.Next(); i++; } fout << " Token_ENDTOKEN Token = " << i << "\n"; fout << ")\n"; fout << "\n"; fout << "//////////////////\n"; fout << "// Scanner part //\n"; fout << "//////////////////\n"; fout << "\n"; fout << "type ScannerStateType int\n"; fout << "\n"; fout << "const (\n"; fout << " ScannerStateType_START ScannerStateType = 0\n"; fout << " ScannerStateType_INTERMEDIATE ScannerStateType = 1\n"; fout << " ScannerStateType_FINAL ScannerStateType = 2\n"; fout << " ScannerStateType_ANY ScannerStateType = 3\n"; fout << ")\n"; fout << "\n"; fout << "type ScannerStateEntry struct {\n"; fout << " state int\n"; fout << " stateType ScannerStateType\n"; fout << "}\n"; fout << "\n"; fout << "type ScannerTransEntry struct {\n"; fout << " state int\n"; fout << " fstate int\n"; fout << " c byte\n"; fout << "}\n"; fout << "\n"; fout << "type Scanner struct {\n"; fout << " tok Token\n"; fout << " stateList []ScannerStateEntry\n"; fout << " transList []ScannerTransEntry\n"; fout << "}\n"; fout << "\n"; fout << "func (s *Scanner) addState(state int, stateType ScannerStateType ) {\n"; fout << " s.stateList = append(s.stateList, ScannerStateEntry{ state: state, stateType: stateType })\n"; fout << "}\n"; fout << "\n"; fout << "func (s *Scanner) addTrans(state int, c byte, fstate int ) {\n"; // fout << " fmt.Printf(\"Adding c = %c\\n\", c)\n"; fout << " s.transList = append(s.transList, ScannerTransEntry{ state: state, fstate: fstate, c: c })\n"; fout << "}\n"; fout << "\n"; fout << "func (s *Scanner) getStateIndex(state int) int {\n"; fout << " i := 0\n"; fout << " for i < len(s.stateList) {\n"; fout << " if s.stateList[i].state == state {\n"; fout << " return i\n"; fout << " }\n"; fout << " i++\n"; fout << " }\n"; fout << " return -1\n"; fout << "}\n"; fout << "\n"; fout << "func (s *Scanner) getTransIndex(state int, c byte ) int {\n"; fout << " i := 0\n"; fout << " for i < len(s.transList) {\n"; // fout << " fmt.Printf(\"Checking transition State=%d C=%c\\n\", s.transList[i].state, s.transList[i].c)\n"; fout << "\n"; fout << " if s.transList[i].state == state && s.transList[i].c == c {\n"; // fout << " fmt.Println(\"Match \\n\")\n"; fout << " return i\n"; fout << " }\n"; fout << " i++\n"; fout << " }\n"; // fout << " fmt.Println(\"#### No Match\\n\")\n"; fout << " return -1\n"; fout << "}\n"; fout << "\n"; fout << "func (s *Scanner) checkPattern( pattern string ) bool {\n"; // fout << " fmt.Println(\"CHECKING Pattern\")\n"; fout << " state := 0\n"; fout << " i := 0\n"; fout << " for i < len(s.stateList) {\n"; fout << " ss := s.stateList[i]\n"; fout << " if ss.stateType == ScannerStateType_START || ss.stateType == ScannerStateType_ANY {\n"; fout << " state = ss.state\n"; fout << " }\n"; fout << " i++\n"; fout << " }\n"; fout << " i = 0\n"; // fout << " fmt.Printf(\"state = %d, c = %c\\n\", i, pattern[i])\n"; fout << " trsidx := s.getTransIndex ( state, pattern[i] )\n"; fout << " if trsidx >= 0 {\n"; // fout << " fmt.Println(\"Found transindex %d\\n\", trsidx)\n"; fout << " for {\n"; fout << " trans := s.transList[trsidx]\n"; fout << " statidx := s.getStateIndex(trans.fstate)\n"; fout << " if statidx >= 0 {\n"; fout << " stateEntry := s.stateList[statidx]\n"; fout << " if i == len(pattern) - 1 && ( stateEntry.stateType == ScannerStateType_FINAL || stateEntry.stateType == ScannerStateType_ANY ) {\n"; fout << " return true\n"; fout << " } else {\n"; fout << " state = trans.fstate\n"; fout << " }\n"; fout << " } else {\n"; fout << " return false\n"; fout << " }\n"; fout << " i++\n"; fout << " trsidx = s.getTransIndex ( state, pattern[i] )\n"; fout << " if trsidx >= 0 {\n"; fout << " trans = s.transList[trsidx]\n"; fout << " } else {\n"; fout << " return false\n"; fout << " }\n"; fout << " }\n"; fout << " } else {\n"; fout << " return false\n"; fout << " }\n"; fout << "}\n"; fout << "\n"; fout << "/////////////////\n"; fout << "// Parser part //\n"; fout << "/////////////////\n"; fout << "\n"; fout << "type Production int\n"; // filter out distinct production symbols SetT symbolSet; pProd = _productionSet.First(); while (pProd) { symbolSet.Insert(pProd->getName()); pProd = _productionSet.Next(); } fout << "const (\n"; Chain* pSymbol = symbolSet.First(); i = 0; while (pSymbol) { fout << " Production_" << *pSymbol << " Production = " << i << "\n"; pSymbol = symbolSet.Next(); i++; } fout << ")\n"; fout << "\n"; fout << "type ParserStateAction int\n"; fout << "const (\n"; fout << " ParserStateAction_SHIFT ParserStateAction = 0\n"; fout << " ParserStateAction_REDUCE ParserStateAction = 1\n"; fout << " ParserStateAction_ACCEPT ParserStateAction = 2\n"; fout << ")\n"; fout << "\n"; fout << "type ParserActionEntry struct {\n"; fout << " state int\n"; fout << " token Token\n"; fout << " action ParserStateAction\n"; fout << " num int\n"; fout << "}\n"; fout << "\n"; fout << "type ParserJumpEntry struct {\n"; fout << " state int\n"; fout << " prod Production\n"; fout << " fstate int\n"; fout << "}\n"; fout << "\n"; fout << "type ProductionEntry struct {\n"; fout << " id int\n"; fout << " prod Production\n"; fout << " numSymbol int\n"; fout << "}\n"; fout << "\n"; fout << "type ParserStackEntry struct {\n"; fout << " s Symbol\n"; fout << " num int\n"; fout << " state int\n"; fout << " tval string\n"; fout << "}\n"; fout << "\n"; fout << "type ParserStack struct {\n"; fout << " s []ParserStackEntry\n"; fout << "}\n"; fout << "\n"; fout << "func (ps *ParserStack) Push(pse ParserStackEntry) {\n"; fout << " ps.s = append(ps.s, pse)\n"; fout << "}\n"; fout << "\n"; fout << "func (ps *ParserStack) Pop() ParserStackEntry {\n"; fout << " // FIXME: What do we do if the stack is empty, though?\n"; fout << " l := len(ps.s)\n"; fout << " res := ps.s[l-1]\n"; fout << " ps.s = ps.s[:l-1]\n"; fout << " return res\n"; fout << "}\n"; fout << "\n"; fout << "func (ps *ParserStack) getPeekState() int {\n"; fout << " l := len(ps.s)\n"; fout << " return ps.s[l-1].state\n"; fout << "}\n"; fout << "\n"; fout << "type Parser struct {\n"; fout << " act ParserAction\n"; fout << " token Token\n"; fout << " tokenVal [MAXTOKENLEN]byte\n"; fout << " tokenLen int\n"; fout << " scannerList []Scanner\n"; fout << " actAction ParserStateAction\n"; fout << " actNum int\n"; fout << " actionMap []ParserActionEntry\n"; fout << " jumpMap []ParserJumpEntry\n"; fout << " prodMap []ProductionEntry\n"; fout << " actFState int\n"; fout << " tokenList []string\n"; fout << " Error string\n"; fout << "}\n"; fout << "\n"; fout << "func (p *Parser) isSepIgnore(c byte) bool {\n"; Chain* pSep = _sepignoreList.First(); while (pSep) { fout << " if c == " << *pSep << " { return true }\n"; pSep = _sepignoreList.Next(); } fout << " return false\n"; fout << "}\n"; fout << "\n"; fout << "func (p *Parser) isSepSign(c byte) bool {\n"; pSep = _sepsignList.First(); while (pSep) { fout << " if c == " << *pSep << " { return true }\n"; pSep = _sepsignList.Next(); } fout << " return false\n"; fout << "}\n"; fout << "\n"; fout << "func (p *Parser) shiftToken() bool {\n"; fout << " i := 0\n"; fout << " var nb byte\n"; fout << " goOn := true\n"; fout << " for goOn {\n"; fout << " nb = p.act.NextChar()\n"; fout << " goOn = p.isSepIgnore(nb) && ! p.act.IsReserved()\n"; fout << " }\n"; fout << " if p.act.IsReserved() == true {\n"; fout << " p.token = p.act.GetAndResetReserved()\n"; fout << " return true\n"; fout << " }\n"; fout << " if nb == 0 {\n"; fout << " p.token = Token_ENDTOKEN\n"; fout << " return true\n"; fout << " }\n"; fout << " if p.isSepSign(nb) {\n"; fout << " p.tokenVal[i]=nb\n"; fout << " i++\n"; fout << " } else {\n"; fout << " for nb != 0 && ! p.isSepIgnore(nb) && ! ( p.isSepSign(nb) && i>0 ) {\n"; fout << " p.tokenVal[i]=nb\n"; fout << " i++\n"; fout << " nb = p.act.NextChar()\n"; fout << " }\n"; fout << " if p.isSepSign(nb) {\n"; fout << " p.act.BackChar()\n"; fout << " }\n"; fout << " }\n"; fout << " p.tokenVal[i]=0\n"; fout << " p.tokenLen=i\n"; fout << " j := 0\n"; fout << " for j < len(p.scannerList) {\n"; fout << " scan := p.scannerList[j]\n"; // fout << " fmt.Printf(\"Check pattern for %s %s\\n\", p.tokenVal, string(p.tokenVal[0:i]))\n"; fout << " if scan.checkPattern( string(p.tokenVal[0:i]) ) {\n"; fout << " p.token = scan.tok\n"; fout << " return true\n"; fout << " }\n"; fout << " j++\n"; fout << " }\n"; fout << " return false\n"; fout << "}\n"; fout << "\n"; fout << "func (p *Parser) getActionIndex(state int, t Token ) int {\n"; fout << " for i :=0; i= 0 {\n"; fout << " actionEntry := p.actionMap[actidx]\n"; fout << " p.actAction = actionEntry.action\n"; fout << " p.actNum = actionEntry.num\n"; fout << " return true\n"; fout << " } else {\n"; fout << " return false\n"; fout << " }\n"; fout << "}\n"; fout << "\n"; fout << "func (p *Parser) getJumpIndex(state int, prod Production ) int {\n"; fout << " for i :=0; i= 0 {\n"; fout << " jumpEntry := p.jumpMap[jmpidx]\n"; fout << " p.actFState = jumpEntry.fstate\n"; fout << " return true\n"; fout << " } else {\n"; fout << " return false\n"; fout << " }\n"; fout << "}\n"; fout << "\n"; fout << "func (p *Parser) loadScanner() {\n"; int sid=0; for (int i = 1; i<=_terminalSet.Size(); i++) { Terminal *pTerm = _terminalSet.First(); while (pTerm && pTerm->getNum() != i) { pTerm = _terminalSet.Next(); } if (pTerm) { Worm w(pTerm->getRegExp(), pTerm->getName()); w.makeOptimalDEA(); Chain scanner = "s" + Chain(sid); fout << scanner << " := Scanner{ tok: Token_" << pTerm->getName() << "}\n"; FSMState *pS = w.getStateTable().First(); while (pS) { fout << " " << scanner << ".addState(" << pS->Num() << " ,"; switch (pS->Type()) { case START: fout << "ScannerStateType_START)\n"; break; case FINAL: fout << "ScannerStateType_FINAL)\n"; break; case ANY: fout << "ScannerStateType_ANY)\n"; break; case NONE: fout << "ScannerStateType_INTERMEDIATE)\n"; break; } pS = w.getStateTable().Next(); } FSMTransition *pT = w.getTransitionTable().First(); while (pT) { fout << " " << scanner << ".addTrans(" << pT->Source() << " ,'" << pT->Sign() << "' ," << pT->Target() << ")\n"; pT = w.getTransitionTable().Next(); } fout << " p.scannerList = append(p.scannerList, " << scanner << ")\n"; fout << "\n"; sid++; } } fout << "}\n"; fout << "\n"; int mcount = 0; fout << "func (p *Parser) loadParser" + Chain(mcount) + "() {\n"; int lcount=0; ParseTableEntry *pPTE = _parseTable.First(); while (pPTE) { Chain token = pPTE->getToken(); if ( token == Chain("$") ) token = Chain("ENDTOKEN"); switch (pPTE->getAction()) { case ParseTableEntry::SHIFT: fout << " p.actionMap = append(p.actionMap, ParserActionEntry{" << "state: " << pPTE->getState() << ", token: Token_" << token << ", action: ParserStateAction_SHIFT" << ", num: " << pPTE->getArg() << "})\n"; break; case ParseTableEntry::REDUCE: fout << " p.actionMap = append(p.actionMap, ParserActionEntry{" << "state: " << pPTE->getState() << ", token: Token_" << token << ", action: ParserStateAction_REDUCE" << ", num: " << pPTE->getArg() << "})\n"; break; case ParseTableEntry::JUMP: fout << " p.jumpMap = append(p.jumpMap, ParserJumpEntry{" << "state: " << pPTE->getState() << ", prod: Production_" << token << ", fstate: " << pPTE->getArg() << "})\n"; break; case ParseTableEntry::ACCEPT: fout << " p.actionMap = append(p.actionMap, ParserActionEntry{" << "state: " << pPTE->getState() << ", token: Token_" << token << ", action: ParserStateAction_ACCEPT" << ", num: " << pPTE->getArg() << "})\n"; break; } lcount++; pPTE = _parseTable.Next(); if ( pPTE && lcount == LOADCOUNT ) { mcount++; lcount=0; fout << "}\n"; fout << "func (p *Parser) loadParser" + Chain(mcount) + "() {\n"; } } fout << "}\n"; fout << "\n"; fout << "func (p *Parser) loadProduction() {\n"; pProd = _productionSet.First(); while (pProd) { fout << " p.prodMap = append(p.prodMap, ProductionEntry {" << "id: " << pProd->getId() << ", prod: Production_" << pProd->getName() << ", numSymbol : " << pProd->getMaxPos() << "});\n"; pProd = _productionSet.Next(); } fout << "}\n"; fout << "\n"; fout << "func (p *Parser) Parse () bool {\n"; fout << " ps := ParserStack{ s: make([]ParserStackEntry,0)}\n"; fout << " ps.Push( ParserStackEntry {\n"; fout << " s: Symbol_NONE,\n"; fout << " num: 0,\n"; fout << " state: 0 ,\n"; fout << " tval: \"NONE\" } )\n"; fout << " if p.shiftToken() == false {\n"; fout << " p.Error = \"Invalid token <\" + string(p.tokenVal[0:p.tokenLen]) + \">\"\n"; fout << " return false\n"; fout << " } else {\n"; fout << " for {\n"; // fout << " fmt.Printf(\"Go on parsing : peekState = %d, token = %d\\n\", ps.getPeekState(), p.token)\n"; fout << " if p.getAction(ps.getPeekState(), p.token) {\n"; fout << " if p.actAction == ParserStateAction_SHIFT {\n"; fout << " ps.Push( ParserStackEntry {\n"; fout << " s: Symbol_TOKEN,\n"; fout << " num: int(p.token),\n"; fout << " state: p.actNum,\n"; fout << " tval: string(p.tokenVal[0:p.tokenLen]) } )\n"; fout << " if p.shiftToken() == false {\n"; fout << " p.Error = \"Invalid token <\" + string(p.tokenVal[0:p.tokenLen]) + \">\"\n"; fout << " return false\n"; fout << " // print error here : invalid token\n"; fout << " }\n"; fout << " } else if p.actAction == ParserStateAction_REDUCE {\n"; fout << " p.tokenList = nil\n"; fout << " prodidx := p.getProdIndex(p.actNum)\n"; fout << " if prodidx == -1 {\n"; fout << " p.Error = \"No production entry found\"\n"; fout << " return false\n"; fout << " }\n"; fout << " for i := 0; i < p.prodMap[prodidx].numSymbol; i++ {\n"; fout << " ste := ps.Pop();\n"; fout << " if ste.s == Symbol_TOKEN {\n"; fout << " p.tokenList = append(p.tokenList, ste.tval)\n"; fout << " }\n"; fout << " }\n"; fout << " if p.getJump ( ps.getPeekState(), p.prodMap[prodidx].prod ) {\n"; fout << " ps.Push( ParserStackEntry {\n"; fout << " s: Symbol_PROD,\n"; fout << " num: p.prodMap[prodidx].id,\n"; fout << " state: p.actFState,\n"; fout << " tval: string(p.tokenVal[0:p.tokenLen]) } )\n"; fout << " } else {\n"; fout << " p.Error = \"Cannot reduce after token <\" + string(p.tokenVal[0:p.tokenLen]) + \">\"\n"; fout << " return false\n"; fout << " }\n"; fout << " switch p.actNum {\n"; pProd = _productionSet.First(); while (pProd) { if ( pProd->getId() != 0 && pProd->getAction() ) { fout << " case " << pProd->getId() << ":\n"; fout << " p.act.SetTokenList(p.tokenList)\n"; fout << " p.act." << pProd->getAction() << "()\n"; } pProd = _productionSet.Next(); } fout << " }\n"; fout << " p.tokenList = nil\n"; fout << " } else if p.actAction == ParserStateAction_ACCEPT {\n"; pProd = _productionSet.First(); while (pProd) { if ( pProd->getId() == 0 && pProd->getAction() ) { fout << " p.act.SetTokenList(p.tokenList)\n"; fout << " p.act." << pProd->getAction() << "()\n"; } pProd = _productionSet.Next(); } fout << " return true\n"; fout << " }\n"; fout << " } else {\n"; fout << " p.Error = \"Parse error at token <\" + string(p.tokenVal[0:p.tokenLen]) + \">\"\n"; fout << " return false\n"; fout << " // print error message parse error\n"; fout << " }\n"; fout << " }\n"; fout << " }\n"; fout << "}\n"; fout << "\n"; // constructor fout << "func NewParser( a ParserAction ) Parser {\n"; fout << " p := Parser{ act: a }\n"; fout << " p.loadScanner()\n"; for ( int i=0; i<=mcount; i++) { fout << " p.loadParser" + Chain(i) + "()\n"; } fout << " p.loadProduction()\n"; fout << " return p\n"; fout << "}\n"; fout.close(); }