mirror of https://github.com/t1meshift/js.git
Compare commits
6 Commits
c09b52638c
...
041f4c31fb
Author | SHA1 | Date |
---|---|---|
Yury Kurlykov | 041f4c31fb | |
Yury Kurlykov | 6b4865af8d | |
Yury Kurlykov | eea056550c | |
Yury Kurlykov | 494ed06f28 | |
Yury Kurlykov | 47d6d31239 | |
Yury Kurlykov | 6414fecbfe |
|
@ -3,7 +3,7 @@ So here it is.
|
||||||
"""
|
"""
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
__version__ = "0.0.2"
|
__version__ = "0.0.7"
|
||||||
__snake__ = r"""
|
__snake__ = r"""
|
||||||
_________ _________
|
_________ _________
|
||||||
/ \ / \
|
/ \ / \
|
||||||
|
|
|
@ -10,7 +10,7 @@ import coloredlogs
|
||||||
from jasminesnake import __version__, __snake__, LOG_LEVELS
|
from jasminesnake import __version__, __snake__, LOG_LEVELS
|
||||||
from .js_stream import JSBaseStream, JSStringStream, JSFileStream
|
from .js_stream import JSBaseStream, JSStringStream, JSFileStream
|
||||||
from .lex.ErrorListeners import LogErrorListener
|
from .lex.ErrorListeners import LogErrorListener
|
||||||
import ast
|
from ast import nodes, to_ascii_tree, from_parse_tree
|
||||||
|
|
||||||
|
|
||||||
def create_argument_parser():
|
def create_argument_parser():
|
||||||
|
@ -70,8 +70,11 @@ def main():
|
||||||
stream = JSFileStream(args.infile, LogErrorListener())
|
stream = JSFileStream(args.infile, LogErrorListener())
|
||||||
|
|
||||||
tree = stream.parse()
|
tree = stream.parse()
|
||||||
ast_tree = ast.from_parse_tree(tree)
|
|
||||||
|
|
||||||
|
ast_tree = from_parse_tree(tree)
|
||||||
|
ascii_ast = to_ascii_tree(ast_tree)
|
||||||
|
|
||||||
|
logging.info("Got an AST!\n%s", ascii_ast)
|
||||||
# TODO: run logic
|
# TODO: run logic
|
||||||
sys.exit(0)
|
sys.exit(0)
|
||||||
|
|
||||||
|
@ -92,7 +95,11 @@ def main():
|
||||||
tree = stream.parse()
|
tree = stream.parse()
|
||||||
logging.debug("Got tree %s", tree.toStringTree(stream.parser.ruleNames))
|
logging.debug("Got tree %s", tree.toStringTree(stream.parser.ruleNames))
|
||||||
|
|
||||||
ast_tree = ast.from_parse_tree(tree)
|
ast_tree = from_parse_tree(tree)
|
||||||
|
ascii_ast = to_ascii_tree(ast_tree)
|
||||||
|
|
||||||
|
logging.info("Got an AST!")
|
||||||
|
logging.info(ascii_ast)
|
||||||
# TODO: run logic
|
# TODO: run logic
|
||||||
except EOFError:
|
except EOFError:
|
||||||
print("Ctrl-D received, shutting down...")
|
print("Ctrl-D received, shutting down...")
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
"""AST module."""
|
"""AST module."""
|
||||||
|
|
||||||
|
from enum import Enum
|
||||||
|
from typing import Union
|
||||||
from antlr4 import ParseTreeWalker
|
from antlr4 import ParseTreeWalker
|
||||||
from tree_format import format_tree
|
|
||||||
|
|
||||||
import lex.JavaScriptParser as Parser
|
import lex.JavaScriptParser as Parser
|
||||||
import ast.nodes
|
import ast.nodes
|
||||||
|
@ -24,6 +25,46 @@ def from_parse_tree(tree: JSP.ProgramContext) -> ast.nodes.Program:
|
||||||
return ast_listener.program_node
|
return ast_listener.program_node
|
||||||
|
|
||||||
|
|
||||||
|
def to_ascii_tree(
|
||||||
|
node: Union[ast.nodes.Position, ast.nodes.SourceLocation, ast.nodes.Node],
|
||||||
|
name_prefix: str = "",
|
||||||
|
nesting_lvl: int = 0,
|
||||||
|
):
|
||||||
|
if nesting_lvl < 0:
|
||||||
|
raise ValueError("Nesting level can't be below 0")
|
||||||
|
|
||||||
|
FORK = "+"
|
||||||
|
VERTICAL = "|"
|
||||||
|
HORIZONTAL = "-"
|
||||||
|
|
||||||
|
SUBENTRY_PREFIX = f"{FORK}{HORIZONTAL}{HORIZONTAL} "
|
||||||
|
NESTED_PREFIX = f"{VERTICAL} "
|
||||||
|
|
||||||
|
value = str(node)
|
||||||
|
children = None
|
||||||
|
|
||||||
|
if isinstance(node, Enum):
|
||||||
|
value = str(node.value)
|
||||||
|
|
||||||
|
if isinstance(node, list):
|
||||||
|
value = ""
|
||||||
|
children = [(index, val) for index, val in enumerate(node)]
|
||||||
|
|
||||||
|
if hasattr(node, "fields"):
|
||||||
|
children = [(k, node.fields[k]) for k in node.fields.keys()]
|
||||||
|
|
||||||
|
result = f"{NESTED_PREFIX * (nesting_lvl - 1)}{SUBENTRY_PREFIX * (nesting_lvl > 0)}"
|
||||||
|
result += f"{name_prefix}{value}\n"
|
||||||
|
|
||||||
|
if children is not None:
|
||||||
|
for (child_name, child_value) in children:
|
||||||
|
result += to_ascii_tree(child_value, f"{child_name}: ", nesting_lvl + 1)
|
||||||
|
|
||||||
|
# result += "\n"
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
# Delete temporary imports
|
# Delete temporary imports
|
||||||
del JSP
|
del JSP
|
||||||
del Parser
|
del Parser
|
||||||
|
|
|
@ -21,8 +21,9 @@ Todo:
|
||||||
* Add support for lacking features
|
* Add support for lacking features
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from typing import List, Union, Optional, Literal as TypeLiteral, TypedDict
|
from typing import List, Union, Optional, Literal as TypeLiteral, TypedDict, Any
|
||||||
from enum import Enum
|
from enum import Enum
|
||||||
|
from collections import OrderedDict
|
||||||
|
|
||||||
# The Lord sees I actually wanted to split it up, but ESTree hierarchy is so messed up... No. It's actually *fucked up*
|
# The Lord sees I actually wanted to split it up, but ESTree hierarchy is so messed up... No. It's actually *fucked up*
|
||||||
# that much that I couldn't even resolve circular dependencies in the submodules. I have to reap what I've sown.
|
# that much that I couldn't even resolve circular dependencies in the submodules. I have to reap what I've sown.
|
||||||
|
@ -140,6 +141,10 @@ class Property:
|
||||||
...
|
...
|
||||||
|
|
||||||
|
|
||||||
|
class Identifier:
|
||||||
|
...
|
||||||
|
|
||||||
|
|
||||||
# "Node objects" block
|
# "Node objects" block
|
||||||
|
|
||||||
|
|
||||||
|
@ -155,6 +160,9 @@ class Position:
|
||||||
self.line = line
|
self.line = line
|
||||||
self.column = column
|
self.column = column
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return f"{self.line}:{self.column}"
|
||||||
|
|
||||||
|
|
||||||
class SourceLocation:
|
class SourceLocation:
|
||||||
"""
|
"""
|
||||||
|
@ -172,6 +180,14 @@ class SourceLocation:
|
||||||
self.start = start
|
self.start = start
|
||||||
self.end = end
|
self.end = end
|
||||||
|
|
||||||
|
@property
|
||||||
|
def fields(self):
|
||||||
|
return OrderedDict({"start": self.start, "end": self.end})
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
src = "" if self.source is None else f"{self.source}:"
|
||||||
|
return f"{src}{str(self.start)}"
|
||||||
|
|
||||||
|
|
||||||
class Node:
|
class Node:
|
||||||
"""ESTree AST nodes are represented as Node objects, which may have any prototype inheritance but which implement
|
"""ESTree AST nodes are represented as Node objects, which may have any prototype inheritance but which implement
|
||||||
|
@ -191,16 +207,15 @@ class Node:
|
||||||
self.type = node_type
|
self.type = node_type
|
||||||
self.loc = loc
|
self.loc = loc
|
||||||
|
|
||||||
|
self._fields: OrderedDict[str, Any] = OrderedDict()
|
||||||
|
self._fields.update({"type": self.type, "loc": self.loc})
|
||||||
|
|
||||||
# "Identifier" block
|
def __str__(self):
|
||||||
|
return f"{self.type} at {str(self.loc)}"
|
||||||
|
|
||||||
|
@property
|
||||||
class Identifier(Expression, Pattern):
|
def fields(self):
|
||||||
"""An identifier. Note that an identifier may be an expression or a destructuring pattern."""
|
return self._fields
|
||||||
|
|
||||||
def __init__(self, loc: Optional[SourceLocation], name: str):
|
|
||||||
super(Identifier, self).__init__("Identifier", loc)
|
|
||||||
self.name = name
|
|
||||||
|
|
||||||
|
|
||||||
# "Literal" block
|
# "Literal" block
|
||||||
|
@ -214,6 +229,7 @@ class Literal(Expression):
|
||||||
):
|
):
|
||||||
super().__init__("Literal", loc)
|
super().__init__("Literal", loc)
|
||||||
self.value = value
|
self.value = value
|
||||||
|
self._fields.update({"value": self.value})
|
||||||
|
|
||||||
|
|
||||||
# "Programs" block
|
# "Programs" block
|
||||||
|
@ -231,6 +247,7 @@ class Program(Node):
|
||||||
super().__init__("Program", loc)
|
super().__init__("Program", loc)
|
||||||
self.body = body
|
self.body = body
|
||||||
self.source_type = source_type
|
self.source_type = source_type
|
||||||
|
self._fields.update({"sourceType": self.source_type, "body": self.body})
|
||||||
|
|
||||||
|
|
||||||
# "Functions" block
|
# "Functions" block
|
||||||
|
@ -257,6 +274,7 @@ class Function(Node):
|
||||||
self.id = function_id
|
self.id = function_id
|
||||||
self.params = params
|
self.params = params
|
||||||
self.body = body
|
self.body = body
|
||||||
|
self._fields.update({"id": self.id, "params": self.params, "body": self.body})
|
||||||
|
|
||||||
|
|
||||||
# "Statements" block
|
# "Statements" block
|
||||||
|
@ -282,6 +300,7 @@ class BlockStatement(Statement):
|
||||||
def __init__(self, loc: Optional[SourceLocation], body: List[Statement]):
|
def __init__(self, loc: Optional[SourceLocation], body: List[Statement]):
|
||||||
super().__init__("BlockStatement", loc)
|
super().__init__("BlockStatement", loc)
|
||||||
self.body = body
|
self.body = body
|
||||||
|
self._fields.update({"body": self.body})
|
||||||
|
|
||||||
|
|
||||||
class ExpressionStatement(Statement):
|
class ExpressionStatement(Statement):
|
||||||
|
@ -290,6 +309,7 @@ class ExpressionStatement(Statement):
|
||||||
def __init__(self, loc: Optional[SourceLocation], expression: Expression):
|
def __init__(self, loc: Optional[SourceLocation], expression: Expression):
|
||||||
super().__init__("ExpressionStatement", loc)
|
super().__init__("ExpressionStatement", loc)
|
||||||
self.expression = expression
|
self.expression = expression
|
||||||
|
self._fields.update({"expression": self.expression})
|
||||||
|
|
||||||
|
|
||||||
class Directive(Node):
|
class Directive(Node):
|
||||||
|
@ -303,6 +323,9 @@ class Directive(Node):
|
||||||
super().__init__("Directive", loc)
|
super().__init__("Directive", loc)
|
||||||
self.expression = expression
|
self.expression = expression
|
||||||
self.directive = directive
|
self.directive = directive
|
||||||
|
self._fields.update(
|
||||||
|
{"expression": self.expression, "directive": self.directive}
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class FunctionBody(BlockStatement):
|
class FunctionBody(BlockStatement):
|
||||||
|
@ -320,6 +343,7 @@ class ReturnStatement(Statement):
|
||||||
def __init__(self, loc: Optional[SourceLocation], argument: Optional[Expression]):
|
def __init__(self, loc: Optional[SourceLocation], argument: Optional[Expression]):
|
||||||
super().__init__("ReturnStatement", loc)
|
super().__init__("ReturnStatement", loc)
|
||||||
self.argument = argument
|
self.argument = argument
|
||||||
|
self._fields.update({"argument": self.argument})
|
||||||
|
|
||||||
|
|
||||||
class BreakStatement(Statement):
|
class BreakStatement(Statement):
|
||||||
|
@ -328,6 +352,7 @@ class BreakStatement(Statement):
|
||||||
def __init__(self, loc: Optional[SourceLocation], label: Optional[Identifier]):
|
def __init__(self, loc: Optional[SourceLocation], label: Optional[Identifier]):
|
||||||
super().__init__("BreakStatement", loc)
|
super().__init__("BreakStatement", loc)
|
||||||
self.label = label
|
self.label = label
|
||||||
|
self._fields.update({"label": self.label})
|
||||||
|
|
||||||
|
|
||||||
class ContinueStatement(Statement):
|
class ContinueStatement(Statement):
|
||||||
|
@ -336,6 +361,7 @@ class ContinueStatement(Statement):
|
||||||
def __init__(self, loc: Optional[SourceLocation], label: Optional[Identifier]):
|
def __init__(self, loc: Optional[SourceLocation], label: Optional[Identifier]):
|
||||||
super().__init__("ContinueStatement", loc)
|
super().__init__("ContinueStatement", loc)
|
||||||
self.label = label
|
self.label = label
|
||||||
|
self._fields.update({"label": self.label})
|
||||||
|
|
||||||
|
|
||||||
class IfStatement(Statement):
|
class IfStatement(Statement):
|
||||||
|
@ -352,6 +378,13 @@ class IfStatement(Statement):
|
||||||
self.test = test
|
self.test = test
|
||||||
self.consequent = consequent
|
self.consequent = consequent
|
||||||
self.alternate = alternate
|
self.alternate = alternate
|
||||||
|
self._fields.update(
|
||||||
|
{
|
||||||
|
"test": self.test,
|
||||||
|
"consequent": self.consequent,
|
||||||
|
"alternate": self.alternate,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class WhileStatement(Statement):
|
class WhileStatement(Statement):
|
||||||
|
@ -363,6 +396,7 @@ class WhileStatement(Statement):
|
||||||
super().__init__("WhileStatement", loc)
|
super().__init__("WhileStatement", loc)
|
||||||
self.test = test
|
self.test = test
|
||||||
self.body = body
|
self.body = body
|
||||||
|
self._fields.update({"test": self.test, "body": self.body})
|
||||||
|
|
||||||
|
|
||||||
class DoWhileStatement(Statement):
|
class DoWhileStatement(Statement):
|
||||||
|
@ -374,6 +408,7 @@ class DoWhileStatement(Statement):
|
||||||
super().__init__("DoWhileStatement", loc)
|
super().__init__("DoWhileStatement", loc)
|
||||||
self.body = body
|
self.body = body
|
||||||
self.test = test
|
self.test = test
|
||||||
|
self._fields.update({"body": self.body, "test": self.test})
|
||||||
|
|
||||||
|
|
||||||
class ForStatement(Statement):
|
class ForStatement(Statement):
|
||||||
|
@ -392,6 +427,14 @@ class ForStatement(Statement):
|
||||||
self.test = test
|
self.test = test
|
||||||
self.update = update
|
self.update = update
|
||||||
self.body = body
|
self.body = body
|
||||||
|
self._fields.update(
|
||||||
|
{
|
||||||
|
"init": self.init,
|
||||||
|
"test": self.test,
|
||||||
|
"update": self.update,
|
||||||
|
"body": self.body,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class ForInStatement(Statement):
|
class ForInStatement(Statement):
|
||||||
|
@ -408,6 +451,7 @@ class ForInStatement(Statement):
|
||||||
self.left = left
|
self.left = left
|
||||||
self.right = right
|
self.right = right
|
||||||
self.body = body
|
self.body = body
|
||||||
|
self._fields.update({"left": self.left, "right": self.right, "body": self.body})
|
||||||
|
|
||||||
|
|
||||||
# "Declarations" block
|
# "Declarations" block
|
||||||
|
@ -438,11 +482,12 @@ class VariableDeclarator(Node):
|
||||||
"""A variable declarator."""
|
"""A variable declarator."""
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self, loc: Optional[SourceLocation], var_id: Pattern, init: Optional[Exception]
|
self, loc: Optional[SourceLocation], var_id: Pattern, init: Optional[Expression]
|
||||||
):
|
):
|
||||||
super().__init__("VariableDeclarator", loc)
|
super().__init__("VariableDeclarator", loc)
|
||||||
self.id = var_id
|
self.id = var_id
|
||||||
self.init = init
|
self.init = init
|
||||||
|
self._fields.update({"id": self.id, "init": self.init})
|
||||||
|
|
||||||
|
|
||||||
class VariableDeclaration(Declaration):
|
class VariableDeclaration(Declaration):
|
||||||
|
@ -457,6 +502,7 @@ class VariableDeclaration(Declaration):
|
||||||
super().__init__("VariableDeclaration", loc)
|
super().__init__("VariableDeclaration", loc)
|
||||||
self.declarations = declarations
|
self.declarations = declarations
|
||||||
self.kind = kind
|
self.kind = kind
|
||||||
|
self._fields.update({"kind": self.kind, "declarations": self.declarations})
|
||||||
|
|
||||||
|
|
||||||
# "Expressions" block
|
# "Expressions" block
|
||||||
|
@ -487,6 +533,7 @@ class SpreadElement(Node):
|
||||||
def __init__(self, loc: Optional[SourceLocation], argument: Expression):
|
def __init__(self, loc: Optional[SourceLocation], argument: Expression):
|
||||||
super().__init__("SpreadElement", loc)
|
super().__init__("SpreadElement", loc)
|
||||||
self.argument = argument
|
self.argument = argument
|
||||||
|
self._fields.update({"argument": self.argument})
|
||||||
|
|
||||||
|
|
||||||
class ThisExpression(Expression):
|
class ThisExpression(Expression):
|
||||||
|
@ -506,6 +553,7 @@ class ArrayExpression(Expression):
|
||||||
):
|
):
|
||||||
super().__init__("ArrayExpression", loc)
|
super().__init__("ArrayExpression", loc)
|
||||||
self.elements = elements
|
self.elements = elements
|
||||||
|
self._fields.update({"elements": self.elements})
|
||||||
|
|
||||||
|
|
||||||
class ObjectExpression(Expression):
|
class ObjectExpression(Expression):
|
||||||
|
@ -514,6 +562,7 @@ class ObjectExpression(Expression):
|
||||||
def __init__(self, loc: Optional[SourceLocation], properties: List[Property]):
|
def __init__(self, loc: Optional[SourceLocation], properties: List[Property]):
|
||||||
super().__init__("ObjectExpression", loc)
|
super().__init__("ObjectExpression", loc)
|
||||||
self.properties = properties
|
self.properties = properties
|
||||||
|
self._fields.update({"properties": self.properties})
|
||||||
|
|
||||||
|
|
||||||
class FunctionExpression(Function, Expression):
|
class FunctionExpression(Function, Expression):
|
||||||
|
@ -541,6 +590,7 @@ class ArrowFunctionExpression(Function, Expression):
|
||||||
):
|
):
|
||||||
super().__init__("ArrowFunctionExpression", loc, None, params, body)
|
super().__init__("ArrowFunctionExpression", loc, None, params, body)
|
||||||
self.expression = expression
|
self.expression = expression
|
||||||
|
self._fields.update({"expression": self.expression})
|
||||||
|
|
||||||
|
|
||||||
class UnaryExpression(Expression):
|
class UnaryExpression(Expression):
|
||||||
|
@ -557,6 +607,13 @@ class UnaryExpression(Expression):
|
||||||
self.operator = operator
|
self.operator = operator
|
||||||
self.prefix = prefix
|
self.prefix = prefix
|
||||||
self.argument = argument
|
self.argument = argument
|
||||||
|
self._fields.update(
|
||||||
|
{
|
||||||
|
"operator": self.operator,
|
||||||
|
"prefix": self.prefix,
|
||||||
|
"argument": self.argument,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class UpdateExpression(Expression):
|
class UpdateExpression(Expression):
|
||||||
|
@ -573,6 +630,13 @@ class UpdateExpression(Expression):
|
||||||
self.operator = operator
|
self.operator = operator
|
||||||
self.argument = argument
|
self.argument = argument
|
||||||
self.prefix = prefix
|
self.prefix = prefix
|
||||||
|
self._fields.update(
|
||||||
|
{
|
||||||
|
"operator": self.operator,
|
||||||
|
"argument": self.argument,
|
||||||
|
"prefix": self.prefix,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class BinaryExpression(Expression):
|
class BinaryExpression(Expression):
|
||||||
|
@ -589,6 +653,9 @@ class BinaryExpression(Expression):
|
||||||
self.operator = operator
|
self.operator = operator
|
||||||
self.left = left
|
self.left = left
|
||||||
self.right = right
|
self.right = right
|
||||||
|
self._fields.update(
|
||||||
|
{"operator": self.operator, "left": self.left, "right": self.right}
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class AssignmentExpression(Expression):
|
class AssignmentExpression(Expression):
|
||||||
|
@ -607,6 +674,9 @@ class AssignmentExpression(Expression):
|
||||||
self.operator = operator
|
self.operator = operator
|
||||||
self.left = left
|
self.left = left
|
||||||
self.right = right
|
self.right = right
|
||||||
|
self._fields.update(
|
||||||
|
{"operator": self.operator, "left": self.left, "right": self.right}
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class LogicalExpression(Expression):
|
class LogicalExpression(Expression):
|
||||||
|
@ -623,6 +693,9 @@ class LogicalExpression(Expression):
|
||||||
self.operator = operator
|
self.operator = operator
|
||||||
self.left = left
|
self.left = left
|
||||||
self.right = right
|
self.right = right
|
||||||
|
self._fields.update(
|
||||||
|
{"operator": self.operator, "left": self.left, "right": self.right}
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class MemberExpression(Expression, Pattern):
|
class MemberExpression(Expression, Pattern):
|
||||||
|
@ -641,6 +714,13 @@ class MemberExpression(Expression, Pattern):
|
||||||
self.object = member_object
|
self.object = member_object
|
||||||
self.property = member_property
|
self.property = member_property
|
||||||
self.computed = computed
|
self.computed = computed
|
||||||
|
self._fields.update(
|
||||||
|
{
|
||||||
|
"object": self.object,
|
||||||
|
"property": self.property,
|
||||||
|
"computed": self.computed,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class ConditionalExpression(Expression):
|
class ConditionalExpression(Expression):
|
||||||
|
@ -657,6 +737,13 @@ class ConditionalExpression(Expression):
|
||||||
self.test = test
|
self.test = test
|
||||||
self.alternate = alternate
|
self.alternate = alternate
|
||||||
self.consequent = consequent
|
self.consequent = consequent
|
||||||
|
self._fields.update(
|
||||||
|
{
|
||||||
|
"test": self.test,
|
||||||
|
"alternate": self.alternate,
|
||||||
|
"consequent": self.consequent,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class CallExpression(Expression):
|
class CallExpression(Expression):
|
||||||
|
@ -671,6 +758,7 @@ class CallExpression(Expression):
|
||||||
super().__init__("CallExpression", loc)
|
super().__init__("CallExpression", loc)
|
||||||
self.callee = callee
|
self.callee = callee
|
||||||
self.arguments = arguments
|
self.arguments = arguments
|
||||||
|
self._fields.update({"callee": self.callee, "arguments": self.arguments})
|
||||||
|
|
||||||
|
|
||||||
class NewExpression(Expression):
|
class NewExpression(Expression):
|
||||||
|
@ -685,6 +773,7 @@ class NewExpression(Expression):
|
||||||
super().__init__("NewExpression", loc)
|
super().__init__("NewExpression", loc)
|
||||||
self.callee = callee
|
self.callee = callee
|
||||||
self.arguments = arguments
|
self.arguments = arguments
|
||||||
|
self._fields.update({"callee": self.callee, "arguments": self.arguments})
|
||||||
|
|
||||||
|
|
||||||
class SequenceExpression(Expression):
|
class SequenceExpression(Expression):
|
||||||
|
@ -693,6 +782,7 @@ class SequenceExpression(Expression):
|
||||||
def __init__(self, loc: Optional[SourceLocation], expressions: List[Expression]):
|
def __init__(self, loc: Optional[SourceLocation], expressions: List[Expression]):
|
||||||
super().__init__("SequenceExpression", loc)
|
super().__init__("SequenceExpression", loc)
|
||||||
self.expressions = expressions
|
self.expressions = expressions
|
||||||
|
self._fields.update({"expressions": self.expressions})
|
||||||
|
|
||||||
|
|
||||||
def _generate_unary_expression(operator: UnaryOperator, docstring: str):
|
def _generate_unary_expression(operator: UnaryOperator, docstring: str):
|
||||||
|
@ -940,6 +1030,16 @@ class Property(Node):
|
||||||
self.method = method
|
self.method = method
|
||||||
self.shorthand = shorthand
|
self.shorthand = shorthand
|
||||||
self.computed = computed
|
self.computed = computed
|
||||||
|
self._fields.update(
|
||||||
|
{
|
||||||
|
"key": self.key,
|
||||||
|
"value": self.value,
|
||||||
|
"kind": self.kind,
|
||||||
|
"method": self.method,
|
||||||
|
"shorthand": self.shorthand,
|
||||||
|
"computed": self.computed,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class AssignmentProperty(Property):
|
class AssignmentProperty(Property):
|
||||||
|
@ -978,6 +1078,7 @@ class ObjectPattern(Pattern):
|
||||||
):
|
):
|
||||||
super().__init__("ObjectPattern", loc)
|
super().__init__("ObjectPattern", loc)
|
||||||
self.properties = properties
|
self.properties = properties
|
||||||
|
self._fields.update({"properties": self.properties})
|
||||||
|
|
||||||
|
|
||||||
class ArrayPattern(Pattern):
|
class ArrayPattern(Pattern):
|
||||||
|
@ -986,3 +1087,15 @@ class ArrayPattern(Pattern):
|
||||||
):
|
):
|
||||||
super().__init__("ArrayPattern", loc)
|
super().__init__("ArrayPattern", loc)
|
||||||
self.elements = elements
|
self.elements = elements
|
||||||
|
self._fields.update({"elements": self.elements})
|
||||||
|
|
||||||
|
|
||||||
|
# "Identifier" block
|
||||||
|
|
||||||
|
|
||||||
|
class Identifier(Expression, Pattern):
|
||||||
|
"""An identifier. Note that an identifier may be an expression or a destructuring pattern."""
|
||||||
|
|
||||||
|
def __init__(self, loc: Optional[SourceLocation], name: str):
|
||||||
|
super().__init__("Identifier", loc)
|
||||||
|
self.name = name
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import logging
|
import logging
|
||||||
from typing import Optional, List
|
from typing import Optional, List, Union
|
||||||
import antlr4.ParserRuleContext
|
import antlr4.ParserRuleContext
|
||||||
|
|
||||||
from lex.JavaScriptParser import JavaScriptParser
|
from lex.JavaScriptParser import JavaScriptParser
|
||||||
|
@ -23,6 +23,52 @@ def _get_source_location(
|
||||||
return ast.nodes.SourceLocation(source=source, start=start_pos, end=end_pos)
|
return ast.nodes.SourceLocation(source=source, start=start_pos, end=end_pos)
|
||||||
|
|
||||||
|
|
||||||
|
class AssignableListener(JSBaseListener):
|
||||||
|
_result: Union[
|
||||||
|
ast.nodes.Identifier, ast.nodes.ObjectPattern, ast.nodes.ArrayPattern
|
||||||
|
]
|
||||||
|
|
||||||
|
@property
|
||||||
|
def result(self):
|
||||||
|
return self._result
|
||||||
|
|
||||||
|
def enterAssignable(self, ctx: JavaScriptParser.AssignableContext):
|
||||||
|
logging.debug("Entered section Assignable")
|
||||||
|
ctx.getChild(0).enterRule(self)
|
||||||
|
|
||||||
|
def enterIdentifier(self, ctx: JavaScriptParser.IdentifierContext):
|
||||||
|
logging.debug("Entered section Identifier")
|
||||||
|
loc = _get_source_location(ctx, None)
|
||||||
|
self._result = ast.nodes.Identifier(loc, ctx.getText())
|
||||||
|
|
||||||
|
def enterArrayLiteral(self, ctx: JavaScriptParser.ArrayLiteralContext):
|
||||||
|
logging.debug("Entered section ArrayLiteral")
|
||||||
|
pass # TODO
|
||||||
|
|
||||||
|
def enterObjectLiteral(self, ctx: JavaScriptParser.ObjectLiteralContext):
|
||||||
|
logging.debug("Entered section ObjectLiteral")
|
||||||
|
pass # TODO
|
||||||
|
|
||||||
|
|
||||||
|
class VariableDeclarationListener(JSBaseListener):
|
||||||
|
_var_decl: ast.nodes.VariableDeclarator
|
||||||
|
|
||||||
|
@property
|
||||||
|
def var_declarator(self):
|
||||||
|
return self._var_decl
|
||||||
|
|
||||||
|
def enterVariableDeclaration(
|
||||||
|
self, ctx: JavaScriptParser.VariableDeclarationContext
|
||||||
|
):
|
||||||
|
loc = _get_source_location(ctx, None)
|
||||||
|
assign_listener = AssignableListener()
|
||||||
|
ctx.assignable().enterRule(assign_listener)
|
||||||
|
# ctx.singleExpression().enterRule(expression_listener) # FIXME No ExpressionListener yet
|
||||||
|
self._var_decl = ast.nodes.VariableDeclarator(
|
||||||
|
loc, assign_listener.result, None
|
||||||
|
) # FIXME
|
||||||
|
|
||||||
|
|
||||||
class StatementListener(JSBaseListener):
|
class StatementListener(JSBaseListener):
|
||||||
_stmt: ast.nodes.Statement
|
_stmt: ast.nodes.Statement
|
||||||
|
|
||||||
|
@ -50,12 +96,26 @@ class StatementListener(JSBaseListener):
|
||||||
loc = _get_source_location(ctx, None) # FIXME source param is None
|
loc = _get_source_location(ctx, None) # FIXME source param is None
|
||||||
self._stmt = ast.nodes.BlockStatement(loc, stmt_list)
|
self._stmt = ast.nodes.BlockStatement(loc, stmt_list)
|
||||||
|
|
||||||
|
def enterVariableStatement(self, ctx: JavaScriptParser.VariableStatementContext):
|
||||||
|
logging.debug("Entered section VariableStatement")
|
||||||
|
ctx.variableDeclarationList().enterRule(self)
|
||||||
|
|
||||||
def enterVariableDeclarationList(
|
def enterVariableDeclarationList(
|
||||||
self, ctx: JavaScriptParser.VariableDeclarationListContext
|
self, ctx: JavaScriptParser.VariableDeclarationListContext
|
||||||
):
|
):
|
||||||
"""Listener for VariableDeclaration."""
|
"""Listener for VariableDeclaration."""
|
||||||
logging.debug("Entered section VariableDeclaration")
|
logging.debug("Entered section VariableDeclaration")
|
||||||
pass
|
|
||||||
|
var_modifier: ast.nodes.VarDeclKind = ctx.varModifier().getText()
|
||||||
|
var_decls: List[ast.nodes.VariableDeclarator] = []
|
||||||
|
|
||||||
|
for var_decl in ctx.variableDeclaration():
|
||||||
|
var_decl_listener = VariableDeclarationListener()
|
||||||
|
var_decl.enterRule(var_decl_listener)
|
||||||
|
var_decls.append(var_decl_listener.var_declarator)
|
||||||
|
|
||||||
|
loc = _get_source_location(ctx, None)
|
||||||
|
self._stmt = ast.nodes.VariableDeclaration(loc, var_modifier, var_decls)
|
||||||
|
|
||||||
def enterEmptyStatement(self, ctx: JavaScriptParser.EmptyStatementContext):
|
def enterEmptyStatement(self, ctx: JavaScriptParser.EmptyStatementContext):
|
||||||
"""Listener for EmptyStatement."""
|
"""Listener for EmptyStatement."""
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
antlr4-python3-runtime==4.8
|
antlr4-python3-runtime==4.8
|
||||||
colorama==0.4.3
|
colorama==0.4.3
|
||||||
coloredlogs==14.0
|
coloredlogs==14.0
|
||||||
tree_format==0.1.2
|
|
Loading…
Reference in New Issue