MI2 grammar

Daniel Gutson daniel.gutson@tallertechnologies.com
Wed May 18 19:55:00 GMT 2016


Hi,

   this is a very initial version of the MI grammar for lex and yacc.

This is actually a standalone application (containing C++ source code)
that accepts
the gdb MI output; the important part is the .y and .l files, the rest is just
a C++ thing using the parser.

I'm posting this here for two purposes:

 - so other people can use it if interested
 - to propose create an official grammar by adding the .l and .y files
somewhere to the
   source tree, and keeping them updated if the grammar changes.

As a side note, the quit command replies a nonconforming output since
the "(gdb)" string is not included,
as required in https://sourceware.org/gdb/onlinedocs/gdb/GDB_002fMI-Output-Syntax.html#GDB_002fMI-Output-Syntax

Thanks,

   Daniel.


diff -Naur ./nothing/examples/example1.mi ./MI/examples/example1.mi
--- ./nothing/examples/example1.mi    1969-12-31 21:00:00.000000000 -0300
+++ ./MI/examples/example1.mi    2016-05-18 14:41:26.814610554 -0300
@@ -0,0 +1,3 @@
+^done,bkpt={number="1",type="breakpoint",disp="keep",enabled="y",addr="0x00000000004007c5",func="main()",file="shuffle.cpp",fullname="/home/dgutson/sandbox/shuffle.cpp",line="223",thread-groups=["i1"],times="0",original-location="main"}
+(gdb)
+
diff -Naur ./nothing/examples/example2.mi ./MI/examples/example2.mi
--- ./nothing/examples/example2.mi    1969-12-31 21:00:00.000000000 -0300
+++ ./MI/examples/example2.mi    2016-05-18 14:41:31.994610323 -0300
@@ -0,0 +1,17 @@
+^done,OSDataTable={nr_rows="9",nr_cols="3",hdr=[{width="10",alignment="-1",col_name="col0",colhdr="Type"},{width="10",alignment="-1",col_name="col1",colhdr="Description"},{width="10",alignment="-1",col_name="col2",colhdr="Title"}],body=[item={col0="processes",col1="Listing
+of all processes",col2="Processes"},item={col0="procgroups",col1="Listing
+of all process groups",col2="Process
+groups"},item={col0="threads",col1="Listing of all
+threads",col2="Threads"},item={col0="files",col1="Listing of all file
+descriptors",col2="File
+descriptors"},item={col0="sockets",col1="Listing of all
+internet-domain
+sockets",col2="Sockets"},item={col0="shm",col1="Listing of all
+shared-memory regions",col2="Shared-memory
+regions"},item={col0="semaphores",col1="Listing of all
+semaphores",col2="Semaphores"},item={col0="msg",col1="Listing of all
+message queues",col2="Message
+queues"},item={col0="modules",col1="Listing of all loaded kernel
+modules",col2="Kernel modules"}]}
+(gdb)
+
diff -Naur ./nothing/examples/example3.mi ./MI/examples/example3.mi
--- ./nothing/examples/example3.mi    1969-12-31 21:00:00.000000000 -0300
+++ ./MI/examples/example3.mi    2016-05-18 15:30:56.374478158 -0300
@@ -0,0 +1,22 @@
+=thread-group-added,id="i1"
+~"GNU gdb (Ubuntu 7.7.1-0ubuntu5~14.04.2) 7.7.1\n"
+~"Copyright (C) 2014 Free Software Foundation, Inc.\n"
+~"License GPLv3+: GNU GPL version 3 or later
<http://gnu.org/licenses/gpl.html>\nThis is free software: you are
free to change and redistribute it.\nThere is NO WARRANTY, to the
extent permitted by law.  Type \"show copying\"\nand \"show warranty\"
for details.\n"
+~"This GDB was configured as \"x86_64-linux-gnu\".\nType \"show
configuration\" for configuration details."
+~"\nFor bug reporting instructions, please see:\n"
+~"<http://www.gnu.org/software/gdb/bugs/>.\n"
+~"Find the GDB manual and other documentation resources online
at:\n<http://www.gnu.org/software/gdb/documentation/>.\n"
+~"For help, type \"help\".\n"
+~"Type \"apropos word\" to search for commands related to \"word\"...\n"
+=cmd-param-changed,param="print object",value="on"
+~"Reading symbols from ../bin/mi..."
+~"(no debugging symbols found)...done.\n"
+(gdb)
+^done,bkpt={number="1",type="breakpoint",disp="keep",enabled="y",addr="0x0000000000403d8b",at="<main+4>",thread-groups=["i1"],times="0",original-location="main"}
+(gdb)
+^done,OSDataTable={nr_rows="9",nr_cols="3",hdr=[{width="10",alignment="-1",col_name="col0",colhdr="Type"},{width="10",alignment="-1",col_name="col1",colhdr="Description"},{width="10",alignment="-1",col_name="col2",colhdr="Title"}],body=[item={col0="processes",col1="Listing
of all processes",col2="Processes"},item={col0="procgroups",col1="Listing
of all process groups",col2="Process
groups"},item={col0="threads",col1="Listing of all
threads",col2="Threads"},item={col0="files",col1="Listing of all file
descriptors",col2="File
descriptors"},item={col0="sockets",col1="Listing of all
internet-domain
sockets",col2="Sockets"},item={col0="shm",col1="Listing of all
shared-memory regions",col2="Shared-memory
regions"},item={col0="semaphores",col1="Listing of all
semaphores",col2="Semaphores"},item={col0="msg",col1="Listing of all
message queues",col2="Message
queues"},item={col0="modules",col1="Listing of all loaded kernel
modules",col2="Kernel modules"}]}
+(gdb)
+^done,OSDataTable={nr_rows="9",nr_cols="3",hdr=[{width="10",alignment="-1",col_name="col0",colhdr="Type"},{width="10",alignment="-1",col_name="col1",colhdr="Description"},{width="10",alignment="-1",col_name="col2",colhdr="Title"}],body=[item={col0="processes",col1="Listing
of all processes",col2="Processes"},item={col0="procgroups",col1="Listing
of all process groups",col2="Process
groups"},item={col0="threads",col1="Listing of all
threads",col2="Threads"},item={col0="files",col1="Listing of all file
descriptors",col2="File
descriptors"},item={col0="sockets",col1="Listing of all
internet-domain
sockets",col2="Sockets"},item={col0="shm",col1="Listing of all
shared-memory regions",col2="Shared-memory
regions"},item={col0="semaphores",col1="Listing of all
semaphores",col2="Semaphores"},item={col0="msg",col1="Listing of all
message queues",col2="Message
queues"},item={col0="modules",col1="Listing of all loaded kernel
modules",col2="Kernel modules"}]}
+(gdb)
+&"quit\n"
+(gdb)
diff -Naur ./nothing/main.cpp ./MI/main.cpp
--- ./nothing/main.cpp    1969-12-31 21:00:00.000000000 -0300
+++ ./MI/main.cpp    2016-05-18 16:42:18.510287243 -0300
@@ -0,0 +1,50 @@
+/*
+   Main function.
+   Copyright (C) 2016 Roman Alarcon, Taller Technologies S.A.
+
+   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 3 of the License, 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.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <cstdlib>
+#include <iostream>
+#include "MIParserController.h"
+
+int main(int argc, char **argv)
+{
+    int ret = EXIT_SUCCESS;
+
+    std::clog << "mi parser - v0.2" << std::endl;
+
+    MIParserController controller;
+
+    switch(argc)
+    {
+        case 1:
+            controller.runOverStdIn();
+            break;
+
+        case 2:
+            controller.runOverFile(argv[1]);
+            break;
+
+        default:
+            std::cerr << "Usage: " << argv[0] << " [input-file]" << std::endl;
+            ret = EXIT_FAILURE;
+    }
+
+    if(ret == EXIT_SUCCESS)
+        std::cout << "DONE." << std::endl;
+
+    return ret;
+}
diff -Naur ./nothing/Makefile ./MI/Makefile
--- ./nothing/Makefile    1969-12-31 21:00:00.000000000 -0300
+++ ./MI/Makefile    2016-05-18 13:54:30.000000000 -0300
@@ -0,0 +1,36 @@
+CC=g++
+CFLAGS=-c -Wno-write-strings -Wreturn-type
+LDFLAGS=
+SOURCES=MIFlexScanner.cpp MIBisonParser.cpp MIParserController.cpp main.cpp
+OBJECTS=$(SOURCES:.cpp=.o)
+EXECUTABLE_PATH=../bin
+EXECUTABLE="$(EXECUTABLE_PATH)/mi"
+LIBPATH=
+INCPATH=
+LIBS=
+
+all: $(SOURCES) $(EXECUTABLE)
+
+clean:
+    rm -f $(EXECUTABLE)
+    rm -f $(OBJECTS)
+    rm -f *.cpp~
+    rm -f *.h~
+    rm -f MIFlexScanner.cpp MIBisonParser.cpp MIBisonParser.h
+
+$(EXECUTABLE): $(OBJECTS)
+    @if [ ! -d "$(EXECUTABLE_PATH)" ]; then \
+       mkdir "$(EXECUTABLE_PATH)"; \
+    fi
+    $(CC) $(LDFLAGS) $(OBJECTS) -o $@ $(LIBPATH) $(LIBS)
+
+MIBisonParser.cpp: MIGrammar.y
+    bison -d MIGrammar.y
+    mv MIGrammar.tab.c MIBisonParser.cpp
+    mv MIGrammar.tab.h MIBisonParser.h
+
+MIFlexScanner.cpp: MILexer.l
+    flex -oMIFlexScanner.cpp MILexer.l
+
+.cpp.o:
+    $(CC) $(INCPATH) $(CFLAGS) $< -o $@
diff -Naur ./nothing/MIGrammar.y ./MI/MIGrammar.y
--- ./nothing/MIGrammar.y    1969-12-31 21:00:00.000000000 -0300
+++ ./MI/MIGrammar.y    2016-05-18 16:35:21.378305840 -0300
@@ -0,0 +1,259 @@
+/*
+   MI Grammar specification.
+   Copyright (C) 2016 Roman Alarcon, Taller Technologies S.A.
+
+   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 3 of the License, 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.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+%{
+
+#include <cstdio>
+#include "MIParserDelegate.h"
+
+/*
+ * "Private" variables
+ */
+static MIParserDelegate *_parserDelegate;
+
+/*
+ * Imported functions
+ */
+extern int yylex();
+extern std::string getLexLastToken();
+extern int getLexLineNumber();
+extern int getLexColumnNumber();
+
+/*
+ * Exported functions
+ */
+void setParserDelegate(MIParserDelegate *parserDelegate);
+
+static int yyerror(char *s);
+std::string removeDoubleQuote(const std::string& inputString);
+
+%}
+
+%union
+{
+    char* stringValue;
+}
+
+%token MI_GDB
+%token MI_THREAD_GROUP_ADDED
+%token MI_CMD_PARAM_CHANGED
+%token MI_DONE
+%token MI_RUNNING
+%token MI_CONNECTED
+%token MI_ERROR
+%token MI_EXIT
+%token MI_STOPPED
+%token MI_CONST
+%token MI_EMPTY_TUPLE
+%token MI_EMPTY_LIST
+%token MI_CR
+%token MI_CRLF
+%token <stringValue> MI_NUMBER
+%token <stringValue> MI_STRING
+%token <stringValue> MI_IDENTIFIER
+
+%%
+
+outputList          : outputList output
+                      {
+                      }
+                    | output
+                      {
+                      }
+                    ;
+
+output              : outOfBandRecordList resultRecord MI_GDB
+                      {
+                      }
+                    ;
+
+outOfBandRecordList : outOfBandRecordList outOfBandRecord
+                      {
+                      }
+                    | /* EPSILON */
+                      {
+                      }
+                    ;
+
+outOfBandRecord     : tokenOpt asyncRecord
+                      {
+                      }
+                    | streamRecord
+                      {
+                      }
+                    ;
+
+asyncRecord         : '*' asyncOutput
+                      {
+                      }
+                    | '+' asyncOutput
+                      {
+                      }
+                    | '=' asyncOutput
+                      {
+                      }
+                    ;
+
+asyncOutput         : asyncClass
+                      {
+                      }
+                    | asyncClass ',' resultList
+                      {
+                      }
+                    ;
+
+asyncClass          : MI_STOPPED
+                      {
+
+                      }
+                    | MI_THREAD_GROUP_ADDED
+                      {
+
+                      }
+                    | MI_CMD_PARAM_CHANGED
+                      {
+
+                      }
+                    ;
+
+resultRecord        : tokenOpt '^' resultClass ',' resultListOpt
+                      {
+                      }
+                    | /* EPSILON */
+                      {
+                      }
+                    ;
+
+resultClass         : MI_DONE
+                      {
+                      }
+                    | MI_RUNNING
+                      {
+                      }
+                    | MI_CONNECTED
+                      {
+                      }
+                    | MI_ERROR
+                      {
+                      }
+                    | MI_EXIT
+                      {
+                      }
+                    ;
+
+resultListOpt       : resultList
+                      {
+                      }
+                    | /* EPSILON */
+                      {
+                      }
+                    ;
+
+resultList          : resultList ',' result
+                      {
+                      }
+                    | result
+                      {
+                      }
+                    ;
+
+result              : MI_IDENTIFIER '=' value
+                      {
+                        free($1);
+                      }
+                    ;
+
+value               : MI_NUMBER
+                      {
+                        free($1);
+                      }
+                    | MI_STRING
+                      {
+                        free($1);
+                      }
+                    | tuple
+                      {
+                      }
+                    | list
+                      {
+                      }
+                    ;
+
+tuple               : MI_EMPTY_TUPLE
+                      {
+                      }
+                    | '{' resultList '}'
+                      {
+                      }
+                    ;
+
+list                : MI_EMPTY_LIST
+                      {
+                      }
+                    | '[' valueList ']'
+                      {
+                      }
+                    | '[' resultList ']'
+                      {
+                      }
+                    ;
+
+valueList           : valueList ',' value
+                      {
+                      }
+                    | value
+                      {
+                      }
+                    ;
+
+streamRecord        : '~' MI_STRING
+                      {
+                        free($2);
+                      }
+                    | '@' MI_STRING
+                      {
+                        free($2);
+                      }
+                    | '&' MI_STRING
+                      {
+                        free($2);
+                      }
+                    ;
+
+tokenOpt            : MI_NUMBER
+                      {
+                        free($1);
+                      }
+                    | /* EPSILON */
+                      {
+                      }
+                    ;
+
+%%
+
+void setParserDelegate(MIParserDelegate *parserDelegate)
+{
+    _parserDelegate = parserDelegate;
+}
+
+int yyerror(char *s)
+{
+    _parserDelegate->notifySyntaxError(getLexLastToken());
+
+    return 0;
+}
diff -Naur ./nothing/MILexer.l ./MI/MILexer.l
--- ./nothing/MILexer.l    1969-12-31 21:00:00.000000000 -0300
+++ ./MI/MILexer.l    2016-05-18 16:43:23.558284342 -0300
@@ -0,0 +1,135 @@
+/*
+   MI Scanner specification.
+   Copyright (C) 2016 Roman Alarcon, Taller Technologies S.A.
+
+   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 3 of the License, 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.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+%{
+
+#include <assert.h>
+#include <string>
+#include <cstdio>
+#include "MIBisonParser.h"
+
+/*
+ * "Private" variables
+ */
+static std::string _lastToken;
+
+/*
+ * Functions able to be accessed from outside
+ */
+int setInputFile(const char * filename);
+std::string getLexLastToken();
+
+/*
+ * "Private" functions
+ */
+static void updateLastToken(const char * token);
+static void skipSingleLineComment();
+
+%}
+
+digit                   [0-9]
+letter                  [A-Za-z_\-]
+no_quote_or_backslash   [^\"\\]
+utf8char                \\(u|U)[0-9A-Fa-f]+
+escapechar              \\[^uU]
+string                  \"({no_quote_or_backslash}|{utf8char}|{escapechar})*\"
+identifier              {letter}({letter}|{digit})*
+number                  (0|[1-9]{digit}*)
+
+%%
+
+[\t\r\n ]+            {}
+"(gdb)"               { updateLastToken(yytext); return MI_GDB;
         }
+"thread-group-added"  { updateLastToken(yytext); return
MI_THREAD_GROUP_ADDED; }
+"cmd-param-changed"   { updateLastToken(yytext); return
MI_CMD_PARAM_CHANGED;  }
+"done"                { updateLastToken(yytext); return MI_DONE;
         }
+"running"             { updateLastToken(yytext); return MI_RUNNING;
         }
+"connected"           { updateLastToken(yytext); return MI_CONNECTED;
         }
+"error"               { updateLastToken(yytext); return MI_ERROR;
         }
+"exit"                { updateLastToken(yytext); return MI_EXIT;
         }
+"stopped"             { updateLastToken(yytext); return MI_STOPPED;
         }
+"{}"                  { updateLastToken(yytext); return
MI_EMPTY_TUPLE;        }
+"[]"                  { updateLastToken(yytext); return
MI_EMPTY_LIST;         }
+
+{string}              {
+                          yylval.stringValue = strdup(yytext);
+                          updateLastToken(yytext);
+                          return MI_STRING;
+                      }
+
+{number}              {
+                          yylval.stringValue = strdup(yytext);
+                          updateLastToken(yytext);
+                          return MI_NUMBER;
+                      }
+
+{identifier}          {
+                          yylval.stringValue = strdup(yytext);
+                          updateLastToken(yytext);
+                          return MI_IDENTIFIER;
+                      }
+
+.                     {
+                          updateLastToken((std::string(&yytext[0],
1)).c_str());
+                          return yytext[0];
+                      }
+
+%%
+
+/**
+ * setInputFile: sets the file to be scanned
+ * Return values: 0 means OK, file is opened to read. 1 means error.
+ */
+int setInputFile(const char* filename)
+{
+    assert(filename != NULL);
+
+    if (filename[0] != 0)
+        yyin = std::fopen(filename, "r");
+    else
+        yyin = stdin;
+    return (yyin != NULL);
+}
+
+/**
+ * getLexLastToken: returns the last token read
+ */
+std::string getLexLastToken()
+{
+    return _lastToken;
+}
+
+/**
+ *
+ */
+static void updateLastToken(const char* token)
+{
+    _lastToken = std::string(yytext);
+
+    // Uncomment out to see list of tokens
+    // std::printf("Token '%s'\n", _lastToken.c_str());
+}
+
+/**
+ *
+ */
+int yywrap()
+{
+    return 1;
+}
+
diff -Naur ./nothing/MIParserController.cpp ./MI/MIParserController.cpp
--- ./nothing/MIParserController.cpp    1969-12-31 21:00:00.000000000 -0300
+++ ./MI/MIParserController.cpp    2016-05-18 15:48:00.710432489 -0300
@@ -0,0 +1,54 @@
+/*
+   MIParserController - Wrapper for C-based parser
+   Copyright (C) 2016 Roman Alarcon, Taller Technologies S.A.
+
+   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 3 of the License, 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.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <iostream>
+#include "MIParserController.h"
+
+extern int yyparse();
+extern int setInputFile(const char * filename);
+void setParserDelegate(MIParserDelegate *parserDelegate);
+
+
+MIParserController::MIParserController()
+{
+    setParserDelegate(this);
+}
+
+MIParserController::~MIParserController()
+{
+}
+
+void MIParserController::runOverFile(const std::string& inputFile)
+{
+    setInputFile(inputFile.c_str());
+    if(yyparse() == 0)
+    {
+        std::cout << "Parsing was successful." << std::endl;
+    }
+}
+
+void MIParserController::runOverStdIn()
+{
+    runOverFile(std::string());
+}
+
+void MIParserController::notifySyntaxError(const std::string& token)
+{
+    std::cerr << "Error: unexpected token '" <<  token << "'" << std::endl;
+}
+
diff -Naur ./nothing/MIParserController.h ./MI/MIParserController.h
--- ./nothing/MIParserController.h    1969-12-31 21:00:00.000000000 -0300
+++ ./MI/MIParserController.h    2016-05-18 15:46:15.706437171 -0300
@@ -0,0 +1,38 @@
+/*
+   MIParserController - Wrapper for C-based parser
+   Copyright (C) 2016 Roman Alarcon, Taller Technologies S.A.
+
+   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 3 of the License, 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.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef __MIPARSERCONTROLLER_H
+#define __MIPARSERCONTROLLER_H
+
+#include "MIParserDelegate.h"
+
+class MIParserController: private MIParserDelegate
+{
+public:
+    MIParserController();
+    ~MIParserController();
+
+    void runOverFile(const std::string& inputFile);
+    void runOverStdIn();
+
+private:
+    virtual void notifySyntaxError(const std::string& token);
+};
+
+#endif
+
diff -Naur ./nothing/MIParserDelegate.h ./MI/MIParserDelegate.h
--- ./nothing/MIParserDelegate.h    1969-12-31 21:00:00.000000000 -0300
+++ ./MI/MIParserDelegate.h    2016-05-18 14:39:36.000000000 -0300
@@ -0,0 +1,30 @@
+/*
+   MIParserDelegate - Callbacks declarations
+   Copyright (C) 2016 Roman Alarcon, Taller Technologies S.A.
+
+   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 3 of the License, 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.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef __MIPARSERDELEGATE_H
+#define __MIPARSERDELEGATE_H
+
+#include <string>
+
+class MIParserDelegate
+{
+public:
+    virtual void notifySyntaxError(const std::string& token) = 0;
+};
+
+#endif



More information about the Gdb-patches mailing list