Skip to content

Waxeye Parser Generator for the Haxe Language Target#43

Open
darmie wants to merge 18 commits into
waxeye-org:masterfrom
darmie:devhaxe
Open

Waxeye Parser Generator for the Haxe Language Target#43
darmie wants to merge 18 commits into
waxeye-org:masterfrom
darmie:devhaxe

Conversation

@darmie

@darmie darmie commented Aug 14, 2017

Copy link
Copy Markdown

I have written a parser generator for Haxe based on the Javascript implementation. Parser has been tested and it's working.

Please see https://github.com/darmie/waxeye-hx-sample for full implementation of the Calculator example.

Build Waxeye source and Generate Parser code

waxeye -g haxe . grammars/calc.waxeye

Generated Code

/*
 * Generated by the Waxeye Parser Generator - version 0.8.1
 * www.waxeye.org
 */
package;

import org.waxeye.parser.*;
import org.waxeye.parser.Exp.ExpType;
import org.waxeye.parser.Modes;
//import haxe.ds.StringMap;
/**
 * A parser generated by the Waxeye Parser Generator.
 *
 * @author Waxeye Parser Generator
 */
class Parser extends org.waxeye.parser.Parser
{
    /**
     * Creates a new Parser.
     */
	
    public function new()
    {
        super(makeDefinition(), 'calc');
    }

    /**
     * Builds the grammar definitions for the parser.
     *
     * @return The definitions grammar for the parser.
     */
	@:keep
    private function makeDefinition():Dynamic
    {
        var def:Dynamic = {calc : {'mode' : Modes.NORMAL, 'exp' : new Exp(ExpType.SEQ, [new Exp(ExpType.NT, ['ws']),
                new Exp(ExpType.NT, ['sum'])]) },
            sum : {'mode' : Modes.NORMAL, 'exp' : new Exp(ExpType.SEQ, [new Exp(ExpType.NT, ['prod']),
                new Exp(ExpType.STAR, [new Exp(ExpType.SEQ, [new Exp(ExpType.CHAR_CLASS, ['+',
                            '-']),
                        new Exp(ExpType.NT, ['ws']),
                        new Exp(ExpType.NT, ['prod'])])])]) },
            prod : {'mode' : Modes.NORMAL, 'exp' : new Exp(ExpType.SEQ, [new Exp(ExpType.NT, ['unary']),
                new Exp(ExpType.STAR, [new Exp(ExpType.SEQ, [new Exp(ExpType.CHAR_CLASS, ['*',
                            '/']),
                        new Exp(ExpType.NT, ['ws']),
                        new Exp(ExpType.NT, ['unary'])])])]) },
            unary : {'mode' : Modes.PRUNING, 'exp' : new Exp(ExpType.ALT, [new Exp(ExpType.SEQ, [new Exp(ExpType.CHAR, ['-']),
                    new Exp(ExpType.NT, ['ws']),
                    new Exp(ExpType.NT, ['unary'])]),
                new Exp(ExpType.SEQ, [new Exp(ExpType.VOID, [new Exp(ExpType.CHAR, ['('])]),
                    new Exp(ExpType.NT, ['ws']),
                    new Exp(ExpType.NT, ['sum']),
                    new Exp(ExpType.VOID, [new Exp(ExpType.CHAR, [')'])]),
                    new Exp(ExpType.NT, ['ws'])]),
                new Exp(ExpType.NT, ['num'])]) },
            num : {'mode' : Modes.NORMAL, 'exp' : new Exp(ExpType.SEQ, [new Exp(ExpType.PLUS, [new Exp(ExpType.CHAR_CLASS, [['0', '9']])]),
                new Exp(ExpType.OPT, [new Exp(ExpType.SEQ, [new Exp(ExpType.CHAR, ['.']),
                        new Exp(ExpType.PLUS, [new Exp(ExpType.CHAR_CLASS, [['0', '9']])])])]),
                new Exp(ExpType.NT, ['ws'])]) },
            ws : {'mode' : Modes.VOIDING, 'exp' : new Exp(ExpType.STAR, [new Exp(ExpType.CHAR_CLASS, [['\t', '\n'],
                    '\r',
                    ' '])]) }}

        return def;
    }
    
}

Implementation of the calculator

package;
import Parser;
import org.waxeye.parser.AST;
import org.waxeye.parser.ParseError;
import haxe.Json;

/**
 * ...
 * @author Damilare Akinlaja
 */
class Main 
{

	public static function main() 
	{

		var math = Sys.stdin();
		Sys.print("Calc: ");
		var calc = math.readLine();
		var ast = (new Parser()).parse(calc);
		if (Std.is(ast, AST)){
			Sys.print("=> "+calc+" = "+sum(ast.children[0]));
		}else if(Std.is(ast, ParseError)){
			Sys.print(ast.toString());
		}
		


	}

	private static function binOp(ast:AST, fn:AST->Dynamic, ch:String, op1:Dynamic, op2:Dynamic):String
	{
		var chil:Array<Any> = ast.children;
		// apply the visitor function to our first sub-tree
		var val = fn(chil[0]);
		
		var i = 1;
		
		while(i != chil.length){
			// choose our operator function
			 var operator = chil[i] == ch ? op1 : op2;
			
			 // apply the visitor function to our second sub-tree
			
			 var operand = fn(chil[i + 1]);
			 
			 // apply the operator to our current value and the second sub-tree
			 val = operator(val, operand);
			 // move on to the next operator and sub-tree
			 i += 2;
		}
		
		return val;
		
	}
	
	private static function sum(ast:AST):String
	{
		var add = function(a, b){return a + b; };
		var sub = function(a, b){return a - b; };
		
		return binOp(ast, prod, '+', add, sub);
	}
	
	
	private static function prod(ast:AST):String
	{
		var mult = function(a, b){return a * b; };
		var div = function(a, b){return a / b; };
		
		return binOp(ast, unary, '*', mult, div);
	}
	
	private static function unary(ast:AST):Dynamic
	{
		if (ast.type == 'unary') {
			// the unary rule is a pruning non-terminal
			// the only case we will see it is if we have negation
			return - unary(ast.children[1]);
		}
		else {
			if (ast.type == 'sum') {
				return sum(ast);
			}
			else {
				return num(ast);
			}
		}		
		
	}
	
	
	private static function num(ast:AST):Float
	{
		return Std.parseFloat(ast.children.join(''));
	}
	
	
	
}

How to run implementation

Download and Install Haxe

Install haxe binary from http://haxe.org

Clone Repo

git clone https://github.com/darmie/waxeye-hx-sample.git waxeye-sample

Build and Run Project

> haxe waxeye-sample/build.hxml
> neko neko/Main.n

Tested and Works on the following Haxe supported Targets

  1. C/C++
  2. Java
  3. NekoVM
  4. C#
  5. Lua
    It is expected to work on all Haxe supported targets

@darmie darmie mentioned this pull request Aug 14, 2017

@jishi9 jishi9 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks darmie for doing this! :)

I haven't taken a detailed look yet, but jiust some things I noticed skimming through.

  1. There are some extra files and changes which are checked in that should be deleted, like:

.vscode/tasks.json
edit to build/exe.bat
lib/*.dll

  1. Some changes probably belong in a separate pull request, like:
    src/waxeye/header.txt
    test/java/Example.java

  2. Some commented out code in Continuations.hx:35 and ParseError.hx:42, Util.hx:2,4

  3. ParseError.hx:57 also has a 'trace', maybe accidental?

@darmie

darmie commented Aug 17, 2017

Copy link
Copy Markdown
Author

@jishi9 Thanks, those were not supposed to make it to the PR, I would make neccessary corrections and push.

@glebm

glebm commented Aug 20, 2017

Copy link
Copy Markdown
Contributor

Could you please add tests for Haxe similar to the JavaScript tests in test/ (added in #45)?

Also, I wonder if this support Unicode when compiled to JavaScript? For the native JavaScript runtime, Unicode support is added in #47.

@darmie

darmie commented Aug 20, 2017

Copy link
Copy Markdown
Author

@glebm I'll work on the /test and would look into how Unicode is supported in Haxe.

@darmie

darmie commented Aug 20, 2017

Copy link
Copy Markdown
Author

There's a Haxe API for ensuring Unicode support across target platforms.

http://api.haxe.org/haxe/Utf8.html

@glebm

glebm commented Aug 20, 2017

Copy link
Copy Markdown
Contributor

Using UTF-8 is a bit inefficient in languages that use UTF-16 natively (JavaScript, Java, C#).

I was hoping Haxe had a solution for Unicode support using native String types on each platform, but looks like that is still a work in progress.

HaxeFoundation/haxe#3072
https://try.haxe.org/#d9D04

@darmie

darmie commented Aug 20, 2017

Copy link
Copy Markdown
Author

@glebm thanks for pointing this out. My knowledge of unicode is somewhat limited. I would sleep on it and see what solutions are out there. 👍

@bkil

bkil commented Mar 13, 2021

Copy link
Copy Markdown

It seems that the linked Haxe issue had been solved in 2018, so it might be worthwhile to look into this question again. I'd really find support of either Haxe (or PHP directly via #104) useful, as it is a pretty common freely hosted server side language.

@bkil bkil mentioned this pull request Mar 13, 2021
@darmie

darmie commented Mar 13, 2021

Copy link
Copy Markdown
Author

@bkil waxeye has really evolved since I opened this PR. There have been lots of changes in the Haxe ecosystem too. Maybe I'll work on this again.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants