Beispiel #1
0
def compile(src_jack_file, output):
    print(src_jack_file)
    tokenizer = JackTokenizer(src_jack_file)
    symbol_table = SymbolTable()
    vm_writer = VMWriter(output)
    compilation_engine = CompilationEngine(tokenizer, symbol_table, vm_writer)
    compilation_engine.compile()
Beispiel #2
0
    def compile(input_file_path):
        input_file = open(input_file_path)

        output_file_path = f"{input_file_path.strip('.jack')}_.xml"
        output_file = open(output_file_path, 'w')

        comp_engine = CompilationEngine()
        comp_engine.compile(input_file, output_file)
Beispiel #3
0
 def compile_file(self, file_path):
     print("Compiling", file_path, "...")
     file_name = os.path.splitext(os.path.basename(file_path))[0]
     dir_name = os.path.split(file_path)[0]
     output_file_name = os.path.join(dir_name, file_name + "__.xml")
     with open(output_file_name, "w") as output_file:
         tokenizer = Tokenizer(file_path)
         try:
             compiler = CompilationEngine(tokenizer, output_file)
             compiler.compile()
             print("Compilation successful!", file_path, "=>",
                   output_file_name)
         except CompilationError as err:
             tokenizer.close()
             raise CompilationError("ERROR: " + err.message)
def main():
    if len(sys.argv) != 2:
        print(
            "Expected 1 argument (either the .jack file or a directory containing .jack files). Exiting!"
        )
        return

    is_file_arg = sys.argv[1].endswith(".jack")

    if is_file_arg:
        jack_files = [sys.argv[1]]
    else:
        jack_files = [
            join(sys.argv[1], f) for f in listdir(sys.argv[1])
            if f.endswith(".jack")
        ]

    for jack_file in jack_files:
        ce = CompilationEngine(JackTokenizer(jack_file),
                               jack_file.split(".jack")[0] + "Nisarg.xml")
        ce.compile()
class CompilationEngineTest(unittest.TestCase):
    def setUp(self):
        self.compiler = CompilationEngine()
        self.maxDiff = None

    def reformat_xml_to_standardize_whitespace(self, xml):
        tree = ET.fromstring(''.join(xml.split()))
        self.compiler.prettify_elements(tree)
        return ET.tostring(tree,
                           encoding='unicode',
                           short_empty_elements=False)

    def assert_xml_equal(self, actual_xml, expected_xml, debug_output=False):
        if debug_output:
            print('expected_xml:')
            print(self.reformat_xml_to_standardize_whitespace(expected_xml))
            print('actual_xml:')
            print(self.reformat_xml_to_standardize_whitespace(actual_xml))

        self.assertEqual(
            self.reformat_xml_to_standardize_whitespace(expected_xml),
            self.reformat_xml_to_standardize_whitespace(actual_xml))

    def test_empty_class(self):
        output = self.compiler.compile("""
class Main { }
""")

        self.assert_xml_equal(
            output, """<class>
    <keyword> class </keyword>
    <identifier> Main </identifier>
    <symbol> { </symbol>
    <symbol> } </symbol>
    </class>""")

    def test_class_with_class_variables(self):
        output = self.compiler.compile("""
        class Main {
            field int x, y;
            field int size;
            static boolean test;
            field Square square;
        }
""")

        self.assert_xml_equal(
            output, """<class>
    <keyword> class </keyword>
    <identifier> Main </identifier>
    <symbol> { </symbol>
    <classVarDec>
        <keyword> field </keyword>
        <keyword> int </keyword>
        <identifier> x </identifier>
        <symbol> , </symbol>
        <identifier> y </identifier>
        <symbol> ; </symbol>
    </classVarDec>
    <classVarDec>
        <keyword> field </keyword>
        <keyword> int </keyword>
        <identifier> size </identifier>
        <symbol> ; </symbol>
    </classVarDec>
    <classVarDec>
        <keyword> static </keyword>
        <keyword> boolean </keyword>
        <identifier> test </identifier>
        <symbol> ; </symbol>
    </classVarDec>
    <classVarDec>
        <keyword> field </keyword>
        <identifier> Square </identifier>
        <identifier> square </identifier>
        <symbol> ; </symbol>
    </classVarDec>
    <symbol> } </symbol>
    </class>""")

    def test_class_with_variables_and_empty_subroutine(self):
        output = self.compiler.compile("""
        class Main {
            field int size;
            function void main() { }
        }
""")

        self.assert_xml_equal(
            output, """<class>
    <keyword> class </keyword>
    <identifier> Main </identifier>
    <symbol> { </symbol>
    <classVarDec>
        <keyword> field </keyword>
        <keyword> int </keyword>
        <identifier> size </identifier>
        <symbol> ; </symbol>
    </classVarDec>
    <subroutineDec>
        <keyword> function </keyword>
        <keyword> void </keyword>
        <identifier> main </identifier>
        <symbol> ( </symbol>
        <parameterList>
        </parameterList>
        <symbol> ) </symbol>
        <subroutineBody>
          <symbol> { </symbol>
          <statements/>
          <symbol> } </symbol>
        </subroutineBody>
    </subroutineDec>
    <symbol> } </symbol>
</class>""")

    def test_subroutine_with_variables_and_no_statements(self):
        output = self.compiler.compile("""
        class Main {
            function void main() {
                var Array a;
                var int length;
                var int i, sum;
            }
        }
""")

        self.assert_xml_equal(
            output, """<class>
    <keyword> class </keyword>
    <identifier> Main </identifier>
    <symbol> { </symbol>
    <subroutineDec>
        <keyword> function </keyword>
        <keyword> void </keyword>
        <identifier> main </identifier>
        <symbol> ( </symbol>
        <parameterList>
        </parameterList>
        <symbol> ) </symbol>
        <subroutineBody>
          <symbol> { </symbol>
          <varDec>
            <keyword> var </keyword>
            <identifier> Array </identifier>
            <identifier> a </identifier>
            <symbol> ; </symbol>
          </varDec>
          <varDec>
            <keyword> var </keyword>
            <keyword> int </keyword>
            <identifier> length </identifier>
            <symbol> ; </symbol>
          </varDec>
          <varDec>
            <keyword> var </keyword>
            <keyword> int </keyword>
            <identifier> i </identifier>
            <symbol> , </symbol>
            <identifier> sum </identifier>
            <symbol> ; </symbol>
          </varDec>
          <statements></statements>
          <symbol> } </symbol>
        </subroutineBody>
    </subroutineDec>
    <symbol> } </symbol>
</class>""")

    def test_let_statement(self):
        output = self.compiler.compile("""
        class Main {
            function void main() {
                let i = 0;
            }
        }
""")

        self.assert_xml_equal(
            output, """<class>
    <keyword> class </keyword>
    <identifier> Main </identifier>
    <symbol> { </symbol>
    <subroutineDec>
        <keyword> function </keyword>
        <keyword> void </keyword>
        <identifier> main </identifier>
        <symbol> ( </symbol>
        <parameterList>
        </parameterList>
        <symbol> ) </symbol>
        <subroutineBody>
          <symbol> { </symbol>
          <statements>
              <letStatement>
                <keyword> let </keyword>
                <identifier> i </identifier>
                <symbol> = </symbol>
                <expression>
                  <term>
                    <integerConstant> 0 </integerConstant>
                  </term>
                </expression>
                <symbol> ; </symbol>
              </letStatement>
           </statements>
          <symbol> } </symbol>
        </subroutineBody>
    </subroutineDec>
    <symbol> } </symbol>
    </class>""")

    def test_method_call(self):
        output = self.compiler.compile("""
        class Main {
            function void dispose () {
                do square.dispose();
                do Memory.deAlloc(square);
                return;
            }
        }""")

        self.assert_xml_equal(
            output, """<class>
  <keyword> class </keyword>
  <identifier> Main </identifier>
  <symbol> { </symbol>
    <subroutineDec>
    <keyword> function </keyword>
    <keyword> void </keyword>
    <identifier> dispose </identifier>
    <symbol> ( </symbol>
    <parameterList>
    </parameterList>
    <symbol> ) </symbol>
    <subroutineBody>
      <symbol> { </symbol>
      <statements>
        <doStatement>
          <keyword> do </keyword>
          <identifier> square </identifier>
          <symbol> . </symbol>
          <identifier> dispose </identifier>
          <symbol> ( </symbol>
          <expressionList>
          </expressionList>
          <symbol> ) </symbol>
          <symbol> ; </symbol>
        </doStatement>
        <doStatement>
          <keyword> do </keyword>
          <identifier> Memory </identifier>
          <symbol> . </symbol>
          <identifier> deAlloc </identifier>
          <symbol> ( </symbol>
          <expressionList>
            <expression>
              <term>
                <identifier> square </identifier>
              </term>
            </expression>
          </expressionList>
          <symbol> ) </symbol>
          <symbol> ; </symbol>
        </doStatement>
        <returnStatement>
          <keyword> return </keyword>
          <symbol> ; </symbol>
        </returnStatement>
      </statements>
      <symbol> } </symbol>
    </subroutineBody>
  </subroutineDec>
  <symbol> } </symbol>
</class>""", True)

    def test_if_no_else(self):
        output = self.compiler.compile("""
        class Main {
        method void moveSquare() {
        if (direction) { do square.moveUp(); }
        if (direction) { do square.moveDown(); }
        return;
        }
        }""")

        self.assert_xml_equal(
            output, """<class>
  <keyword> class </keyword>
  <identifier> Main </identifier>
  <symbol> { </symbol>
  <subroutineDec>
    <keyword> method </keyword>
    <keyword> void </keyword>
    <identifier> moveSquare </identifier>
    <symbol> ( </symbol>
    <parameterList>
    </parameterList>
    <symbol> ) </symbol>
    <subroutineBody>
      <symbol> { </symbol>
      <statements>
        <ifStatement>
          <keyword> if </keyword>
          <symbol> ( </symbol>
          <expression>
            <term>
              <identifier> direction </identifier>
            </term>
          </expression>
          <symbol> ) </symbol>
          <symbol> { </symbol>
          <statements>
            <doStatement>
              <keyword> do </keyword>
              <identifier> square </identifier>
              <symbol> . </symbol>
              <identifier> moveUp </identifier>
              <symbol> ( </symbol>
              <expressionList>
              </expressionList>
              <symbol> ) </symbol>
              <symbol> ; </symbol>
            </doStatement>
          </statements>
          <symbol> } </symbol>
        </ifStatement>
        <ifStatement>
          <keyword> if </keyword>
          <symbol> ( </symbol>
          <expression>
            <term>
              <identifier> direction </identifier>
            </term>
          </expression>
          <symbol> ) </symbol>
          <symbol> { </symbol>
          <statements>
            <doStatement>
              <keyword> do </keyword>
              <identifier> square </identifier>
              <symbol> . </symbol>
              <identifier> moveDown </identifier>
              <symbol> ( </symbol>
              <expressionList>
              </expressionList>
              <symbol> ) </symbol>
              <symbol> ; </symbol>
            </doStatement>
          </statements>
          <symbol> } </symbol>
        </ifStatement>
         <returnStatement>
           <keyword>return</keyword>
           <symbol>;</symbol>
         </returnStatement>
      </statements>
        <symbol> } </symbol>
    </subroutineBody>
  </subroutineDec>
  <symbol> } </symbol>
</class>""")

    def test_compound_let_statement(self):
        output = self.compiler.compile("""
            class Main {
                function void main() {
                    let i = i | j;
                    return;
                }
            }""")

        self.assert_xml_equal(
            output, """<class>
  <keyword>class</keyword>
  <identifier>Main</identifier>
  <symbol>{</symbol>
  <subroutineDec>
    <keyword>function</keyword>
    <keyword>void</keyword>
    <identifier>main</identifier>
    <symbol>(</symbol>
    <parameterList></parameterList>
    <symbol>)</symbol>
    <subroutineBody>
      <symbol>{</symbol>
      <statements>
        <letStatement>
          <keyword>let</keyword>
          <identifier>i</identifier>
          <symbol>=</symbol>
          <expression>
            <term>
              <identifier>i</identifier>
            </term>
            <symbol>|</symbol>
            <term>
              <identifier>j</identifier>
            </term>
          </expression>
          <symbol>;</symbol>
        </letStatement>
        <returnStatement>
          <keyword>return</keyword>
          <symbol>;</symbol>
        </returnStatement>
      </statements>
      <symbol>}</symbol>
    </subroutineBody>
  </subroutineDec>
  <symbol>}</symbol>
</class>
            """, True)