Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/thomas-crane/sgml
A static analysis tool for GML.
https://github.com/thomas-crane/sgml
Last synced: 5 days ago
JSON representation
A static analysis tool for GML.
- Host: GitHub
- URL: https://github.com/thomas-crane/sgml
- Owner: thomas-crane
- License: mit
- Created: 2019-09-06T12:04:32.000Z (over 5 years ago)
- Default Branch: master
- Last Pushed: 2022-12-30T18:34:22.000Z (almost 2 years ago)
- Last Synced: 2024-10-30T16:11:55.535Z (about 2 months ago)
- Language: TypeScript
- Homepage:
- Size: 375 KB
- Stars: 2
- Watchers: 2
- Forks: 0
- Open Issues: 10
-
Metadata Files:
- Readme: readme.md
- License: license.md
Awesome Lists containing this project
README
# SGML
Safe Game Maker Language.
[![Build Status](https://travis-ci.com/thomas-crane/sgml.svg?token=stAj7zoP2UACMHFzdTXv&branch=master)](https://travis-ci.com/thomas-crane/sgml)
[![Coverage Status](https://coveralls.io/repos/github/thomas-crane/sgml/badge.svg?branch=master)](https://coveralls.io/github/thomas-crane/sgml?branch=master)## Contents
- [SGML](#sgml)
- [Contents](#contents)
- [About](#about)
- [Roadmap](#roadmap)
- [Install](#install)
- [Setup](#setup)
- [Installing](#installing)
- [Building](#building)
- [Testing](#testing)
- [Running](#running)
- [Acknowledgements](#acknowledgements)## About
GML is a very dynamic scripting language with a relaxed type system. The compiler which Game Maker Studio uses does little to prevent the kinds of errors which modern compilers are capable of detecting at compile time.
As such, the goal of SGML is to provide a tool for GML developers to fill the gap between the GMS compiler and the expectations of a modern compiler.
The primary focus of SGML is not to provide a compiler which transforms GML into some other form, but rather a tool which can be used to perform static analysis of GML code. SGML aims to perform the following types of analysis
+ Type checking
+ Data flow analysis
+ Control flow analysis## Roadmap
+ [x] Lexical analysis
+ [x] Lexer implementation
+ [x] Test cases
+ [x] Syntax analysis
+ [x] AST implementations
+ [x] Parser implementation
+ [x] Test cases
+ [ ] Semantic analysis
+ [ ] Symbol implementations
+ [ ] Visitor/pass pattern implementation
+ [ ] Support built in functions and variables
+ [ ] Find references to undefined symbols
+ [ ] Find symbols with no references (dead code)
+ [ ] Find shadowed or redeclared symbols
+ [ ] Test cases
+ [ ] Type checking
+ [ ] Bound AST implementations
+ [ ] Binder implementation
+ [ ] Test cases## Install
Currently, the only way to install the SGML tool is by cloning the source and following the setup steps. When SGML is in a more useful state, the tool will be published on npm.
## Setup
### Installing
Clone this repository
```bash
$ git clone https://github.com/thomas-crane/sgml.git
$ cd sgml```
Install the dependencies
```bash
$ npm install```
### Building
Whenever changes are made to the source code, the build command must be run in order for the changes to take effect.
```bash
$ npm run compile```
### Testing
The unit tests can be run by using the following command. This will also use nyc to report coverage statistics.
```bash
$ npm test
```## Running
There is currently no way to run the SGML tool, however there is a public interface for the compiler which can be used from a simple harness. The following script simply parses a script and then traverses the AST to print the script to the console. If the parser is working properly, the printed result should exactly match the input.
```typescript
import { DiagnosticBag } from './diagnostics/diagnostic-bag';
import { Parser } from './parser/parser';
import { SyntaxKind } from './syntax/syntax-kind';
import { SyntaxToken } from './syntax/syntax-token';const TEST_SCRIPT =
`with (instance_create(x, y, obj_Ball))
{
speed = other.speed;
direction = other.direction;
}
`;// create a new parser
const parser = new Parser(TEST_SCRIPT, new DiagnosticBag());// get a root node.
const root = parser.parseRoot();// traverse each child in the root node.
root.forEachChild((child) => {
// if the child is a token.
if (child.kind > SyntaxKind.FirstToken && child.kind < SyntaxKind.LastToken) {
const leadingTrivia = (child as SyntaxToken).leadingTrivia.map((trivia) => trivia.value);
const trailingTrivia = (child as SyntaxToken).trailingTrivia.map((trivia) => trivia.value);// print that token in full fidelity.
process.stdout.write(`${leadingTrivia.join('')}${(child as SyntaxToken).value}${trailingTrivia.join('')}`);
}
});// prints:
// with (instance_create(x, y, obj_Ball))
// {
// speed = other.speed;
// direction = other.direction;
// }```
## Acknowledgements
Test scripts for the purpose of testing the parser were sourced from the [GameMakerDiscord/Emmet](https://github.com/GameMakerDiscord/Emmets) repository.