changeset 5:818f80afa78b

Added handy highlighting to IDE
author windel-eee
date Thu, 22 Sep 2011 17:44:31 +0200
parents 0d5ef85b8698
children 1784af239df4
files ide/compiler/codegenerator.py ide/compiler/compiler.py ide/compiler/parser.py ide/ide/ide.py ide/runtests.py
diffstat 5 files changed, 58 insertions(+), 30 deletions(-) [+]
line wrap: on
line diff
--- a/ide/compiler/codegenerator.py	Wed Sep 21 19:05:18 2011 +0200
+++ b/ide/compiler/codegenerator.py	Thu Sep 22 17:44:31 2011 +0200
@@ -312,7 +312,6 @@
       elif isinstance(node, StatementSequence):
          for s in node.statements:
             self.gencode(s)
-            assert(len(self.usedregs) == 0)
 
       elif type(node) is ProcedureCall:
          # Prepare parameters on the stack:
--- a/ide/compiler/compiler.py	Wed Sep 21 19:05:18 2011 +0200
+++ b/ide/compiler/compiler.py	Thu Sep 22 17:44:31 2011 +0200
@@ -1,7 +1,7 @@
 import hashlib
 # Import compiler components:
 from . import lexer
-from . import parser
+from .parser import Parser
 from .codegenerator import CodeGenerator
 from .nodes import ExportedSymbol
 
@@ -16,8 +16,15 @@
 
    def compilesource(self, src):
       """ Front end that handles the stages: """
+      # Pass 1: parsing and type checking
       tokens = lexer.tokenize(src) # Lexical stage
-      ast = parser.Parser(tokens).parseModule() # Parse a module
+      p = Parser(tokens)
+      ast = p.parseModule() # Parse a module
+      print(p.errorlist)
+      if len(p.errorlist) > 0:
+         self.errorlist = p.errorlist
+         return
+      # Pass 2: code generation
       CodeGenerator().generatecode(ast)
       # Attach a signature:
       ast.signature = self.generateSignature(src)
--- a/ide/compiler/parser.py	Wed Sep 21 19:05:18 2011 +0200
+++ b/ide/compiler/parser.py	Thu Sep 22 17:44:31 2011 +0200
@@ -2,7 +2,6 @@
   This module parses source code into an abstract syntax tree (AST)
 """
 
-import shelve
 from .symboltable import SymbolTable
 from .nodes import *
 from .errors import CompilerException, Error
@@ -16,6 +15,7 @@
       """ provide the parser with the tokens iterator from the lexer. """
       self.tokens = tokens
       self.NextToken()
+      self.errorlist = []
 
    def Error(self, msg):
      raise CompilerException(msg, self.token.row, self.token.col)
@@ -570,32 +570,37 @@
       return AsmCode(asmcode)
 
    def parseStatement(self):
-     # Determine statement type based on the pending token:
-     if self.token.typ == 'if':
-        return self.parseIfStatement()
-     elif self.token.typ == 'case':
-        return self.parseCaseStatement()
-     elif self.token.typ == 'while':
-       return self.parseWhileStatement()
-     elif self.token.typ == 'repeat':
-        return self.parseRepeatStatement()
-     elif self.token.typ == 'for':
-        return self.parseForStatement()
-     elif self.token.typ == 'asm':
-        return self.parseAsmcode()
-     elif self.token.typ == 'ID':
-        # Assignment or procedure call
-        designator = self.parseDesignator()
-        if self.token.typ == '(' and type(designator.typ) is ProcedureType:
-           return self.parseProcedureCall(designator)
-        elif self.token.typ == ':=':
-           return self.parseAssignment(designator)
+     try:
+        # Determine statement type based on the pending token:
+        if self.token.typ == 'if':
+           return self.parseIfStatement()
+        elif self.token.typ == 'case':
+           return self.parseCaseStatement()
+        elif self.token.typ == 'while':
+          return self.parseWhileStatement()
+        elif self.token.typ == 'repeat':
+           return self.parseRepeatStatement()
+        elif self.token.typ == 'for':
+           return self.parseForStatement()
+        elif self.token.typ == 'asm':
+           return self.parseAsmcode()
+        elif self.token.typ == 'ID':
+           # Assignment or procedure call
+           designator = self.parseDesignator()
+           if self.token.typ == '(' and type(designator.typ) is ProcedureType:
+              return self.parseProcedureCall(designator)
+           elif self.token.typ == ':=':
+              return self.parseAssignment(designator)
+           else:
+              self.Error('Unknown statement following designator: {0}'.format(self.token))
         else:
-           self.Error('Unknown statement following designator: {0}'.format(self.token))
-     else:
-        # TODO: return empty statement??:
-        return EmptyStatement()
-        self.Error('Unknown statement {0}'.format(self.token))
+           # TODO: return empty statement??:
+           return EmptyStatement()
+           self.Error('Unknown statement {0}'.format(self.token))
+     except CompilerException as e:
+         print(e)
+         self.errorlist.append( (e.row, e.col, e.msg))
+         return EmptyStatement()
 
    def parseStatementSequence(self):
        """ Sequence of statements seperated by ';' """
--- a/ide/ide/ide.py	Wed Sep 21 19:05:18 2011 +0200
+++ b/ide/ide/ide.py	Thu Sep 22 17:44:31 2011 +0200
@@ -9,6 +9,12 @@
 module x;
 var 
  a,b,c : integer;
+procedure test(x:integer);
+ var y,z:integer;
+begin
+  y := x * 3 + 2;
+  z := x + y + a;
+end test;
 begin
   a := 12;
   b := a * 12 + 33;
@@ -26,6 +32,13 @@
       self.setReadOnly(True)
       self.append('Build output will appear here!')
 
+class BuildErrors(QListWidget):
+   def __init__(self, parent=None):
+      super(BuildErrors, self).__init__(parent)
+      item = QListWidgetItem('Hallo dan!')
+      self.addItem(item)
+      
+
 class Ide(QMainWindow):
   def __init__(self, parent=None):
     super(Ide, self).__init__(parent)
@@ -49,6 +62,9 @@
     self.addComponent('AST viewer', self.astViewer)
     self.astViewer.sigNodeSelected.connect(self.nodeSelected)
 
+    self.builderrors = BuildErrors()
+    self.addComponent('Build errors', self.builderrors)
+
     # Create actions:
     self.buildAction = QAction('Build!', self)
     self.buildAction.setShortcut(QKeySequence('F7'))
@@ -70,6 +86,7 @@
      dw.setObjectName(name)
      self.addDockWidget(Qt.RightDockWidgetArea, dw)
      self.viewMenu.addAction(dw.toggleViewAction())
+
   def loadSettings(self):
      if self.settings.contains('mainwindowstate'):
         self.restoreState(self.settings.value('mainwindowstate'))
--- a/ide/runtests.py	Wed Sep 21 19:05:18 2011 +0200
+++ b/ide/runtests.py	Thu Sep 22 17:44:31 2011 +0200
@@ -92,7 +92,7 @@
       """
       pc = Compiler()
       pc.compilesource(source)
-   def testForStatement(self):
+   def tstForStatement(self):
       source = """
       module fortest;
       var