├── linux ├── .gitignore ├── main.cc ├── flutter │ ├── generated_plugin_registrant.h │ ├── generated_plugin_registrant.cc │ ├── generated_plugins.cmake │ └── CMakeLists.txt ├── my_application.h ├── my_application.cc └── CMakeLists.txt ├── ios ├── Flutter │ ├── Debug.xcconfig │ ├── Release.xcconfig │ └── AppFrameworkInfo.plist ├── Runner │ ├── Runner-Bridging-Header.h │ ├── Assets.xcassets │ │ ├── LaunchImage.imageset │ │ │ ├── LaunchImage.png │ │ │ ├── LaunchImage@2x.png │ │ │ ├── LaunchImage@3x.png │ │ │ ├── README.md │ │ │ └── Contents.json │ │ └── AppIcon.appiconset │ │ │ ├── Icon-App-20x20@1x.png │ │ │ ├── Icon-App-20x20@2x.png │ │ │ ├── Icon-App-20x20@3x.png │ │ │ ├── Icon-App-29x29@1x.png │ │ │ ├── Icon-App-29x29@2x.png │ │ │ ├── Icon-App-29x29@3x.png │ │ │ ├── Icon-App-40x40@1x.png │ │ │ ├── Icon-App-40x40@2x.png │ │ │ ├── Icon-App-40x40@3x.png │ │ │ ├── Icon-App-60x60@2x.png │ │ │ ├── Icon-App-60x60@3x.png │ │ │ ├── Icon-App-76x76@1x.png │ │ │ ├── Icon-App-76x76@2x.png │ │ │ ├── Icon-App-1024x1024@1x.png │ │ │ ├── Icon-App-83.5x83.5@2x.png │ │ │ └── Contents.json │ ├── AppDelegate.swift │ ├── Base.lproj │ │ ├── Main.storyboard │ │ └── LaunchScreen.storyboard │ └── Info.plist ├── Runner.xcodeproj │ ├── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ │ ├── WorkspaceSettings.xcsettings │ │ │ └── IDEWorkspaceChecks.plist │ └── xcshareddata │ │ └── xcschemes │ │ └── Runner.xcscheme ├── Runner.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ │ ├── WorkspaceSettings.xcsettings │ │ └── IDEWorkspaceChecks.plist └── .gitignore ├── Peek-parsing.gif ├── Peek-semantic.gif ├── peek-lexical.gif ├── graphite_modify.png ├── InterpreterVisualizer ├── src │ ├── main │ │ ├── resources │ │ │ └── application.properties │ │ └── java │ │ │ ├── simpleinterpreter │ │ │ ├── RuntimeError.java │ │ │ ├── TokenType.java │ │ │ ├── Environment.java │ │ │ ├── InterpreterAdapter.java │ │ │ ├── Token.java │ │ │ ├── Stmt.java │ │ │ ├── Expr.java │ │ │ ├── SimpleInterpreter.java │ │ │ ├── StatementGraph.java │ │ │ ├── Scanner.java │ │ │ └── AST.java │ │ │ └── api │ │ │ └── interpretervisualizer │ │ │ ├── InterpreterVisualizerAPI.java │ │ │ └── controller │ │ │ └── WebController.java │ └── test │ │ └── java │ │ └── api │ │ └── interpretervisualizer │ │ └── InterpreterVisualizerApplicationTests.java ├── .mvn │ └── wrapper │ │ ├── maven-wrapper.jar │ │ ├── maven-wrapper.properties │ │ └── MavenWrapperDownloader.java ├── .gitignore ├── pom.xml └── mvnw.cmd ├── peek-hello-lexical.gif ├── peek-lexical-error.gif ├── peek-hello-semantic.gif ├── android ├── gradle.properties ├── app │ ├── src │ │ ├── main │ │ │ ├── res │ │ │ │ ├── mipmap-hdpi │ │ │ │ │ └── ic_launcher.png │ │ │ │ ├── mipmap-mdpi │ │ │ │ │ └── ic_launcher.png │ │ │ │ ├── mipmap-xhdpi │ │ │ │ │ └── ic_launcher.png │ │ │ │ ├── mipmap-xxhdpi │ │ │ │ │ └── ic_launcher.png │ │ │ │ ├── mipmap-xxxhdpi │ │ │ │ │ └── ic_launcher.png │ │ │ │ ├── drawable │ │ │ │ │ └── launch_background.xml │ │ │ │ ├── drawable-v21 │ │ │ │ │ └── launch_background.xml │ │ │ │ ├── values │ │ │ │ │ └── styles.xml │ │ │ │ └── values-night │ │ │ │ │ └── styles.xml │ │ │ ├── java │ │ │ │ └── com │ │ │ │ │ └── example │ │ │ │ │ └── flutterdesktopapp │ │ │ │ │ └── MainActivity.java │ │ │ └── AndroidManifest.xml │ │ ├── debug │ │ │ └── AndroidManifest.xml │ │ └── profile │ │ │ └── AndroidManifest.xml │ └── build.gradle ├── gradle │ └── wrapper │ │ └── gradle-wrapper.properties ├── .gitignore ├── settings.gradle └── build.gradle ├── lib ├── main.dart ├── components │ ├── snackbar.dart │ └── resusable_circle.dart ├── ui_elements │ ├── card_box.dart │ ├── colored_card_box.dart │ ├── text_highlighter.dart │ ├── symbo_table_item.dart │ ├── code_text.dart │ ├── modes_circles.dart │ ├── console_panel.dart │ ├── symbol_table.dart │ ├── freescrollview.dart │ ├── token_item.dart │ ├── single_graph.dart │ └── control_buttons.dart ├── utils │ ├── graphs_provider.dart │ ├── utilities_provider.dart │ ├── constants.dart │ └── app_data.dart ├── models │ ├── parsing_ast.dart │ ├── response.dart │ ├── Ast.dart │ ├── tokens.dart │ └── statement.dart ├── screens │ ├── first_page.dart │ ├── material_main_page.dart │ ├── select_visualization_mode.dart │ ├── tokens_page.dart │ ├── home_page.dart │ ├── ast_graph.dart │ ├── parsing_ast_page.dart │ ├── syntactic_and_statement_page.dart │ └── semantic_page.dart └── services │ └── networking.dart ├── .metadata ├── assets └── tokens_file.txt ├── .gitignore ├── test └── widget_test.dart ├── LoxGrammar ├── contribution.md ├── pubspec.yaml └── README.md /linux/.gitignore: -------------------------------------------------------------------------------- 1 | flutter/ephemeral 2 | -------------------------------------------------------------------------------- /ios/Flutter/Debug.xcconfig: -------------------------------------------------------------------------------- 1 | #include "Generated.xcconfig" 2 | -------------------------------------------------------------------------------- /ios/Flutter/Release.xcconfig: -------------------------------------------------------------------------------- 1 | #include "Generated.xcconfig" 2 | -------------------------------------------------------------------------------- /ios/Runner/Runner-Bridging-Header.h: -------------------------------------------------------------------------------- 1 | #import "GeneratedPluginRegistrant.h" 2 | -------------------------------------------------------------------------------- /Peek-parsing.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OsamaMaani/Interpreter-Visualizer/HEAD/Peek-parsing.gif -------------------------------------------------------------------------------- /Peek-semantic.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OsamaMaani/Interpreter-Visualizer/HEAD/Peek-semantic.gif -------------------------------------------------------------------------------- /peek-lexical.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OsamaMaani/Interpreter-Visualizer/HEAD/peek-lexical.gif -------------------------------------------------------------------------------- /graphite_modify.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OsamaMaani/Interpreter-Visualizer/HEAD/graphite_modify.png -------------------------------------------------------------------------------- /InterpreterVisualizer/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | server.port=9090 2 | server.address=192.168.1.5 -------------------------------------------------------------------------------- /peek-hello-lexical.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OsamaMaani/Interpreter-Visualizer/HEAD/peek-hello-lexical.gif -------------------------------------------------------------------------------- /peek-lexical-error.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OsamaMaani/Interpreter-Visualizer/HEAD/peek-lexical-error.gif -------------------------------------------------------------------------------- /peek-hello-semantic.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OsamaMaani/Interpreter-Visualizer/HEAD/peek-hello-semantic.gif -------------------------------------------------------------------------------- /android/gradle.properties: -------------------------------------------------------------------------------- 1 | org.gradle.jvmargs=-Xmx1536M 2 | android.useAndroidX=true 3 | android.enableJetifier=true 4 | -------------------------------------------------------------------------------- /InterpreterVisualizer/.mvn/wrapper/maven-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OsamaMaani/Interpreter-Visualizer/HEAD/InterpreterVisualizer/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OsamaMaani/Interpreter-Visualizer/HEAD/android/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OsamaMaani/Interpreter-Visualizer/HEAD/android/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OsamaMaani/Interpreter-Visualizer/HEAD/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OsamaMaani/Interpreter-Visualizer/HEAD/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OsamaMaani/Interpreter-Visualizer/HEAD/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /lib/main.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutterdesktopapp/screens/material_main_page.dart'; 3 | 4 | void main() { 5 | runApp(MyApp()); 6 | } 7 | -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OsamaMaani/Interpreter-Visualizer/HEAD/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png -------------------------------------------------------------------------------- /android/app/src/main/java/com/example/flutterdesktopapp/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.example.flutterdesktopapp; 2 | 3 | 4 | public class MainActivity extends FlutterActivity { 5 | 6 | } 7 | 8 | 9 | -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OsamaMaani/Interpreter-Visualizer/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OsamaMaani/Interpreter-Visualizer/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OsamaMaani/Interpreter-Visualizer/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OsamaMaani/Interpreter-Visualizer/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OsamaMaani/Interpreter-Visualizer/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OsamaMaani/Interpreter-Visualizer/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OsamaMaani/Interpreter-Visualizer/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OsamaMaani/Interpreter-Visualizer/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OsamaMaani/Interpreter-Visualizer/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OsamaMaani/Interpreter-Visualizer/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OsamaMaani/Interpreter-Visualizer/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OsamaMaani/Interpreter-Visualizer/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OsamaMaani/Interpreter-Visualizer/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OsamaMaani/Interpreter-Visualizer/HEAD/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OsamaMaani/Interpreter-Visualizer/HEAD/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OsamaMaani/Interpreter-Visualizer/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OsamaMaani/Interpreter-Visualizer/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png -------------------------------------------------------------------------------- /linux/main.cc: -------------------------------------------------------------------------------- 1 | #include "my_application.h" 2 | 3 | int main(int argc, char** argv) { 4 | g_autoptr(MyApplication) app = my_application_new(); 5 | return g_application_run(G_APPLICATION(app), argc, argv); 6 | } 7 | -------------------------------------------------------------------------------- /ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /ios/Runner.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /InterpreterVisualizer/.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.8.1/apache-maven-3.8.1-bin.zip 2 | wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar 3 | -------------------------------------------------------------------------------- /android/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Fri Jun 23 08:50:38 CEST 2017 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-6.7-all.zip 7 | -------------------------------------------------------------------------------- /InterpreterVisualizer/src/main/java/simpleinterpreter/RuntimeError.java: -------------------------------------------------------------------------------- 1 | package simpleinterpreter; 2 | 3 | class RuntimeError extends RuntimeException { 4 | final Token token; 5 | 6 | RuntimeError(Token token, String message) { 7 | super(message); 8 | this.token = token; 9 | } 10 | } -------------------------------------------------------------------------------- /ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreviewsEnabled 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /android/.gitignore: -------------------------------------------------------------------------------- 1 | gradle-wrapper.jar 2 | /.gradle 3 | /captures/ 4 | /gradlew 5 | /gradlew.bat 6 | /local.properties 7 | GeneratedPluginRegistrant.java 8 | 9 | # Remember to never publicly share your keystore. 10 | # See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app 11 | key.properties 12 | -------------------------------------------------------------------------------- /ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreviewsEnabled 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /lib/components/snackbar.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | class SnackBarMessage extends StatelessWidget { 4 | String path; 5 | SnackBarMessage(this.path); 6 | 7 | @override 8 | Widget build(BuildContext context) { 9 | return SnackBar( 10 | content: Text('Graph is saved to $path'), 11 | ); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /.metadata: -------------------------------------------------------------------------------- 1 | # This file tracks properties of this Flutter project. 2 | # Used by Flutter tool to assess capabilities and perform upgrades etc. 3 | # 4 | # This file should be version controlled and should not be manually edited. 5 | 6 | version: 7 | revision: b1395592de68cc8ac4522094ae59956dd21a91db 8 | channel: stable 9 | 10 | project_type: app 11 | -------------------------------------------------------------------------------- /linux/flutter/generated_plugin_registrant.h: -------------------------------------------------------------------------------- 1 | // 2 | // Generated file. Do not edit. 3 | // 4 | 5 | #ifndef GENERATED_PLUGIN_REGISTRANT_ 6 | #define GENERATED_PLUGIN_REGISTRANT_ 7 | 8 | #include 9 | 10 | // Registers Flutter plugins. 11 | void fl_register_plugins(FlPluginRegistry* registry); 12 | 13 | #endif // GENERATED_PLUGIN_REGISTRANT_ 14 | -------------------------------------------------------------------------------- /android/app/src/debug/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /android/app/src/profile/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /InterpreterVisualizer/src/test/java/api/interpretervisualizer/InterpreterVisualizerApplicationTests.java: -------------------------------------------------------------------------------- 1 | package api.interpretervisualizer; 2 | 3 | import org.junit.jupiter.api.Test; 4 | import org.springframework.boot.test.context.SpringBootTest; 5 | 6 | @SpringBootTest 7 | class InterpreterVisualizerApplicationTests { 8 | 9 | @Test 10 | void contextLoads() { 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md: -------------------------------------------------------------------------------- 1 | # Launch Screen Assets 2 | 3 | You can customize the launch screen with your own desired assets by replacing the image files in this directory. 4 | 5 | You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images. -------------------------------------------------------------------------------- /assets/tokens_file.txt: -------------------------------------------------------------------------------- 1 | VAR,var,null,1,0,2,4 2 | IDENTIFIER,x,null,1,4,4,3 3 | EQUAL,=,null,1,6,6,2 4 | NUMBER,3,3.0,1,8,8,3 5 | SEMICOLON,;,null,1,9,9,1 6 | VAR,var,null,2,12,14,4 7 | IDENTIFIER,y,null,2,16,16,3 8 | EQUAL,=,null,2,18,18,2 9 | NUMBER,10,10.0,2,20,21,3 10 | SEMICOLON,;,null,2,22,22,1 11 | PRINT,print,null,3,25,29,4 12 | NUMBER,5,5.0,3,31,31,3 13 | PLUS,+,null,3,33,33,1 14 | NUMBER,3,3.0,3,35,35,3 15 | SEMICOLON,;,null,3,36,36,1 16 | EOF,,null,3,37,37,0 -------------------------------------------------------------------------------- /ios/Runner/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | import Flutter 3 | 4 | @UIApplicationMain 5 | @objc class AppDelegate: FlutterAppDelegate { 6 | override func application( 7 | _ application: UIApplication, 8 | didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? 9 | ) -> Bool { 10 | GeneratedPluginRegistrant.register(with: self) 11 | return super.application(application, didFinishLaunchingWithOptions: launchOptions) 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /linux/flutter/generated_plugin_registrant.cc: -------------------------------------------------------------------------------- 1 | // 2 | // Generated file. Do not edit. 3 | // 4 | 5 | #include "generated_plugin_registrant.h" 6 | 7 | #include 8 | 9 | void fl_register_plugins(FlPluginRegistry* registry) { 10 | g_autoptr(FlPluginRegistrar) window_size_registrar = 11 | fl_plugin_registry_get_registrar_for_plugin(registry, "WindowSizePlugin"); 12 | window_size_plugin_register_with_registrar(window_size_registrar); 13 | } 14 | -------------------------------------------------------------------------------- /linux/my_application.h: -------------------------------------------------------------------------------- 1 | #ifndef FLUTTER_MY_APPLICATION_H_ 2 | #define FLUTTER_MY_APPLICATION_H_ 3 | 4 | #include 5 | 6 | G_DECLARE_FINAL_TYPE(MyApplication, my_application, MY, APPLICATION, 7 | GtkApplication) 8 | 9 | /** 10 | * my_application_new: 11 | * 12 | * Creates a new Flutter-based application. 13 | * 14 | * Returns: a new #MyApplication. 15 | */ 16 | MyApplication* my_application_new(); 17 | 18 | #endif // FLUTTER_MY_APPLICATION_H_ 19 | -------------------------------------------------------------------------------- /InterpreterVisualizer/src/main/java/api/interpretervisualizer/InterpreterVisualizerAPI.java: -------------------------------------------------------------------------------- 1 | package api.interpretervisualizer; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class InterpreterVisualizerAPI { 8 | 9 | public static void main(String[] args) { 10 | 11 | SpringApplication.run(InterpreterVisualizerAPI.class, args); 12 | } 13 | 14 | } 15 | -------------------------------------------------------------------------------- /android/settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app' 2 | 3 | def localPropertiesFile = new File(rootProject.projectDir, "local.properties") 4 | def properties = new Properties() 5 | 6 | assert localPropertiesFile.exists() 7 | localPropertiesFile.withReader("UTF-8") { reader -> properties.load(reader) } 8 | 9 | def flutterSdkPath = properties.getProperty("flutter.sdk") 10 | assert flutterSdkPath != null, "flutter.sdk not set in local.properties" 11 | apply from: "$flutterSdkPath/packages/flutter_tools/gradle/app_plugin_loader.gradle" 12 | -------------------------------------------------------------------------------- /android/app/src/main/res/drawable/launch_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 12 | 13 | -------------------------------------------------------------------------------- /android/app/src/main/res/drawable-v21/launch_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 12 | 13 | -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "LaunchImage.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "LaunchImage@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "LaunchImage@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /InterpreterVisualizer/.gitignore: -------------------------------------------------------------------------------- 1 | HELP.md 2 | target/ 3 | !.mvn/wrapper/maven-wrapper.jar 4 | !**/src/main/**/target/ 5 | !**/src/test/**/target/ 6 | 7 | ### STS ### 8 | .apt_generated 9 | .classpath 10 | .factorypath 11 | .project 12 | .settings 13 | .springBeans 14 | .sts4-cache 15 | 16 | ### IntelliJ IDEA ### 17 | .idea 18 | *.iws 19 | *.iml 20 | *.ipr 21 | 22 | ### NetBeans ### 23 | /nbproject/private/ 24 | /nbbuild/ 25 | /dist/ 26 | /nbdist/ 27 | /.nb-gradle/ 28 | build/ 29 | !**/src/main/**/build/ 30 | !**/src/test/**/build/ 31 | 32 | ### VS Code ### 33 | .vscode/ 34 | -------------------------------------------------------------------------------- /linux/flutter/generated_plugins.cmake: -------------------------------------------------------------------------------- 1 | # 2 | # Generated file, do not edit. 3 | # 4 | 5 | list(APPEND FLUTTER_PLUGIN_LIST 6 | window_size 7 | ) 8 | 9 | set(PLUGIN_BUNDLED_LIBRARIES) 10 | 11 | foreach(plugin ${FLUTTER_PLUGIN_LIST}) 12 | add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/linux plugins/${plugin}) 13 | target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin) 14 | list(APPEND PLUGIN_BUNDLED_LIBRARIES $) 15 | list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries}) 16 | endforeach(plugin) 17 | -------------------------------------------------------------------------------- /InterpreterVisualizer/src/main/java/simpleinterpreter/TokenType.java: -------------------------------------------------------------------------------- 1 | package simpleinterpreter; 2 | 3 | enum TokenType { 4 | // Single-character tokens. 5 | LEFT_PAREN, RIGHT_PAREN, LEFT_BRACE, RIGHT_BRACE, 6 | COMMA, DOT, MINUS, PLUS, SEMICOLON, SLASH, STAR, 7 | 8 | // One or two character tokens. 9 | BANG, BANG_EQUAL, 10 | EQUAL, EQUAL_EQUAL, 11 | GREATER, GREATER_EQUAL, 12 | LESS, LESS_EQUAL, 13 | 14 | // Liter 15 | // als. 16 | IDENTIFIER, STRING, NUMBER, 17 | 18 | // Keywords. 19 | AND, CLASS, ELSE, FALSE, FUN, FOR, IF, NIL, OR, 20 | PRINT, RETURN, SUPER, THIS, TRUE, VAR, WHILE, 21 | 22 | EOF 23 | } -------------------------------------------------------------------------------- /ios/.gitignore: -------------------------------------------------------------------------------- 1 | *.mode1v3 2 | *.mode2v3 3 | *.moved-aside 4 | *.pbxuser 5 | *.perspectivev3 6 | **/*sync/ 7 | .sconsign.dblite 8 | .tags* 9 | **/.vagrant/ 10 | **/DerivedData/ 11 | Icon? 12 | **/Pods/ 13 | **/.symlinks/ 14 | profile 15 | xcuserdata 16 | **/.generated/ 17 | Flutter/App.framework 18 | Flutter/Flutter.framework 19 | Flutter/Flutter.podspec 20 | Flutter/Generated.xcconfig 21 | Flutter/app.flx 22 | Flutter/app.zip 23 | Flutter/flutter_assets/ 24 | Flutter/flutter_export_environment.sh 25 | ServiceDefinitions.json 26 | Runner/GeneratedPluginRegistrant.* 27 | 28 | # Exceptions to above rules. 29 | !default.mode1v3 30 | !default.mode2v3 31 | !default.pbxuser 32 | !default.perspectivev3 33 | -------------------------------------------------------------------------------- /lib/ui_elements/card_box.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | class CardBox extends StatelessWidget { 4 | final Widget child; 5 | 6 | CardBox({this.child}); 7 | 8 | @override 9 | Widget build(BuildContext context) { 10 | return Container( 11 | child: Card( 12 | child: Padding( 13 | padding: const EdgeInsets.all(5.0), 14 | child: child, 15 | ), 16 | elevation: 1.0, 17 | shape: RoundedRectangleBorder( 18 | borderRadius: BorderRadius.circular(10.0), 19 | side: BorderSide( 20 | color: Colors.blue, 21 | width: 3, 22 | ), 23 | ), 24 | ), 25 | ); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /android/build.gradle: -------------------------------------------------------------------------------- 1 | buildscript { 2 | ext.kotlin_version = '1.3.50' 3 | repositories { 4 | google() 5 | jcenter() 6 | } 7 | 8 | dependencies { 9 | classpath 'com.android.tools.build:gradle:4.1.0' 10 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" 11 | } 12 | } 13 | 14 | allprojects { 15 | repositories { 16 | google() 17 | jcenter() 18 | } 19 | } 20 | 21 | rootProject.buildDir = '../build' 22 | subprojects { 23 | project.buildDir = "${rootProject.buildDir}/${project.name}" 24 | } 25 | subprojects { 26 | project.evaluationDependsOn(':app') 27 | } 28 | 29 | task clean(type: Delete) { 30 | delete rootProject.buildDir 31 | } 32 | -------------------------------------------------------------------------------- /lib/ui_elements/colored_card_box.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | class ColoredCardBox extends StatelessWidget { 4 | final Widget child; 5 | final Color color; 6 | 7 | ColoredCardBox({this.child, this.color}); 8 | 9 | @override 10 | Widget build(BuildContext context) { 11 | return Container( 12 | child: Card( 13 | color: color, 14 | child: Padding( 15 | padding: const EdgeInsets.all(5.0), 16 | child: child, 17 | ), 18 | elevation: 1.0, 19 | shape: RoundedRectangleBorder( 20 | borderRadius: BorderRadius.circular(10.0), 21 | side: BorderSide( 22 | color: Colors.blue, 23 | width: 3, 24 | ), 25 | ), 26 | ), 27 | ); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /lib/utils/graphs_provider.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/cupertino.dart'; 2 | import 'package:flutter/material.dart'; 3 | 4 | class GraphProvider with ChangeNotifier { 5 | int _visualizedGraphIndex = 0; 6 | int _visualizedStatementIndex = 0; 7 | int _visualizedStepIndex = 0; 8 | 9 | int get visualizedStatementIndex => _visualizedStatementIndex; 10 | 11 | set visualizedStatementIndex(int value) { 12 | _visualizedStatementIndex = value; 13 | notifyListeners(); 14 | } 15 | 16 | set visualizedGraphIndex(int value) { 17 | _visualizedGraphIndex = value; 18 | notifyListeners(); 19 | } 20 | 21 | int get visualizedGraphIndex => _visualizedGraphIndex; 22 | 23 | int get visualizedStepIndex => _visualizedStepIndex; 24 | 25 | set visualizedStepIndex(int value) { 26 | _visualizedStepIndex = value; 27 | notifyListeners(); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /lib/models/parsing_ast.dart: -------------------------------------------------------------------------------- 1 | class ParsingAst { 2 | List _nodesData; 3 | List _graphs; 4 | List _visitedNode; 5 | 6 | ParsingAst(this._nodesData, this._graphs, this._visitedNode); 7 | 8 | factory ParsingAst.fromJson(Map json) { 9 | List nodesData = (json["Nodes"] as List); 10 | 11 | List graphs = (json["Graphs"] as List); 12 | 13 | List visitedNodes = (json["Visited Nodes"] as List); 14 | 15 | return ParsingAst(nodesData, graphs, visitedNodes); 16 | } 17 | 18 | set nodesData(List value) { 19 | _nodesData = value; 20 | } 21 | 22 | List get nodesData => _nodesData; 23 | 24 | List get graphs => _graphs; 25 | 26 | List get visitedNode => _visitedNode; 27 | 28 | set graphs(List value) { 29 | _graphs = value; 30 | } 31 | 32 | set visitedNode(List value) { 33 | _visitedNode = value; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /ios/Flutter/AppFrameworkInfo.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | App 9 | CFBundleIdentifier 10 | io.flutter.flutter.app 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | App 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1.0 23 | MinimumOSVersion 24 | 8.0 25 | 26 | 27 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Miscellaneous 2 | *.class 3 | *.log 4 | *.pyc 5 | *.swp 6 | .DS_Store 7 | .atom/ 8 | .buildlog/ 9 | .history 10 | .svn/ 11 | 12 | # IntelliJ related 13 | *.iml 14 | *.ipr 15 | *.iws 16 | .idea/ 17 | 18 | # The .vscode folder contains launch configuration and tasks you configure in 19 | # VS Code which you may wish to be included in version control, so this line 20 | # is commented out by default. 21 | #.vscode/ 22 | 23 | # Flutter/Dart/Pub related 24 | **/doc/api/ 25 | **/ios/Flutter/.last_build_id 26 | .dart_tool/ 27 | .flutter-plugins 28 | .flutter-plugins-dependencies 29 | .packages 30 | .pub-cache/ 31 | .pub/ 32 | /build/ 33 | 34 | # Web related 35 | lib/generated_plugin_registrant.dart 36 | 37 | # Symbolication related 38 | app.*.symbols 39 | 40 | # Obfuscation related 41 | app.*.map.json 42 | 43 | # Android Studio will place build artifacts here 44 | /android/app/debug 45 | /android/app/profile 46 | /android/app/release 47 | -------------------------------------------------------------------------------- /lib/ui_elements/text_highlighter.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutterdesktopapp/utils/utilities_provider.dart'; 3 | import 'package:provider/provider.dart'; 4 | 5 | class TextHighlighter extends StatefulWidget { 6 | @override 7 | _TextHighlighterState createState() => _TextHighlighterState(); 8 | } 9 | 10 | class _TextHighlighterState extends State { 11 | @override 12 | Widget build(BuildContext context) { 13 | final utilsProvider = Provider.of(context); 14 | var list = utilsProvider.richTextList; 15 | 16 | return Container( 17 | child: RichText( 18 | text: TextSpan( 19 | children: list.map((e) { 20 | return TextSpan( 21 | text: e[0], 22 | style: TextStyle( 23 | backgroundColor: e[1], 24 | fontSize: 30, 25 | fontWeight: FontWeight.bold)); 26 | }).toList())), 27 | ); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /android/app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 15 | 18 | 19 | -------------------------------------------------------------------------------- /android/app/src/main/res/values-night/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 15 | 18 | 19 | -------------------------------------------------------------------------------- /lib/screens/first_page.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutterdesktopapp/utils/app_data.dart'; 3 | import 'package:provider/provider.dart'; 4 | 5 | import '../ui_elements/modes_circles.dart'; 6 | 7 | class PageOne extends StatelessWidget { 8 | const PageOne({Key key}) : super(key: key); 9 | 10 | @override 11 | Widget build(BuildContext context) { 12 | final appData = Provider.of(context); 13 | bool syntaxError = appData.astsList.length == 0; 14 | 15 | return Column( 16 | mainAxisAlignment: MainAxisAlignment.center, 17 | children: [ 18 | ThreeCircles( 19 | headline1: "1", 20 | title1: "Lexical Analysis", 21 | function1: appData.changeCircleOneState, 22 | headline2: "2", 23 | title2: "Syntactic Analysis", 24 | function2: appData.changeCircleTwoState, 25 | headline3: "3", 26 | title3: "Semantic Analysis & Execution", 27 | function3: (syntaxError ? null : appData.changeCircleThreeState), 28 | ), 29 | ], 30 | ); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /test/widget_test.dart: -------------------------------------------------------------------------------- 1 | // This is a basic Flutter widget test. 2 | // 3 | // To perform an interaction with a widget in your test, use the WidgetTester 4 | // utility that Flutter provides. For example, you can send tap and scroll 5 | // gestures. You can also use WidgetTester to find child widgets in the widget 6 | // tree, read text, and verify that the values of widget properties are correct. 7 | 8 | import 'package:flutter/material.dart'; 9 | import 'package:flutter_test/flutter_test.dart'; 10 | 11 | import 'package:flutterdesktopapp/main.dart'; 12 | 13 | void main() { 14 | testWidgets('Counter increments smoke test', (WidgetTester tester) async { 15 | // Build our app and trigger a frame. 16 | // await tester.pumpWidget(MyApp()); 17 | 18 | // Verify that our counter starts at 0. 19 | expect(find.text('0'), findsOneWidget); 20 | expect(find.text('1'), findsNothing); 21 | 22 | // Tap the '+' icon and trigger a frame. 23 | await tester.tap(find.byIcon(Icons.add)); 24 | await tester.pump(); 25 | 26 | // Verify that our counter has incremented. 27 | expect(find.text('0'), findsNothing); 28 | expect(find.text('1'), findsOneWidget); 29 | }); 30 | } 31 | -------------------------------------------------------------------------------- /lib/screens/material_main_page.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutterdesktopapp/utils/app_data.dart'; 3 | import 'package:flutterdesktopapp/utils/graphs_provider.dart'; 4 | import 'package:flutterdesktopapp/utils/utilities_provider.dart'; 5 | import 'package:provider/provider.dart'; 6 | import 'package:window_size/window_size.dart'; 7 | 8 | import 'home_page.dart'; 9 | 10 | class MyApp extends StatelessWidget { 11 | const MyApp({Key key}) : super(key: key); 12 | 13 | @override 14 | Widget build(BuildContext context) { 15 | setWindowTitle("Interpreter Visualizer"); 16 | 17 | return MultiProvider( 18 | providers: [ 19 | ChangeNotifierProvider(create: (_) => AppData()), 20 | ChangeNotifierProvider( 21 | create: (_) => UtilitiesProvider()), 22 | ChangeNotifierProvider(create: (_) => GraphProvider()), 23 | ], 24 | builder: (context, child) { 25 | return MaterialApp( 26 | title: 'Interpreter Visualizer', 27 | //theme: , 28 | debugShowCheckedModeBanner: false, 29 | home: HomePage(), 30 | ); 31 | }); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /lib/components/resusable_circle.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutterdesktopapp/utils/app_data.dart'; 3 | import 'package:flutterdesktopapp/utils/constants.dart'; 4 | import 'package:provider/provider.dart'; 5 | 6 | class ReusableCircle extends StatelessWidget { 7 | final Function function; 8 | final String headline, title; 9 | 10 | ReusableCircle({this.headline, this.title, this.function}); 11 | 12 | @override 13 | Widget build(BuildContext context) { 14 | final isVisualizedProvider = Provider.of(context).isVisualized; 15 | return InkWell( 16 | onTap: isVisualizedProvider ? function : null, 17 | child: CircleAvatar( 18 | backgroundColor: 19 | (isVisualizedProvider ? Colors.indigo : Colors.blueGrey), 20 | radius: 150.0, 21 | child: Column( 22 | crossAxisAlignment: CrossAxisAlignment.center, 23 | mainAxisAlignment: MainAxisAlignment.center, 24 | children: [ 25 | Text("$headline", style: text_style_circle), 26 | SizedBox( 27 | height: 20, 28 | ), 29 | Text("$title", style: text_style_circle), 30 | ], 31 | ), 32 | ), 33 | ); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /lib/utils/utilities_provider.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/cupertino.dart'; 2 | import 'package:flutter/material.dart'; 3 | 4 | class UtilitiesProvider with ChangeNotifier { 5 | List _consoleMessages = []; 6 | 7 | List get consoleMessages => _consoleMessages; 8 | 9 | set consoleMessages(List value) { 10 | _consoleMessages = value; 11 | notifyListeners(); 12 | } 13 | 14 | void clearConsoleMessages() { 15 | consoleMessages = []; 16 | } 17 | 18 | void addConsoleMessage(String message, int type) { 19 | // 0 for errors, 1 otherwise 20 | _consoleMessages.add([message, type]); 21 | var temp = List.from(consoleMessages); 22 | consoleMessages = temp; 23 | } 24 | 25 | void addConsoleMessageList(List messages) { 26 | // 0 for errors, 1 otherwise 27 | if (messages == null) return; 28 | for (var m in messages) { 29 | _consoleMessages.add([m[0], m[1]]); 30 | } 31 | 32 | var temp = List.from(consoleMessages); 33 | consoleMessages = temp; 34 | } 35 | 36 | List _richTextList = []; 37 | 38 | List get richTextList => _richTextList; 39 | 40 | set richTextList(List value) { 41 | _richTextList = value; 42 | notifyListeners(); 43 | } 44 | 45 | void resetRichTextListColors() { 46 | var len = _richTextList.length; 47 | for (int i = 0; i < len; i++) _richTextList[i][1] = Colors.black; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /lib/utils/constants.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | final ButtonStyle run_button_style = 4 | ElevatedButton.styleFrom(minimumSize: Size(300, 70)); 5 | 6 | var text_style_header_button = 7 | TextStyle(color: Colors.white, fontWeight: FontWeight.bold, fontSize: 20); 8 | 9 | var text_style_phase_title = 10 | TextStyle(color: Colors.black, fontWeight: FontWeight.bold, fontSize: 20); 11 | 12 | var text_style_table = TextStyle(fontWeight: FontWeight.bold, fontSize: 20.0); 13 | 14 | var text_style_console_normal = 15 | TextStyle(fontWeight: FontWeight.bold, fontSize: 18.0); 16 | 17 | var text_style_console_error = 18 | TextStyle(fontWeight: FontWeight.bold, color: Colors.red, fontSize: 18.0); 19 | 20 | var text_style_highlight = TextStyle( 21 | fontWeight: FontWeight.bold, 22 | fontSize: 20.0, 23 | backgroundColor: Colors.yellow, 24 | ); 25 | 26 | var text_style_circle = 27 | TextStyle(fontWeight: FontWeight.bold, fontSize: 18.0, color: Colors.white); 28 | 29 | var text_style_graph_title = 30 | TextStyle(fontWeight: FontWeight.bold, fontSize: 12.0, color: Colors.white); 31 | 32 | var text_style_graph_text = 33 | TextStyle(fontWeight: FontWeight.bold, fontSize: 10.0, color: Colors.white); 34 | 35 | var text_style_table_row = TextStyle( 36 | fontWeight: FontWeight.bold, 37 | fontSize: 14.0, 38 | color: Colors.black, 39 | ); 40 | -------------------------------------------------------------------------------- /InterpreterVisualizer/src/main/java/simpleinterpreter/Environment.java: -------------------------------------------------------------------------------- 1 | package simpleinterpreter; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | 6 | class Environment { 7 | final Environment enclosing; 8 | private final Map values = new HashMap<>(); 9 | 10 | Environment() { 11 | enclosing = null; 12 | } 13 | 14 | Environment(Environment enclosing) { 15 | this.enclosing = enclosing; 16 | } 17 | 18 | void define(String name, Object value) { 19 | values.put(name, value); 20 | } 21 | 22 | Object get(Token name) { 23 | if (values.containsKey(name.lexeme)) { 24 | return values.get(name.lexeme); 25 | } 26 | 27 | if (enclosing != null) return enclosing.get(name); 28 | 29 | throw new RuntimeError(name, 30 | "Undefined variable '" + name.lexeme + "'."); 31 | } 32 | 33 | void assign(Token name, Object value) { 34 | if (values.containsKey(name.lexeme)) { 35 | values.put(name.lexeme, value); 36 | return; 37 | } 38 | 39 | if (enclosing != null) { 40 | enclosing.assign(name, value); 41 | return; 42 | } 43 | 44 | throw new RuntimeError(name, "Undefined variable '" + name.lexeme + "'."); 45 | } 46 | 47 | public Map getValues() { 48 | return values; 49 | } 50 | } -------------------------------------------------------------------------------- /LoxGrammar: -------------------------------------------------------------------------------- 1 | Here is the grammar of the language which shows its simplicity in the following list of productions flavoured with regular expressions: 2 | 3 | program → declaration* EOF 4 | 5 | declaration → varDecl 6 | | statement; 7 | 8 | varDecl → "var" IDENTIFIER ( "=" expression )? ";" 9 | 10 | statement → exprStmt 11 | | ifStmt 12 | | printStmt 13 | | whileStmt 14 | | block 15 | 16 | exprStmt → expression";" 17 | 18 | ifStmt → "if" "(" expression ")" statement 19 | ( "else" statement )? 20 | 21 | printStmt → "print" expression ";" 22 | 23 | whileStmt → "while" "(" expression ")" statement 24 | 25 | block → "{" declaration* "}" 26 | 27 | expression → assignment 28 | 29 | assignment → IDENTIFIER "=" assignment 30 | | logic_or 31 | 32 | logic_or → logic_and ( "or" logic_and )* 33 | 34 | logic_and → equality ( "and" equality )* 35 | 36 | equality → comparison ( ( "!=" | "==" ) comparison )* 37 | 38 | comparison → term ( ( ">" | ">=" | "<" | "<=" ) term )* 39 | 40 | term → factor ( ( "-" | "+" ) factor )* 41 | 42 | factor → factor ( "/" | "*" ) unary 43 | | unary 44 | 45 | 46 | unary → ( "!" | "-" ) unary 47 | | primary 48 | 49 | primary → "true" | "false" | "nil" 50 | | NUMBER | STRING 51 | | "(" expression ")" 52 | | IDENTIFIER 53 | 54 | -------------------------------------------------------------------------------- /lib/ui_elements/symbo_table_item.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutterdesktopapp/utils/constants.dart'; 3 | 4 | import 'colored_card_box.dart'; 5 | 6 | class SymbolTableItem extends StatefulWidget { 7 | final String scope; 8 | final String variable; 9 | final String value; 10 | 11 | SymbolTableItem(this.scope, this.variable, this.value); 12 | 13 | @override 14 | _SymbolTableItemState createState() => _SymbolTableItemState(); 15 | } 16 | 17 | class _SymbolTableItemState extends State { 18 | // @override 19 | void dispose() { 20 | print("Symbol Table Item Disposed"); 21 | // // TODO: implement dispose 22 | super.dispose(); 23 | } 24 | 25 | @override 26 | Widget build(BuildContext context) { 27 | return ColoredCardBox( 28 | color: Colors.lightGreenAccent[200], 29 | child: Row( 30 | mainAxisAlignment: MainAxisAlignment.spaceAround, 31 | children: [ 32 | SizedBox( 33 | child: Container( 34 | child: Text("${widget.variable}", style: text_style_table_row)), 35 | width: 125.0, 36 | ), 37 | SizedBox( 38 | child: Container( 39 | child: Text("${widget.value}", style: text_style_table_row)), 40 | width: 80.0, 41 | ), 42 | SizedBox( 43 | child: Container( 44 | child: Text("${widget.scope}", style: text_style_table_row)), 45 | width: 80.0, 46 | ), 47 | ], 48 | ), 49 | ); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /lib/models/response.dart: -------------------------------------------------------------------------------- 1 | import 'dart:convert'; 2 | 3 | import 'package:flutterdesktopapp/models/statement.dart'; 4 | import 'package:flutterdesktopapp/models/tokens.dart'; 5 | 6 | import 'Ast.dart'; 7 | 8 | class ResponseParser { 9 | List listOfTokens(String responseBody) { 10 | Map jsonList = json.decode(responseBody); 11 | int len = (jsonList["Tokens"] as List).length; 12 | List listOfTokens = []; 13 | for (int tokenIndex = 0; tokenIndex < len; tokenIndex++) { 14 | listOfTokens.add(Token.fromJson(tokenIndex, jsonList)); 15 | } 16 | return listOfTokens; 17 | } 18 | 19 | List listOfParsedStatements(String responseBody) { 20 | Map jsonList = json.decode(responseBody); 21 | 22 | int len = (jsonList["Statements"] as List).length; 23 | 24 | List statements = []; 25 | for (int statementIndex = 0; statementIndex < len; statementIndex++) { 26 | statements 27 | .add(Statement.fromJson(jsonList["Statements"][statementIndex])); 28 | } 29 | 30 | return statements; 31 | } 32 | 33 | List listOfASTs(String responseBody) { 34 | Map jsonList = json.decode(responseBody); 35 | 36 | int len = 0; 37 | try { 38 | len = (jsonList["Statements"] as List).length; 39 | } catch (e) {} 40 | 41 | List statements = []; 42 | for (int statementIndex = 0; statementIndex < len; statementIndex++) { 43 | statements.add(Ast.fromJson(jsonList["Statements"][statementIndex])); 44 | } 45 | 46 | return statements; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /lib/ui_elements/code_text.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter/services.dart'; 3 | import 'package:flutterdesktopapp/ui_elements/text_highlighter.dart'; 4 | import 'package:flutterdesktopapp/utils/app_data.dart'; 5 | import 'package:provider/provider.dart'; 6 | 7 | class CodeText extends StatefulWidget { 8 | CodeText({Key key}) : super(key: key); 9 | 10 | @override 11 | _CodeTextState createState() => _CodeTextState(); 12 | } 13 | 14 | class _CodeTextState extends State { 15 | void refresh() { 16 | setState(() {}); 17 | } 18 | 19 | @override 20 | Widget build(BuildContext context) { 21 | final appData = Provider.of(context, listen: true); 22 | 23 | var atLeastOneCircle = appData.atLeastOneCircle(); 24 | 25 | return SingleChildScrollView( 26 | child: SizedBox( 27 | height: 800, 28 | width: 1200, 29 | child: (atLeastOneCircle) 30 | ? TextHighlighter() 31 | : TextField( 32 | onChanged: (text) { 33 | appData.isVisualizationReady = true; 34 | }, 35 | controller: appData.editingController, 36 | autofocus: true, 37 | style: TextStyle(fontSize: 30, fontWeight: FontWeight.bold), 38 | decoration: InputDecoration( 39 | hintText: "Write some code here and visualize!", 40 | ), 41 | keyboardType: TextInputType.multiline, 42 | expands: true, 43 | maxLines: null, 44 | ), 45 | ), 46 | ); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /lib/ui_elements/modes_circles.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutterdesktopapp/components/resusable_circle.dart'; 3 | 4 | class ThreeCircles extends StatelessWidget { 5 | final String headline1, title1, headline2, title2, headline3, title3; 6 | final Function function1; 7 | final Function function2; 8 | final Function function3; 9 | 10 | ThreeCircles( 11 | {this.headline1, 12 | this.title1, 13 | this.function1, 14 | this.headline2, 15 | this.title2, 16 | this.function2, 17 | this.headline3, 18 | this.title3, 19 | this.function3}); 20 | 21 | @override 22 | Widget build(BuildContext context) { 23 | return Expanded( 24 | child: Column( 25 | children: [ 26 | Expanded( 27 | child: Row( 28 | mainAxisAlignment: MainAxisAlignment.center, 29 | children: [ 30 | Expanded( 31 | child: ReusableCircle( 32 | headline: headline1, 33 | title: title1, 34 | function: function1, 35 | )), 36 | SizedBox( 37 | width: 30, 38 | ), 39 | Expanded( 40 | child: ReusableCircle( 41 | headline: headline2, 42 | title: title2, 43 | function: function2, 44 | )) 45 | ], 46 | ), 47 | ), 48 | Expanded( 49 | child: ReusableCircle( 50 | headline: headline3, title: title3, function: function3)), 51 | ], 52 | ), 53 | ); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /ios/Runner/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /ios/Runner/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | flutterdesktopapp 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | $(FLUTTER_BUILD_NAME) 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | $(FLUTTER_BUILD_NUMBER) 23 | LSRequiresIPhoneOS 24 | 25 | UILaunchStoryboardName 26 | LaunchScreen 27 | UIMainStoryboardFile 28 | Main 29 | UISupportedInterfaceOrientations 30 | 31 | UIInterfaceOrientationPortrait 32 | UIInterfaceOrientationLandscapeLeft 33 | UIInterfaceOrientationLandscapeRight 34 | 35 | UISupportedInterfaceOrientations~ipad 36 | 37 | UIInterfaceOrientationPortrait 38 | UIInterfaceOrientationPortraitUpsideDown 39 | UIInterfaceOrientationLandscapeLeft 40 | UIInterfaceOrientationLandscapeRight 41 | 42 | UIViewControllerBasedStatusBarAppearance 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /lib/screens/select_visualization_mode.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutterdesktopapp/screens/first_page.dart'; 3 | import 'package:flutterdesktopapp/screens/semantic_page.dart'; 4 | import 'package:flutterdesktopapp/screens/syntactic_and_statement_page.dart'; 5 | import 'package:flutterdesktopapp/screens/tokens_page.dart'; 6 | import 'package:flutterdesktopapp/utils/app_data.dart'; 7 | import 'package:provider/provider.dart'; 8 | 9 | class Modes extends StatefulWidget { 10 | Modes({Key key}) : super(key: key); 11 | 12 | @override 13 | _ModesState createState() => _ModesState(); 14 | } 15 | 16 | class _ModesState extends State { 17 | @override 18 | Widget build(BuildContext context) { 19 | final appData = Provider.of(context); 20 | 21 | Widget getClickedPage() { 22 | if (appData.isVisualized && appData.circleOneClicked) { 23 | return TokensPage(appData.tokensList.length); 24 | } else if (appData.isVisualized && appData.circleTwoClicked) { 25 | return SyntacticPage( 26 | appData.parsedStatementsList[appData.visualizedStatementIndex] 27 | .graphs.length, 28 | appData.visualizedStatementIndex); 29 | } else if (appData.isVisualized && appData.circleThreeClicked) { 30 | return SemanticPage( 31 | appData 32 | .astsList[appData.visualizedStatementIndex].visitedNode.length, 33 | appData.visualizedStatementIndex); 34 | } 35 | 36 | return PageOne(); 37 | } 38 | 39 | return Builder( 40 | builder: (context) { 41 | return Container( 42 | child: getClickedPage(), 43 | ); 44 | }, 45 | ); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /lib/ui_elements/console_panel.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutterdesktopapp/utils/constants.dart'; 3 | import 'package:flutterdesktopapp/utils/utilities_provider.dart'; 4 | import 'package:provider/provider.dart'; 5 | 6 | class ConsolePanel extends StatefulWidget { 7 | const ConsolePanel({Key key}) : super(key: key); 8 | 9 | @override 10 | _ConsolePanelState createState() => _ConsolePanelState(); 11 | } 12 | 13 | class _ConsolePanelState extends State { 14 | @override 15 | Widget build(BuildContext context) { 16 | final appData = Provider.of(context); 17 | var consoleMessages = appData.consoleMessages; 18 | return SizedBox( 19 | width: 1200, 20 | child: Padding( 21 | padding: const EdgeInsets.all(8.0), 22 | child: (consoleMessages.isEmpty 23 | ? null 24 | : ListView.builder( 25 | itemCount: consoleMessages.length, 26 | itemBuilder: (context, index) { 27 | return Padding( 28 | padding: const EdgeInsets.all(6.0), 29 | child: Text( 30 | "-> " + 31 | consoleMessages[ 32 | consoleMessages.length - index - 1][0], 33 | style: (consoleMessages[consoleMessages.length - 34 | index - 35 | 1][1] == 36 | 0 37 | ? text_style_console_error 38 | : text_style_console_normal)), 39 | ); 40 | })))); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /InterpreterVisualizer/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | 6 | org.springframework.boot 7 | spring-boot-starter-parent 8 | 2.5.2 9 | 10 | 11 | com.example 12 | InterpreterVisualizer 13 | 0.0.1-SNAPSHOT 14 | InterpreterVisualizer 15 | Demo project for Spring Boot 16 | 17 | 11 18 | 19 | 20 | 21 | org.springframework.boot 22 | spring-boot-starter-web 23 | 24 | 25 | 26 | org.springframework.boot 27 | spring-boot-starter-test 28 | test 29 | 30 | 31 | org.json 32 | json 33 | 20210307 34 | 35 | 36 | 37 | 38 | 39 | org.springframework.boot 40 | spring-boot-maven-plugin 41 | 42 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /InterpreterVisualizer/src/main/java/simpleinterpreter/InterpreterAdapter.java: -------------------------------------------------------------------------------- 1 | package simpleinterpreter; 2 | 3 | import org.json.JSONObject; 4 | 5 | import java.util.HashMap; 6 | import java.util.Map; 7 | 8 | public class InterpreterAdapter { 9 | 10 | private static final JSONObject invalidTokenError = new JSONObject().put("ERROR", "Invalid Token."); 11 | private static final InterpreterAdapter interpreterAdapter = new InterpreterAdapter(); 12 | private static final Map interpreters = new HashMap<>(); 13 | 14 | 15 | private InterpreterAdapter() { 16 | } 17 | 18 | public static InterpreterAdapter getInterpreterAdapter() { 19 | return interpreterAdapter; 20 | } 21 | 22 | 23 | public void startInterpreter(String token, String source) { 24 | interpreters.put(token, new SimpleInterpreter(source)); 25 | } 26 | 27 | public JSONObject getLexicalAnalysis(String token) { 28 | if (interpreters.get(token) == null) { 29 | return invalidTokenError; 30 | } 31 | SimpleInterpreter interpreter = interpreters.get(token); 32 | return interpreter.getLexicalAnalysis(); 33 | } 34 | 35 | public JSONObject getSyntacticAnalysis(String token) { 36 | if (interpreters.get(token) == null) { 37 | return invalidTokenError; 38 | } 39 | SimpleInterpreter interpreter = interpreters.get(token); 40 | return interpreter.getSyntacticAnalysis(); 41 | } 42 | 43 | public JSONObject getSemanticAnalysis(String token) { 44 | if (interpreters.get(token) == null) { 45 | return invalidTokenError; 46 | } 47 | SimpleInterpreter interpreter = interpreters.get(token); 48 | return interpreter.getSemanticAnalysis(); 49 | } 50 | 51 | } 52 | -------------------------------------------------------------------------------- /lib/models/Ast.dart: -------------------------------------------------------------------------------- 1 | class Ast { 2 | String _astGraph; 3 | List _visitedNode; 4 | List _nodesData; 5 | List _symbolTableIndexSync; 6 | List _symbolTable; 7 | Map _errors; 8 | Map _outputMessages; 9 | 10 | Ast( 11 | this._astGraph, 12 | this._visitedNode, 13 | this._nodesData, 14 | this._symbolTableIndexSync, 15 | this._symbolTable, 16 | this._errors, 17 | this._outputMessages); 18 | 19 | factory Ast.fromJson(Map json) { 20 | String ast = json["AST"].toString(); 21 | 22 | List visitedNode = (json["Visited Nodes"] as List); 23 | 24 | List nodesData = (json["Nodes"] as List); 25 | 26 | List symbolTableIndexSync = 27 | (json["Symbol Table Index Sync"] as List); 28 | 29 | Map errorsString = 30 | (json["Errors"] as Map); 31 | 32 | Map errors = {}; 33 | for (String s in errorsString.keys) { 34 | errors[int.parse(s)] = errorsString[s].toString(); 35 | } 36 | 37 | Map outputMessagesString = 38 | (json["Output Messages"] as Map); 39 | Map outputMessages = {}; 40 | for (String s in outputMessagesString.keys) { 41 | outputMessages[int.parse(s)] = outputMessagesString[s].toString(); 42 | } 43 | 44 | List symbolTable = (json["Symbol Table"] as List); 45 | 46 | return Ast(ast, visitedNode, nodesData, symbolTableIndexSync, symbolTable, 47 | errors, outputMessages); 48 | } 49 | 50 | Map get outputMessages => _outputMessages; 51 | 52 | Map get errors => _errors; 53 | 54 | List get symbolTable => _symbolTable; 55 | 56 | List get symbolTableIndexSync => _symbolTableIndexSync; 57 | 58 | List get nodesData => _nodesData; 59 | 60 | List get visitedNode => _visitedNode; 61 | 62 | String get astGraph => _astGraph; 63 | } 64 | -------------------------------------------------------------------------------- /lib/models/tokens.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | class Token { 4 | String _tokenType; 5 | String _lexeme; 6 | String _literal; 7 | int _line; 8 | int _start; 9 | int _end; 10 | Color _color; 11 | List _errors; 12 | 13 | List get errors => _errors; 14 | 15 | Color get color => _color; 16 | 17 | Token(this._tokenType, this._lexeme, this._literal, this._line, this._start, 18 | this._end, int category, this._errors) { 19 | this._color = getTokenColor(category); 20 | } 21 | 22 | factory Token.fromJson(int tokenIndex, Map json) { 23 | List errors = []; 24 | if (json["Errors"][tokenIndex.toString()] != null) { 25 | int length = 26 | (json["Errors"][tokenIndex.toString()] as List).length; 27 | for (int i = 0; i < length; i++) { 28 | errors.add(json["Errors"][tokenIndex.toString()][i].toString()); 29 | } 30 | } 31 | return Token( 32 | json["Tokens"][tokenIndex]['type'], 33 | json["Tokens"][tokenIndex]['lexeme'], 34 | json["Tokens"][tokenIndex]['literal'], 35 | json["Tokens"][tokenIndex]['line'], 36 | json["Tokens"][tokenIndex]['start'], 37 | json["Tokens"][tokenIndex]['end'], 38 | json["Tokens"][tokenIndex]['category'], 39 | errors, 40 | ); 41 | } 42 | 43 | String get tokenType => _tokenType; 44 | 45 | String get lexeme => _lexeme; 46 | 47 | int get line => _line; 48 | 49 | String get literal => _literal; 50 | 51 | int get end => _end; 52 | 53 | int get start => _start; 54 | 55 | Color getTokenColor(var tokenType) { 56 | switch (tokenType) { 57 | case 1: 58 | return Colors.teal; 59 | break; 60 | case 2: 61 | return Colors.greenAccent; 62 | break; 63 | case 3: 64 | return Colors.amberAccent; 65 | break; 66 | case 4: 67 | return Colors.blueAccent; 68 | break; 69 | default: 70 | return Colors.grey; 71 | } 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /InterpreterVisualizer/src/main/java/api/interpretervisualizer/controller/WebController.java: -------------------------------------------------------------------------------- 1 | package api.interpretervisualizer.controller; 2 | 3 | import org.springframework.web.bind.annotation.*; 4 | import simpleinterpreter.InterpreterAdapter; 5 | 6 | import java.security.SecureRandom; 7 | import java.util.Base64; 8 | 9 | @CrossOrigin(origins = "*", allowedHeaders = "*") 10 | @RestController 11 | public class WebController { 12 | 13 | private static final SecureRandom secureRandom = new SecureRandom(); //threadsafe 14 | private static final Base64.Encoder base64Encoder = Base64.getUrlEncoder(); //threadsafe 15 | private static final InterpreterAdapter interpreterAdapter = InterpreterAdapter.getInterpreterAdapter(); 16 | 17 | String generateToken() { 18 | byte[] randomBytes = new byte[24]; 19 | secureRandom.nextBytes(randomBytes); 20 | String token = base64Encoder.encodeToString(randomBytes); 21 | return token; 22 | } 23 | 24 | @RequestMapping("/interpreter/lexical") 25 | public String lexicalAnalysis(@RequestParam(value = "token") String token) { 26 | System.out.println("Lexical Analysis Requested!"); 27 | return interpreterAdapter.getLexicalAnalysis(token).toString(); 28 | } 29 | 30 | @RequestMapping("/interpreter/syntactic") 31 | public String syntacticAnalysis(@RequestParam(value = "token") String token) { 32 | System.out.println("Syntactic Analysis Requested!"); 33 | return interpreterAdapter.getSyntacticAnalysis(token).toString(); 34 | } 35 | 36 | @RequestMapping("/interpreter/semantic") 37 | public String semanticAnalysis(@RequestParam(value = "token") String token) { 38 | System.out.println("Semantic Analysis Requested!"); 39 | return interpreterAdapter.getSemanticAnalysis(token).toString(); 40 | } 41 | 42 | @RequestMapping(value = "/interpreter/sourcecode", method = RequestMethod.POST) 43 | public String sourceCode(@RequestBody String source) { 44 | String generatedtoken = generateToken(); 45 | interpreterAdapter.startInterpreter(generatedtoken, source); 46 | return "{\"Token\":\"" + generatedtoken + "\"}"; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /InterpreterVisualizer/src/main/java/simpleinterpreter/Token.java: -------------------------------------------------------------------------------- 1 | package simpleinterpreter; 2 | 3 | import org.json.JSONObject; 4 | 5 | import java.util.Arrays; 6 | 7 | import static simpleinterpreter.TokenType.*; 8 | 9 | class Token { 10 | final TokenType type; 11 | final String lexeme; 12 | final Object literal; 13 | final int line; 14 | final int start; 15 | final int end; 16 | 17 | Token(TokenType type, String lexeme, Object literal, int line, int start, int end) { 18 | this.type = type; 19 | this.lexeme = lexeme; 20 | this.literal = literal; 21 | this.line = line; 22 | this.start = start; 23 | this.end = end; 24 | } 25 | 26 | int getTokenCategory() { 27 | TokenType[] single_char = {LEFT_PAREN, RIGHT_PAREN, LEFT_BRACE, RIGHT_BRACE, COMMA, DOT, MINUS, PLUS, SEMICOLON, SLASH, STAR}; 28 | 29 | TokenType[] two_chars = {BANG, BANG_EQUAL, EQUAL, EQUAL_EQUAL, GREATER, GREATER_EQUAL, LESS, LESS_EQUAL}; 30 | 31 | TokenType[] literals = {IDENTIFIER, STRING, NUMBER}; 32 | 33 | TokenType[] keywords = {AND, CLASS, ELSE, FALSE, FUN, FOR, IF, NIL, OR, PRINT, RETURN, SUPER, THIS, TRUE, VAR, WHILE}; 34 | 35 | if (Arrays.asList(single_char).contains(type)) { 36 | return 1; 37 | } else if (Arrays.asList(two_chars).contains(type)) { 38 | return 2; 39 | } else if (Arrays.asList(literals).contains(type)) { 40 | return 3; 41 | } else if (Arrays.asList(keywords).contains(type)) { 42 | return 4; 43 | } 44 | return 0; 45 | } 46 | 47 | public String toString() { 48 | return type + "," + lexeme + "," + literal + "," + line + "," + start + "," + end + "," + getTokenCategory(); 49 | } 50 | 51 | JSONObject getTokenJSON() { 52 | JSONObject tokenJSON = new JSONObject(); 53 | tokenJSON.put("type", type); 54 | tokenJSON.put("lexeme", lexeme); 55 | tokenJSON.put("literal", (literal == null ? "" : literal.toString())); 56 | tokenJSON.put("line", line); 57 | tokenJSON.put("line", line); 58 | tokenJSON.put("start", start); 59 | tokenJSON.put("end", end); 60 | tokenJSON.put("category", getTokenCategory()); 61 | return tokenJSON; 62 | } 63 | } -------------------------------------------------------------------------------- /android/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 6 | 13 | 17 | 21 | 26 | 30 | 31 | 32 | 33 | 34 | 35 | 37 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /contribution.md: -------------------------------------------------------------------------------- 1 | # Contribution Guidelines 2 | We are very grateful for your contribution and your time you spend to help us enhance the application and we are excited to welcome you. 3 | Make sure to understand the file structure before any edit. 4 | 5 | If you're new to open source, read [this article](https://en.wikipedia.org/wiki/Open_source) to get involved. 6 | 7 | # Here are the ways you can help 8 | 1. Improve existing features. 9 | 2. Add a new feature. 10 | 3. Test for issues and report them. 11 | 4. Help in code reviewing and provide feedback. 12 | 13 | # Required Steps to follow to make your PR accepted and merged 14 | 1. Take care about Encapsulation rules. 15 | 2. The names of functions, variables, components and classes should be descriptive 16 | and be according to the Dart [Naming Conventions](https://dart.dev/guides/language/effective-dart/style) and the Java [Naming Conventions](https://www.javatpoint.com/java-naming-conventions). 17 | 3. No unnecessary comments. 18 | 4. No warnings on the console or the terminal (always lint your code). 19 | 20 | # Add a new module or component 21 | If you see that there's a new module suitable for the application, write a proposal first that describes the following: 22 | 1. What the module is ? and what does it do ? 23 | 2. Why you think it's required ? 24 | 3. What are the requirements you want to finish this module ? 25 | 4. What is the time expected to finish it ? 26 | 5. What are the tools you will use to build it ? 27 | 6. What are the components and services you'll add ? (specify the name of the component and the function of this component). 28 | 29 | After your proposal is accepted you can start adding the new module or the component that you wish, 30 | but make sure that you adhere to the project structure and if any dependency is added, also, 31 | make sure that you add it in the readme.md file. 32 | 33 | # Found a critical bug 34 | If you found a critical bug, open an issue on the issues tab and provide a detailed description about what you found. 35 | 36 | # Frequently Asked Questions 37 | **I found a typo, should I report an issue before I can make a pull request?** 38 | 39 | For typos and other wording changes, you can directly open pull requests without first creating an issue. 40 | Issues are more for discussing larger problems associated with code or structural aspects of the curriculum. 41 | -------------------------------------------------------------------------------- /ios/Runner/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /lib/screens/tokens_page.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/cupertino.dart'; 2 | import 'package:flutter/material.dart'; 3 | import 'package:flutterdesktopapp/ui_elements/card_box.dart'; 4 | import 'package:flutterdesktopapp/ui_elements/token_item.dart'; 5 | import 'package:flutterdesktopapp/utils/constants.dart'; 6 | 7 | class TokensPage extends StatefulWidget { 8 | final int numberOfTokens; 9 | 10 | TokensPage(this.numberOfTokens); 11 | 12 | @override 13 | _TokensPageState createState() => _TokensPageState(); 14 | } 15 | 16 | class _TokensPageState extends State with TickerProviderStateMixin { 17 | AnimationController _animationController; 18 | double animationDuration; 19 | int durationOfSingleToken; 20 | int totalDuration; 21 | 22 | @override 23 | void initState() { 24 | // TODO: implement initState 25 | super.initState(); 26 | durationOfSingleToken = 1500; 27 | totalDuration = widget.numberOfTokens * durationOfSingleToken; 28 | _animationController = AnimationController( 29 | vsync: this, duration: new Duration(milliseconds: totalDuration)); 30 | 31 | animationDuration = durationOfSingleToken / totalDuration; 32 | _animationController.forward(); 33 | } 34 | 35 | @override 36 | void dispose() { 37 | print("Tokens Page Disposed"); 38 | _animationController.dispose(); 39 | super.dispose(); 40 | } 41 | 42 | @override 43 | Widget build(BuildContext context) { 44 | return Container( 45 | child: Column( 46 | mainAxisAlignment: MainAxisAlignment.center, 47 | children: [ 48 | CardBox( 49 | child: SizedBox( 50 | height: 30, 51 | child: Row( 52 | mainAxisAlignment: MainAxisAlignment.spaceBetween, 53 | children: [ 54 | Text( 55 | "Token Type", 56 | style: text_style_table, 57 | ), 58 | Text( 59 | "Lexeme", 60 | style: text_style_table, 61 | ), 62 | Text( 63 | "Literal", 64 | style: text_style_table, 65 | ), 66 | Text( 67 | "Line No.", 68 | style: text_style_table, 69 | ) 70 | ], 71 | ), 72 | ), 73 | ), 74 | Expanded( 75 | child: ListView.builder( 76 | itemCount: widget.numberOfTokens, 77 | itemBuilder: (context, index) { 78 | return TokenItem( 79 | index, animationDuration, _animationController); 80 | }, 81 | ), 82 | ) 83 | ], 84 | ), 85 | ); 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /lib/services/networking.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | import 'dart:convert'; 3 | 4 | import 'package:flutterdesktopapp/models/Ast.dart'; 5 | import 'package:flutterdesktopapp/models/response.dart'; 6 | import 'package:flutterdesktopapp/models/statement.dart'; 7 | import 'package:flutterdesktopapp/models/tokens.dart'; 8 | import 'package:http/http.dart' as http; 9 | 10 | class NetworkHelper { 11 | factory NetworkHelper() { 12 | return internalObject; 13 | } 14 | 15 | static const String ip_address = "http://192.168.1.5"; 16 | static const String port = "9090"; 17 | static const String url_sendCode = "/interpreter/sourcecode/"; 18 | static const String url_getLexical = "/interpreter/lexical?token="; 19 | static const String url_getSyntactic = "/interpreter/syntactic?token="; 20 | static const String url_getSemantic = "/interpreter/semantic?token="; 21 | 22 | static final NetworkHelper internalObject = NetworkHelper._internal(); 23 | 24 | static var token; 25 | 26 | NetworkHelper._internal(); 27 | 28 | ResponseParser responseParser = ResponseParser(); 29 | 30 | Future sendCodeToInterpreter(String code) async { 31 | List consoleMessages = []; 32 | 33 | final response = await http.post( 34 | Uri.parse('$ip_address:$port$url_sendCode'), 35 | headers: { 36 | 'Content-Type': 'application/json', 37 | 'Access-Control-Allow-Origin': '*' 38 | }, 39 | body: code, 40 | ); 41 | 42 | if (response.statusCode == 200) { 43 | consoleMessages.add(["Connection Established!", 1]); 44 | consoleMessages.add(["Authentication Token Received Successfully!", 1]); 45 | token = json.decode(response.body)["Token"]; 46 | } else { 47 | consoleMessages.add(["Failed to send the code.", 0]); 48 | } 49 | 50 | return consoleMessages; 51 | } 52 | 53 | Future> getLexicalAnalysis() async { 54 | final response = 55 | await http.get(Uri.parse('$ip_address:$port$url_getLexical$token')); 56 | if (response.statusCode == 200) { 57 | print("Requesting Lexical Analysis Completed Successfully!"); 58 | // print(responseParser.listOfTokens(response.body)); 59 | return responseParser.listOfTokens(response.body); 60 | } else {} 61 | } 62 | 63 | Future> getSyntacticAnalysis() async { 64 | final response = 65 | await http.get(Uri.parse('$ip_address:$port$url_getSyntactic$token')); 66 | if (response.statusCode == 200) { 67 | return responseParser.listOfParsedStatements(response.body); 68 | } else {} 69 | } 70 | 71 | Future> getSemanticAnalysis() async { 72 | final response = 73 | await http.get(Uri.parse('$ip_address:$port$url_getSemantic$token')); 74 | if (response.statusCode == 200) { 75 | return responseParser.listOfASTs(response.body); 76 | } else {} 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /lib/ui_elements/symbol_table.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/cupertino.dart'; 2 | import 'package:flutter/material.dart'; 3 | import 'package:flutterdesktopapp/ui_elements/card_box.dart'; 4 | import 'package:flutterdesktopapp/ui_elements/symbo_table_item.dart'; 5 | import 'package:flutterdesktopapp/utils/app_data.dart'; 6 | import 'package:flutterdesktopapp/utils/constants.dart'; 7 | import 'package:flutterdesktopapp/utils/graphs_provider.dart'; 8 | import 'package:provider/provider.dart'; 9 | 10 | class SymbolTable extends StatefulWidget { 11 | @override 12 | _SymbolTableState createState() => _SymbolTableState(); 13 | } 14 | 15 | class _SymbolTableState extends State 16 | with TickerProviderStateMixin { 17 | @override 18 | void dispose() { 19 | print("Symbol Table Page Disposed"); 20 | super.dispose(); 21 | } 22 | 23 | @override 24 | Widget build(BuildContext context) { 25 | var appData = Provider.of(context); 26 | final graphProvider = Provider.of(context); 27 | 28 | var symbolTable = 29 | appData.astsList[graphProvider.visualizedStatementIndex].symbolTable; 30 | var symbolTableSyncIndex = appData 31 | .astsList[graphProvider.visualizedStatementIndex] 32 | .symbolTableIndexSync[graphProvider.visualizedStepIndex]; 33 | var currentSymbolTable = symbolTable[symbolTableSyncIndex]; 34 | 35 | List scopes = [], variables = [], values = []; 36 | for (var scope in currentSymbolTable.keys) { 37 | for (var variable in currentSymbolTable[scope].keys) { 38 | scopes.add(scope); 39 | variables.add(variable); 40 | values.add(currentSymbolTable[scope][variable]); 41 | } 42 | } 43 | 44 | int len = scopes.length; 45 | 46 | return Container( 47 | child: Column( 48 | mainAxisAlignment: MainAxisAlignment.center, 49 | children: [ 50 | CardBox( 51 | child: SizedBox( 52 | height: 30, 53 | child: Row( 54 | mainAxisAlignment: MainAxisAlignment.spaceAround, 55 | children: [ 56 | Text( 57 | "Variable Name", 58 | style: text_style_table, 59 | ), 60 | Text( 61 | "Value", 62 | style: text_style_table, 63 | ), 64 | Text( 65 | "Scope", 66 | style: text_style_table, 67 | ), 68 | ], 69 | ), 70 | ), 71 | ), 72 | Expanded( 73 | child: ListView.builder( 74 | itemCount: len, 75 | itemBuilder: (context, index) { 76 | return SymbolTableItem(scopes[index].toString(), 77 | variables[index].toString(), values[index].toString()); 78 | }, 79 | ), 80 | ) 81 | ], 82 | ), 83 | ); 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /lib/screens/home_page.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutterdesktopapp/screens/select_visualization_mode.dart'; 3 | import 'package:flutterdesktopapp/ui_elements/card_box.dart'; 4 | import 'package:flutterdesktopapp/ui_elements/code_text.dart'; 5 | import 'package:flutterdesktopapp/ui_elements/console_panel.dart'; 6 | import 'package:flutterdesktopapp/ui_elements/control_buttons.dart'; 7 | import 'package:flutterdesktopapp/ui_elements/symbol_table.dart'; 8 | import 'package:flutterdesktopapp/utils/app_data.dart'; 9 | import 'package:provider/provider.dart'; 10 | 11 | import 'parsing_ast_page.dart'; 12 | 13 | class HomePage extends StatelessWidget { 14 | const HomePage({Key key}) : super(key: key); 15 | 16 | @override 17 | Widget build(BuildContext context) { 18 | final appData = Provider.of(context); 19 | 20 | return Scaffold( 21 | appBar: AppBar( 22 | toolbarHeight: 40, 23 | title: Center(child: Text("Interpreter Visualizer", style: TextStyle(fontWeight: FontWeight.bold),)), 24 | ), 25 | body: Container( 26 | child: Row( 27 | crossAxisAlignment: CrossAxisAlignment.stretch, 28 | mainAxisAlignment: MainAxisAlignment.start, 29 | children: [ 30 | Expanded( 31 | flex: 3, 32 | child: Column( 33 | mainAxisAlignment: MainAxisAlignment.start, 34 | crossAxisAlignment: CrossAxisAlignment.start, 35 | children: [ 36 | Expanded( 37 | flex: 3, 38 | child: CardBox( 39 | child: CodeText(), 40 | )), 41 | Expanded(flex: 1, child: CardBox(child: ConsolePanel())), 42 | ], 43 | ), 44 | ), 45 | Expanded( 46 | flex: 7, 47 | child: Column( 48 | crossAxisAlignment: CrossAxisAlignment.stretch, 49 | mainAxisAlignment: MainAxisAlignment.start, 50 | children: [ 51 | Expanded(flex: 1, child: CardBox(child: ControlButtons())), 52 | Expanded( 53 | flex: 7, 54 | child: Row( 55 | children: [ 56 | Expanded(flex: 1, child: CardBox(child: Modes())), 57 | Visibility( 58 | visible: appData.circleTwoClicked, 59 | child: Expanded( 60 | flex: 1, 61 | child: CardBox(child: ParsingASTPage()))), 62 | ], 63 | )), 64 | Visibility( 65 | visible: (appData.circleThreeClicked), 66 | child: 67 | Expanded(flex: 3, child: CardBox(child: SymbolTable())), 68 | ), 69 | ], 70 | ), 71 | ), 72 | ], 73 | ), 74 | ), 75 | ); 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /lib/models/statement.dart: -------------------------------------------------------------------------------- 1 | import 'parsing_ast.dart'; 2 | 3 | class Statement { 4 | ParsingAst _astGraph; 5 | List _nodesData; 6 | List _graphs; 7 | List _visitedNode; 8 | List _astGraphIndexSync; 9 | Map _consumedTokens; 10 | Map _errors; 11 | 12 | Statement( 13 | this._nodesData, 14 | this._graphs, 15 | this._visitedNode, 16 | this._consumedTokens, 17 | this._errors, 18 | this._astGraphIndexSync, 19 | this._astGraph); 20 | 21 | factory Statement.fromJson(Map json) { 22 | List nodesDataJSON = (json["Nodes"] as List); 23 | List nodesData = []; 24 | 25 | nodesData = nodesDataJSON; 26 | 27 | List graphs = (json["Graphs"] as List); 28 | 29 | List visitedNodes = (json["Visited Nodes"] as List); 30 | 31 | List consumedTokensJSON = (json["Consumed Tokens"] as List); 32 | Map consumedTokens = {}; 33 | for (var consumedTokensMap in consumedTokensJSON) { 34 | var key = 35 | int.parse((consumedTokensMap as Map).keys.first); 36 | var listOfTokens = 37 | (consumedTokensMap as Map).values.first; 38 | consumedTokens[key] = listOfTokens; 39 | } 40 | 41 | List errorsJSON = (json["Errors"] as List); 42 | Map errors = {}; 43 | for (var errorMap in errorsJSON) { 44 | var key = int.parse((errorMap as Map).keys.first); 45 | 46 | var errorMessage = 47 | (errorMap as Map).values.first.toString(); 48 | 49 | if (errors.containsKey(key)) { 50 | errors[key].add(errorMessage); 51 | } else { 52 | errors[key] = [errorMessage]; 53 | } 54 | } 55 | 56 | List astGraphIndexSync = (json["AST Graph Index Sync"] as List); 57 | 58 | ParsingAst astGraph = ParsingAst.fromJson(json["AST"]); 59 | 60 | return Statement(nodesData, graphs, visitedNodes, consumedTokens, errors, 61 | astGraphIndexSync, astGraph); 62 | } 63 | 64 | Map get errors => _errors; 65 | 66 | set errors(Map value) { 67 | _errors = value; 68 | } 69 | 70 | Map get consumedTokens => _consumedTokens; 71 | 72 | set consumedTokens(Map value) { 73 | _consumedTokens = value; 74 | } 75 | 76 | List get astGraphIndexSync => _astGraphIndexSync; 77 | 78 | set astGraphIndexSync(List value) { 79 | _astGraphIndexSync = value; 80 | } 81 | 82 | List get visitedNode => _visitedNode; 83 | 84 | set visitedNode(List value) { 85 | _visitedNode = value; 86 | } 87 | 88 | List get graphs => _graphs; 89 | 90 | set graphs(List value) { 91 | _graphs = value; 92 | } 93 | 94 | List get nodesData => _nodesData; 95 | 96 | set nodesData(List value) { 97 | _nodesData = value; 98 | } 99 | 100 | ParsingAst get astGraph => _astGraph; 101 | 102 | set astGraph(ParsingAst value) { 103 | _astGraph = value; 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "size" : "20x20", 5 | "idiom" : "iphone", 6 | "filename" : "Icon-App-20x20@2x.png", 7 | "scale" : "2x" 8 | }, 9 | { 10 | "size" : "20x20", 11 | "idiom" : "iphone", 12 | "filename" : "Icon-App-20x20@3x.png", 13 | "scale" : "3x" 14 | }, 15 | { 16 | "size" : "29x29", 17 | "idiom" : "iphone", 18 | "filename" : "Icon-App-29x29@1x.png", 19 | "scale" : "1x" 20 | }, 21 | { 22 | "size" : "29x29", 23 | "idiom" : "iphone", 24 | "filename" : "Icon-App-29x29@2x.png", 25 | "scale" : "2x" 26 | }, 27 | { 28 | "size" : "29x29", 29 | "idiom" : "iphone", 30 | "filename" : "Icon-App-29x29@3x.png", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "size" : "40x40", 35 | "idiom" : "iphone", 36 | "filename" : "Icon-App-40x40@2x.png", 37 | "scale" : "2x" 38 | }, 39 | { 40 | "size" : "40x40", 41 | "idiom" : "iphone", 42 | "filename" : "Icon-App-40x40@3x.png", 43 | "scale" : "3x" 44 | }, 45 | { 46 | "size" : "60x60", 47 | "idiom" : "iphone", 48 | "filename" : "Icon-App-60x60@2x.png", 49 | "scale" : "2x" 50 | }, 51 | { 52 | "size" : "60x60", 53 | "idiom" : "iphone", 54 | "filename" : "Icon-App-60x60@3x.png", 55 | "scale" : "3x" 56 | }, 57 | { 58 | "size" : "20x20", 59 | "idiom" : "ipad", 60 | "filename" : "Icon-App-20x20@1x.png", 61 | "scale" : "1x" 62 | }, 63 | { 64 | "size" : "20x20", 65 | "idiom" : "ipad", 66 | "filename" : "Icon-App-20x20@2x.png", 67 | "scale" : "2x" 68 | }, 69 | { 70 | "size" : "29x29", 71 | "idiom" : "ipad", 72 | "filename" : "Icon-App-29x29@1x.png", 73 | "scale" : "1x" 74 | }, 75 | { 76 | "size" : "29x29", 77 | "idiom" : "ipad", 78 | "filename" : "Icon-App-29x29@2x.png", 79 | "scale" : "2x" 80 | }, 81 | { 82 | "size" : "40x40", 83 | "idiom" : "ipad", 84 | "filename" : "Icon-App-40x40@1x.png", 85 | "scale" : "1x" 86 | }, 87 | { 88 | "size" : "40x40", 89 | "idiom" : "ipad", 90 | "filename" : "Icon-App-40x40@2x.png", 91 | "scale" : "2x" 92 | }, 93 | { 94 | "size" : "76x76", 95 | "idiom" : "ipad", 96 | "filename" : "Icon-App-76x76@1x.png", 97 | "scale" : "1x" 98 | }, 99 | { 100 | "size" : "76x76", 101 | "idiom" : "ipad", 102 | "filename" : "Icon-App-76x76@2x.png", 103 | "scale" : "2x" 104 | }, 105 | { 106 | "size" : "83.5x83.5", 107 | "idiom" : "ipad", 108 | "filename" : "Icon-App-83.5x83.5@2x.png", 109 | "scale" : "2x" 110 | }, 111 | { 112 | "size" : "1024x1024", 113 | "idiom" : "ios-marketing", 114 | "filename" : "Icon-App-1024x1024@1x.png", 115 | "scale" : "1x" 116 | } 117 | ], 118 | "info" : { 119 | "version" : 1, 120 | "author" : "xcode" 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /linux/flutter/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.10) 2 | 3 | set(EPHEMERAL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ephemeral") 4 | 5 | # Configuration provided via flutter tool. 6 | include(${EPHEMERAL_DIR}/generated_config.cmake) 7 | 8 | # TODO: Move the rest of this into files in ephemeral. See 9 | # https://github.com/flutter/flutter/issues/57146. 10 | 11 | # Serves the same purpose as list(TRANSFORM ... PREPEND ...), 12 | # which isn't available in 3.10. 13 | function(list_prepend LIST_NAME PREFIX) 14 | set(NEW_LIST "") 15 | foreach(element ${${LIST_NAME}}) 16 | list(APPEND NEW_LIST "${PREFIX}${element}") 17 | endforeach(element) 18 | set(${LIST_NAME} "${NEW_LIST}" PARENT_SCOPE) 19 | endfunction() 20 | 21 | # === Flutter Library === 22 | # System-level dependencies. 23 | find_package(PkgConfig REQUIRED) 24 | pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0) 25 | pkg_check_modules(GLIB REQUIRED IMPORTED_TARGET glib-2.0) 26 | pkg_check_modules(GIO REQUIRED IMPORTED_TARGET gio-2.0) 27 | pkg_check_modules(BLKID REQUIRED IMPORTED_TARGET blkid) 28 | pkg_check_modules(LZMA REQUIRED IMPORTED_TARGET liblzma) 29 | 30 | set(FLUTTER_LIBRARY "${EPHEMERAL_DIR}/libflutter_linux_gtk.so") 31 | 32 | # Published to parent scope for install step. 33 | set(FLUTTER_LIBRARY ${FLUTTER_LIBRARY} PARENT_SCOPE) 34 | set(FLUTTER_ICU_DATA_FILE "${EPHEMERAL_DIR}/icudtl.dat" PARENT_SCOPE) 35 | set(PROJECT_BUILD_DIR "${PROJECT_DIR}/build/" PARENT_SCOPE) 36 | set(AOT_LIBRARY "${PROJECT_DIR}/build/lib/libapp.so" PARENT_SCOPE) 37 | 38 | list(APPEND FLUTTER_LIBRARY_HEADERS 39 | "fl_basic_message_channel.h" 40 | "fl_binary_codec.h" 41 | "fl_binary_messenger.h" 42 | "fl_dart_project.h" 43 | "fl_engine.h" 44 | "fl_json_message_codec.h" 45 | "fl_json_method_codec.h" 46 | "fl_message_codec.h" 47 | "fl_method_call.h" 48 | "fl_method_channel.h" 49 | "fl_method_codec.h" 50 | "fl_method_response.h" 51 | "fl_plugin_registrar.h" 52 | "fl_plugin_registry.h" 53 | "fl_standard_message_codec.h" 54 | "fl_standard_method_codec.h" 55 | "fl_string_codec.h" 56 | "fl_value.h" 57 | "fl_view.h" 58 | "flutter_linux.h" 59 | ) 60 | list_prepend(FLUTTER_LIBRARY_HEADERS "${EPHEMERAL_DIR}/flutter_linux/") 61 | add_library(flutter INTERFACE) 62 | target_include_directories(flutter INTERFACE 63 | "${EPHEMERAL_DIR}" 64 | ) 65 | target_link_libraries(flutter INTERFACE "${FLUTTER_LIBRARY}") 66 | target_link_libraries(flutter INTERFACE 67 | PkgConfig::GTK 68 | PkgConfig::GLIB 69 | PkgConfig::GIO 70 | PkgConfig::BLKID 71 | PkgConfig::LZMA 72 | ) 73 | add_dependencies(flutter flutter_assemble) 74 | 75 | # === Flutter tool backend === 76 | # _phony_ is a non-existent file to force this command to run every time, 77 | # since currently there's no way to get a full input/output list from the 78 | # flutter tool. 79 | add_custom_command( 80 | OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS} 81 | ${CMAKE_CURRENT_BINARY_DIR}/_phony_ 82 | COMMAND ${CMAKE_COMMAND} -E env 83 | ${FLUTTER_TOOL_ENVIRONMENT} 84 | "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.sh" 85 | linux-x64 ${CMAKE_BUILD_TYPE} 86 | VERBATIM 87 | ) 88 | add_custom_target(flutter_assemble DEPENDS 89 | "${FLUTTER_LIBRARY}" 90 | ${FLUTTER_LIBRARY_HEADERS} 91 | ) 92 | -------------------------------------------------------------------------------- /InterpreterVisualizer/src/main/java/simpleinterpreter/Stmt.java: -------------------------------------------------------------------------------- 1 | package simpleinterpreter; 2 | 3 | import java.util.List; 4 | 5 | abstract class Stmt { 6 | interface Visitor { 7 | R visitBlockStmt(Block stmt); 8 | 9 | R visitExpressionStmt(Expression stmt); 10 | 11 | R visitIfStmt(If stmt); 12 | 13 | R visitPrintStmt(Print stmt); 14 | 15 | R visitVarStmt(Var stmt); 16 | 17 | R visitWhileStmt(While stmt); 18 | } 19 | 20 | int astNodeIndex; 21 | 22 | static class Block extends Stmt { 23 | Block(List statements, int astNodeIndex) { 24 | this.statements = statements; 25 | this.astNodeIndex = astNodeIndex; 26 | } 27 | 28 | @Override 29 | R accept(Visitor visitor) { 30 | return visitor.visitBlockStmt(this); 31 | } 32 | 33 | final List statements; 34 | } 35 | 36 | static class Expression extends Stmt { 37 | Expression(Expr expression, int astNodeIndex) { 38 | this.expression = expression; 39 | this.astNodeIndex = astNodeIndex; 40 | } 41 | 42 | @Override 43 | R accept(Visitor visitor) { 44 | return visitor.visitExpressionStmt(this); 45 | } 46 | 47 | final Expr expression; 48 | } 49 | 50 | static class If extends Stmt { 51 | If(Expr condition, 52 | Stmt thenBranch, 53 | Stmt elseBranch, 54 | int astNodeIndex) { 55 | this.condition = condition; 56 | this.thenBranch = thenBranch; 57 | this.elseBranch = elseBranch; 58 | this.astNodeIndex = astNodeIndex; 59 | } 60 | 61 | @Override 62 | R accept(Visitor visitor) { 63 | return visitor.visitIfStmt(this); 64 | } 65 | 66 | final Expr condition; 67 | final Stmt thenBranch; 68 | final Stmt elseBranch; 69 | } 70 | 71 | static class Print extends Stmt { 72 | Print(Expr expression, int astNodeIndex) { 73 | this.expression = expression; 74 | this.astNodeIndex = astNodeIndex; 75 | } 76 | 77 | @Override 78 | R accept(Visitor visitor) { 79 | return visitor.visitPrintStmt(this); 80 | } 81 | 82 | final Expr expression; 83 | } 84 | 85 | static class Var extends Stmt { 86 | Var(Token name, Expr initializer, int astNodeIndex) { 87 | this.name = name; 88 | this.initializer = initializer; 89 | this.astNodeIndex = astNodeIndex; 90 | } 91 | 92 | @Override 93 | R accept(Visitor visitor) { 94 | return visitor.visitVarStmt(this); 95 | } 96 | 97 | final Token name; 98 | final Expr initializer; 99 | } 100 | 101 | static class While extends Stmt { 102 | While(Expr condition, Stmt body, int astNodeIndex) { 103 | this.condition = condition; 104 | this.body = body; 105 | this.astNodeIndex = astNodeIndex; 106 | } 107 | 108 | @Override 109 | R accept(Visitor visitor) { 110 | return visitor.visitWhileStmt(this); 111 | } 112 | 113 | final Expr condition; 114 | final Stmt body; 115 | } 116 | 117 | 118 | abstract R accept(Visitor visitor); 119 | } -------------------------------------------------------------------------------- /pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: flutterdesktopapp 2 | description: A new Flutter project. 3 | 4 | # The following line prevents the package from being accidentally published to 5 | # pub.dev using `pub publish`. This is preferred for private packages. 6 | publish_to: 'none' # Remove this line if you wish to publish to pub.dev 7 | 8 | # The following defines the version and build number for your application. 9 | # A version number is three numbers separated by dots, like 1.2.43 10 | # followed by an optional build number separated by a +. 11 | # Both the version and the builder number may be overridden in flutter 12 | # build by specifying --build-name and --build-number, respectively. 13 | # In Android, build-name is used as versionName while build-number used as versionCode. 14 | # Read more about Android versioning at https://developer.android.com/studio/publish/versioning 15 | # In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion. 16 | # Read more about iOS versioning at 17 | # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html 18 | version: 1.0.0+1 19 | 20 | environment: 21 | sdk: ">=2.7.0 <3.0.0" 22 | 23 | dependencies: 24 | flutter: 25 | sdk: flutter 26 | 27 | 28 | # The following adds the Cupertino Icons font to your application. 29 | # Use with the CupertinoIcons class for iOS style icons. 30 | cupertino_icons: ^1.0.2 31 | provider: ^5.0.0 32 | path_provider: ^2.0.2 33 | flutter_progress_hud: ^2.0.0 34 | graphite: ^0.3.0 35 | bidirectional_listview: ^1.0.2+4 36 | http: ^0.13.3 37 | screenshot: ^1.2.1 38 | 39 | window_size: 40 | git: 41 | url: git://github.com/google/flutter-desktop-embedding.git 42 | path: plugins/window_size 43 | ref: fd519be1e8398c6b6c2062c2447bac960a71bc02 44 | 45 | 46 | dev_dependencies: 47 | flutter_test: 48 | sdk: flutter 49 | 50 | # For information on the generic Dart part of this file, see the 51 | # following page: https://dart.dev/tools/pub/pubspec 52 | 53 | # The following section is specific to Flutter. 54 | flutter: 55 | 56 | # The following line ensures that the Material Icons font is 57 | # included with your application, so that you can use the icons in 58 | # the material Icons class. 59 | uses-material-design: true 60 | 61 | # To add assets to your application, add an assets section, like this: 62 | assets: 63 | - assets/tokens_file.txt 64 | # - images/a_dot_ham.jpeg 65 | 66 | # An image asset can refer to one or more resolution-specific "variants", see 67 | # https://flutter.dev/assets-and-images/#resolution-aware. 68 | 69 | # For details regarding adding assets from package dependencies, see 70 | # https://flutter.dev/assets-and-images/#from-packages 71 | 72 | # To add custom fonts to your application, add a fonts section here, 73 | # in this "flutter" section. Each entry in this list should have a 74 | # "family" key with the font family name, and a "fonts" key with a 75 | # list giving the asset and other descriptors for the font. For 76 | # example: 77 | # fonts: 78 | # - family: Schyler 79 | # fonts: 80 | # - asset: fonts/Schyler-Regular.ttf 81 | # - asset: fonts/Schyler-Italic.ttf 82 | # style: italic 83 | # - family: Trajan Pro 84 | # fonts: 85 | # - asset: fonts/TrajanPro.ttf 86 | # - asset: fonts/TrajanPro_Bold.ttf 87 | # weight: 700 88 | # 89 | # For details regarding fonts from package dependencies, 90 | # see https://flutter.dev/custom-fonts/#from-packages 91 | -------------------------------------------------------------------------------- /ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 39 | 40 | 41 | 42 | 43 | 44 | 54 | 56 | 62 | 63 | 64 | 65 | 66 | 67 | 73 | 75 | 81 | 82 | 83 | 84 | 86 | 87 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /InterpreterVisualizer/src/main/java/simpleinterpreter/Expr.java: -------------------------------------------------------------------------------- 1 | package simpleinterpreter; 2 | 3 | abstract class Expr { 4 | interface Visitor { 5 | R visitAssignExpr(Assign expr); 6 | 7 | R visitBinaryExpr(Binary expr); 8 | 9 | R visitGroupingExpr(Grouping expr); 10 | 11 | R visitLiteralExpr(Literal expr); 12 | 13 | R visitLogicalExpr(Logical expr); 14 | 15 | R visitUnaryExpr(Unary expr); 16 | 17 | R visitVariableExpr(Variable expr); 18 | } 19 | 20 | int astNodeIndex; 21 | 22 | static class Assign extends Expr { 23 | Assign(Token name, Expr value, int astNodeIndex) { 24 | this.name = name; 25 | this.value = value; 26 | this.astNodeIndex = astNodeIndex; 27 | } 28 | 29 | @Override 30 | R accept(Visitor visitor) { 31 | return visitor.visitAssignExpr(this); 32 | } 33 | 34 | final Token name; 35 | final Expr value; 36 | } 37 | 38 | static class Binary extends Expr { 39 | Binary(Expr left, Token operator, Expr right, int astNodeIndex) { 40 | this.left = left; 41 | this.operator = operator; 42 | this.right = right; 43 | this.astNodeIndex = astNodeIndex; 44 | } 45 | 46 | @Override 47 | R accept(Visitor visitor) { 48 | return visitor.visitBinaryExpr(this); 49 | } 50 | 51 | final Expr left; 52 | final Token operator; 53 | final Expr right; 54 | } 55 | 56 | static class Grouping extends Expr { 57 | Grouping(Expr expression, int astNodeIndex) { 58 | this.expression = expression; 59 | this.astNodeIndex = astNodeIndex; 60 | } 61 | 62 | @Override 63 | R accept(Visitor visitor) { 64 | return visitor.visitGroupingExpr(this); 65 | } 66 | 67 | final Expr expression; 68 | } 69 | 70 | static class Literal extends Expr { 71 | Literal(Object value, int astNodeIndex) { 72 | this.value = value; 73 | this.astNodeIndex = astNodeIndex; 74 | } 75 | 76 | @Override 77 | R accept(Visitor visitor) { 78 | return visitor.visitLiteralExpr(this); 79 | } 80 | 81 | final Object value; 82 | } 83 | 84 | static class Logical extends Expr { 85 | Logical(Expr left, Token operator, Expr right, int astNodeIndex) { 86 | this.left = left; 87 | this.operator = operator; 88 | this.right = right; 89 | this.astNodeIndex = astNodeIndex; 90 | } 91 | 92 | @Override 93 | R accept(Visitor visitor) { 94 | return visitor.visitLogicalExpr(this); 95 | } 96 | 97 | final Expr left; 98 | final Token operator; 99 | final Expr right; 100 | } 101 | 102 | static class Unary extends Expr { 103 | Unary(Token operator, Expr right, int astNodeIndex) { 104 | this.operator = operator; 105 | this.right = right; 106 | this.astNodeIndex = astNodeIndex; 107 | } 108 | 109 | @Override 110 | R accept(Visitor visitor) { 111 | return visitor.visitUnaryExpr(this); 112 | } 113 | 114 | final Token operator; 115 | final Expr right; 116 | } 117 | 118 | static class Variable extends Expr { 119 | Variable(Token name, int astNodeIndex) { 120 | this.name = name; 121 | this.astNodeIndex = astNodeIndex; 122 | } 123 | 124 | @Override 125 | R accept(Visitor visitor) { 126 | return visitor.visitVariableExpr(this); 127 | } 128 | 129 | final Token name; 130 | } 131 | 132 | abstract R accept(Visitor visitor); 133 | } -------------------------------------------------------------------------------- /android/app/build.gradle: -------------------------------------------------------------------------------- 1 | //def localProperties = new Properties() 2 | //def localPropertiesFile = rootProject.file('local.properties') 3 | //if (localPropertiesFile.exists()) { 4 | // localPropertiesFile.withReader('UTF-8') { reader -> 5 | // localProperties.load(reader) 6 | // } 7 | //} 8 | // 9 | //def flutterRoot = localProperties.getProperty('flutter.sdk') 10 | //if (flutterRoot == null) { 11 | // throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.") 12 | //} 13 | // 14 | //def flutterVersionCode = localProperties.getProperty('flutter.versionCode') 15 | //if (flutterVersionCode == null) { 16 | // flutterVersionCode = '1' 17 | //} 18 | // 19 | //def flutterVersionName = localProperties.getProperty('flutter.versionName') 20 | //if (flutterVersionName == null) { 21 | // flutterVersionName = '1.0' 22 | //} 23 | // 24 | //apply plugin: 'com.android.application' 25 | //apply plugin: 'kotlin-android' 26 | //apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" 27 | // 28 | //android { 29 | // compileSdkVersion 30 30 | // 31 | // sourceSets { 32 | // main.java.srcDirs += 'src/main/kotlin' 33 | // } 34 | // 35 | // defaultConfig { 36 | // // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). 37 | // applicationId "com.example.flutterdesktopapp" 38 | // minSdkVersion 16 39 | // targetSdkVersion 30 40 | // versionCode flutterVersionCode.toInteger() 41 | // versionName flutterVersionName 42 | // } 43 | // 44 | // buildTypes { 45 | // release { 46 | // // TODO: Add your own signing config for the release build. 47 | // // Signing with the debug keys for now, so `flutter run --release` works. 48 | // signingConfig signingConfigs.debug 49 | // } 50 | // } 51 | //} 52 | // 53 | //flutter { 54 | // source '../..' 55 | //} 56 | // 57 | //dependencies { 58 | // implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" 59 | //} 60 | // 61 | // 62 | //***************************** 63 | 64 | def localProperties = new Properties() 65 | def localPropertiesFile = rootProject.file('local.properties') 66 | if (localPropertiesFile.exists()) { 67 | localPropertiesFile.withReader('UTF-8') { reader -> 68 | localProperties.load(reader) 69 | } 70 | } 71 | 72 | def flutterRoot = localProperties.getProperty('flutter.sdk') 73 | if (flutterRoot == null) { 74 | throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.") 75 | } 76 | 77 | def flutterVersionCode = localProperties.getProperty('flutter.versionCode') 78 | if (flutterVersionCode == null) { 79 | flutterVersionCode = '1' 80 | } 81 | 82 | def flutterVersionName = localProperties.getProperty('flutter.versionName') 83 | if (flutterVersionName == null) { 84 | flutterVersionName = '1.0' 85 | } 86 | 87 | apply plugin: 'com.android.application' 88 | apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" 89 | 90 | android { 91 | compileSdkVersion 30 92 | 93 | defaultConfig { 94 | // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). 95 | applicationId "com.example.flutterdesktopapp" 96 | minSdkVersion 16 97 | targetSdkVersion 30 98 | versionCode flutterVersionCode.toInteger() 99 | versionName flutterVersionName 100 | } 101 | 102 | buildTypes { 103 | release { 104 | // TODO: Add your own signing config for the release build. 105 | // Signing with the debug keys for now, so `flutter run --release` works. 106 | signingConfig signingConfigs.debug 107 | } 108 | } 109 | } 110 | 111 | flutter { 112 | source '../..' 113 | } 114 | 115 | 116 | -------------------------------------------------------------------------------- /linux/my_application.cc: -------------------------------------------------------------------------------- 1 | #include "my_application.h" 2 | 3 | #include 4 | #ifdef GDK_WINDOWING_X11 5 | #include 6 | #endif 7 | 8 | #include "flutter/generated_plugin_registrant.h" 9 | 10 | struct _MyApplication { 11 | GtkApplication parent_instance; 12 | char** dart_entrypoint_arguments; 13 | }; 14 | 15 | G_DEFINE_TYPE(MyApplication, my_application, GTK_TYPE_APPLICATION) 16 | 17 | // Implements GApplication::activate. 18 | static void my_application_activate(GApplication* application) { 19 | MyApplication* self = MY_APPLICATION(application); 20 | GtkWindow* window = 21 | GTK_WINDOW(gtk_application_window_new(GTK_APPLICATION(application))); 22 | 23 | // Use a header bar when running in GNOME as this is the common style used 24 | // by applications and is the setup most users will be using (e.g. Ubuntu 25 | // desktop). 26 | // If running on X and not using GNOME then just use a traditional title bar 27 | // in case the window manager does more exotic layout, e.g. tiling. 28 | // If running on Wayland assume the header bar will work (may need changing 29 | // if future cases occur). 30 | gboolean use_header_bar = TRUE; 31 | #ifdef GDK_WINDOWING_X11 32 | GdkScreen *screen = gtk_window_get_screen(window); 33 | if (GDK_IS_X11_SCREEN(screen)) { 34 | const gchar* wm_name = gdk_x11_screen_get_window_manager_name(screen); 35 | if (g_strcmp0(wm_name, "GNOME Shell") != 0) { 36 | use_header_bar = FALSE; 37 | } 38 | } 39 | #endif 40 | if (use_header_bar) { 41 | GtkHeaderBar *header_bar = GTK_HEADER_BAR(gtk_header_bar_new()); 42 | gtk_widget_show(GTK_WIDGET(header_bar)); 43 | gtk_header_bar_set_title(header_bar, "flutterdesktopapp"); 44 | gtk_header_bar_set_show_close_button(header_bar, TRUE); 45 | gtk_window_set_titlebar(window, GTK_WIDGET(header_bar)); 46 | } 47 | else { 48 | gtk_window_set_title(window, "flutterdesktopapp"); 49 | } 50 | 51 | gtk_window_set_default_size(window, 1280, 720); 52 | gtk_widget_show(GTK_WIDGET(window)); 53 | 54 | g_autoptr(FlDartProject) project = fl_dart_project_new(); 55 | fl_dart_project_set_dart_entrypoint_arguments(project, self->dart_entrypoint_arguments); 56 | 57 | FlView* view = fl_view_new(project); 58 | gtk_widget_show(GTK_WIDGET(view)); 59 | gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(view)); 60 | 61 | fl_register_plugins(FL_PLUGIN_REGISTRY(view)); 62 | 63 | gtk_widget_grab_focus(GTK_WIDGET(view)); 64 | } 65 | 66 | // Implements GApplication::local_command_line. 67 | static gboolean my_application_local_command_line(GApplication* application, gchar ***arguments, int *exit_status) { 68 | MyApplication* self = MY_APPLICATION(application); 69 | // Strip out the first argument as it is the binary name. 70 | self->dart_entrypoint_arguments = g_strdupv(*arguments + 1); 71 | 72 | g_autoptr(GError) error = nullptr; 73 | if (!g_application_register(application, nullptr, &error)) { 74 | g_warning("Failed to register: %s", error->message); 75 | *exit_status = 1; 76 | return TRUE; 77 | } 78 | 79 | g_application_activate(application); 80 | *exit_status = 0; 81 | 82 | return TRUE; 83 | } 84 | 85 | // Implements GObject::dispose. 86 | static void my_application_dispose(GObject *object) { 87 | MyApplication* self = MY_APPLICATION(object); 88 | g_clear_pointer(&self->dart_entrypoint_arguments, g_strfreev); 89 | G_OBJECT_CLASS(my_application_parent_class)->dispose(object); 90 | } 91 | 92 | static void my_application_class_init(MyApplicationClass* klass) { 93 | G_APPLICATION_CLASS(klass)->activate = my_application_activate; 94 | G_APPLICATION_CLASS(klass)->local_command_line = my_application_local_command_line; 95 | G_OBJECT_CLASS(klass)->dispose = my_application_dispose; 96 | } 97 | 98 | static void my_application_init(MyApplication* self) {} 99 | 100 | MyApplication* my_application_new() { 101 | return MY_APPLICATION(g_object_new(my_application_get_type(), 102 | "application-id", APPLICATION_ID, 103 | nullptr)); 104 | } 105 | -------------------------------------------------------------------------------- /linux/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.10) 2 | project(runner LANGUAGES CXX) 3 | 4 | set(BINARY_NAME "flutterdesktopapp") 5 | set(APPLICATION_ID "com.example.flutterdesktopapp") 6 | 7 | cmake_policy(SET CMP0063 NEW) 8 | 9 | set(CMAKE_INSTALL_RPATH "$ORIGIN/lib") 10 | 11 | # Configure build options. 12 | if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) 13 | set(CMAKE_BUILD_TYPE "Debug" CACHE 14 | STRING "Flutter build mode" FORCE) 15 | set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS 16 | "Debug" "Profile" "Release") 17 | endif() 18 | 19 | # Compilation settings that should be applied to most targets. 20 | function(APPLY_STANDARD_SETTINGS TARGET) 21 | target_compile_features(${TARGET} PUBLIC cxx_std_14) 22 | target_compile_options(${TARGET} PRIVATE -Wall -Werror) 23 | target_compile_options(${TARGET} PRIVATE "$<$>:-O3>") 24 | target_compile_definitions(${TARGET} PRIVATE "$<$>:NDEBUG>") 25 | endfunction() 26 | 27 | set(FLUTTER_MANAGED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/flutter") 28 | 29 | # Flutter library and tool build rules. 30 | add_subdirectory(${FLUTTER_MANAGED_DIR}) 31 | 32 | # System-level dependencies. 33 | find_package(PkgConfig REQUIRED) 34 | pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0) 35 | 36 | add_definitions(-DAPPLICATION_ID="${APPLICATION_ID}") 37 | 38 | # Application build 39 | add_executable(${BINARY_NAME} 40 | "main.cc" 41 | "my_application.cc" 42 | "${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc" 43 | ) 44 | apply_standard_settings(${BINARY_NAME}) 45 | target_link_libraries(${BINARY_NAME} PRIVATE flutter) 46 | target_link_libraries(${BINARY_NAME} PRIVATE PkgConfig::GTK) 47 | add_dependencies(${BINARY_NAME} flutter_assemble) 48 | # Only the install-generated bundle's copy of the executable will launch 49 | # correctly, since the resources must in the right relative locations. To avoid 50 | # people trying to run the unbundled copy, put it in a subdirectory instead of 51 | # the default top-level location. 52 | set_target_properties(${BINARY_NAME} 53 | PROPERTIES 54 | RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/intermediates_do_not_run" 55 | ) 56 | 57 | # Generated plugin build rules, which manage building the plugins and adding 58 | # them to the application. 59 | include(flutter/generated_plugins.cmake) 60 | 61 | 62 | # === Installation === 63 | # By default, "installing" just makes a relocatable bundle in the build 64 | # directory. 65 | set(BUILD_BUNDLE_DIR "${PROJECT_BINARY_DIR}/bundle") 66 | if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) 67 | set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE) 68 | endif() 69 | 70 | # Start with a clean build bundle directory every time. 71 | install(CODE " 72 | file(REMOVE_RECURSE \"${BUILD_BUNDLE_DIR}/\") 73 | " COMPONENT Runtime) 74 | 75 | set(INSTALL_BUNDLE_DATA_DIR "${CMAKE_INSTALL_PREFIX}/data") 76 | set(INSTALL_BUNDLE_LIB_DIR "${CMAKE_INSTALL_PREFIX}/lib") 77 | 78 | install(TARGETS ${BINARY_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}" 79 | COMPONENT Runtime) 80 | 81 | install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" 82 | COMPONENT Runtime) 83 | 84 | install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" 85 | COMPONENT Runtime) 86 | 87 | if(PLUGIN_BUNDLED_LIBRARIES) 88 | install(FILES "${PLUGIN_BUNDLED_LIBRARIES}" 89 | DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" 90 | COMPONENT Runtime) 91 | endif() 92 | 93 | # Fully re-copy the assets directory on each build to avoid having stale files 94 | # from a previous install. 95 | set(FLUTTER_ASSET_DIR_NAME "flutter_assets") 96 | install(CODE " 97 | file(REMOVE_RECURSE \"${INSTALL_BUNDLE_DATA_DIR}/${FLUTTER_ASSET_DIR_NAME}\") 98 | " COMPONENT Runtime) 99 | install(DIRECTORY "${PROJECT_BUILD_DIR}/${FLUTTER_ASSET_DIR_NAME}" 100 | DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime) 101 | 102 | # Install the AOT library on non-Debug builds only. 103 | if(NOT CMAKE_BUILD_TYPE MATCHES "Debug") 104 | install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" 105 | COMPONENT Runtime) 106 | endif() 107 | -------------------------------------------------------------------------------- /lib/utils/app_data.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/cupertino.dart'; 2 | import 'package:flutterdesktopapp/models/Ast.dart'; 3 | import 'package:flutterdesktopapp/models/statement.dart'; 4 | import 'package:flutterdesktopapp/models/tokens.dart'; 5 | 6 | class AppData with ChangeNotifier { 7 | bool _isVisualized = false; 8 | bool _isVisualizationReady = false; 9 | 10 | bool get isVisualizationReady => _isVisualizationReady; 11 | 12 | set isVisualizationReady(bool value) { 13 | _isVisualizationReady = value; 14 | notifyListeners(); 15 | } 16 | 17 | bool atLeastOneCircle() { 18 | return (circleOneClicked || circleTwoClicked || circleThreeClicked); 19 | } 20 | 21 | bool _cirlcleOneClicked = false; 22 | bool _circleTwoClicked = false; 23 | bool _circleThreeClicked = false; 24 | bool _circleFourClicked = false; 25 | bool _tokensChange = false; 26 | 27 | List _tokensColors = []; 28 | List _tokensIndices = []; 29 | List _tokensList = []; 30 | 31 | List _parsedStatementsList = []; 32 | List _astsList = []; 33 | 34 | List get astsList => _astsList; 35 | 36 | set astsList(List value) { 37 | _astsList = value; 38 | } 39 | 40 | List get parsedStatementsList => _parsedStatementsList; 41 | 42 | set parsedStatementsList(List value) { 43 | _parsedStatementsList = value; 44 | } 45 | 46 | int _visualizedStatementIndex = 0; 47 | 48 | int get visualizedStatementIndex => _visualizedStatementIndex; 49 | 50 | void resetVisualizerStatementIndex() { 51 | _visualizedStatementIndex = 0; 52 | } 53 | 54 | set visualizedStatementIndex(int value) { 55 | _visualizedStatementIndex = value; 56 | notifyListeners(); 57 | } 58 | 59 | // List _jsonList = []; 60 | // List _newNodeID = []; 61 | // List _nodeDataList = []; 62 | 63 | // List get jsonList => _jsonList; 64 | 65 | // set jsonList(List value) { 66 | // _jsonList = value; 67 | // } 68 | 69 | void refreshTokensChange() { 70 | _tokensChange = !_tokensChange; 71 | notifyListeners(); 72 | } 73 | 74 | bool get tokensChange => _tokensChange; 75 | 76 | set tokensList(List value) { 77 | _tokensList = value; 78 | } 79 | 80 | List get tokensList => _tokensList; 81 | 82 | List get tokensIndices => _tokensIndices; 83 | 84 | set tokensIndices(List value) { 85 | _tokensIndices = value; 86 | } 87 | 88 | List get tokensColors => _tokensColors; 89 | 90 | set tokensColors(List value) { 91 | _tokensColors = value; 92 | notifyListeners(); 93 | } 94 | 95 | TextEditingController _editingController = TextEditingController(); 96 | 97 | void changeCircleOneState() { 98 | if (_cirlcleOneClicked) { 99 | _cirlcleOneClicked = false; 100 | } else { 101 | _cirlcleOneClicked = true; 102 | } 103 | notifyListeners(); 104 | } 105 | 106 | void changeCircleTwoState() { 107 | if (_circleTwoClicked) { 108 | _circleTwoClicked = false; 109 | } else { 110 | _circleTwoClicked = true; 111 | } 112 | notifyListeners(); 113 | } 114 | 115 | void changeCircleThreeState() { 116 | if (_circleThreeClicked) { 117 | _circleThreeClicked = false; 118 | } else { 119 | _circleThreeClicked = true; 120 | } 121 | notifyListeners(); 122 | } 123 | 124 | void changeCircleFourState() { 125 | if (_circleFourClicked) { 126 | _circleFourClicked = false; 127 | } else { 128 | _circleFourClicked = true; 129 | } 130 | notifyListeners(); 131 | } 132 | 133 | void visualize() { 134 | _isVisualized = true; 135 | notifyListeners(); 136 | } 137 | 138 | bool get circleOneClicked => _cirlcleOneClicked; 139 | 140 | bool get circleTwoClicked => _circleTwoClicked; 141 | 142 | bool get circleThreeClicked => _circleThreeClicked; 143 | 144 | bool get circleFourClicked => _circleFourClicked; 145 | 146 | bool get isVisualized => _isVisualized; 147 | 148 | TextEditingController get editingController => _editingController; 149 | 150 | // List get newNodeID => _newNodeID; 151 | 152 | // set newNodeID(List value) { 153 | // _newNodeID = value; 154 | // } 155 | 156 | // List get nodeDataList => _nodeDataList; 157 | 158 | // set nodeDataList(List value) { 159 | // _nodeDataList = value; 160 | // } 161 | } 162 | -------------------------------------------------------------------------------- /lib/ui_elements/freescrollview.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/gestures.dart'; 2 | import 'package:flutter/material.dart'; 3 | 4 | class FreeScrollView extends StatefulWidget { 5 | final Widget child; 6 | final ScrollPhysics physics; 7 | 8 | const FreeScrollView( 9 | {Key key, 10 | this.physics = const ClampingScrollPhysics(), 11 | @required this.child}) 12 | : super(key: key); 13 | 14 | @override 15 | State createState() => _FreeScrollViewState(); 16 | } 17 | 18 | class _FreeScrollViewState extends State { 19 | final ScrollController _verticalController = ScrollController(); 20 | final ScrollController _horizontalController = ScrollController(); 21 | final Map _gestureRecognizers = 22 | {}; 23 | 24 | @override 25 | void initState() { 26 | super.initState(); 27 | _gestureRecognizers[PanGestureRecognizer] = 28 | GestureRecognizerFactoryWithHandlers( 29 | () => PanGestureRecognizer(), 30 | (instance) => instance 31 | ..onDown = _handleDragDown 32 | ..onStart = _handleDragStart 33 | ..onUpdate = _handleDragUpdate 34 | ..onEnd = _handleDragEnd 35 | ..onCancel = _handleDragCancel 36 | ..minFlingDistance = widget.physics.minFlingDistance 37 | ..minFlingVelocity = widget.physics.minFlingVelocity 38 | ..maxFlingVelocity = widget.physics.maxFlingVelocity 39 | ..velocityTrackerBuilder = ScrollConfiguration.of(context) 40 | .velocityTrackerBuilder(context) 41 | ..dragStartBehavior = DragStartBehavior.start); 42 | } 43 | 44 | @override 45 | Widget build(BuildContext context) => Stack(children: [ 46 | SingleChildScrollView( 47 | scrollDirection: Axis.horizontal, 48 | controller: _horizontalController, 49 | physics: widget.physics, 50 | child: SingleChildScrollView( 51 | scrollDirection: Axis.vertical, 52 | // ignore: avoid_redundant_argument_values 53 | controller: _verticalController, 54 | physics: widget.physics, 55 | child: widget.child)), 56 | Positioned.fill( 57 | child: RawGestureDetector( 58 | gestures: _gestureRecognizers, 59 | behavior: HitTestBehavior.opaque, 60 | excludeFromSemantics: true, 61 | )), 62 | ]); 63 | 64 | Drag _horizontalDrag; 65 | Drag _verticalDrag; 66 | ScrollHoldController _horizontalHold; 67 | ScrollHoldController _verticalHold; 68 | 69 | void _handleDragDown(DragDownDetails details) { 70 | _horizontalHold = 71 | _horizontalController.position.hold(() => _horizontalHold = null); 72 | _verticalHold = 73 | _verticalController.position.hold(() => _verticalHold = null); 74 | } 75 | 76 | void _handleDragStart(DragStartDetails details) { 77 | _horizontalDrag = _horizontalController.position 78 | .drag(details, () => _horizontalDrag = null); 79 | _verticalDrag = 80 | _verticalController.position.drag(details, () => _verticalDrag = null); 81 | } 82 | 83 | void _handleDragUpdate(DragUpdateDetails details) { 84 | _horizontalDrag?.update(DragUpdateDetails( 85 | sourceTimeStamp: details.sourceTimeStamp, 86 | delta: Offset(details.delta.dx, 0), 87 | primaryDelta: details.delta.dx, 88 | globalPosition: details.globalPosition)); 89 | _verticalDrag?.update(DragUpdateDetails( 90 | sourceTimeStamp: details.sourceTimeStamp, 91 | delta: Offset(0, details.delta.dy), 92 | primaryDelta: details.delta.dy, 93 | globalPosition: details.globalPosition)); 94 | } 95 | 96 | void _handleDragEnd(DragEndDetails details) { 97 | _horizontalDrag?.end(DragEndDetails( 98 | velocity: details.velocity, 99 | primaryVelocity: details.velocity.pixelsPerSecond.dx)); 100 | _verticalDrag?.end(DragEndDetails( 101 | velocity: details.velocity, 102 | primaryVelocity: details.velocity.pixelsPerSecond.dy)); 103 | } 104 | 105 | void _handleDragCancel() { 106 | _horizontalHold?.cancel(); 107 | _horizontalDrag?.cancel(); 108 | _verticalHold?.cancel(); 109 | _verticalDrag?.cancel(); 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /lib/ui_elements/token_item.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutterdesktopapp/utils/app_data.dart'; 3 | import 'package:flutterdesktopapp/utils/constants.dart'; 4 | import 'package:flutterdesktopapp/utils/utilities_provider.dart'; 5 | import 'package:provider/provider.dart'; 6 | 7 | import 'colored_card_box.dart'; 8 | 9 | class TokenItem extends StatefulWidget { 10 | final int index; 11 | final double duration; 12 | final AnimationController animationController; 13 | 14 | TokenItem(this.index, this.duration, this.animationController); 15 | 16 | @override 17 | _TokenItemState createState() => _TokenItemState(); 18 | } 19 | 20 | class _TokenItemState extends State { 21 | Animation animation; 22 | Animation animationColor; 23 | double start; 24 | double end; 25 | bool showErrors = true; 26 | 27 | @override 28 | void initState() { 29 | print(widget.index.toString() + " signing in"); 30 | super.initState(); 31 | start = (widget.duration * widget.index).toDouble(); 32 | end = start + widget.duration; 33 | // end = (end > 1.0 ? 1.0 : end); 34 | print("START $start , end $end"); 35 | 36 | animation = Tween( 37 | begin: 0.0, 38 | end: 1.0, 39 | ).animate( 40 | CurvedAnimation( 41 | parent: widget.animationController, 42 | curve: Interval( 43 | start, 44 | end, 45 | curve: Curves.easeInOutCirc, 46 | ), 47 | ), 48 | ); 49 | 50 | var appData = Provider.of(context, listen: false); 51 | var tokenIndex = appData.tokensIndices[widget.index]; 52 | var tokenGoalColor = appData.tokensColors[tokenIndex]; 53 | 54 | animationColor = ColorTween( 55 | begin: Colors.black, 56 | end: tokenGoalColor, 57 | ).animate( 58 | CurvedAnimation( 59 | parent: widget.animationController, 60 | curve: Interval( 61 | start, 62 | end, 63 | curve: Curves.easeInOutCirc, 64 | ), 65 | ), 66 | ); 67 | 68 | widget.animationController.addListener(() { 69 | if (this.mounted) setState(() {}); 70 | }); 71 | } 72 | 73 | // @override 74 | void dispose() { 75 | print("Token Disposed"); 76 | // // TODO: implement dispose 77 | super.dispose(); 78 | } 79 | 80 | @override 81 | Widget build(BuildContext context) { 82 | var appData = Provider.of(context); 83 | final utilsProvider = Provider.of(context); 84 | 85 | var tokensList = appData.tokensList; 86 | var tokenIndex = appData.tokensIndices[widget.index]; 87 | var token = tokensList[widget.index]; 88 | 89 | if (tokenIndex < utilsProvider.richTextList.length) { 90 | utilsProvider.richTextList[tokenIndex][1] = animationColor.value; 91 | } 92 | 93 | WidgetsBinding.instance.addPostFrameCallback((_) { 94 | if (showErrors && animation.value >= start) { 95 | for (var error in token.errors) { 96 | utilsProvider.addConsoleMessage(error, 0); 97 | } 98 | showErrors = false; 99 | } 100 | 101 | var temp = List.from(utilsProvider.richTextList); 102 | utilsProvider.richTextList = temp; 103 | }); 104 | 105 | return Opacity( 106 | opacity: animation.value, 107 | child: ColoredCardBox( 108 | color: animationColor.value, 109 | child: Row( 110 | mainAxisAlignment: MainAxisAlignment.spaceBetween, 111 | children: [ 112 | SizedBox( 113 | child: Container( 114 | child: Text("${tokensList[widget.index].tokenType}", 115 | style: text_style_table_row)), 116 | width: 125.0, 117 | ), 118 | SizedBox( 119 | child: Container( 120 | child: Text("${tokensList[widget.index].lexeme}", 121 | style: text_style_table_row)), 122 | width: 80.0, 123 | ), 124 | SizedBox( 125 | child: Container( 126 | child: Text("${tokensList[widget.index].literal}", 127 | style: text_style_table_row)), 128 | width: 80.0, 129 | ), 130 | SizedBox( 131 | child: Container( 132 | child: Text("${tokensList[widget.index].line}", 133 | style: text_style_table_row)), 134 | width: 80.0, 135 | ), 136 | ], 137 | ), 138 | ), 139 | ); 140 | } 141 | } 142 | -------------------------------------------------------------------------------- /lib/screens/ast_graph.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutterdesktopapp/utils/app_data.dart'; 3 | import 'package:flutterdesktopapp/utils/constants.dart'; 4 | import 'package:flutterdesktopapp/utils/utilities_provider.dart'; 5 | import 'package:graphite/core/matrix.dart'; 6 | import 'package:graphite/graphite.dart'; 7 | import 'package:provider/provider.dart'; 8 | 9 | class ASTGraph extends StatefulWidget { 10 | final int statementIndex; 11 | final int index; 12 | final double duration; 13 | final AnimationController animationController; 14 | 15 | ASTGraph( 16 | this.index, this.statementIndex, this.animationController, this.duration); 17 | 18 | @override 19 | _ASTGraphState createState() => _ASTGraphState(); 20 | } 21 | 22 | class _ASTGraphState extends State { 23 | Animation animation; 24 | Animation animationColor; 25 | double start; 26 | double end; 27 | var showErrors = true; 28 | var showOutput = true; 29 | 30 | @override 31 | void initState() { 32 | print(widget.index.toString() + " signing in"); 33 | super.initState(); 34 | start = (widget.duration * widget.index).toDouble(); 35 | end = start + widget.duration; 36 | print("START $start , end $end"); 37 | 38 | animation = Tween( 39 | begin: 0.0, 40 | end: 1.0, 41 | ).animate( 42 | CurvedAnimation( 43 | parent: widget.animationController, 44 | curve: Interval( 45 | start, 46 | end, 47 | curve: Curves.easeInOutCirc, 48 | ), 49 | ), 50 | ); 51 | 52 | widget.animationController.addListener(() { 53 | if (this.mounted) setState(() {}); 54 | }); 55 | } 56 | 57 | @override 58 | void dispose() { 59 | print("AST Graph Disposed"); 60 | // TODO: implement dispose 61 | super.dispose(); 62 | } 63 | 64 | @override 65 | Widget build(BuildContext context) { 66 | var appData = Provider.of(context, listen: false); 67 | final utilsProvider = 68 | Provider.of(context, listen: false); 69 | 70 | var currentStatement = appData.astsList[widget.statementIndex]; 71 | 72 | var graph = nodeInputFromJson(currentStatement.astGraph); 73 | 74 | WidgetsBinding.instance.addPostFrameCallback((_) { 75 | var error = currentStatement.errors[widget.index]; 76 | if (showErrors && error != null && error != "") { 77 | utilsProvider.addConsoleMessage(error, 0); 78 | showErrors = false; 79 | } 80 | var outputMessage = currentStatement.outputMessages[widget.index]; 81 | if (showOutput && outputMessage != null && outputMessage != "") { 82 | utilsProvider.addConsoleMessage(outputMessage, 1); 83 | showOutput = false; 84 | } 85 | }); 86 | 87 | return DirectGraph( 88 | list: graph, 89 | cellWidth: 180.0, 90 | cellPadding: 14.0, 91 | contactEdgesDistance: 5.0, 92 | orientation: MatrixOrientation.Vertical, 93 | // pathBuilder: customEdgePathBuilder, 94 | builder: (ctx, node) { 95 | return Container( 96 | color: 97 | (currentStatement.visitedNode[widget.index] == int.parse(node.id) 98 | ? Colors.red 99 | : Colors.blue), 100 | child: Padding( 101 | padding: const EdgeInsets.all(10.0), 102 | child: ListView.builder( 103 | // controller: scrollController, 104 | itemCount: 105 | currentStatement.nodesData[widget.index][node.id].length, 106 | itemBuilder: (context, index) { 107 | if (index == 0) { 108 | return Center( 109 | child: Text( 110 | currentStatement.nodesData[widget.index][node.id] 111 | [index], 112 | style: text_style_graph_title)); 113 | } 114 | return Text( 115 | "- " + 116 | currentStatement.nodesData[widget.index][node.id] 117 | [index], 118 | style: text_style_graph_text); 119 | }, 120 | ), 121 | ), 122 | ); 123 | }, 124 | paintBuilder: (edge) { 125 | var p = Paint() 126 | ..color = Colors.blueGrey 127 | ..style = PaintingStyle.stroke 128 | ..strokeCap = StrokeCap.round 129 | ..strokeJoin = StrokeJoin.round 130 | ..strokeWidth = 2; 131 | return p; 132 | }, 133 | ); 134 | } 135 | } 136 | -------------------------------------------------------------------------------- /InterpreterVisualizer/.mvn/wrapper/MavenWrapperDownloader.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2007-present the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | import java.net.*; 18 | import java.io.*; 19 | import java.nio.channels.*; 20 | import java.util.Properties; 21 | 22 | public class MavenWrapperDownloader { 23 | 24 | private static final String WRAPPER_VERSION = "0.5.6"; 25 | /** 26 | * Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided. 27 | */ 28 | private static final String DEFAULT_DOWNLOAD_URL = "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/" 29 | + WRAPPER_VERSION + "/maven-wrapper-" + WRAPPER_VERSION + ".jar"; 30 | 31 | /** 32 | * Path to the maven-wrapper.properties file, which might contain a downloadUrl property to 33 | * use instead of the default one. 34 | */ 35 | private static final String MAVEN_WRAPPER_PROPERTIES_PATH = 36 | ".mvn/wrapper/maven-wrapper.properties"; 37 | 38 | /** 39 | * Path where the maven-wrapper.jar will be saved to. 40 | */ 41 | private static final String MAVEN_WRAPPER_JAR_PATH = 42 | ".mvn/wrapper/maven-wrapper.jar"; 43 | 44 | /** 45 | * Name of the property which should be used to override the default download url for the wrapper. 46 | */ 47 | private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl"; 48 | 49 | public static void main(String args[]) { 50 | System.out.println("- Downloader started"); 51 | File baseDirectory = new File(args[0]); 52 | System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath()); 53 | 54 | // If the maven-wrapper.properties exists, read it and check if it contains a custom 55 | // wrapperUrl parameter. 56 | File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH); 57 | String url = DEFAULT_DOWNLOAD_URL; 58 | if (mavenWrapperPropertyFile.exists()) { 59 | FileInputStream mavenWrapperPropertyFileInputStream = null; 60 | try { 61 | mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile); 62 | Properties mavenWrapperProperties = new Properties(); 63 | mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream); 64 | url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url); 65 | } catch (IOException e) { 66 | System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'"); 67 | } finally { 68 | try { 69 | if (mavenWrapperPropertyFileInputStream != null) { 70 | mavenWrapperPropertyFileInputStream.close(); 71 | } 72 | } catch (IOException e) { 73 | // Ignore ... 74 | } 75 | } 76 | } 77 | System.out.println("- Downloading from: " + url); 78 | 79 | File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH); 80 | if (!outputFile.getParentFile().exists()) { 81 | if (!outputFile.getParentFile().mkdirs()) { 82 | System.out.println( 83 | "- ERROR creating output directory '" + outputFile.getParentFile().getAbsolutePath() + "'"); 84 | } 85 | } 86 | System.out.println("- Downloading to: " + outputFile.getAbsolutePath()); 87 | try { 88 | downloadFileFromURL(url, outputFile); 89 | System.out.println("Done"); 90 | System.exit(0); 91 | } catch (Throwable e) { 92 | System.out.println("- Error downloading"); 93 | e.printStackTrace(); 94 | System.exit(1); 95 | } 96 | } 97 | 98 | private static void downloadFileFromURL(String urlString, File destination) throws Exception { 99 | if (System.getenv("MVNW_USERNAME") != null && System.getenv("MVNW_PASSWORD") != null) { 100 | String username = System.getenv("MVNW_USERNAME"); 101 | char[] password = System.getenv("MVNW_PASSWORD").toCharArray(); 102 | Authenticator.setDefault(new Authenticator() { 103 | @Override 104 | protected PasswordAuthentication getPasswordAuthentication() { 105 | return new PasswordAuthentication(username, password); 106 | } 107 | }); 108 | } 109 | URL website = new URL(urlString); 110 | ReadableByteChannel rbc; 111 | rbc = Channels.newChannel(website.openStream()); 112 | FileOutputStream fos = new FileOutputStream(destination); 113 | fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE); 114 | fos.close(); 115 | rbc.close(); 116 | } 117 | 118 | } 119 | -------------------------------------------------------------------------------- /lib/screens/parsing_ast_page.dart: -------------------------------------------------------------------------------- 1 | import 'dart:io'; 2 | import 'dart:typed_data'; 3 | 4 | import 'package:flutter/material.dart'; 5 | import 'package:flutterdesktopapp/utils/app_data.dart'; 6 | import 'package:flutterdesktopapp/utils/constants.dart'; 7 | import 'package:flutterdesktopapp/utils/graphs_provider.dart'; 8 | import 'package:graphite/core/matrix.dart'; 9 | import 'package:graphite/graphite.dart'; 10 | import 'package:path_provider/path_provider.dart'; 11 | import 'package:provider/provider.dart'; 12 | import 'package:screenshot/screenshot.dart'; 13 | 14 | class ParsingASTPage extends StatefulWidget { 15 | @override 16 | _ParsingASTPageState createState() => _ParsingASTPageState(); 17 | } 18 | 19 | class _ParsingASTPageState extends State { 20 | 21 | ScreenshotController screenshotController = ScreenshotController(); 22 | int _counter = 0; 23 | Uint8List _imageFile; 24 | 25 | void _takeScreenshot(var context) { 26 | screenshotController.capture().then((Uint8List image) async { 27 | //Capture Done 28 | setState(() { 29 | _imageFile = image; 30 | print("hi"); 31 | }); 32 | 33 | Directory directory = await getDownloadsDirectory(); 34 | String fileName = "Statement AST Tree" + ".png"; 35 | var p = directory.path; 36 | var path = '$p'; 37 | print(path); 38 | screenshotController.captureAndSave(path, fileName: fileName); 39 | final snackBar = SnackBar( 40 | content: Text('Graph is saved to $path'), 41 | ); 42 | ; 43 | ScaffoldMessenger.of(context).showSnackBar(snackBar); 44 | }).catchError((onError) { 45 | print(onError); 46 | }); 47 | } 48 | 49 | @override 50 | Widget build(BuildContext context) { 51 | return Container( 52 | child: Column( 53 | children: [ 54 | Expanded( 55 | flex: 1, 56 | child: Row( 57 | mainAxisAlignment: MainAxisAlignment.center, 58 | children: [ 59 | Text("Abstract Syntax Tree", 60 | style: text_style_phase_title), 61 | SizedBox( 62 | width: 10, 63 | ), 64 | IconButton( 65 | icon: Icon(Icons.camera_alt), 66 | onPressed: () => _takeScreenshot(context), 67 | ) 68 | ], 69 | )), 70 | Expanded( 71 | flex: 10, 72 | child: SingleChildScrollView( 73 | scrollDirection: Axis.vertical, 74 | child: SingleChildScrollView( 75 | scrollDirection: Axis.horizontal, 76 | child: Screenshot( 77 | controller: screenshotController, 78 | child: SizedBox( 79 | width: 3000, 80 | height: 2000, 81 | child: Container( 82 | child: ParsingASTGraph(), 83 | ), 84 | ), 85 | ), 86 | ), 87 | ), 88 | ), 89 | ], 90 | ), 91 | ); 92 | } 93 | } 94 | 95 | class ParsingASTGraph extends StatefulWidget { 96 | @override 97 | _ParsingASTGraphState createState() => _ParsingASTGraphState(); 98 | } 99 | 100 | class _ParsingASTGraphState extends State { 101 | @override 102 | Widget build(BuildContext context) { 103 | var appData = Provider.of(context, listen: false); 104 | final graphProvider = Provider.of(context); 105 | 106 | int statementIndex = appData.visualizedStatementIndex; 107 | int graphIndex = graphProvider.visualizedGraphIndex; 108 | 109 | var currentStatement = appData.parsedStatementsList[statementIndex]; 110 | var astGraphIndex = currentStatement.astGraphIndexSync[graphIndex]; 111 | 112 | if (astGraphIndex == -1) return Container(); 113 | 114 | var astGraph = currentStatement.astGraph; 115 | 116 | var graph = nodeInputFromJson(astGraph.graphs[astGraphIndex].toString()); 117 | 118 | return DirectGraph( 119 | list: graph, 120 | cellWidth: 180.0, 121 | cellPadding: 14.0, 122 | contactEdgesDistance: 5.0, 123 | orientation: MatrixOrientation.Vertical, 124 | // pathBuilder: customEdgePathBuilder, 125 | builder: (ctx, node) { 126 | return Container( 127 | color: (astGraph.visitedNode[astGraphIndex] == int.parse(node.id) 128 | ? Colors.red 129 | : Colors.blue), 130 | child: Padding( 131 | padding: const EdgeInsets.all(10.0), 132 | child: ListView.builder( 133 | // controller: scrollController, 134 | itemCount: astGraph.nodesData[astGraphIndex][node.id].length, 135 | itemBuilder: (context, index) { 136 | if (index == 0) { 137 | return Center( 138 | child: Text( 139 | astGraph.nodesData[astGraphIndex][node.id][index], 140 | style: text_style_graph_title)); 141 | } 142 | return Text( 143 | "- " + astGraph.nodesData[astGraphIndex][node.id][index], 144 | style: text_style_graph_text); 145 | }, 146 | ), 147 | ), 148 | ); 149 | }, 150 | paintBuilder: (edge) { 151 | var p = Paint() 152 | ..color = Colors.blueGrey 153 | ..style = PaintingStyle.stroke 154 | ..strokeCap = StrokeCap.round 155 | ..strokeJoin = StrokeJoin.round 156 | ..strokeWidth = 2; 157 | return p; 158 | }, 159 | ); 160 | } 161 | } 162 | -------------------------------------------------------------------------------- /InterpreterVisualizer/src/main/java/simpleinterpreter/SimpleInterpreter.java: -------------------------------------------------------------------------------- 1 | package simpleinterpreter; 2 | 3 | import org.json.JSONArray; 4 | import org.json.JSONObject; 5 | 6 | import java.util.List; 7 | 8 | public class SimpleInterpreter { 9 | private Scanner scanner; 10 | private Parser parser; 11 | private Interpreter interpreter; 12 | 13 | private boolean run = false; 14 | private boolean hadError = false; 15 | private boolean hadRuntimeError = false; 16 | private final String source; 17 | 18 | public SimpleInterpreter(String source) { 19 | this.source = source; 20 | run(); 21 | } 22 | 23 | public void run() { 24 | if (run) return; 25 | run = true; 26 | scanner = new Scanner(source, this); 27 | scanner.scanTokens(); 28 | List tokens = scanner.getTokens(); 29 | parser = new Parser(tokens, this); 30 | parser.parse(); 31 | List statements = parser.getStatements(); 32 | if (hadError) return; 33 | interpreter = new Interpreter(this, parser.getStatmentsGraph()); 34 | interpreter.interpret(statements); 35 | 36 | //Testing 37 | // System.out.println(parser.getStatmentsGraph().get(0).getAstGraph().getAstJSON().toString()); 38 | // System.out.println(parser.getStatmentsGraph().get(0).getAstGraph().getNodesData().toString()); 39 | // System.out.println(parser.getStatmentsGraph().get(0).getAstGraph().getVisitedNode().toString()); 40 | // System.out.println(parser.getStatmentsGraph().get(0).getAstGraphIndexSync().toString()); 41 | 42 | // System.out.println(interpreter.statmentsGraph.get(0).getAstGraph().; 43 | // System.out.println(interpreter.statmentsGraph.get(1).getAstGraph().getSymbolTableJSON().get(0).toString()); 44 | // System.out.println(interpreter.statmentsGraph.get(2).getAstGraph().getSymbolTableJSON().get(0).toString()); 45 | // System.out.println(interpreter.statmentsGraph.get(3).getAstGraph().getSymbolTableJSON().get(0).toString()); 46 | } 47 | 48 | JSONObject getLexicalAnalysis() { 49 | run(); 50 | JSONObject lexicalAnalysis = new JSONObject(); 51 | 52 | List tokens = scanner.getTokens(); 53 | JSONArray tokensJSON = new JSONArray(); 54 | for (Token token : tokens) { 55 | tokensJSON.put(token.getTokenJSON()); 56 | } 57 | 58 | JSONObject errorsJSON = scanner.getErrors(); 59 | 60 | lexicalAnalysis.put("Tokens", tokensJSON); 61 | lexicalAnalysis.put("Errors", errorsJSON); 62 | 63 | return lexicalAnalysis; 64 | } 65 | 66 | JSONObject getSyntacticAnalysis() { 67 | run(); 68 | JSONObject syntacticAnalysis = new JSONObject(); 69 | 70 | List graph = parser.getStatmentsGraph(); 71 | for (StatementGraph s : graph) { 72 | JSONObject statement = new JSONObject(); 73 | statement.put("Graphs", s.getStatmentJSON()); 74 | statement.put("Visited Nodes", s.getVisitedNode()); 75 | statement.put("Nodes", s.getNodesData()); 76 | statement.put("Consumed Tokens", s.getConsumedTokens()); 77 | statement.put("Errors", s.getErrors()); 78 | statement.put("AST Graph Index Sync", s.getAstGraphIndexSync()); 79 | 80 | JSONObject ast = new JSONObject(); 81 | ast.put("Graphs", s.getAstGraph().getAstJSON()); 82 | ast.put("Visited Nodes", s.getAstGraph().getVisitedNode()); 83 | ast.put("Nodes", s.getAstGraph().getNodesData()); 84 | statement.put("AST", ast); 85 | 86 | syntacticAnalysis.append("Statements", statement); 87 | } 88 | 89 | return syntacticAnalysis; 90 | } 91 | 92 | JSONObject getSemanticAnalysis() { 93 | run(); 94 | JSONObject semanticAnalysis = new JSONObject(); 95 | 96 | if (hadError) return semanticAnalysis; 97 | 98 | List graph = interpreter.getStatmentsGraph(); 99 | for (StatementGraph s : graph) { 100 | JSONObject statement = new JSONObject(); 101 | statement.put("AST", s.getAstGraph().getInterpreterCompleteAST()); 102 | statement.put("Visited Nodes", s.getAstGraph().getInterpreterVisitedNode()); 103 | statement.put("Nodes", s.getAstGraph().getInterpreterNodesData()); 104 | statement.put("Symbol Table Index Sync", s.getAstGraph().getSymbolTableIndexSync()); 105 | statement.put("Symbol Table", s.getAstGraph().getSymbolTableJSON()); 106 | statement.put("Errors", s.getAstGraph().getInterpreterRuntimeErrors()); 107 | statement.put("Output Messages", s.getAstGraph().getInterpreterOutputMessages()); 108 | 109 | semanticAnalysis.append("Statements", statement); 110 | } 111 | 112 | return semanticAnalysis; 113 | } 114 | 115 | void error(Token token, String message) { 116 | if (token.type == TokenType.EOF) { 117 | report(token.line, " at end", message); 118 | } else { 119 | report(token.line, " at '" + token.lexeme + "'", message); 120 | } 121 | } 122 | 123 | void error(int line, String message) { 124 | report(line, "", message); 125 | } 126 | 127 | void report(int line, String where, 128 | String message) { 129 | String output = "[line " + line + "] Error" + where + ": " + message; 130 | System.err.println(output); 131 | hadError = true; 132 | } 133 | 134 | void runtimeError(RuntimeError error) { 135 | String output = error.getMessage() + "\n[line " + error.token.line + "]"; 136 | System.err.println(output); 137 | hadRuntimeError = true; 138 | } 139 | } 140 | 141 | 142 | -------------------------------------------------------------------------------- /lib/screens/syntactic_and_statement_page.dart: -------------------------------------------------------------------------------- 1 | import 'dart:io'; 2 | import 'dart:typed_data'; 3 | 4 | import 'package:flutter/material.dart'; 5 | import 'package:flutter/rendering.dart'; 6 | import 'package:flutterdesktopapp/ui_elements/single_graph.dart'; 7 | import 'package:flutterdesktopapp/utils/constants.dart'; 8 | import 'package:flutterdesktopapp/utils/graphs_provider.dart'; 9 | import 'package:path_provider/path_provider.dart'; 10 | import 'package:provider/provider.dart'; 11 | import 'package:screenshot/screenshot.dart'; 12 | 13 | class SyntacticPage extends StatefulWidget { 14 | final int numberOfGraphs; 15 | final int visualizedStatementIndex; 16 | 17 | SyntacticPage(this.numberOfGraphs, this.visualizedStatementIndex); 18 | 19 | final statementPageKey = GlobalKey<_StatementPageState>(); 20 | 21 | @override 22 | _SyntacticPageState createState() => _SyntacticPageState(); 23 | } 24 | 25 | class _SyntacticPageState extends State { 26 | @override 27 | Widget build(BuildContext context) { 28 | return Container( 29 | child: StatementPage( 30 | key: widget.statementPageKey, 31 | numberOfGraphs: widget.numberOfGraphs, 32 | statementIndex: widget.visualizedStatementIndex), 33 | ); 34 | } 35 | } 36 | 37 | class StatementPage extends StatefulWidget { 38 | final int numberOfGraphs; 39 | final int statementIndex; 40 | 41 | const StatementPage({Key key, this.numberOfGraphs, this.statementIndex}) 42 | : super(key: key); 43 | 44 | @override 45 | _StatementPageState createState() => _StatementPageState(); 46 | } 47 | 48 | class _StatementPageState extends State 49 | with TickerProviderStateMixin { 50 | AnimationController _animationController; 51 | double animationDuration; 52 | int durationOfSingleGraph; 53 | int totalDuration; 54 | int graphIndex = 0; 55 | Animation animation; 56 | 57 | 58 | 59 | @override 60 | void initState() { 61 | super.initState(); 62 | durationOfSingleGraph = 900; 63 | totalDuration = widget.numberOfGraphs * durationOfSingleGraph; 64 | _animationController = AnimationController( 65 | vsync: this, duration: new Duration(milliseconds: totalDuration)); 66 | 67 | _animationController.addListener(() { 68 | if (this.mounted) setState(() {}); 69 | }); 70 | 71 | animationDuration = durationOfSingleGraph / totalDuration; 72 | _animationController.forward(); 73 | } 74 | 75 | @override 76 | void setState(VoidCallback fn) { 77 | var start = (animationDuration * graphIndex).toDouble(); 78 | var end = start + animationDuration; 79 | 80 | start *= totalDuration; 81 | end *= totalDuration; 82 | 83 | if (_animationController.lastElapsedDuration != null && 84 | _animationController.lastElapsedDuration.inMilliseconds.toDouble() > 85 | end) { 86 | graphIndex++; 87 | } 88 | // TODO: implement setState 89 | super.setState(fn); 90 | } 91 | 92 | @override 93 | void dispose() { 94 | print("Statement Disposed"); 95 | _animationController.dispose(); 96 | super.dispose(); 97 | } 98 | 99 | ScreenshotController screenshotController = ScreenshotController(); 100 | int _counter = 0; 101 | Uint8List _imageFile; 102 | 103 | void _takeScreenshot(var context) { 104 | screenshotController.capture().then((Uint8List image) async { 105 | //Capture Done 106 | setState(() { 107 | _imageFile = image; 108 | print("hi"); 109 | }); 110 | 111 | Directory directory = await getDownloadsDirectory(); 112 | String fileName = "Parsing Tree Statement #" + 113 | widget.statementIndex.toString() + 114 | ".png"; 115 | var p = directory.path; 116 | var path = '$p'; 117 | print(path); 118 | screenshotController.captureAndSave(path, fileName: fileName); 119 | final snackBar = SnackBar( 120 | content: Text('Graph is saved to $path'), 121 | ); 122 | ; 123 | ScaffoldMessenger.of(context).showSnackBar(snackBar); 124 | }).catchError((onError) { 125 | print(onError); 126 | }); 127 | } 128 | 129 | @override 130 | Widget build(BuildContext context) { 131 | final graphProvider = Provider.of(context, listen: false); 132 | WidgetsBinding.instance.addPostFrameCallback((_) { 133 | graphProvider.visualizedGraphIndex = graphIndex; 134 | }); 135 | 136 | return Container( 137 | child: Column( 138 | children: [ 139 | Expanded( 140 | flex: 1, 141 | child: Row( 142 | mainAxisAlignment: MainAxisAlignment.center, 143 | children: [ 144 | Text("Parsing Tree", style: text_style_phase_title), 145 | SizedBox( 146 | width: 10, 147 | ), 148 | IconButton( 149 | icon: Icon(Icons.camera_alt), 150 | onPressed: () => _takeScreenshot(context), 151 | ) 152 | ], 153 | )), 154 | Expanded( 155 | flex: 10, 156 | child: SingleChildScrollView( 157 | scrollDirection: Axis.vertical, 158 | child: SingleChildScrollView( 159 | scrollDirection: Axis.horizontal, 160 | child: Screenshot( 161 | controller: screenshotController, 162 | child: SizedBox( 163 | height: 5000, 164 | width: 2000, 165 | child: Container( 166 | child: SingleGraph(graphIndex, widget.statementIndex, 167 | _animationController, animationDuration), 168 | ), 169 | ), 170 | ), 171 | ), 172 | ), 173 | ), 174 | ], 175 | ), 176 | ); 177 | } 178 | } 179 | -------------------------------------------------------------------------------- /lib/screens/semantic_page.dart: -------------------------------------------------------------------------------- 1 | import 'dart:io'; 2 | import 'dart:typed_data'; 3 | 4 | import 'package:flutter/material.dart'; 5 | import 'package:flutter/rendering.dart'; 6 | import 'package:flutterdesktopapp/utils/constants.dart'; 7 | import 'package:flutterdesktopapp/utils/graphs_provider.dart'; 8 | import 'package:path_provider/path_provider.dart'; 9 | import 'package:provider/provider.dart'; 10 | import 'package:screenshot/screenshot.dart'; 11 | 12 | import 'ast_graph.dart'; 13 | 14 | class SemanticPage extends StatefulWidget { 15 | final int numberOfSteps; 16 | final int visualizedStatementIndex; 17 | 18 | SemanticPage(this.numberOfSteps, this.visualizedStatementIndex); 19 | 20 | final semanticStatementPageKey = GlobalKey<_SemanticStatementPageState>(); 21 | 22 | @override 23 | _SemanticPageState createState() => _SemanticPageState(); 24 | } 25 | 26 | class _SemanticPageState extends State { 27 | @override 28 | Widget build(BuildContext context) { 29 | return Container( 30 | child: SemanticStatementPage( 31 | key: widget.semanticStatementPageKey, 32 | numberOfSteps: widget.numberOfSteps, 33 | statementIndex: widget.visualizedStatementIndex), 34 | ); 35 | } 36 | } 37 | 38 | class SemanticStatementPage extends StatefulWidget { 39 | final int numberOfSteps; 40 | final int statementIndex; 41 | 42 | const SemanticStatementPage( 43 | {Key key, this.numberOfSteps, this.statementIndex}) 44 | : super(key: key); 45 | 46 | @override 47 | _SemanticStatementPageState createState() => _SemanticStatementPageState(); 48 | } 49 | 50 | class _SemanticStatementPageState extends State 51 | with TickerProviderStateMixin { 52 | AnimationController _animationController; 53 | double animationDuration; 54 | int durationOfSingleStep; 55 | int totalDuration; 56 | int stepIndex = 0; 57 | Animation animation; 58 | 59 | @override 60 | void initState() { 61 | super.initState(); 62 | durationOfSingleStep = 900; 63 | totalDuration = widget.numberOfSteps * durationOfSingleStep; 64 | _animationController = AnimationController( 65 | vsync: this, duration: new Duration(milliseconds: totalDuration)); 66 | 67 | _animationController.addListener(() { 68 | if (this.mounted) setState(() {}); 69 | }); 70 | 71 | animationDuration = durationOfSingleStep / totalDuration; 72 | _animationController.forward(); 73 | } 74 | 75 | @override 76 | void setState(VoidCallback fn) { 77 | var start = (animationDuration * stepIndex).toDouble(); 78 | var end = start + animationDuration; 79 | 80 | start *= totalDuration; 81 | end *= totalDuration; 82 | 83 | if (_animationController.lastElapsedDuration != null && 84 | _animationController.lastElapsedDuration.inMilliseconds.toDouble() > 85 | end) { 86 | stepIndex++; 87 | } 88 | // TODO: implement setState 89 | super.setState(fn); 90 | } 91 | 92 | @override 93 | void dispose() { 94 | print("Statement AST Disposed"); 95 | _animationController.dispose(); 96 | super.dispose(); 97 | } 98 | 99 | 100 | ScreenshotController screenshotController = ScreenshotController(); 101 | int _counter = 0; 102 | Uint8List _imageFile; 103 | 104 | void _takeScreenshot(var context) { 105 | screenshotController.capture().then((Uint8List image) async { 106 | //Capture Done 107 | setState(() { 108 | _imageFile = image; 109 | print("hi"); 110 | }); 111 | 112 | Directory directory = await getDownloadsDirectory(); 113 | String fileName = "AST Tree Statement #" + 114 | widget.statementIndex.toString() + 115 | ".png"; 116 | var p = directory.path; 117 | var path = '$p'; 118 | print(path); 119 | screenshotController.captureAndSave(path, fileName: fileName); 120 | final snackBar = SnackBar( 121 | content: Text('Graph is saved to $path'), 122 | ); 123 | ; 124 | ScaffoldMessenger.of(context).showSnackBar(snackBar); 125 | }).catchError((onError) { 126 | print(onError); 127 | }); 128 | } 129 | 130 | @override 131 | Widget build(BuildContext context) { 132 | final graphProvider = Provider.of(context, listen: false); 133 | WidgetsBinding.instance.addPostFrameCallback((_) { 134 | graphProvider.visualizedStatementIndex = widget.statementIndex; 135 | graphProvider.visualizedStepIndex = stepIndex; 136 | }); 137 | 138 | return Container( 139 | child: Column( 140 | children: [ 141 | Expanded( 142 | flex: 1, 143 | child: Row( 144 | mainAxisAlignment: MainAxisAlignment.center, 145 | children: [ 146 | Text("Abstract Syntax Tree", 147 | style: text_style_phase_title), 148 | IconButton( 149 | icon: Icon(Icons.camera_alt), 150 | onPressed: () => _takeScreenshot(context), 151 | ) 152 | ], 153 | )), 154 | Expanded( 155 | flex: 10, 156 | child: SingleChildScrollView( 157 | scrollDirection: Axis.vertical, 158 | child: SingleChildScrollView( 159 | scrollDirection: Axis.horizontal, 160 | child: Screenshot( 161 | controller: screenshotController, 162 | child: SizedBox( 163 | height: 3000, 164 | width: 2000, 165 | child: Container( 166 | child: ASTGraph(stepIndex, widget.statementIndex, 167 | _animationController, animationDuration), 168 | ), 169 | ), 170 | ), 171 | ), 172 | ), 173 | ), 174 | ], 175 | ), 176 | ); 177 | } 178 | } 179 | -------------------------------------------------------------------------------- /lib/ui_elements/single_graph.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutterdesktopapp/utils/app_data.dart'; 3 | import 'package:flutterdesktopapp/utils/constants.dart'; 4 | import 'package:flutterdesktopapp/utils/utilities_provider.dart'; 5 | import 'package:graphite/core/matrix.dart'; 6 | import 'package:graphite/graphite.dart'; 7 | import 'package:provider/provider.dart'; 8 | 9 | class SingleGraph extends StatefulWidget { 10 | final int statementIndex; 11 | final int index; 12 | final double duration; 13 | final AnimationController animationController; 14 | 15 | SingleGraph( 16 | this.index, this.statementIndex, this.animationController, this.duration); 17 | 18 | @override 19 | _SingleGraphState createState() => _SingleGraphState(); 20 | } 21 | 22 | class _SingleGraphState extends State { 23 | Animation animation; 24 | Animation animationColor; 25 | double start; 26 | double end; 27 | var showErrors = true; 28 | 29 | @override 30 | void initState() { 31 | print(widget.index.toString() + " signing in"); 32 | super.initState(); 33 | start = (widget.duration * widget.index).toDouble(); 34 | end = start + widget.duration; 35 | print("START $start , end $end"); 36 | 37 | animation = Tween( 38 | begin: 0.0, 39 | end: 1.0, 40 | ).animate( 41 | CurvedAnimation( 42 | parent: widget.animationController, 43 | curve: Interval( 44 | start, 45 | end, 46 | curve: Curves.easeInOutCirc, 47 | ), 48 | ), 49 | ); 50 | 51 | animationColor = ColorTween( 52 | begin: Colors.white, 53 | end: Colors.black87, 54 | ).animate( 55 | CurvedAnimation( 56 | parent: widget.animationController, 57 | curve: Interval( 58 | start, 59 | end, 60 | curve: Curves.easeInOutCirc, 61 | ), 62 | ), 63 | ); 64 | 65 | widget.animationController.addListener(() { 66 | if (this.mounted) setState(() {}); 67 | }); 68 | } 69 | 70 | @override 71 | void dispose() { 72 | print("Graph Disposed"); 73 | // TODO: implement dispose 74 | super.dispose(); 75 | } 76 | 77 | @override 78 | Widget build(BuildContext context) { 79 | // ScrollController scrollController = ScrollController(); 80 | // var scrollToBottom = (){ 81 | // scrollController.jumpTo(scrollController.position.maxScrollExtent); 82 | // }; 83 | 84 | var appData = Provider.of(context); 85 | var currentStatement = appData.parsedStatementsList[widget.statementIndex]; 86 | var graph = 87 | nodeInputFromJson(currentStatement.graphs[widget.index].toString()); 88 | 89 | final utilsProvider = 90 | Provider.of(context, listen: false); 91 | 92 | WidgetsBinding.instance.addPostFrameCallback((_) { 93 | // scrollToBottom(); 94 | 95 | var currentErrors = currentStatement.errors[widget.index]; 96 | if (showErrors && currentErrors != null && currentErrors.isNotEmpty) { 97 | for (var error in currentErrors) { 98 | utilsProvider.addConsoleMessage(error, 0); 99 | } 100 | showErrors = false; 101 | } 102 | 103 | var consumedTokens = currentStatement.consumedTokens[widget.index]; 104 | if (consumedTokens != null && consumedTokens.isNotEmpty) { 105 | for (int token in consumedTokens) { 106 | var tokenIndex = appData.tokensIndices[token]; 107 | var tokenGoalColor = appData.tokensColors[tokenIndex]; 108 | Color t = tokenGoalColor; 109 | Color x = animationColor.value; 110 | utilsProvider.richTextList[tokenIndex][1] = t.withOpacity(x.opacity); 111 | } 112 | var temp1 = List.from(utilsProvider.richTextList); 113 | utilsProvider.richTextList = temp1; 114 | } 115 | }); 116 | 117 | return Opacity( 118 | opacity: animation.value, 119 | child: DirectGraph( 120 | list: graph, 121 | cellWidth: 180.0, 122 | cellPadding: 14.0, 123 | contactEdgesDistance: 5.0, 124 | orientation: MatrixOrientation.Vertical, 125 | // pathBuilder: customEdgePathBuilder, 126 | builder: (ctx, node) { 127 | return Container( 128 | color: (currentStatement.visitedNode[widget.index] == 129 | int.parse(node.id) 130 | ? Colors.red 131 | : Colors.blue), 132 | child: Padding( 133 | padding: const EdgeInsets.all(10.0), 134 | child: ListView.builder( 135 | // controller: scrollController, 136 | itemCount: 137 | currentStatement.nodesData[widget.index][node.id].length, 138 | itemBuilder: (context, index) { 139 | if (index == 0) { 140 | return Center( 141 | child: Text( 142 | currentStatement.nodesData[widget.index][node.id] 143 | [index], 144 | style: text_style_graph_title)); 145 | } 146 | return Text( 147 | "- " + 148 | currentStatement.nodesData[widget.index][node.id] 149 | [index], 150 | style: text_style_graph_text); 151 | }, 152 | ), 153 | ), 154 | ); 155 | }, 156 | paintBuilder: (edge) { 157 | var p = Paint() 158 | ..color = Colors.blueGrey 159 | ..style = PaintingStyle.stroke 160 | ..strokeCap = StrokeCap.round 161 | ..strokeJoin = StrokeJoin.round 162 | ..strokeWidth = 2; 163 | return p; 164 | }, 165 | ), 166 | ); 167 | } 168 | 169 | Path customEdgePathBuilder(List> points) { 170 | var path = Path(); 171 | path.moveTo(points[0][0], points[0][1]); 172 | points.sublist(1).forEach((p) { 173 | path.lineTo(p[0], p[1]); 174 | }); 175 | return path; 176 | } 177 | } 178 | -------------------------------------------------------------------------------- /InterpreterVisualizer/src/main/java/simpleinterpreter/StatementGraph.java: -------------------------------------------------------------------------------- 1 | package simpleinterpreter; 2 | 3 | import org.json.JSONArray; 4 | import org.json.JSONObject; 5 | 6 | import java.util.ArrayList; 7 | import java.util.HashMap; 8 | import java.util.List; 9 | import java.util.Map; 10 | 11 | public class StatementGraph { 12 | 13 | public AST getAstGraph() { 14 | return astGraph; 15 | } 16 | 17 | private final AST astGraph; 18 | 19 | //same size 20 | private final List statmentJSON; 21 | private final JSONArray visitedNode; 22 | 23 | public JSONArray getAstGraphIndexSync() { 24 | return astGraphIndexSync; 25 | } 26 | 27 | private final JSONArray astGraphIndexSync; 28 | 29 | private final List nodesData; 30 | 31 | 32 | private final String ID = "\"id\""; 33 | private final String NEXT = "\"next\""; 34 | 35 | private final Map> consumedTokens; 36 | private final JSONArray errors; 37 | 38 | 39 | //helper map 40 | private final Map nodeInIndex; 41 | 42 | StatementGraph() { 43 | astGraph = new AST(); 44 | statmentJSON = new ArrayList<>(); 45 | nodeInIndex = new HashMap<>(); 46 | consumedTokens = new HashMap<>(); 47 | visitedNode = new JSONArray(); 48 | astGraphIndexSync = new JSONArray(); 49 | errors = new JSONArray(); 50 | nodesData = new ArrayList<>(); 51 | } 52 | 53 | void addASTNode(int parsingNodeIndex, int astNodeindex, List data, List neighbours) { 54 | astGraph.addNewNode(astNodeindex, data, neighbours); 55 | visitNode(parsingNodeIndex, ""); 56 | } 57 | 58 | void addNodeData(int index, String data) { 59 | //Data 60 | JSONObject lastDataJSONObject = new JSONObject(getLastJSONObject().toString()); 61 | if (data != "") { 62 | lastDataJSONObject.append(Integer.toString(index), data); 63 | } 64 | nodesData.add(lastDataJSONObject); 65 | } 66 | 67 | void addNewNode(int index, String data) { 68 | nodeInIndex.put(index, getLastJSONArray().length()); 69 | 70 | addNodeData(index, data); 71 | 72 | JSONArray lastJSONArray = new JSONArray(getLastJSONArray().toString()); 73 | 74 | int lastNode = getLastVisitedNodeIndex(); //from 75 | 76 | visitedNode.put(index); 77 | if (lastNode != -1) { 78 | int indexOfNodeInJSON = nodeInIndex.get(lastNode); 79 | lastJSONArray.getJSONObject(indexOfNodeInJSON).append(NEXT, toStringWithDoubleQuotes(index)); 80 | } 81 | 82 | JSONObject currentNode = new JSONObject(); 83 | currentNode.put(ID, toStringWithDoubleQuotes(index)); 84 | currentNode.put(NEXT, new JSONArray()); 85 | 86 | lastJSONArray.put(currentNode); 87 | statmentJSON.add(lastJSONArray); 88 | astGraphIndexSync.put(astGraph.getASTsSize() - 1); 89 | } 90 | 91 | void visitNode(int index, String data) { 92 | visitedNode.put(index); 93 | 94 | addNodeData(index, data); 95 | 96 | // keep the lists consistent 97 | JSONArray last = getLastJSONArray(); 98 | statmentJSON.add(last); 99 | astGraphIndexSync.put(astGraph.getASTsSize() - 1); 100 | } 101 | 102 | void consumeToken(int tokenIndex) { 103 | int index = statmentJSON.size() - 1; 104 | if (consumedTokens.get(index) == null) { 105 | consumedTokens.put(index, new ArrayList<>()); 106 | } 107 | consumedTokens.get(statmentJSON.size() - 1).add(tokenIndex); 108 | } 109 | 110 | void reportSyntaxError(String message) { 111 | int index = statmentJSON.size() - 1; 112 | JSONObject error = new JSONObject(); 113 | error.put(Integer.toString(index), message); 114 | errors.put(error); 115 | } 116 | 117 | 118 | JSONArray getLastJSONArray() { 119 | int size = statmentJSON.size(); 120 | if (size == 0) 121 | return new JSONArray(); 122 | return statmentJSON.get(size - 1); 123 | } 124 | 125 | JSONObject getLastJSONObject() { 126 | int size = nodesData.size(); 127 | if (size == 0) 128 | return new JSONObject(); 129 | return nodesData.get(size - 1); 130 | } 131 | 132 | int getLastVisitedNodeIndex() { 133 | int size = visitedNode.length(); 134 | if (size == 0) 135 | return -1; 136 | return visitedNode.getInt(size - 1); 137 | 138 | } 139 | 140 | public List getStatmentJSON() { 141 | return statmentJSON; 142 | } 143 | 144 | 145 | String toStringWithDoubleQuotes(int index) { 146 | return "\"" + index + "\""; 147 | } 148 | 149 | 150 | // public List getVisitedNode() { 151 | // return visitedNode; 152 | // } 153 | // 154 | // public List getNodesData() { 155 | // return nodesData; 156 | // } 157 | // 158 | // public Map> getConsumedTokens() { 159 | // return consumedTokens; 160 | // } 161 | // 162 | // public List getErrors() { 163 | // return errors; 164 | // } 165 | // 166 | // public Map getNodeInIndex() { 167 | // return nodeInIndex; 168 | // } 169 | 170 | 171 | public JSONArray getVisitedNode() { 172 | return visitedNode; 173 | } 174 | 175 | public JSONArray getNodesData() { 176 | JSONArray nodesDataJSONArray = new JSONArray(); 177 | for (JSONObject jsonObject : nodesData) { 178 | nodesDataJSONArray.put(jsonObject); 179 | } 180 | return nodesDataJSONArray; 181 | } 182 | 183 | public JSONArray getConsumedTokens() { 184 | JSONArray consumedTokensJSON = new JSONArray(); 185 | for (Map.Entry> entry : consumedTokens.entrySet()) { 186 | JSONObject list = new JSONObject(); 187 | list.put(Integer.toString(entry.getKey()), entry.getValue()); 188 | consumedTokensJSON.put(list); 189 | } 190 | return consumedTokensJSON; 191 | } 192 | 193 | public JSONArray getErrors() { 194 | return errors; 195 | } 196 | 197 | } 198 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Interpreter Visualizer 2 | Believing in visualization as a very interactive method to help enhance and improve education, We have developed this very new desktop application to help and inspire Compiler Design learners so that they get a better experience and understand it well. We also want to inspire other programmers around the world to help create more educational applications or improve the already existing ones. 3 | 4 | 5 | ## Table of content: 6 | 1. [Important Note](#note) 7 | 2. [Idea of the project](#idea) 8 | 3. [Lox Language](#lox) 9 | 4. [How to use](#install) 10 | 5. [Examples](#ex) 11 | 6. [Depedencies](#Depend) 12 | 7. [Contribution](#con) 13 | 14 | 15 | ### Important Note 16 | When talking about the interpreter if we mention the front-end part and the back-end part we mean by the front-end the lexical analysis, the syntactic analysis and the semantic analysis(The part of the interperter we have made it possible to visualize). And if we are talking about the project as a code we mean by the front-end the Flutter project and the back-end is the Java Spring project. So, these terms are similar but their meaning is way too different so don't mix them up. 17 | 18 | 19 | ### Idea of the project 20 | 21 | This application simply visualizes the front-end part of interpreters or compilers and that includes Lexical Analysis, Syntactic Analysis and Semantic analysis.
22 | By using this application you will be able to:
23 | 1- Visualize any part of your code in the front-end part of an interpreter or a compiler.
24 | 2- Try and error your understanding of the compiler theory subject.
25 | 3- Know where your code can fail in the front-end part.
26 | 4- Use it as a professor in the university or in the lab class to help you deliver your lectures the best way possible.
27 | 28 | 29 | ### Lox Language 30 | 31 | Lox is the programming laguage used in our application to be visualized. It is an educational language created by [Robert Nystrom](https://github.com/munificent) in his famous book [Crafting interpreters](https://craftinginterpreters.com/contents.html) which we have used to help us create its interpreter. The reason we chose this language is that it is very simple, a C-style language and its grammar is very easy to read through. But our project does not only visualize Lox, **it can actually visaulize any programming language**, but you will need to change the back-end side (The Java Spring Project), but the front-end(The Flutter Project) will just work the same. 32 | Have a look at the language simple grammar [here](LoxGrammar). **We have not implemented yet all the grammar included in the crafting interpreters book**. 33 | 34 | You may also check some examples and learn more about the syntax of the language from [here](https://craftinginterpreters.com/the-lox-language.html). But notice that we have only implemented what you will find in the [grammar file](LoxGrammar), some parts of the language like the OOP or the functions are not implemented yet. So, if you doubt any part of the language to use just check the [grammar file](LoxGrammar). 35 | 36 | 37 | ### How to use 38 | 39 | This application consists of two separate parts the desktop/web front-end part which is written in Flutter and the back-end side written in Java Spring. The back-end side is found in the folder [**InterpreterVisualizer**](https://github.com/OsamaMaani/Interpreter-Visualizer/tree/master/InterpreterVisualizer). 40 | 41 | Make sure to: 42 | 43 | 1- Use the same port and IP address for both the back-end side and the fron-end side and you can modify that in the [properties file](https://github.com/OsamaMaani/Interpreter-Visualizer/blob/master/InterpreterVisualizer/src/main/resources/application.properties) in the back-end project and you can modify that in the [networking file](https://github.com/OsamaMaani/Interpreter-Visualizer/blob/master/lib/services/networking.dart) in the Flutter project. 44 | 45 | 2- Modify the graphite library so that it works properly for the project. You will head to the external libraries in the flutter project and then you will find graphite library folder, you will then open **graphite_edges.dart** and then go to **_GraphiteEdgesState** class and then head to **InteractiveViewer** widget and add **scaleEnabled: false**. This attribute will make sure that the zooming in the screen is off and there will not be unexpected functionalities caused by the zooming. 46 | 47 | ![add](graphite_modify.png). 48 | 49 | 50 | ### Examples 51 | 52 | 53 | **Example One** 54 | 55 | In this example you can see how the tokenization process goes on token by token with each one gets a unique color according to its type. 56 | ![Lexical Analysis](peek-hello-lexical.gif) 57 | 58 | **Example Two** 59 | 60 | In this example you can see here how a character can't be recognized if it is not a part of the language like the **#** symbol in our case. 61 | Also, an immediate message in the **console** appears to indicate that error. 62 | ![Lexical Analysis](peek-lexical-error.gif) 63 | 64 | **Example Three** 65 | 66 | In this example you can see the panel is divided into two smaller panels, the left one to show how the interpreter recursively search the grammar to find the specific grammar of the expression creating **the Parsing Tree** and on the right you can see the **Abstract Syntax Tree**(AST). 67 | You can also see a camera icon beside the title in each panel and if it is clicked it will immediately generate a screenshot to either the parsing tree or the AST to the moment you clicked. 68 | ![Lexical Analysis](Peek-parsing.gif) 69 | 70 | **Example Four** 71 | 72 | In this example you can see the semantic analysis visualization including the symbol table in the bottom of the screen. 73 | ![Lexical Analysis](Peek-semantic.gif) 74 | 75 | **Example Five** 76 | Here, in this example you can see how the semantic analysis phase can produce output in the **console** using print expression. 77 | ![Lexical Analysis](peek-hello-semantic.gif) 78 | 79 | 80 | ### Dependencies 81 | 82 | The Dependencies used in the Flutter Desktop/Web app. 83 | 1. [HTTP package](https://pub.dev/packages/http) 84 | 2. [Provider Package](https://pub.dev/packages/provider) 85 | 3. [path_provider](https://pub.dev/packages/path_provider) 86 | 4. [graphite](https://pub.dev/packages/graphite) 87 | 5. [Flutter Progress Hud](https://pub.dev/packages/flutter_progress_hud) 88 | 6. [screenshot](https://pub.dev/packages/screenshot) 89 | 90 | The Dependencies used in the Java Spring back-end app. 91 | 92 | 1- [JSON](https://mvnrepository.com/artifact/org.json/json/20090211) 93 | 94 | 95 | ## Contribution 96 | 97 | Follow the guides mentioned in the [CONTRIBUTING.md](contribution.md). 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | -------------------------------------------------------------------------------- /InterpreterVisualizer/mvnw.cmd: -------------------------------------------------------------------------------- 1 | @REM ---------------------------------------------------------------------------- 2 | @REM Licensed to the Apache Software Foundation (ASF) under one 3 | @REM or more contributor license agreements. See the NOTICE file 4 | @REM distributed with this work for additional information 5 | @REM regarding copyright ownership. The ASF licenses this file 6 | @REM to you under the Apache License, Version 2.0 (the 7 | @REM "License"); you may not use this file except in compliance 8 | @REM with the License. You may obtain a copy of the License at 9 | @REM 10 | @REM https://www.apache.org/licenses/LICENSE-2.0 11 | @REM 12 | @REM Unless required by applicable law or agreed to in writing, 13 | @REM software distributed under the License is distributed on an 14 | @REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | @REM KIND, either express or implied. See the License for the 16 | @REM specific language governing permissions and limitations 17 | @REM under the License. 18 | @REM ---------------------------------------------------------------------------- 19 | 20 | @REM ---------------------------------------------------------------------------- 21 | @REM Maven Start Up Batch script 22 | @REM 23 | @REM Required ENV vars: 24 | @REM JAVA_HOME - location of a JDK home dir 25 | @REM 26 | @REM Optional ENV vars 27 | @REM M2_HOME - location of maven2's installed home dir 28 | @REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands 29 | @REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending 30 | @REM MAVEN_OPTS - parameters passed to the Java VM when running Maven 31 | @REM e.g. to debug Maven itself, use 32 | @REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 33 | @REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files 34 | @REM ---------------------------------------------------------------------------- 35 | 36 | @REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' 37 | @echo off 38 | @REM set title of command window 39 | title %0 40 | @REM enable echoing by setting MAVEN_BATCH_ECHO to 'on' 41 | @if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% 42 | 43 | @REM set %HOME% to equivalent of $HOME 44 | if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") 45 | 46 | @REM Execute a user defined script before this one 47 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre 48 | @REM check for pre script, once with legacy .bat ending and once with .cmd ending 49 | if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat" 50 | if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd" 51 | :skipRcPre 52 | 53 | @setlocal 54 | 55 | set ERROR_CODE=0 56 | 57 | @REM To isolate internal variables from possible post scripts, we use another setlocal 58 | @setlocal 59 | 60 | @REM ==== START VALIDATION ==== 61 | if not "%JAVA_HOME%" == "" goto OkJHome 62 | 63 | echo. 64 | echo Error: JAVA_HOME not found in your environment. >&2 65 | echo Please set the JAVA_HOME variable in your environment to match the >&2 66 | echo location of your Java installation. >&2 67 | echo. 68 | goto error 69 | 70 | :OkJHome 71 | if exist "%JAVA_HOME%\bin\java.exe" goto init 72 | 73 | echo. 74 | echo Error: JAVA_HOME is set to an invalid directory. >&2 75 | echo JAVA_HOME = "%JAVA_HOME%" >&2 76 | echo Please set the JAVA_HOME variable in your environment to match the >&2 77 | echo location of your Java installation. >&2 78 | echo. 79 | goto error 80 | 81 | @REM ==== END VALIDATION ==== 82 | 83 | :init 84 | 85 | @REM Find the project base dir, i.e. the directory that contains the folder ".mvn". 86 | @REM Fallback to current working directory if not found. 87 | 88 | set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% 89 | IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir 90 | 91 | set EXEC_DIR=%CD% 92 | set WDIR=%EXEC_DIR% 93 | :findBaseDir 94 | IF EXIST "%WDIR%"\.mvn goto baseDirFound 95 | cd .. 96 | IF "%WDIR%"=="%CD%" goto baseDirNotFound 97 | set WDIR=%CD% 98 | goto findBaseDir 99 | 100 | :baseDirFound 101 | set MAVEN_PROJECTBASEDIR=%WDIR% 102 | cd "%EXEC_DIR%" 103 | goto endDetectBaseDir 104 | 105 | :baseDirNotFound 106 | set MAVEN_PROJECTBASEDIR=%EXEC_DIR% 107 | cd "%EXEC_DIR%" 108 | 109 | :endDetectBaseDir 110 | 111 | IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig 112 | 113 | @setlocal EnableExtensions EnableDelayedExpansion 114 | for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a 115 | @endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% 116 | 117 | :endReadAdditionalConfig 118 | 119 | SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" 120 | set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" 121 | set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain 122 | 123 | set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar" 124 | 125 | FOR /F "tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO ( 126 | IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B 127 | ) 128 | 129 | @REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central 130 | @REM This allows using the maven wrapper in projects that prohibit checking in binary data. 131 | if exist %WRAPPER_JAR% ( 132 | if "%MVNW_VERBOSE%" == "true" ( 133 | echo Found %WRAPPER_JAR% 134 | ) 135 | ) else ( 136 | if not "%MVNW_REPOURL%" == "" ( 137 | SET DOWNLOAD_URL="%MVNW_REPOURL%/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar" 138 | ) 139 | if "%MVNW_VERBOSE%" == "true" ( 140 | echo Couldn't find %WRAPPER_JAR%, downloading it ... 141 | echo Downloading from: %DOWNLOAD_URL% 142 | ) 143 | 144 | powershell -Command "&{"^ 145 | "$webclient = new-object System.Net.WebClient;"^ 146 | "if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^ 147 | "$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^ 148 | "}"^ 149 | "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"^ 150 | "}" 151 | if "%MVNW_VERBOSE%" == "true" ( 152 | echo Finished downloading %WRAPPER_JAR% 153 | ) 154 | ) 155 | @REM End of extension 156 | 157 | @REM Provide a "standardized" way to retrieve the CLI args that will 158 | @REM work with both Windows and non-Windows executions. 159 | set MAVEN_CMD_LINE_ARGS=%* 160 | 161 | %MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* 162 | if ERRORLEVEL 1 goto error 163 | goto end 164 | 165 | :error 166 | set ERROR_CODE=1 167 | 168 | :end 169 | @endlocal & set ERROR_CODE=%ERROR_CODE% 170 | 171 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost 172 | @REM check for post script, once with legacy .bat ending and once with .cmd ending 173 | if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat" 174 | if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd" 175 | :skipRcPost 176 | 177 | @REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' 178 | if "%MAVEN_BATCH_PAUSE%" == "on" pause 179 | 180 | if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE% 181 | 182 | exit /B %ERROR_CODE% 183 | -------------------------------------------------------------------------------- /InterpreterVisualizer/src/main/java/simpleinterpreter/Scanner.java: -------------------------------------------------------------------------------- 1 | package simpleinterpreter; 2 | 3 | import org.json.JSONObject; 4 | 5 | import java.util.ArrayList; 6 | import java.util.HashMap; 7 | import java.util.List; 8 | import java.util.Map; 9 | 10 | import static simpleinterpreter.TokenType.*; 11 | 12 | class Scanner { 13 | private static final Map keywords; 14 | 15 | static { 16 | keywords = new HashMap<>(); 17 | keywords.put("and", AND); 18 | keywords.put("class", CLASS); 19 | keywords.put("else", ELSE); 20 | keywords.put("false", FALSE); 21 | keywords.put("for", FOR); 22 | keywords.put("fun", FUN); 23 | keywords.put("if", IF); 24 | keywords.put("nil", NIL); 25 | keywords.put("or", OR); 26 | keywords.put("print", PRINT); 27 | keywords.put("return", RETURN); 28 | keywords.put("super", SUPER); 29 | keywords.put("this", THIS); 30 | keywords.put("true", TRUE); 31 | keywords.put("var", VAR); 32 | keywords.put("while", WHILE); 33 | } 34 | 35 | private final String source; 36 | 37 | private final List tokens = new ArrayList<>(); 38 | private final JSONObject errors = new JSONObject(); 39 | 40 | private int start = 0; 41 | private int current = 0; 42 | private int line = 1; 43 | 44 | 45 | SimpleInterpreter simpleInterpreter; 46 | 47 | Scanner(String source, SimpleInterpreter simpleInterpreter) { 48 | this.source = source; 49 | this.simpleInterpreter = simpleInterpreter; 50 | } 51 | 52 | public List getTokens() { 53 | return tokens; 54 | } 55 | 56 | public JSONObject getErrors() { 57 | return errors; 58 | } 59 | 60 | void scanTokens() { 61 | while (!isAtEnd()) { 62 | start = current; 63 | scanToken(); 64 | } 65 | 66 | tokens.add(new Token(EOF, "", null, line, current, current)); 67 | } 68 | 69 | private void scanToken() { 70 | char c = advance(); 71 | switch (c) { 72 | case '(': 73 | addToken(LEFT_PAREN); 74 | break; 75 | case ')': 76 | addToken(RIGHT_PAREN); 77 | break; 78 | case '{': 79 | addToken(LEFT_BRACE); 80 | break; 81 | case '}': 82 | addToken(RIGHT_BRACE); 83 | break; 84 | case ',': 85 | addToken(COMMA); 86 | break; 87 | case '.': 88 | addToken(DOT); 89 | break; 90 | case '-': 91 | addToken(MINUS); 92 | break; 93 | case '+': 94 | addToken(PLUS); 95 | break; 96 | case ';': 97 | addToken(SEMICOLON); 98 | break; 99 | case '*': 100 | addToken(STAR); 101 | break; 102 | 103 | case '!': 104 | addToken(match('=') ? BANG_EQUAL : BANG); 105 | break; 106 | case '=': 107 | addToken(match('=') ? EQUAL_EQUAL : EQUAL); 108 | break; 109 | case '<': 110 | addToken(match('=') ? LESS_EQUAL : LESS); 111 | break; 112 | case '>': 113 | addToken(match('=') ? GREATER_EQUAL : GREATER); 114 | break; 115 | 116 | case '/': 117 | if (match('/')) { 118 | while (peek() != '\n' && !isAtEnd()) advance(); 119 | } else { 120 | addToken(SLASH); 121 | } 122 | break; 123 | 124 | 125 | case ' ': 126 | case '\r': 127 | case '\t': 128 | break; 129 | 130 | case '\n': 131 | line++; 132 | break; 133 | 134 | 135 | case '"': 136 | string(); 137 | break; 138 | 139 | 140 | default: 141 | if (isDigit(c)) { 142 | number(); 143 | } else if (isAlpha(c)) { 144 | identifier(); 145 | } else { 146 | errors.append(Integer.toString((tokens.size())), "[line " + line + "] Error: Unexpected character."); 147 | // errors.put(new JSONObject().put(Integer.toString((tokens.size() + 1)), "[line " + line + "] Error: Unexpected character.")); 148 | simpleInterpreter.error(line, "Unexpected character."); 149 | } 150 | break; 151 | } 152 | } 153 | 154 | private void identifier() { 155 | while (isAlphaNumeric(peek())) advance(); 156 | 157 | String text = source.substring(start, current); 158 | TokenType type = keywords.get(text); 159 | if (type == null) type = IDENTIFIER; 160 | addToken(type); 161 | } 162 | 163 | private void number() { 164 | while (isDigit(peek())) advance(); 165 | 166 | 167 | if (peek() == '.' && isDigit(peekNext())) { 168 | 169 | advance(); 170 | 171 | while (isDigit(peek())) advance(); 172 | } 173 | 174 | addToken(NUMBER, 175 | Double.parseDouble(source.substring(start, current))); 176 | } 177 | 178 | 179 | private void string() { 180 | while (peek() != '"' && !isAtEnd()) { 181 | if (peek() == '\n') line++; 182 | advance(); 183 | } 184 | 185 | if (isAtEnd()) { 186 | errors.append(Integer.toString((tokens.size())), "[line " + line + "] Error: Unterminated string."); 187 | // errors.put(new JSONObject().put(Integer.toString((tokens.size() + 1)), "[line " + line + "] Error: Unterminated string.")); 188 | simpleInterpreter.error(line, "Unterminated string."); 189 | return; 190 | } 191 | 192 | 193 | advance(); 194 | 195 | 196 | String value = source.substring(start + 1, current - 1); 197 | addToken(STRING, value); 198 | } 199 | 200 | private boolean match(char expected) { 201 | if (isAtEnd()) return false; 202 | if (source.charAt(current) != expected) return false; 203 | 204 | current++; 205 | return true; 206 | } 207 | 208 | 209 | private char peek() { 210 | if (isAtEnd()) return '\0'; 211 | return source.charAt(current); 212 | } 213 | 214 | 215 | private char peekNext() { 216 | if (current + 1 >= source.length()) return '\0'; 217 | return source.charAt(current + 1); 218 | } 219 | 220 | 221 | private boolean isAlpha(char c) { 222 | return (c >= 'a' && c <= 'z') || 223 | (c >= 'A' && c <= 'Z') || 224 | c == '_'; 225 | } 226 | 227 | private boolean isAlphaNumeric(char c) { 228 | return isAlpha(c) || isDigit(c); 229 | } 230 | 231 | 232 | private boolean isDigit(char c) { 233 | return c >= '0' && c <= '9'; 234 | } 235 | 236 | 237 | private boolean isAtEnd() { 238 | return current >= source.length(); 239 | } 240 | 241 | 242 | private char advance() { 243 | current++; 244 | return source.charAt(current - 1); 245 | } 246 | 247 | private void addToken(TokenType type) { 248 | addToken(type, null); 249 | } 250 | 251 | private void addToken(TokenType type, Object literal) { 252 | String text = source.substring(start, current); 253 | tokens.add(new Token(type, text, literal, line, start, current - 1)); 254 | } 255 | } -------------------------------------------------------------------------------- /InterpreterVisualizer/src/main/java/simpleinterpreter/AST.java: -------------------------------------------------------------------------------- 1 | package simpleinterpreter; 2 | 3 | import org.json.JSONArray; 4 | import org.json.JSONObject; 5 | 6 | import java.util.ArrayList; 7 | import java.util.List; 8 | import java.util.Map; 9 | 10 | public class AST { 11 | 12 | //Parser Data 13 | private final List astJSON; 14 | private final JSONArray visitedNode; 15 | private final List nodesData; 16 | 17 | // Interpreter Data 18 | private final JSONArray interpreterVisitedNode; 19 | private final JSONArray SymbolTableIndexSync; 20 | private final List symbolTableJSON; 21 | private final List interpreterNodesData; 22 | private final JSONObject outputMessages; 23 | private final JSONObject runtimeErrors; 24 | 25 | 26 | private final String ID = "\"id\""; 27 | private final String NEXT = "\"next\""; 28 | 29 | AST() { 30 | astJSON = new ArrayList<>(); 31 | visitedNode = new JSONArray(); 32 | nodesData = new ArrayList<>(); 33 | 34 | interpreterVisitedNode = new JSONArray(); 35 | symbolTableJSON = new ArrayList<>(); 36 | SymbolTableIndexSync = new JSONArray(); 37 | interpreterNodesData = new ArrayList<>(); 38 | outputMessages = new JSONObject(); 39 | runtimeErrors = new JSONObject(); 40 | } 41 | 42 | 43 | /* Traversing AST during Semantic Analysis */ 44 | 45 | void initInterpreterAST(Environment environment) { 46 | int rootIndex = getLastVisitedNodeIndex(); 47 | interpreterVisitedNode.put(rootIndex); 48 | JSONObject lastDataJSONObject = new JSONObject(getLastJSONObject().toString()); 49 | interpreterNodesData.add(lastDataJSONObject); 50 | JSONObject symbolTable = buildSymbolTable(environment, 1); 51 | symbolTableJSON.add(symbolTable); 52 | SymbolTableIndexSync.put(0); 53 | } 54 | 55 | void reportRuntimeError(String message) { 56 | int index = interpreterVisitedNode.length() - 1; 57 | runtimeErrors.put(Integer.toString(index), message); 58 | } 59 | 60 | void printOutputMessage(String message) { 61 | int index = interpreterVisitedNode.length() - 1; 62 | outputMessages.put(Integer.toString(index), message); 63 | } 64 | 65 | void addNodeDataInterpreter(int index, List data) { 66 | //Data 67 | JSONObject lastDataJSONObject = new JSONObject(getInterpreterLastJSONObject().toString()); 68 | if (!data.isEmpty()) { 69 | for (String s : data) { 70 | lastDataJSONObject.append(Integer.toString(index), s); 71 | } 72 | } 73 | interpreterNodesData.add(lastDataJSONObject); 74 | } 75 | 76 | JSONObject buildSymbolTable(Environment environment, int scope) { 77 | JSONObject variables = new JSONObject(); 78 | 79 | Map values = environment.getValues(); 80 | for (String name : values.keySet()) { 81 | variables.put(name, values.get(name)); 82 | } 83 | 84 | JSONObject scopes; 85 | if (environment.enclosing != null) { 86 | scopes = buildSymbolTable(environment.enclosing, scope + 1); 87 | } else { 88 | scopes = new JSONObject(); 89 | } 90 | 91 | if (!variables.isEmpty()) 92 | scopes.put(Integer.toString(scope), variables); 93 | 94 | return scopes; 95 | } 96 | 97 | void updateSymbolTable(Environment environment) { 98 | JSONObject symbolTable = buildSymbolTable(environment, 1); 99 | symbolTableJSON.add(symbolTable); 100 | } 101 | 102 | void visitNodeInterpreter(int index, String... args) { 103 | interpreterVisitedNode.put(index); 104 | SymbolTableIndexSync.put(symbolTableJSON.size() - 1); 105 | 106 | ArrayList data = new ArrayList<>(); 107 | 108 | for (String s : args) { 109 | data.add(s); 110 | } 111 | 112 | addNodeDataInterpreter(index, data); 113 | } 114 | 115 | private JSONObject getInterpreterLastJSONObject() { 116 | int size = interpreterNodesData.size(); 117 | if (size == 0) 118 | return new JSONObject(); 119 | return interpreterNodesData.get(size - 1); 120 | } 121 | 122 | /* Building AST during Parsing */ 123 | 124 | void addNodeData(int index, List data) { 125 | //Data 126 | JSONObject lastDataJSONObject = new JSONObject(getLastJSONObject().toString()); 127 | if (!data.isEmpty()) { 128 | for (String s : data) { 129 | lastDataJSONObject.append(Integer.toString(index), s); 130 | } 131 | } 132 | nodesData.add(lastDataJSONObject); 133 | } 134 | 135 | void addNewNode(int index, List data, List neighbours) { 136 | //I'm supposed to draw one edge from (index) to other nodes indices in args 137 | //args also has some data the I need to add to node (Index) 138 | 139 | addNodeData(index, data); 140 | 141 | JSONArray lastJSONArray = new JSONArray(getLastJSONArray().toString()); 142 | 143 | visitedNode.put(index); 144 | 145 | JSONObject currentNode = new JSONObject(); 146 | currentNode.put(ID, toStringWithDoubleQuotes(index)); 147 | currentNode.put(NEXT, new JSONArray()); 148 | for (int to : neighbours) { 149 | currentNode.append(NEXT, toStringWithDoubleQuotes(to)); 150 | } 151 | 152 | lastJSONArray.put(currentNode); 153 | astJSON.add(lastJSONArray); 154 | } 155 | 156 | /* Helper Functions */ 157 | 158 | private JSONArray getLastJSONArray() { 159 | int size = astJSON.size(); 160 | if (size == 0) 161 | return new JSONArray(); 162 | return astJSON.get(size - 1); 163 | } 164 | 165 | private JSONObject getLastJSONObject() { 166 | int size = nodesData.size(); 167 | if (size == 0) 168 | return new JSONObject(); 169 | return nodesData.get(size - 1); 170 | } 171 | 172 | private int getLastVisitedNodeIndex() { 173 | int size = visitedNode.length(); 174 | if (size == 0) 175 | return -1; 176 | return visitedNode.getInt(size - 1); 177 | 178 | } 179 | 180 | private String toStringWithDoubleQuotes(int index) { 181 | return "\"" + index + "\""; 182 | } 183 | 184 | 185 | /* Getters for Generating AST */ 186 | 187 | int getASTsSize() { 188 | return astJSON.size(); 189 | } 190 | 191 | public List getAstJSON() { 192 | return astJSON; 193 | } 194 | 195 | public JSONArray getVisitedNode() { 196 | return visitedNode; 197 | } 198 | 199 | public JSONArray getNodesData() { 200 | JSONArray nodesDataJSONArray = new JSONArray(); 201 | for (JSONObject jsonObject : nodesData) { 202 | nodesDataJSONArray.put(jsonObject); 203 | } 204 | return nodesDataJSONArray; 205 | } 206 | 207 | 208 | /* Getters for Traversing AST */ 209 | 210 | public JSONObject getInterpreterRuntimeErrors() { 211 | return runtimeErrors; 212 | } 213 | 214 | JSONArray getInterpreterCompleteAST() { 215 | return getLastJSONArray(); 216 | } 217 | 218 | public JSONArray getInterpreterVisitedNode() { 219 | return interpreterVisitedNode; 220 | } 221 | 222 | public List getInterpreterNodesData() { 223 | return interpreterNodesData; 224 | } 225 | 226 | public JSONObject getInterpreterOutputMessages() { 227 | return outputMessages; 228 | } 229 | 230 | public JSONArray getSymbolTableIndexSync() { 231 | return SymbolTableIndexSync; 232 | } 233 | 234 | public List getSymbolTableJSON() { 235 | return symbolTableJSON; 236 | } 237 | } 238 | -------------------------------------------------------------------------------- /lib/ui_elements/control_buttons.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutterdesktopapp/models/tokens.dart'; 3 | import 'package:flutterdesktopapp/services/networking.dart'; 4 | import 'package:flutterdesktopapp/utils/app_data.dart'; 5 | import 'package:flutterdesktopapp/utils/constants.dart'; 6 | import 'package:flutterdesktopapp/utils/utilities_provider.dart'; 7 | import 'package:provider/provider.dart'; 8 | 9 | class ControlButtons extends StatefulWidget { 10 | @override 11 | _ControlButtonsState createState() => _ControlButtonsState(); 12 | } 13 | 14 | class _ControlButtonsState extends State { 15 | NetworkHelper networkHelper = NetworkHelper(); 16 | 17 | @override 18 | Widget build(BuildContext context) { 19 | final appData = Provider.of(context); 20 | final utilsProvider = 21 | Provider.of(context, listen: false); 22 | 23 | String getText() { 24 | if (appData.isVisualized && 25 | (appData.circleOneClicked || 26 | appData.circleTwoClicked || 27 | appData.circleThreeClicked || 28 | appData.circleFourClicked)) 29 | return "Back"; 30 | else 31 | return "Visualize"; 32 | } 33 | 34 | Function getPrevButtonFunc() { 35 | var twoORthree = appData.circleTwoClicked | appData.circleThreeClicked; 36 | if (twoORthree && appData.visualizedStatementIndex > 0) { 37 | return () { 38 | appData.visualizedStatementIndex--; 39 | }; 40 | } 41 | return null; 42 | } 43 | 44 | Function getNextButtonFunc() { 45 | var twoORthree = appData.circleTwoClicked | appData.circleThreeClicked; 46 | if (twoORthree && 47 | appData.visualizedStatementIndex + 1 < 48 | appData.parsedStatementsList.length) { 49 | return () { 50 | appData.visualizedStatementIndex++; 51 | }; 52 | } 53 | return null; 54 | } 55 | 56 | void showAlertDialog(BuildContext context) { 57 | Widget okButton = ElevatedButton( 58 | child: Text("OK"), 59 | onPressed: () { 60 | Navigator.of(context).pop(); 61 | }, 62 | ); 63 | 64 | AlertDialog alert = AlertDialog( 65 | title: Text("Notice"), 66 | content: Text( 67 | "Please, write down some code before attempting to visualize!"), 68 | actions: [ 69 | okButton, 70 | ], 71 | ); 72 | 73 | showDialog( 74 | context: context, 75 | builder: (BuildContext context) { 76 | return alert; 77 | }, 78 | ); 79 | } 80 | 81 | void compile(List consoleMessages) { 82 | utilsProvider.addConsoleMessageList(consoleMessages); 83 | 84 | var sourceCode = appData.editingController.text; 85 | var richTextList = [], tokensColors = [], tokensIndices = []; 86 | int lastEnd, shift = 0; 87 | var tokensList = appData.tokensList; 88 | 89 | for (int tokenIndex = 0; tokenIndex < tokensList.length; tokenIndex++) { 90 | Token token = tokensList[tokenIndex]; 91 | 92 | var start = token.start - shift; 93 | var end = token.end - shift; 94 | if (tokenIndex > 0) { 95 | // no between text before the first token 96 | var betweenText = sourceCode.substring(lastEnd + 1, start); 97 | 98 | if (betweenText.length > 1 && betweenText[0] == "\n") { 99 | // betweenText = "\n"; 100 | // shift += 2 * betweenText.length; 101 | // start -= betweenText.length; 102 | // end -= betweenText.length; 103 | } 104 | richTextList.add([betweenText, Colors.black, 0]); 105 | 106 | tokensColors.add(Colors.black); 107 | } 108 | if (token.tokenType != "EOF") { 109 | // no between text after EOF 110 | var tokenText = sourceCode.substring(start, end + 1); 111 | print(tokenText); 112 | richTextList.add([tokenText, Colors.black, 1]); 113 | } 114 | lastEnd = end; 115 | tokensIndices.add(tokensColors.length); 116 | tokensColors.add(tokensList[tokenIndex].color); 117 | } 118 | 119 | appData.tokensIndices = tokensIndices; 120 | utilsProvider.richTextList = richTextList; 121 | appData.tokensColors = tokensColors; 122 | 123 | appData.visualize(); 124 | } 125 | 126 | void callInterpreter(String string, var context) { 127 | // final progress = ProgressHUD.of(context); 128 | // progress.show(); 129 | List consoleMessages = []; 130 | networkHelper 131 | .sendCodeToInterpreter(appData.editingController.text.toString()) 132 | .then((resultMessages) { 133 | consoleMessages = resultMessages; 134 | 135 | networkHelper.getLexicalAnalysis().then((value) { 136 | appData.tokensList = value; 137 | if (value != null) { 138 | consoleMessages.add( 139 | ["Requesting Lexical Analysis Completed Successfully!", 1]); 140 | } else 141 | consoleMessages.add(["Failed to receive lexical analysis.", 0]); 142 | 143 | networkHelper.getSyntacticAnalysis().then((value) { 144 | appData.parsedStatementsList = value; 145 | if (value != null) { 146 | consoleMessages.add( 147 | ["Requesting Syntactic Analysis Completed Successfully!", 1]); 148 | } else 149 | consoleMessages.add(["Failed to receive syntactic analysis.", 0]); 150 | 151 | networkHelper.getSemanticAnalysis().then((value) { 152 | appData.astsList = value; 153 | if (value != null) { 154 | consoleMessages.add([ 155 | "Requesting Semantic Analysis Completed Successfully!", 156 | 1 157 | ]); 158 | } else 159 | consoleMessages 160 | .add(["Failed to receive semantic analysis.", 0]); 161 | 162 | compile(consoleMessages); 163 | }); 164 | }); 165 | }); 166 | }); 167 | } 168 | 169 | void _VisualizeButtonLogic(BuildContext context) { 170 | appData.isVisualizationReady = false; 171 | utilsProvider.clearConsoleMessages(); 172 | if (appData.editingController.text.isEmpty) { 173 | showAlertDialog(context); 174 | } else { 175 | callInterpreter(appData.editingController.text, context); 176 | } 177 | } 178 | 179 | void _BackButtonLogic() { 180 | if (appData.circleOneClicked) { 181 | appData.changeCircleOneState(); 182 | } else if (appData.circleTwoClicked) { 183 | appData.changeCircleTwoState(); 184 | } else if (appData.circleThreeClicked) { 185 | appData.changeCircleThreeState(); 186 | } 187 | utilsProvider.resetRichTextListColors(); 188 | appData.visualizedStatementIndex = 0; 189 | } 190 | 191 | Function getVisualizeButtonFunc(var context) { 192 | var atLeastOneCircle = appData.atLeastOneCircle(); 193 | 194 | if (atLeastOneCircle) { 195 | return () { 196 | _BackButtonLogic(); 197 | }; 198 | } 199 | if (appData.isVisualizationReady || atLeastOneCircle) 200 | return () { 201 | _VisualizeButtonLogic(context); 202 | }; 203 | return null; 204 | } 205 | 206 | return Padding( 207 | padding: const EdgeInsets.all(5.0), 208 | child: Row( 209 | mainAxisAlignment: MainAxisAlignment.spaceEvenly, 210 | children: [ 211 | Expanded( 212 | child: Padding( 213 | padding: const EdgeInsets.only(left: 4.0, right: 4.0), 214 | child: ElevatedButton( 215 | onPressed: getVisualizeButtonFunc(context), 216 | child: Text( 217 | getText(), 218 | style: text_style_header_button, 219 | ), 220 | style: run_button_style, 221 | ), 222 | ), 223 | ), 224 | Expanded( 225 | child: Padding( 226 | padding: const EdgeInsets.only(left: 4.0, right: 4.0), 227 | child: ElevatedButton( 228 | onPressed: getPrevButtonFunc(), 229 | style: run_button_style, 230 | child: Text( 231 | "Previous Statement", 232 | style: text_style_header_button, 233 | )), 234 | ), 235 | ), 236 | Expanded( 237 | child: Padding( 238 | padding: const EdgeInsets.only(left: 4.0, right: 4.0), 239 | child: ElevatedButton( 240 | onPressed: getNextButtonFunc(), 241 | style: run_button_style, 242 | child: 243 | Text("Next Statement", style: text_style_header_button)), 244 | ), 245 | ) 246 | ], 247 | ), 248 | ); 249 | } 250 | } 251 | --------------------------------------------------------------------------------