Related
So I have this problem with a regex. As seen below I use the regex"CreateRuntimeTxd%(.*%)"
local _code = [[
Citizen.CreateThread(function()
local dui = CreateDui("https://www.youtube.com/watch?v=dQw4w9WgXcQ", 1920, 1080)
local duiHandle = GetDuiHandle(dui)
CreateRuntimeTextureFromDuiHandle(CreateRuntimeTxd('rick'), 'nevergonnagiveuup', duiHandle)
while true do
Wait(0)
DrawSprite('rick', 'nevergonnagiveuup', 0.5, 0.5, 1.0, 1.0, 0, 255, 255, 255, 255)
end
end)
]]
for match in string.gmatch(_code, "CreateRuntimeTxd%(.*%)") do
print(match)
end
So the problem is that the current regex matches
CreateRuntimeTxd('rick'), 'nevergonnagiveuup', duiHandle)
while true do
Wait(0)
DrawSprite('rick', 'nevergonnagiveuup', 0.5, 0.5, 1.0, 1.0, 0, 255, 255, 255, 255)
end
end)
but i only want it to match CreateRuntimeTxd('rick')
You need to use
for match in string.gmatch(_code, "CreateRuntimeTxd%(.-%)") do
print(match)
end
See the Lua demo. Details:
CreateRuntimeTxd - a literal text
%( - a literal ( char
.- - zero or more characters (the least amount needed to complete a match)
%) - a ) char.
You may also use a negated character class, [^()]* (if there can be no ( and ) before )) or [^)]* (if ) chars are still expected) instead of .-:
for match in string.gmatch(_code, "CreateRuntimeTxd%([^()]*%)") do
print(match)
end
See this Lua demo.
Script code is for a robot and consist of a block of codes that are waypoints to drop products. I want to save lines by running a single line of code only once and return to the top of the loop and only run the next line of code until the previous line has run once.
function pim60()
script_common_interface("SICKCamera","takePhoto")
script_common_interface("SICKCamera","getResult")
Located = script_common_interface("SICKCamera","partLocated")
end
function intermediatemoves()
X = script_common_interface("SICKCamera","getXposition")
Y = script_common_interface("SICKCamera","getYposition")
R = script_common_interface("SICKCamera","getRotation")
z_offset = 0.24
local offset_pose = {}
table.insert(offset_pose,X)
table.insert(offset_pose,Y)
table.insert(offset_pose,z_offset)
camera_rz = rpy2quaternion({d2r(-180.0), d2r(0.0), d2r(-90.0) + d2r(R)})
move_joint(get_target_pose(offset_pose,camera_rz,false,{0.0, 0.0, 0.0},{1.0, 0.0, 0.0, 0.0}),true)
z_grab = 0.17
local grab_pose = {}
table.insert(grab_pose,X)
table.insert(grab_pose,Y)
table.insert(grab_pose,z_grab)
move_line(get_target_pose(grab_pose,camera_rz,false,{0.0, 0.0, 0.0},{1.0, 0.0, 0.0, 0.0}),true)
set_step_breakpoint()
--(Logic tree item : Gripper) Gripper
script_common_interface("Gripper", "set_robotiq_param|9, 155, 255, 255, true")
set_step_breakpoint()
--(Logic tree item : Move) Movedrp
--(Logic tree item : Waypoint) Waypoint01
move_joint({1.047662, -0.552625, -1.753926, 0.374278, -1.571027, 0.588803}, true)
set_step_breakpoint()
--(Logic tree item : Waypoint) Waypoint02
move_joint({2.307135, 0.811214, -0.349017, 0.045296, -1.569157, -0.006474}, true)
set_step_breakpoint()
end
function returntohome()
--WAYPOINT FOR COLLISION AVOIDANCE
--(Logic tree item : Waypoint) Waypoint02
move_joint({2.307135, 0.811214, -0.349017, 0.045296, -1.569157, -0.006474}, true)
set_step_breakpoint()
--!!HOME POSITION JOINT 5 CAN AFFECT PICK COLLISION WITH PART
--(Logic tree item : Waypoint) Waypointhome
move_joint({1.321444, -0.626547, -2.252496, -0.137991, -1.518901, -0.006779}, true)
set_step_breakpoint()
end
--Open gripper and home
script_common_interface("Gripper", "set_robotiq_param|9, 0, 255, 255, false")
--!!HOME POSITION JOINT 5 CAN AFFECT PICK COLLISION WITH PART
--(Logic tree item : Waypoint) Waypointhome
move_joint({1.321444, -0.626547, -2.252496, -0.137991, -1.518901, -0.006779}, true)
set_step_breakpoint()
--LoopA
repeat
pim60()
until (Located == 1)
intermediatemoves()
move_joint({2.337869, 1.478278, 0.177188, -0.416970, -1.569186, -0.006448}, true)
script_common_interface("Gripper", "set_robotiq_param|9, 0, 0, 83, true")
returntohome()
--LoopB
repeat
pim60()
until (Located == 1)
intermediatemoves()
move_joint({2.145543, 1.478292, 0.177206, -0.416904, -1.569186, -0.006415}, true)
script_common_interface("Gripper", "set_robotiq_param|9, 0, 0, 83, true")
returntohome()
--LoopC
repeat
pim60()
until (Located == 1)
intermediatemoves()
move_joint({2.020320, 1.478307, 0.177206, -0.416897, -1.569190, -0.006412}, true)
script_common_interface("Gripper", "set_robotiq_param|9, 0, 0, 83, true")
returntohome()
--LoopD
repeat
pim60()
until (Located == 1)
intermediatemoves()
move_joint({1.845862, 1.478325, 0.177202, -0.416893, -1.569190, -0.006412}, true)
script_common_interface("Gripper", "set_robotiq_param|9, 0, 0, 83, true")
returntohome()
This is the code being used now and nowhere close to the function that is desired. I've created 4 repeats "loops" that contains 4 different end position to drop products.
If you want to cut on the code duplication (not line number, that's silly), you can wrap the duplicated code in a function.
function locate()
repeat
script_common_interface("SICKCamera","takePhoto")
script_common_interface("SICKCamera","getResult")
until (script_common_interface("SICKCamera","partLocated") == 1)
end
Further, you'd encapsulate the steps
function go_fetch(destination)
locate()
intermediatemoves()
move_joint(destination, true)
script_common_interface("Gripper", "set_robotiq_param|9, 0, 0, 83, true")
returntohome()
end
--instead of LoopsABCD
local destinations = {
{2.020320, 1.478307, 0.177206, -0.416897, -1.569190, -0.006412},
{2.145543, 1.478292, 0.177206, -0.416904, -1.569186, -0.006415},
--etc...
}
for _,d in ipairs(destinations) do
go_fetch(d)
end
You can refactor your other functions to be more concise as well.
p.s. These links may not be immediately related, but I still want to mention them here 1,2
Well you set a flag that helps you remember if you already ran that first line. Or you use the loop counter if you have one.
In many cases it would suffice to simply run that one-time thing befor you enter the loop. But here's a small example:
for i = 0, 10 do
if i == 0 then
print("Enter bar")
else
print("Drink beer no " .. i)
end
end
or
local inBar
while not drunk do
if not inBar then
print("Enter bar")
inBar = true
else
print("Drink another beer")
end
end
I need help with a really annoying error I've been getting with my GMOD gamemode. I am trying to make a custom menu, but I get this error:
[ERROR] gamemodes/tdm/gamemode/custom_menu.lua:20: attempt to call global 'addButtons' (a nil value)
1. gameMenu - gamemodes/tdm/gamemode/custom_menu.lua:20
2. unknown - gamemodes/tdm/gamemode/custom_menu.lua:32
3. include - [C]:-1
4. unknown - gamemodes/tdm/gamemode/cl_init.lua:3
Here is my code:
custom_menu.lua
local Menu
function gameMenu()
if(Menu == nil) then
Menu = vgui.Create("DFrame")
Menu:SetSize(750, 500)
Menu:SetPos(ScrW() / 2 - 325, ScrH() / 2 - 250)
Menu:SetTitle("Gamemode Menu")
Menu:SetDraggable(true)
Menu:ShowCloseButton(false)
Menu:SetDeleteOnClose(false)
Menu.Paint = function()
surface.SetDrawColor(60, 60, 60, 255)
surface.DrawRect(0, 0, Menu:GetWide(), Menu:GetTall())
surface.SetDrawColor(40, 40, 40, 255)
surface.DrawRect(0, 24, Menu:GetWide(), 1)
end
addButtons(Menu)
gui.EnableScreenClicker(true)
else
if(Menu:IsVisible()) then
Menu:SetVisible(false)
gui.EnableScreenClicker(false)
else
Menu:SetVisible(true)
gui.EnableScreenClicker(true)
end
end
end
concommand.Add("open_game_menu", gameMenu())
function addButtons(Menu)
local playerButton = vgui.Create("DButton")
playerButton:SetParent(Menu)
playerButton:SetText("")
playerButton:SetSize(100, 50)
playerButton:SetPos(0, 25)
playerButton.Paint = function()
--Color of entire button
surface.SetDrawColor(50, 50, 50, 255)
surface.DrawRect(0, 0, playerButton:GetWide(), playerButton:GetTall())
--Draw Bottom and Right borders
surface.SetDrawColor(40, 40, 40, 255)
surface.DrawRect(0, 49, playerButton:GetWide(), 1)
surface.DrawRect(99, 0, 1, playerButton:GetTall())
--Draw Text
draw.DrawText("Player", "DermaDefaultBold", playerButton:GetWide() / 2, 17, Color(255, 255, 255, 255), 1)
end
playerButton.DoClick = function(playerButton)
local playerPanel = Menu:Add("PlayerPanel")
end
local shopButton = vgui.Create("DButton")
shopButton:SetParent(Menu)
shopButton:SetText("")
shopButton:SetSize(100, 50)
shopButton:SetPos(0, 75)
shopButton.Paint = function()
--Color of entire button
surface.SetDrawColor(50, 50, 50, 255)
surface.DrawRect(0, 0, shopButton:GetWide(), shopButton:GetTall())
--Draw Bottom and Right borders
surface.SetDrawColor(40, 40, 40, 255)
surface.DrawRect(0, 49, shopButton:GetWide(), 1)
surface.DrawRect(99, 0, 1, shopButton:GetTall())
--Draw Text
draw.DrawText("Shop", "DermaDefaultBold", shopButton:GetWide() / 2, 17, Color(255, 255, 255, 255), 1)
end
shopButton.DoClick = function(shopButton)
local shopPanel = Menu:Add("ShopPanel")
end
end
--Player Panel
PANEL = {} -- Create an empty panel
function PANEL:Init() --Initialize the panel
self:SetSize(650, 475)
self:SetPos(100, 25)
end
function PANEL:Paint(w, h)
draw.RoundedBox(0, 0, 0, w, h, Color(0, 0, 0, 255))
end
vgui.Register("PlayerPanel", PANEL, "Panel")
--End Player Panel
--Shop Panel
PANEL = {} -- Create an empty panel
function PANEL:Init() --Initialize the panel
self:SetSize(650, 475)
self:SetPos(100, 25)
end
function PANEL:Paint(w, h)
draw.RoundedBox(0, 0, 0, w, h, Color(255, 255, 255, 255))
end
vgui.Register("ShopPanel", PANEL, "Panel")
--End Shop Panel
init.lua:
AddCSLuaFile( "shared.lua" )
AddCSLuaFile( "cl_init.lua" )
AddCSLuaFile( "testhud.lua" )
local open = false
include ( 'shared.lua' )
local open = false
function GM:PlayerInitialSpawn(ply)
if(ply:GetPData("playerLvl") == nil) then
ply:SetNWInt("playerLvl", 1)
else
ply:SetNWInt("playerLvl", ply:GetPData("playerLvl"))
end
if(ply:GetPData("playerExp") == nil) then
ply:SetNWInt("playerExp", 0)
else
ply:SetNWInt("playerExp", ply:GetPData("playerExp"))
end
if(ply:GetPData("playerMoney") == nil) then
ply:SetNWInt("playerMoney", 0)
else
ply:SetNWInt("playerMoney", ply:GetPData("playerMoney"))
end
end
function GM:OnNPCKilled(npc, attacker, inflictor)
attacker:SetNWInt("playerMoney", attacker:GetNWInt("playerMoney") + 100)
attacker:SetNWInt("playerExp", attacker:GetNWInt("playerExp") + 100)
checkForLevel(attacker)
end
function GM:PlayerDeath(victim, inflictor, attacker)
attacker:SetNWInt("playerMoney", attacker:GetNWInt("playerMoney") + 100)
attacker:SetNWInt("playerExp", attacker:GetNWInt("playerExp") + 100)
checkForLevel(attacker)
end
function GM:PlayerLoadout(ply)
ply:Give("m9k_l85")
ply:Give("m9k_colt1911")
ply:Give("m9k_knife")
ply:Give("m9k_m61_frag")
ply:GiveAmmo(500, "ar2", true)
ply:GiveAmmo(100, "pistol", true)
return true
end
function checkForLevel(ply)
local expToLevel = (ply:GetNWInt("playerLvl") * 100) * 2
local curExp = ply:GetNWInt("playerExp")
local curLvl = ply:GetNWInt("playerLvl")
if(curExp >= expToLevel) then
curExp = curExp - expToLevel
ply:SetNWInt("playerExp", curExp)
ply:SetNWInt("playerLvl", curLvl + 1)
end
end
function GM:PlayerDisconnected(ply)
ply:SetPData("playerExp", ply:GetNWInt("playerExp"))
ply:SetPData("playerLvl", ply:GetNWInt("playerLvl"))
ply:SetPData("playerMoney", ply:GetNWInt("playerMoney"))
end
function GM:ShutDown()
for k, v in pairs(player.GetAll()) do
v:SetPData("playerExp", v:GetNWInt("playerExp"))
v:SetPData("playerLvl", v:GetNWInt("playerLvl"))
v:SetPData("playerMoney", v:GetNWInt("playerMoney"))
end
end
function GM:ShowSpare2(ply)
ply:ConCommand("open_game_menu")
end
Thanks!
-Graham
You call
concommand.Add("open_game_menu", gameMenu())
which calls addButtons(Menu) which is nil at this point as the function definition follows after concommand.Add("open_game_menu", gameMenu()).
It's all there. You just have to read the error message.
Change the order in your script to fix the error.
I'm trying to use Pybrain to predict sequences of characters belonging to the Reber grammar.
Concretely what I'm doing is generating strings using the Reber grammar graph (you can check it here : http://www.felixgers.de/papers/phd.pdf page 22). An example of such string could be BPVVE. I want my neural network to learn the underlying rules of the grammar. For each of these string I create a sequence that would typically look like this :
[B, T, S, X, P, V, E,] , [B, T, S, X, P, V, E,]
B -> value = [1, 0, 0, 0, 0, 0, 0,] , target = [0, 0, 0, 0, 1, 0, 0,]
P -> value = [0, 0, 0, 0, 1, 0, 0,] , target = [0, 0, 0, 0, 0, 1, 0,]
V -> value = [0, 0, 0, 0, 0, 1, 0,] , target = [0, 0, 0, 0, 0, 1, 0,]
V -> value = [0, 0, 0, 0, 0, 1, 0,] , target = [0, 0, 0, 0, 0, 0, 1,]
E -> E is ignored for now because it marks the end
as you can see the value is just a 7-d vector representing the current letter and the target is the next letter in the Reber word.
Here is the code I'm trying to run :
#!/usr/bin/python
import reberGrammar as reber
import random as rnd
from pylab import *
from pybrain.supervised import RPropMinusTrainer
from pybrain.supervised import BackpropTrainer
from pybrain.datasets import SequenceClassificationDataSet
from pybrain.structure.modules import LSTMLayer, SoftmaxLayer
from pybrain.tools.validation import testOnSequenceData
from pybrain.tools.shortcuts import buildNetwork
def reberToListInt(word): #e.g. "BPVVE" -> [0,4,3,3,5]
out = [None]*len(word)
for i,l in enumerate(word):
if l == 'B':
out[i] = 0
elif l == 'T':
out[i] = 1
elif l == 'S':
out[i] = 2
elif l == 'V':
out[i] = 3
elif l == 'P':
out[i] = 4
elif l == 'E':
out[i] = 5
else :
out[i] = 6
return out
def buildReberDataSet(numSample):
"""Generate a 7 class dataset"""
reberLexicon = reber.ReberGrammarLexicon(numSample)
DS = SequenceClassificationDataSet(7, 7, nb_classes=7)
for rw in reberLexicon.lexicon:
DS.newSequence()
rw2 = reberToListInt(rw)
for i in range(len(rw2)-1): #inserting one letter at a time
inpt = outpt = [0.0]*7
inpt[rw2[i]]=1.0
outpt[rw2[i+1]]=1.0
DS.addSample(inpt,outpt)
return DS
def printDataSet(DS, numLines): #just to print some stat
print "\t############"
print "Number of sequences: ",DS.getNumSequences()
print "Input and output dimensions: ", DS.indim,"\t", DS.outdim
print "\n"
for i in range(numLines):
for inp, target in DS.getSequenceIterator(i):
print inp,
print "\n"
print "\t#############"
'''Dataset creation / split into training and test sets'''
fullDS = buildReberDataSet(700)
tstdata, trndata = fullDS.splitWithProportion( 0.25 )
trndata._convertToOneOfMany( bounds=[0.,1.])
tstdata._convertToOneOfMany( bounds=[0.,1.])
#printDataSet(trndata,2)
'''Network setup / training'''
rnn = buildNetwork( trndata.indim, 7, trndata.outdim, hiddenclass=LSTMLayer, outclass=SoftmaxLayer, outputbias=False, recurrent=True)
trainer = RPropMinusTrainer( rnn, dataset=trndata, verbose=True )
#trainer = BackpropTrainer( rnn, dataset=trndata, verbose=True, momentum=0.9, learningrate=0.5 )
trainError=[]
testError =[]
#errors = trainer.trainUntilConvergence()
for i in range(9):
trainer.trainEpochs( 2 )
trainError.append(100. * (1.0-testOnSequenceData(rnn, trndata)))
testError.append(100. * (1.0-testOnSequenceData(rnn, tstdata)))
print "train error: %5.2f%%" % trainError[i], ", test error: %5.2f%%" % testError[i]
plot(trainError)
hold(True)
plot(testError)
show()
I fail to train this net. The errors are fluctuating a lot and there is no real convergence. I would really appreciate some advises on this.
Here is the code I'm using to generate Reber strings :
#!/usr/bin/python
import random as rnd
class ReberGrammarLexicon(object):
lexicon = set() #contain Reber words
graph = [ [(1,'T'), (5,'P')], \
[(1, 'S'), (2, 'X')], \
[(3,'S') ,(5, 'X')], \
[(6, 'E')], \
[(3, 'V'),(2, 'P')], \
[(4, 'V'), (5, 'T')] ] #store the graph
def __init__(self, num, maxSize = 1000): #fill Lexicon with num words
self.maxSize = maxSize
if maxSize < 5:
raise NameError('maxSize too small, require maxSize > 4')
while len(self.lexicon) < num:
word = self.generateWord()
if word != None:
self.lexicon.add(word)
def generateWord(self): #generate one word
c = 2
currentEdge = 0
word = 'B'
while c <= self.maxSize:
inc = rnd.randint(0,len(self.graph[currentEdge])-1)
nextEdge = self.graph[currentEdge][inc][0]
word += self.graph[currentEdge][inc][1]
currentEdge = nextEdge
if currentEdge == 6 :
break
c+=1
if c > self.maxSize :
return None
return word
Thanks,
Best
I have a quite old C corporate parser code that was generated from an ancient Yacc and uses the yyact, yypact, yypgo, yyr1, yyr2, yytoks, yyexca, yychk, yydef tables (but no yyreds though) and the original grammar source is lost. That legacy piece of code need revamping but I cannot afford to recode it from scratch.
Could it be possible to mechanically retrieve / regenerate the parsing rules by deduction of the parsing tables in order to reconstruct the grammar?
Example with a little expression parser that I can process with the same ancient Yacc:
yytabelem yyexca[] ={
-1, 1,
0, -1,
-2, 0,
-1, 21,
261, 0,
-2, 8,
};
yytabelem yyact[]={
13, 9, 10, 11, 12, 23, 8, 22, 13, 9,
10, 11, 12, 9, 10, 11, 12, 1, 2, 11,
12, 6, 7, 4, 3, 0, 16, 5, 0, 14,
15, 0, 0, 0, 17, 18, 19, 20, 21, 0,
0, 24 };
yytabelem yypact[]={
-248, -1000, -236, -261, -236, -236, -1000, -1000, -248, -236,
-236, -236, -236, -236, -253, -1000, -263, -245, -245, -1000,
-1000, -249, -1000, -248, -1000 };
yytabelem yypgo[]={
0, 17, 24 };
yytabelem yyr1[]={
0, 1, 1, 1, 2, 2, 2, 2, 2, 2,
2, 2, 2 };
yytabelem yyr2[]={
0, 8, 12, 0, 6, 6, 6, 6, 6, 6,
4, 2, 2 };
yytabelem yychk[]={
-1000, -1, 266, -2, 259, 263, 257, 258, 267, 262,
263, 264, 265, 261, -2, -2, -1, -2, -2, -2,
-2, -2, 260, 268, -1 };
yytabelem yydef[]={
3, -2, 0, 0, 0, 0, 11, 12, 3, 0,
0, 0, 0, 0, 0, 10, 1, 4, 5, 6,
7, -2, 9, 3, 2 };
yytoktype yytoks[] =
{
"NAME", 257,
"NUMBER", 258,
"LPAREN", 259,
"RPAREN", 260,
"EQUAL", 261,
"PLUS", 262,
"MINUS", 263,
"TIMES", 264,
"DIVIDE", 265,
"IF", 266,
"THEN", 267,
"ELSE", 268,
"LOW", 269,
"UMINUS", 270,
"-unknown-", -1 /* ends search */
};
/* am getting this table in my example,
but it is not present in the studied parser :^( */
char * yyreds[] =
{
"-no such reduction-",
"stmt : IF exp THEN stmt",
"stmt : IF exp THEN stmt ELSE stmt",
"stmt : /* empty */",
"exp : exp PLUS exp",
"exp : exp MINUS exp",
"exp : exp TIMES exp",
"exp : exp DIVIDE exp",
"exp : exp EQUAL exp",
"exp : LPAREN exp RPAREN",
"exp : MINUS exp",
"exp : NAME",
"exp : NUMBER",
};
I am looking to retrieve
stmt : IF exp THEN stmt
| IF exp THEN stmt ELSE stmt
| /*others*/
;
exp : exp PLUS exp
| exp MINUS exp
| exp TIMES exp
| exp DIVIDE exp
| exp EQUAL exp
| LPAREN exp RPAREN
| MINUS exp
| NAME
| NUMBER
;
Edit: I have stripped down the generated parser of my example for clarity, but to help some analysis i have published the whole generated code as a gist. Please not that for some unknown reason there is no yyreds table in the parser I am trying to study / change. I suppose it would not have been fun :^S
An interesting problem. Just from matching the tables to the grammar, it seems that yyr1 and yyr2 give you the "outline" of the rules -- yyr1 is the symbol on the left side of each rule, while yyr2 is 2x the number of symbols on the right side. You also have the names of all the terminals in a convenient table. But the names of the non-terminals are lost.
To figure out which symbols go on the rhs of each rule, you'll need to reconstruct the state machine from the tables, which likely involves reading and understanding the code in the y.tab.c file that actually does the parsing. Some of the tables (looks like yypact, yychk and yydef) are indexed by state number. It seems likely that yyact is indexed by yypact[state] + token. But those are only guesses. You need to look at the parsing code and understand how its using the tables to encode possible shifts, reduces, and gotos.
Once you have the state machine, you can backtrack from the states containing reductions of specific rules through the states that have shifts and gotos of that rule. A shift into a reduction state means the last symbol on the rhs of that rule is the token shifted. A goto into a reduction state means the last symbol on the rhs is symbol for the goto. The second-to-last symbol comes from the shift/goto to the state that does the shift/goto to the reduction state, and so on.
edit
As I surmised, yypact is the 'primary action' for a state. If the value is YYFLAG (-1000), this is a reduce-only state (no shifts). Otherwise it is a potential shift state and yyact[yypact[state] + token] gives you the potential state to shift to. If yypact[state] + token is out of range for the yyact table, or the token doesn't match the entry symbol for that state, then there's no shift on that token.
yychk is the entry symbol for each state -- a positive number means you shift to that state on that token, while a negative means you goto that state on that non-terminal.
yydef is the reduction for that state -- a positive number means reduce that rule, while 0 means no reduction, and -2 means two or more possible reductions. yyexca is the table of reductions for those states with more than one reduction. The pair -1 state means the following entries are for the given state; following pairs of token rule mean that for lookahead token it should reduce rule. A -2 for token is a wildcard (end of the list), while a 0 for the rule means no rule to reduce (an error instead), and -1 means accept the input.
The yypgo table is the gotos for a symbol -- you go to state yyact[yypgo[sym] + state + 1] if that's in range for yyact and yyact[yypgo[sym]] otherwise.
So to reconstruct rules, look at the yydef and yyexca tables to see which states reduce each rule, and go backwards to see how the state is reached.
For example, rule #1. From the yyr1 and yyr2 tables, we know its of the form S1: X X X X -- non-terminal #1 on the lhs and 4 symbols on the rhs. Its reduced in state 16 (from the yydef table, and the accessing symbol for state 16 (from yychk) is -1. So its:
S1: ?? ?? ?? S1
You get into state 16 from yyact[26], and yypgo[1] == 17, so that means the goto is coming from state 8 (26 == yypgo[1] + 8 + 1. The accessing symbol of state 8 is 267 (THEN) so now we have:
S1: ?? ?? THEN S1
You get into state 8 from yyact[6], so the previous state has yypact[state] == -261 which is state 3. yychk[3] == -2, so we have:
S1: ?? S2 THEN S1
You get into state 3 from yyact[24], and yypgo[2] == 24 so any state might goto 3 here. So we're now kind of stuck for this rule; to figure out what the first symbol is, we need to work our way forward from state 0 (the start state) to reconstruct the state machine.
edit
This code will decode the state machine from the table format above and print out all the shift/reduce/goto actions in each state:
#define ALEN(A) (sizeof(A)/sizeof(A[0]))
for (int state = 0; state < ALEN(yypact); state++) {
printf("state %d:\n", state);
for (int i = 0; i < ALEN(yyact); i++) {
int sym = yychk[yyact[i]];
if (sym > 0 && i == yypact[state] + sym)
printf("\ttoken %d shift state %d\n", sym, yyact[i]);
if (sym < 0 && -sym < ALEN(yypgo) &&
(i == yypgo[-sym] || i == yypgo[-sym] + state + 1))
printf("\tsymbol %d goto state %d\n", -sym, yyact[i]); }
if (yydef[state] > 0)
printf("\tdefault reduce rule %d\n", yydef[state]);
if (yydef[state] < 0) {
for (int i = 0; i < ALEN(yyexca); i+= 2) {
if (yyexca[i] == -1 && yyexca[i+1] == state) {
for (int j = i+2; j < ALEN(yyexca) && yyexca[j] != -1; j += 2) {
if (yyexca[j] < 0) printf ("\tdefault ");
else printf("\ttoken %d ", yyexca[j]);
if (yyexca[j+1] < 0) printf("accept\n");
else if(yyexca[j+1] == 0) printf("error\n");
else printf("reduce rule %d\n", yyexca[j+1]); } } } } }
It will produce output like:
state 0:
symbol 1 goto state 1
token 266 shift state 2
symbol 2 goto state 3
default reduce rule 3
state 1:
symbol 1 goto state 1
symbol 2 goto state 3
token 0 accept
default error
state 2:
symbol 1 goto state 1
token 257 shift state 6
token 258 shift state 7
token 259 shift state 4
symbol 2 goto state 3
token 263 shift state 5
state 3:
token 261 shift state 13
token 262 shift state 9
token 263 shift state 10
token 264 shift state 11
token 265 shift state 12
token 267 shift state 8
symbol 1 goto state 1
symbol 2 goto state 3
..etc
which should be helpful for reconstructing the grammar.