Apply pedantic
This commit is contained in:
parent
e7df87d0c2
commit
3d5ac69ab2
26 changed files with 222 additions and 213 deletions
|
@ -33,9 +33,9 @@ void myFunction() {
|
||||||
</html>
|
</html>
|
||||||
''';
|
''';
|
||||||
|
|
||||||
var buf = new CodeBuffer();
|
var buf = CodeBuffer();
|
||||||
var document = jael.parseDocument(template, sourceUrl: 'test.jael', asDSX: false);
|
var document = jael.parseDocument(template, sourceUrl: 'test.jael', asDSX: false);
|
||||||
var scope = new SymbolTable(values: {
|
var scope = SymbolTable(values: {
|
||||||
'profile': {
|
'profile': {
|
||||||
'avatar': 'thosakwe.png',
|
'avatar': 'thosakwe.png',
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,7 @@ import 'package:symbol_table/symbol_table.dart';
|
||||||
|
|
||||||
main() {
|
main() {
|
||||||
while (true) {
|
while (true) {
|
||||||
var buf = new StringBuffer();
|
var buf = StringBuffer();
|
||||||
int ch;
|
int ch;
|
||||||
print('Enter lines of Jael text, terminated by CTRL^D.');
|
print('Enter lines of Jael text, terminated by CTRL^D.');
|
||||||
print('All environment variables are injected into the template scope.');
|
print('All environment variables are injected into the template scope.');
|
||||||
|
@ -24,11 +24,11 @@ main() {
|
||||||
if (document == null) {
|
if (document == null) {
|
||||||
stderr.writeln('Could not parse the given text.');
|
stderr.writeln('Could not parse the given text.');
|
||||||
} else {
|
} else {
|
||||||
var output = new CodeBuffer();
|
var output = CodeBuffer();
|
||||||
const jael.Renderer().render(
|
const jael.Renderer().render(
|
||||||
document,
|
document,
|
||||||
output,
|
output,
|
||||||
new SymbolTable(values: Platform.environment),
|
SymbolTable(values: Platform.environment),
|
||||||
strictResolution: false,
|
strictResolution: false,
|
||||||
);
|
);
|
||||||
print('GENERATED HTML:\n$output');
|
print('GENERATED HTML:\n$output');
|
||||||
|
|
|
@ -37,7 +37,7 @@ class BinaryExpression extends Expression {
|
||||||
case TokenType.elvis:
|
case TokenType.elvis:
|
||||||
return l ?? r;
|
return l ?? r;
|
||||||
default:
|
default:
|
||||||
throw new UnsupportedError(
|
throw UnsupportedError(
|
||||||
'Unsupported binary operator: "${operator?.span?.text ?? "<null>"}".');
|
'Unsupported binary operator: "${operator?.span?.text ?? "<null>"}".');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,7 +28,7 @@ class Call extends Expression {
|
||||||
|
|
||||||
Map<Symbol, dynamic> computeNamed(SymbolTable scope) {
|
Map<Symbol, dynamic> computeNamed(SymbolTable scope) {
|
||||||
return namedArguments.fold<Map<Symbol, dynamic>>({}, (out, a) {
|
return namedArguments.fold<Map<Symbol, dynamic>>({}, (out, a) {
|
||||||
return out..[new Symbol(a.name.name)] = a.value.compute(scope);
|
return out..[Symbol(a.name.name)] = a.value.compute(scope);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -46,8 +46,9 @@ class Doctype extends AstNode {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
FileSpan get span {
|
FileSpan get span {
|
||||||
if (public == null)
|
if (public == null) {
|
||||||
return lt.span.expand(doctype.span).expand(html.span).expand(gt.span);
|
return lt.span.expand(doctype.span).expand(html.span).expand(gt.span);
|
||||||
|
}
|
||||||
return lt.span
|
return lt.span
|
||||||
.expand(doctype.span)
|
.expand(doctype.span)
|
||||||
.expand(html.span)
|
.expand(html.span)
|
||||||
|
|
|
@ -16,7 +16,7 @@ class TextNode extends ElementChild {
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract class Element extends ElementChild {
|
abstract class Element extends ElementChild {
|
||||||
static const List<String> selfClosing = const [
|
static const List<String> selfClosing = [
|
||||||
'include',
|
'include',
|
||||||
'base',
|
'base',
|
||||||
'basefont',
|
'basefont',
|
||||||
|
|
|
@ -21,8 +21,7 @@ class Identifier extends Expression {
|
||||||
var symbol = scope.resolve(name);
|
var symbol = scope.resolve(name);
|
||||||
if (symbol == null) {
|
if (symbol == null) {
|
||||||
if (scope.resolve('!strict!')?.value == false) return null;
|
if (scope.resolve('!strict!')?.value == false) return null;
|
||||||
throw new ArgumentError(
|
throw ArgumentError('The name "$name" does not exist in this scope.');
|
||||||
'The name "$name" does not exist in this scope.');
|
|
||||||
}
|
}
|
||||||
return scope.resolve(name).value;
|
return scope.resolve(name).value;
|
||||||
}
|
}
|
||||||
|
@ -43,6 +42,6 @@ class SyntheticIdentifier extends Identifier {
|
||||||
@override
|
@override
|
||||||
FileSpan get span {
|
FileSpan get span {
|
||||||
if (id != null) return id.span;
|
if (id != null) return id.span;
|
||||||
throw new UnsupportedError('Cannot get the span of a SyntheticIdentifier.');
|
throw UnsupportedError('Cannot get the span of a SyntheticIdentifier.');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,7 @@ class MemberExpression extends Expression {
|
||||||
compute(SymbolTable scope) {
|
compute(SymbolTable scope) {
|
||||||
var target = expression.compute(scope);
|
var target = expression.compute(scope);
|
||||||
if (op.span.text == '?.' && target == null) return null;
|
if (op.span.text == '?.' && target == null) return null;
|
||||||
return reflect(target).getField(new Symbol(name.name)).reflectee;
|
return reflect(target).getField(Symbol(name.name)).reflectee;
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
|
|
@ -21,11 +21,12 @@ class NewExpression extends Expression {
|
||||||
var named = call.computeNamed(scope);
|
var named = call.computeNamed(scope);
|
||||||
var name = '';
|
var name = '';
|
||||||
|
|
||||||
if (call.target is MemberExpression)
|
if (call.target is MemberExpression) {
|
||||||
name = (call.target as MemberExpression).name.name;
|
name = (call.target as MemberExpression).name.name;
|
||||||
|
}
|
||||||
|
|
||||||
return reflectClass(targetType as Type)
|
return reflectClass(targetType as Type)
|
||||||
.newInstance(new Symbol(name), positional, named)
|
.newInstance(Symbol(name), positional, named)
|
||||||
.reflectee;
|
.reflectee;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,7 +14,7 @@ class StringLiteral extends Literal {
|
||||||
static String parseValue(Token string) {
|
static String parseValue(Token string) {
|
||||||
var text = string.span.text.substring(1, string.span.text.length - 1);
|
var text = string.span.text.substring(1, string.span.text.length - 1);
|
||||||
var codeUnits = text.codeUnits;
|
var codeUnits = text.codeUnits;
|
||||||
var buf = new StringBuffer();
|
var buf = StringBuffer();
|
||||||
|
|
||||||
for (int i = 0; i < codeUnits.length; i++) {
|
for (int i = 0; i < codeUnits.length; i++) {
|
||||||
var ch = codeUnits[i];
|
var ch = codeUnits[i];
|
||||||
|
@ -25,9 +25,9 @@ class StringLiteral extends Literal {
|
||||||
c2 = codeUnits[++i],
|
c2 = codeUnits[++i],
|
||||||
c3 = codeUnits[++i],
|
c3 = codeUnits[++i],
|
||||||
c4 = codeUnits[++i];
|
c4 = codeUnits[++i];
|
||||||
var hexString = new String.fromCharCodes([c1, c2, c3, c4]);
|
var hexString = String.fromCharCodes([c1, c2, c3, c4]);
|
||||||
var hexNumber = int.parse(hexString, radix: 16);
|
var hexNumber = int.parse(hexString, radix: 16);
|
||||||
buf.write(new String.fromCharCode(hexNumber));
|
buf.write(String.fromCharCode(hexNumber));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -53,9 +53,10 @@ class StringLiteral extends Literal {
|
||||||
default:
|
default:
|
||||||
buf.writeCharCode(next);
|
buf.writeCharCode(next);
|
||||||
}
|
}
|
||||||
} else
|
} else {
|
||||||
throw new JaelError(JaelErrorSeverity.error,
|
throw JaelError(JaelErrorSeverity.error,
|
||||||
'Unexpected "\\" in string literal.', string.span);
|
'Unexpected "\\" in string literal.', string.span);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
buf.writeCharCode(ch);
|
buf.writeCharCode(ch);
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,12 +5,12 @@ class JaelFormatter {
|
||||||
final num tabSize;
|
final num tabSize;
|
||||||
final bool insertSpaces;
|
final bool insertSpaces;
|
||||||
final int maxLineLength;
|
final int maxLineLength;
|
||||||
var _buffer = new StringBuffer();
|
var _buffer = StringBuffer();
|
||||||
int _level = 0;
|
int _level = 0;
|
||||||
String _spaces;
|
String _spaces;
|
||||||
|
|
||||||
static String _spaceString(int tabSize) {
|
static String _spaceString(int tabSize) {
|
||||||
var b = new StringBuffer();
|
var b = StringBuffer();
|
||||||
for (int i = 0; i < tabSize; i++) {
|
for (int i = 0; i < tabSize; i++) {
|
||||||
b.write(' ');
|
b.write(' ');
|
||||||
}
|
}
|
||||||
|
@ -30,7 +30,9 @@ class JaelFormatter {
|
||||||
}
|
}
|
||||||
|
|
||||||
void _applySpacing() {
|
void _applySpacing() {
|
||||||
for (int i = 0; i < _level; i++) _buffer.write(_spaces);
|
for (int i = 0; i < _level; i++) {
|
||||||
|
_buffer.write(_spaces);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int get _spaceLength {
|
int get _spaceLength {
|
||||||
|
@ -62,9 +64,9 @@ class JaelFormatter {
|
||||||
|
|
||||||
int _formatChild(ElementChild child, int lineLength,
|
int _formatChild(ElementChild child, int lineLength,
|
||||||
{bool isFirst = false, bool isLast = false}) {
|
{bool isFirst = false, bool isLast = false}) {
|
||||||
if (child == null)
|
if (child == null) {
|
||||||
return lineLength;
|
return lineLength;
|
||||||
else if (child is Element) return _formatElement(child, lineLength);
|
} else if (child is Element) return _formatElement(child, lineLength);
|
||||||
String s;
|
String s;
|
||||||
if (child is Interpolation) {
|
if (child is Interpolation) {
|
||||||
var b = StringBuffer('{{');
|
var b = StringBuffer('{{');
|
||||||
|
|
|
@ -7,21 +7,21 @@ import 'text/scanner.dart';
|
||||||
|
|
||||||
/// Parses a Jael document.
|
/// Parses a Jael document.
|
||||||
Document parseDocument(String text,
|
Document parseDocument(String text,
|
||||||
{sourceUrl, bool asDSX: false, void onError(JaelError error)}) {
|
{sourceUrl, bool asDSX = false, void onError(JaelError error)}) {
|
||||||
var scanner = scan(text, sourceUrl: sourceUrl, asDSX: asDSX);
|
var scanner = scan(text, sourceUrl: sourceUrl, asDSX: asDSX);
|
||||||
|
|
||||||
//scanner.tokens.forEach(print);
|
//scanner.tokens.forEach(print);
|
||||||
|
|
||||||
if (scanner.errors.isNotEmpty && onError != null)
|
if (scanner.errors.isNotEmpty && onError != null) {
|
||||||
scanner.errors.forEach(onError);
|
scanner.errors.forEach(onError);
|
||||||
else if (scanner.errors.isNotEmpty) throw scanner.errors.first;
|
} else if (scanner.errors.isNotEmpty) throw scanner.errors.first;
|
||||||
|
|
||||||
var parser = new Parser(scanner, asDSX: asDSX);
|
var parser = Parser(scanner, asDSX: asDSX);
|
||||||
var doc = parser.parseDocument();
|
var doc = parser.parseDocument();
|
||||||
|
|
||||||
if (parser.errors.isNotEmpty && onError != null)
|
if (parser.errors.isNotEmpty && onError != null) {
|
||||||
parser.errors.forEach(onError);
|
parser.errors.forEach(onError);
|
||||||
else if (parser.errors.isNotEmpty) throw parser.errors.first;
|
} else if (parser.errors.isNotEmpty) throw parser.errors.first;
|
||||||
|
|
||||||
return doc;
|
return doc;
|
||||||
}
|
}
|
||||||
|
@ -80,7 +80,7 @@ class Renderer {
|
||||||
/// If [strictResolution] is `false` (default: `true`), then undefined identifiers will return `null`
|
/// If [strictResolution] is `false` (default: `true`), then undefined identifiers will return `null`
|
||||||
/// instead of throwing.
|
/// instead of throwing.
|
||||||
void render(Document document, CodeBuffer buffer, SymbolTable scope,
|
void render(Document document, CodeBuffer buffer, SymbolTable scope,
|
||||||
{bool strictResolution: true}) {
|
{bool strictResolution = true}) {
|
||||||
scope.create('!strict!', value: strictResolution != false);
|
scope.create('!strict!', value: strictResolution != false);
|
||||||
|
|
||||||
if (document.doctype != null) buffer.writeln(document.doctype.span.text);
|
if (document.doctype != null) buffer.writeln(document.doctype.span.text);
|
||||||
|
@ -126,17 +126,18 @@ class Renderer {
|
||||||
|
|
||||||
buffer.write(' ${attribute.name}');
|
buffer.write(' ${attribute.name}');
|
||||||
|
|
||||||
if (value == true)
|
if (value == true) {
|
||||||
continue;
|
continue;
|
||||||
else
|
} else {
|
||||||
buffer.write('="');
|
buffer.write('="');
|
||||||
|
}
|
||||||
|
|
||||||
String msg;
|
String msg;
|
||||||
|
|
||||||
if (value is Iterable) {
|
if (value is Iterable) {
|
||||||
msg = value.join(' ');
|
msg = value.join(' ');
|
||||||
} else if (value is Map) {
|
} else if (value is Map) {
|
||||||
msg = value.keys.fold<StringBuffer>(new StringBuffer(), (buf, k) {
|
msg = value.keys.fold<StringBuffer>(StringBuffer(), (buf, k) {
|
||||||
var v = value[k];
|
var v = value[k];
|
||||||
if (v == null) return buf;
|
if (v == null) return buf;
|
||||||
return buf..write('$k: $v;');
|
return buf..write('$k: $v;');
|
||||||
|
@ -150,10 +151,11 @@ class Renderer {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (element is SelfClosingElement) {
|
if (element is SelfClosingElement) {
|
||||||
if (html5)
|
if (html5) {
|
||||||
buffer.writeln('>');
|
buffer.writeln('>');
|
||||||
else
|
} else {
|
||||||
buffer.writeln('/>');
|
buffer.writeln('/>');
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
buffer.writeln('>');
|
buffer.writeln('>');
|
||||||
buffer.indent();
|
buffer.indent();
|
||||||
|
@ -185,11 +187,11 @@ class Renderer {
|
||||||
(a) => a.name != 'for-each' && a.name != 'as' && a.name != 'index-as');
|
(a) => a.name != 'for-each' && a.name != 'as' && a.name != 'index-as');
|
||||||
Element strippedElement;
|
Element strippedElement;
|
||||||
|
|
||||||
if (element is SelfClosingElement)
|
if (element is SelfClosingElement) {
|
||||||
strippedElement = new SelfClosingElement(element.lt, element.tagName,
|
strippedElement = SelfClosingElement(element.lt, element.tagName,
|
||||||
otherAttributes, element.slash, element.gt);
|
otherAttributes, element.slash, element.gt);
|
||||||
else if (element is RegularElement)
|
} else if (element is RegularElement) {
|
||||||
strippedElement = new RegularElement(
|
strippedElement = RegularElement(
|
||||||
element.lt,
|
element.lt,
|
||||||
element.tagName,
|
element.tagName,
|
||||||
otherAttributes,
|
otherAttributes,
|
||||||
|
@ -199,6 +201,7 @@ class Renderer {
|
||||||
element.slash,
|
element.slash,
|
||||||
element.tagName2,
|
element.tagName2,
|
||||||
element.gt2);
|
element.gt2);
|
||||||
|
}
|
||||||
|
|
||||||
int i = 0;
|
int i = 0;
|
||||||
for (var item in attribute.value.compute(scope)) {
|
for (var item in attribute.value.compute(scope)) {
|
||||||
|
@ -224,11 +227,11 @@ class Renderer {
|
||||||
var otherAttributes = element.attributes.where((a) => a.name != 'if');
|
var otherAttributes = element.attributes.where((a) => a.name != 'if');
|
||||||
Element strippedElement;
|
Element strippedElement;
|
||||||
|
|
||||||
if (element is SelfClosingElement)
|
if (element is SelfClosingElement) {
|
||||||
strippedElement = new SelfClosingElement(element.lt, element.tagName,
|
strippedElement = SelfClosingElement(element.lt, element.tagName,
|
||||||
otherAttributes, element.slash, element.gt);
|
otherAttributes, element.slash, element.gt);
|
||||||
else if (element is RegularElement)
|
} else if (element is RegularElement) {
|
||||||
strippedElement = new RegularElement(
|
strippedElement = RegularElement(
|
||||||
element.lt,
|
element.lt,
|
||||||
element.tagName,
|
element.tagName,
|
||||||
otherAttributes,
|
otherAttributes,
|
||||||
|
@ -238,6 +241,7 @@ class Renderer {
|
||||||
element.slash,
|
element.slash,
|
||||||
element.tagName2,
|
element.tagName2,
|
||||||
element.gt2);
|
element.gt2);
|
||||||
|
}
|
||||||
|
|
||||||
renderElement(strippedElement, buffer, scope, html5);
|
renderElement(strippedElement, buffer, scope, html5);
|
||||||
}
|
}
|
||||||
|
@ -298,21 +302,23 @@ class Renderer {
|
||||||
void renderElementChild(Element parent, ElementChild child, CodeBuffer buffer,
|
void renderElementChild(Element parent, ElementChild child, CodeBuffer buffer,
|
||||||
SymbolTable scope, bool html5, int index, int total) {
|
SymbolTable scope, bool html5, int index, int total) {
|
||||||
if (child is Text && parent?.tagName?.name != 'textarea') {
|
if (child is Text && parent?.tagName?.name != 'textarea') {
|
||||||
if (index == 0)
|
if (index == 0) {
|
||||||
buffer.write(child.span.text.trimLeft());
|
buffer.write(child.span.text.trimLeft());
|
||||||
else if (index == total - 1)
|
} else if (index == total - 1) {
|
||||||
buffer.write(child.span.text.trimRight());
|
buffer.write(child.span.text.trimRight());
|
||||||
else
|
} else {
|
||||||
buffer.write(child.span.text);
|
buffer.write(child.span.text);
|
||||||
|
}
|
||||||
} else if (child is Interpolation) {
|
} else if (child is Interpolation) {
|
||||||
var value = child.expression.compute(scope);
|
var value = child.expression.compute(scope);
|
||||||
|
|
||||||
if (value != null) {
|
if (value != null) {
|
||||||
if (child.isRaw)
|
if (child.isRaw) {
|
||||||
buffer.write(value);
|
buffer.write(value);
|
||||||
else
|
} else {
|
||||||
buffer.write(htmlEscape.convert(value.toString()));
|
buffer.write(htmlEscape.convert(value.toString()));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
} else if (child is Element) {
|
} else if (child is Element) {
|
||||||
if (buffer?.lastLine?.text?.isNotEmpty == true) buffer.writeln();
|
if (buffer?.lastLine?.text?.isNotEmpty == true) buffer.writeln();
|
||||||
renderElement(child, buffer, scope, html5);
|
renderElement(child, buffer, scope, html5);
|
||||||
|
@ -324,14 +330,14 @@ class Renderer {
|
||||||
void registerCustomElement(
|
void registerCustomElement(
|
||||||
Element element, CodeBuffer buffer, SymbolTable scope, bool html5) {
|
Element element, CodeBuffer buffer, SymbolTable scope, bool html5) {
|
||||||
if (element is! RegularElement) {
|
if (element is! RegularElement) {
|
||||||
throw new JaelError(JaelErrorSeverity.error,
|
throw JaelError(JaelErrorSeverity.error,
|
||||||
"Custom elements cannot be self-closing.", element.span);
|
"Custom elements cannot be self-closing.", element.span);
|
||||||
}
|
}
|
||||||
|
|
||||||
var name = element.getAttribute('name')?.value?.compute(scope)?.toString();
|
var name = element.getAttribute('name')?.value?.compute(scope)?.toString();
|
||||||
|
|
||||||
if (name == null) {
|
if (name == null) {
|
||||||
throw new JaelError(
|
throw JaelError(
|
||||||
JaelErrorSeverity.error,
|
JaelErrorSeverity.error,
|
||||||
"Attribute 'name' is required when registering a custom element.",
|
"Attribute 'name' is required when registering a custom element.",
|
||||||
element.tagName.span);
|
element.tagName.span);
|
||||||
|
@ -341,7 +347,7 @@ class Renderer {
|
||||||
var p = scope.isRoot ? scope : scope.parent;
|
var p = scope.isRoot ? scope : scope.parent;
|
||||||
p.create(customElementName(name), value: element, constant: true);
|
p.create(customElementName(name), value: element, constant: true);
|
||||||
} on StateError {
|
} on StateError {
|
||||||
throw new JaelError(
|
throw JaelError(
|
||||||
JaelErrorSeverity.error,
|
JaelErrorSeverity.error,
|
||||||
"Cannot re-define element '$name' in this scope.",
|
"Cannot re-define element '$name' in this scope.",
|
||||||
element.getAttribute('name').span);
|
element.getAttribute('name').span);
|
||||||
|
@ -371,16 +377,16 @@ class Renderer {
|
||||||
} else {
|
} else {
|
||||||
var tagName = renderAs?.toString() ?? 'div';
|
var tagName = renderAs?.toString() ?? 'div';
|
||||||
|
|
||||||
var syntheticElement = new RegularElement(
|
var syntheticElement = RegularElement(
|
||||||
template.lt,
|
template.lt,
|
||||||
new SyntheticIdentifier(tagName),
|
SyntheticIdentifier(tagName),
|
||||||
element.attributes
|
element.attributes
|
||||||
.where((a) => a.name != 'as' && !a.name.startsWith('@')),
|
.where((a) => a.name != 'as' && !a.name.startsWith('@')),
|
||||||
template.gt,
|
template.gt,
|
||||||
template.children,
|
template.children,
|
||||||
template.lt2,
|
template.lt2,
|
||||||
template.slash,
|
template.slash,
|
||||||
new SyntheticIdentifier(tagName),
|
SyntheticIdentifier(tagName),
|
||||||
template.gt2);
|
template.gt2);
|
||||||
|
|
||||||
renderElement(syntheticElement, buffer, scope, html5);
|
renderElement(syntheticElement, buffer, scope, html5);
|
||||||
|
|
|
@ -1,24 +1,24 @@
|
||||||
part of jael.src.text.parselet;
|
part of jael.src.text.parselet;
|
||||||
|
|
||||||
const Map<TokenType, InfixParselet> infixParselets = const {
|
const Map<TokenType, InfixParselet> infixParselets = {
|
||||||
TokenType.lParen: const CallParselet(),
|
TokenType.lParen: CallParselet(),
|
||||||
TokenType.elvis_dot: const MemberParselet(),
|
TokenType.elvis_dot: MemberParselet(),
|
||||||
TokenType.dot: const MemberParselet(),
|
TokenType.dot: MemberParselet(),
|
||||||
TokenType.lBracket: const IndexerParselet(),
|
TokenType.lBracket: IndexerParselet(),
|
||||||
TokenType.asterisk: const BinaryParselet(14),
|
TokenType.asterisk: BinaryParselet(14),
|
||||||
TokenType.slash: const BinaryParselet(14),
|
TokenType.slash: BinaryParselet(14),
|
||||||
TokenType.percent: const BinaryParselet(14),
|
TokenType.percent: BinaryParselet(14),
|
||||||
TokenType.plus: const BinaryParselet(13),
|
TokenType.plus: BinaryParselet(13),
|
||||||
TokenType.minus: const BinaryParselet(13),
|
TokenType.minus: BinaryParselet(13),
|
||||||
TokenType.lt: const BinaryParselet(11),
|
TokenType.lt: BinaryParselet(11),
|
||||||
TokenType.lte: const BinaryParselet(11),
|
TokenType.lte: BinaryParselet(11),
|
||||||
TokenType.gt: const BinaryParselet(11),
|
TokenType.gt: BinaryParselet(11),
|
||||||
TokenType.gte: const BinaryParselet(11),
|
TokenType.gte: BinaryParselet(11),
|
||||||
TokenType.equ: const BinaryParselet(10),
|
TokenType.equ: BinaryParselet(10),
|
||||||
TokenType.nequ: const BinaryParselet(10),
|
TokenType.nequ: BinaryParselet(10),
|
||||||
TokenType.question: const ConditionalParselet(),
|
TokenType.question: ConditionalParselet(),
|
||||||
TokenType.equals: const BinaryParselet(3),
|
TokenType.equals: BinaryParselet(3),
|
||||||
TokenType.elvis: const BinaryParselet(3),
|
TokenType.elvis: BinaryParselet(3),
|
||||||
};
|
};
|
||||||
|
|
||||||
class ConditionalParselet implements InfixParselet {
|
class ConditionalParselet implements InfixParselet {
|
||||||
|
@ -32,13 +32,13 @@ class ConditionalParselet implements InfixParselet {
|
||||||
var ifTrue = parser.parseExpression(0);
|
var ifTrue = parser.parseExpression(0);
|
||||||
|
|
||||||
if (ifTrue == null) {
|
if (ifTrue == null) {
|
||||||
parser.errors.add(new JaelError(JaelErrorSeverity.error,
|
parser.errors.add(JaelError(JaelErrorSeverity.error,
|
||||||
'Missing expression in conditional expression.', token.span));
|
'Missing expression in conditional expression.', token.span));
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!parser.next(TokenType.colon)) {
|
if (!parser.next(TokenType.colon)) {
|
||||||
parser.errors.add(new JaelError(JaelErrorSeverity.error,
|
parser.errors.add(JaelError(JaelErrorSeverity.error,
|
||||||
'Missing ":" in conditional expression.', ifTrue.span));
|
'Missing ":" in conditional expression.', ifTrue.span));
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -47,12 +47,12 @@ class ConditionalParselet implements InfixParselet {
|
||||||
var ifFalse = parser.parseExpression(0);
|
var ifFalse = parser.parseExpression(0);
|
||||||
|
|
||||||
if (ifFalse == null) {
|
if (ifFalse == null) {
|
||||||
parser.errors.add(new JaelError(JaelErrorSeverity.error,
|
parser.errors.add(JaelError(JaelErrorSeverity.error,
|
||||||
'Missing expression in conditional expression.', colon.span));
|
'Missing expression in conditional expression.', colon.span));
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return new Conditional(left, token, ifTrue, colon, ifFalse);
|
return Conditional(left, token, ifTrue, colon, ifFalse);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -66,15 +66,16 @@ class BinaryParselet implements InfixParselet {
|
||||||
var right = parser.parseExpression(precedence);
|
var right = parser.parseExpression(precedence);
|
||||||
|
|
||||||
if (right == null) {
|
if (right == null) {
|
||||||
if (token.type != TokenType.gt)
|
if (token.type != TokenType.gt) {
|
||||||
parser.errors.add(new JaelError(
|
parser.errors.add(JaelError(
|
||||||
JaelErrorSeverity.error,
|
JaelErrorSeverity.error,
|
||||||
'Missing expression after operator "${token.span.text}", following expression ${left.span.text}.',
|
'Missing expression after operator "${token.span.text}", following expression ${left.span.text}.',
|
||||||
token.span));
|
token.span));
|
||||||
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return new BinaryExpression(left, token, right);
|
return BinaryExpression(left, token, right);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -109,12 +110,12 @@ class CallParselet implements InfixParselet {
|
||||||
if (!parser.next(TokenType.rParen)) {
|
if (!parser.next(TokenType.rParen)) {
|
||||||
var lastSpan = arguments.isEmpty ? null : arguments.last.span;
|
var lastSpan = arguments.isEmpty ? null : arguments.last.span;
|
||||||
lastSpan ??= token.span;
|
lastSpan ??= token.span;
|
||||||
parser.errors.add(new JaelError(JaelErrorSeverity.error,
|
parser.errors.add(JaelError(JaelErrorSeverity.error,
|
||||||
'Missing ")" after argument list.', lastSpan));
|
'Missing ")" after argument list.', lastSpan));
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return new Call(left, token, parser.current, arguments, namedArguments);
|
return Call(left, token, parser.current, arguments, namedArguments);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -129,18 +130,18 @@ class IndexerParselet implements InfixParselet {
|
||||||
var indexer = parser.parseExpression(0);
|
var indexer = parser.parseExpression(0);
|
||||||
|
|
||||||
if (indexer == null) {
|
if (indexer == null) {
|
||||||
parser.errors.add(new JaelError(
|
parser.errors.add(JaelError(
|
||||||
JaelErrorSeverity.error, 'Missing expression after "[".', left.span));
|
JaelErrorSeverity.error, 'Missing expression after "[".', left.span));
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!parser.next(TokenType.rBracket)) {
|
if (!parser.next(TokenType.rBracket)) {
|
||||||
parser.errors.add(
|
parser.errors.add(
|
||||||
new JaelError(JaelErrorSeverity.error, 'Missing "]".', indexer.span));
|
JaelError(JaelErrorSeverity.error, 'Missing "]".', indexer.span));
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return new IndexerExpression(left, token, indexer, parser.current);
|
return IndexerExpression(left, token, indexer, parser.current);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -155,11 +156,11 @@ class MemberParselet implements InfixParselet {
|
||||||
var name = parser.parseIdentifier();
|
var name = parser.parseIdentifier();
|
||||||
|
|
||||||
if (name == null) {
|
if (name == null) {
|
||||||
parser.errors.add(new JaelError(JaelErrorSeverity.error,
|
parser.errors.add(JaelError(JaelErrorSeverity.error,
|
||||||
'Expected the name of a property following "."', token.span));
|
'Expected the name of a property following "."', token.span));
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return new MemberExpression(left, token, name);
|
return MemberExpression(left, token, name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,15 +1,15 @@
|
||||||
part of jael.src.text.parselet;
|
part of jael.src.text.parselet;
|
||||||
|
|
||||||
const Map<TokenType, PrefixParselet> prefixParselets = const {
|
const Map<TokenType, PrefixParselet> prefixParselets = {
|
||||||
TokenType.exclamation: const NotParselet(),
|
TokenType.exclamation: NotParselet(),
|
||||||
TokenType.$new: const NewParselet(),
|
TokenType.$new: NewParselet(),
|
||||||
TokenType.number: const NumberParselet(),
|
TokenType.number: NumberParselet(),
|
||||||
TokenType.hex: const HexParselet(),
|
TokenType.hex: HexParselet(),
|
||||||
TokenType.string: const StringParselet(),
|
TokenType.string: StringParselet(),
|
||||||
TokenType.lCurly: const MapParselet(),
|
TokenType.lCurly: MapParselet(),
|
||||||
TokenType.lBracket: const ArrayParselet(),
|
TokenType.lBracket: ArrayParselet(),
|
||||||
TokenType.id: const IdentifierParselet(),
|
TokenType.id: IdentifierParselet(),
|
||||||
TokenType.lParen: const ParenthesisParselet(),
|
TokenType.lParen: ParenthesisParselet(),
|
||||||
};
|
};
|
||||||
|
|
||||||
class NotParselet implements PrefixParselet {
|
class NotParselet implements PrefixParselet {
|
||||||
|
@ -20,11 +20,11 @@ class NotParselet implements PrefixParselet {
|
||||||
var expression = parser.parseExpression(0);
|
var expression = parser.parseExpression(0);
|
||||||
|
|
||||||
if (expression == null) {
|
if (expression == null) {
|
||||||
parser.errors.add(new JaelError(JaelErrorSeverity.error,
|
parser.errors.add(JaelError(JaelErrorSeverity.error,
|
||||||
'Missing expression after "!" in negation expression.', token.span));
|
'Missing expression after "!" in negation expression.', token.span));
|
||||||
}
|
}
|
||||||
|
|
||||||
return new Negation(token, expression);
|
return Negation(token, expression);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -36,15 +36,15 @@ class NewParselet implements PrefixParselet {
|
||||||
var call = parser.parseExpression(0);
|
var call = parser.parseExpression(0);
|
||||||
|
|
||||||
if (call == null) {
|
if (call == null) {
|
||||||
parser.errors.add(new JaelError(
|
parser.errors.add(JaelError(
|
||||||
JaelErrorSeverity.error,
|
JaelErrorSeverity.error,
|
||||||
'"new" must precede a call expression. Nothing was found.',
|
'"new" must precede a call expression. Nothing was found.',
|
||||||
call.span));
|
call.span));
|
||||||
return null;
|
return null;
|
||||||
} else if (call is Call) {
|
} else if (call is Call) {
|
||||||
return new NewExpression(token, call);
|
return NewExpression(token, call);
|
||||||
} else {
|
} else {
|
||||||
parser.errors.add(new JaelError(
|
parser.errors.add(JaelError(
|
||||||
JaelErrorSeverity.error,
|
JaelErrorSeverity.error,
|
||||||
'"new" must precede a call expression, not a(n) ${call.runtimeType}.',
|
'"new" must precede a call expression, not a(n) ${call.runtimeType}.',
|
||||||
call.span));
|
call.span));
|
||||||
|
@ -57,14 +57,14 @@ class NumberParselet implements PrefixParselet {
|
||||||
const NumberParselet();
|
const NumberParselet();
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Expression parse(Parser parser, Token token) => new NumberLiteral(token);
|
Expression parse(Parser parser, Token token) => NumberLiteral(token);
|
||||||
}
|
}
|
||||||
|
|
||||||
class HexParselet implements PrefixParselet {
|
class HexParselet implements PrefixParselet {
|
||||||
const HexParselet();
|
const HexParselet();
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Expression parse(Parser parser, Token token) => new HexLiteral(token);
|
Expression parse(Parser parser, Token token) => HexLiteral(token);
|
||||||
}
|
}
|
||||||
|
|
||||||
class StringParselet implements PrefixParselet {
|
class StringParselet implements PrefixParselet {
|
||||||
|
@ -72,7 +72,7 @@ class StringParselet implements PrefixParselet {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Expression parse(Parser parser, Token token) =>
|
Expression parse(Parser parser, Token token) =>
|
||||||
new StringLiteral(token, StringLiteral.parseValue(token));
|
StringLiteral(token, StringLiteral.parseValue(token));
|
||||||
}
|
}
|
||||||
|
|
||||||
class ArrayParselet implements PrefixParselet {
|
class ArrayParselet implements PrefixParselet {
|
||||||
|
@ -93,12 +93,12 @@ class ArrayParselet implements PrefixParselet {
|
||||||
if (!parser.next(TokenType.rBracket)) {
|
if (!parser.next(TokenType.rBracket)) {
|
||||||
var lastSpan = items.isEmpty ? null : items.last.span;
|
var lastSpan = items.isEmpty ? null : items.last.span;
|
||||||
lastSpan ??= token.span;
|
lastSpan ??= token.span;
|
||||||
parser.errors.add(new JaelError(JaelErrorSeverity.error,
|
parser.errors.add(JaelError(JaelErrorSeverity.error,
|
||||||
'Missing "]" to terminate array literal.', lastSpan));
|
'Missing "]" to terminate array literal.', lastSpan));
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return new Array(token, parser.current, items);
|
return Array(token, parser.current, items);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -119,12 +119,12 @@ class MapParselet implements PrefixParselet {
|
||||||
|
|
||||||
if (!parser.next(TokenType.rCurly)) {
|
if (!parser.next(TokenType.rCurly)) {
|
||||||
var lastSpan = pairs.isEmpty ? token.span : pairs.last.span;
|
var lastSpan = pairs.isEmpty ? token.span : pairs.last.span;
|
||||||
parser.errors.add(new JaelError(
|
parser.errors.add(JaelError(
|
||||||
JaelErrorSeverity.error, 'Missing "}" in map literal.', lastSpan));
|
JaelErrorSeverity.error, 'Missing "}" in map literal.', lastSpan));
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return new MapLiteral(token, pairs, parser.current);
|
return MapLiteral(token, pairs, parser.current);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -132,7 +132,7 @@ class IdentifierParselet implements PrefixParselet {
|
||||||
const IdentifierParselet();
|
const IdentifierParselet();
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Expression parse(Parser parser, Token token) => new Identifier(token);
|
Expression parse(Parser parser, Token token) => Identifier(token);
|
||||||
}
|
}
|
||||||
|
|
||||||
class ParenthesisParselet implements PrefixParselet {
|
class ParenthesisParselet implements PrefixParselet {
|
||||||
|
@ -143,14 +143,14 @@ class ParenthesisParselet implements PrefixParselet {
|
||||||
var expression = parser.parseExpression(0);
|
var expression = parser.parseExpression(0);
|
||||||
|
|
||||||
if (expression == null) {
|
if (expression == null) {
|
||||||
parser.errors.add(new JaelError(JaelErrorSeverity.error,
|
parser.errors.add(JaelError(JaelErrorSeverity.error,
|
||||||
'Missing expression after "(".', token.span));
|
'Missing expression after "(".', token.span));
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!parser.next(TokenType.rParen)) {
|
if (!parser.next(TokenType.rParen)) {
|
||||||
parser.errors.add(new JaelError(
|
parser.errors.add(
|
||||||
JaelErrorSeverity.error, 'Missing ")".', expression.span));
|
JaelError(JaelErrorSeverity.error, 'Missing ")".', expression.span));
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,7 @@ class Parser {
|
||||||
Token _current;
|
Token _current;
|
||||||
int _index = -1;
|
int _index = -1;
|
||||||
|
|
||||||
Parser(this.scanner, {this.asDSX: false});
|
Parser(this.scanner, {this.asDSX = false});
|
||||||
|
|
||||||
Token get current => _current;
|
Token get current => _current;
|
||||||
|
|
||||||
|
@ -52,18 +52,18 @@ class Parser {
|
||||||
if (doctype == null) {
|
if (doctype == null) {
|
||||||
var root = parseElement();
|
var root = parseElement();
|
||||||
if (root == null) return null;
|
if (root == null) return null;
|
||||||
return new Document(null, root);
|
return Document(null, root);
|
||||||
}
|
}
|
||||||
|
|
||||||
var root = parseElement();
|
var root = parseElement();
|
||||||
|
|
||||||
if (root == null) {
|
if (root == null) {
|
||||||
errors.add(new JaelError(JaelErrorSeverity.error,
|
errors.add(JaelError(JaelErrorSeverity.error,
|
||||||
'Missing root element after !DOCTYPE declaration.', doctype.span));
|
'Missing root element after !DOCTYPE declaration.', doctype.span));
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return new Document(doctype, root);
|
return Document(doctype, root);
|
||||||
}
|
}
|
||||||
|
|
||||||
StringLiteral implicitString() {
|
StringLiteral implicitString() {
|
||||||
|
@ -88,7 +88,7 @@ class Parser {
|
||||||
}
|
}
|
||||||
var doctype = _current, html = parseIdentifier();
|
var doctype = _current, html = parseIdentifier();
|
||||||
if (html?.span?.text?.toLowerCase() != 'html') {
|
if (html?.span?.text?.toLowerCase() != 'html') {
|
||||||
errors.add(new JaelError(
|
errors.add(JaelError(
|
||||||
JaelErrorSeverity.error,
|
JaelErrorSeverity.error,
|
||||||
'Expected "html" in doctype declaration.',
|
'Expected "html" in doctype declaration.',
|
||||||
html?.span ?? doctype.span));
|
html?.span ?? doctype.span));
|
||||||
|
@ -98,16 +98,16 @@ class Parser {
|
||||||
var public = parseIdentifier();
|
var public = parseIdentifier();
|
||||||
if (public == null) {
|
if (public == null) {
|
||||||
if (!next(TokenType.gt)) {
|
if (!next(TokenType.gt)) {
|
||||||
errors.add(new JaelError(JaelErrorSeverity.error,
|
errors.add(JaelError(JaelErrorSeverity.error,
|
||||||
'Expected ">" in doctype declaration.', html.span));
|
'Expected ">" in doctype declaration.', html.span));
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return new Doctype(lt, doctype, html, null, null, null, _current);
|
return Doctype(lt, doctype, html, null, null, null, _current);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (public?.span?.text?.toLowerCase() != 'public') {
|
if (public?.span?.text?.toLowerCase() != 'public') {
|
||||||
errors.add(new JaelError(
|
errors.add(JaelError(
|
||||||
JaelErrorSeverity.error,
|
JaelErrorSeverity.error,
|
||||||
'Expected "public" in doctype declaration.',
|
'Expected "public" in doctype declaration.',
|
||||||
public?.span ?? html.span));
|
public?.span ?? html.span));
|
||||||
|
@ -117,7 +117,7 @@ class Parser {
|
||||||
var stringParser = prefixParselets[TokenType.string];
|
var stringParser = prefixParselets[TokenType.string];
|
||||||
|
|
||||||
if (!next(TokenType.string)) {
|
if (!next(TokenType.string)) {
|
||||||
errors.add(new JaelError(JaelErrorSeverity.error,
|
errors.add(JaelError(JaelErrorSeverity.error,
|
||||||
'Expected string in doctype declaration.', public.span));
|
'Expected string in doctype declaration.', public.span));
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -125,7 +125,7 @@ class Parser {
|
||||||
var name = stringParser.parse(this, _current) as StringLiteral;
|
var name = stringParser.parse(this, _current) as StringLiteral;
|
||||||
|
|
||||||
if (!next(TokenType.string)) {
|
if (!next(TokenType.string)) {
|
||||||
errors.add(new JaelError(JaelErrorSeverity.error,
|
errors.add(JaelError(JaelErrorSeverity.error,
|
||||||
'Expected string in doctype declaration.', name.span));
|
'Expected string in doctype declaration.', name.span));
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -133,12 +133,12 @@ class Parser {
|
||||||
var url = stringParser.parse(this, _current) as StringLiteral;
|
var url = stringParser.parse(this, _current) as StringLiteral;
|
||||||
|
|
||||||
if (!next(TokenType.gt)) {
|
if (!next(TokenType.gt)) {
|
||||||
errors.add(new JaelError(JaelErrorSeverity.error,
|
errors.add(JaelError(JaelErrorSeverity.error,
|
||||||
'Expected ">" in doctype declaration.', url.span));
|
'Expected ">" in doctype declaration.', url.span));
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return new Doctype(lt, doctype, html, public, name, url, _current);
|
return Doctype(lt, doctype, html, public, name, url, _current);
|
||||||
}
|
}
|
||||||
|
|
||||||
ElementChild parseElementChild() =>
|
ElementChild parseElementChild() =>
|
||||||
|
@ -148,9 +148,9 @@ class Parser {
|
||||||
parseElement();
|
parseElement();
|
||||||
|
|
||||||
HtmlComment parseHtmlComment() =>
|
HtmlComment parseHtmlComment() =>
|
||||||
next(TokenType.htmlComment) ? new HtmlComment(_current) : null;
|
next(TokenType.htmlComment) ? HtmlComment(_current) : null;
|
||||||
|
|
||||||
Text parseText() => next(TokenType.text) ? new Text(_current) : null;
|
Text parseText() => next(TokenType.text) ? Text(_current) : null;
|
||||||
|
|
||||||
Interpolation parseInterpolation() {
|
Interpolation parseInterpolation() {
|
||||||
if (!next(asDSX ? TokenType.lCurly : TokenType.lDoubleCurly)) return null;
|
if (!next(asDSX ? TokenType.lCurly : TokenType.lDoubleCurly)) return null;
|
||||||
|
@ -159,19 +159,19 @@ class Parser {
|
||||||
var expression = parseExpression(0);
|
var expression = parseExpression(0);
|
||||||
|
|
||||||
if (expression == null) {
|
if (expression == null) {
|
||||||
errors.add(new JaelError(JaelErrorSeverity.error,
|
errors.add(JaelError(JaelErrorSeverity.error,
|
||||||
'Missing expression in interpolation.', doubleCurlyL.span));
|
'Missing expression in interpolation.', doubleCurlyL.span));
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!next(asDSX ? TokenType.rCurly : TokenType.rDoubleCurly)) {
|
if (!next(asDSX ? TokenType.rCurly : TokenType.rDoubleCurly)) {
|
||||||
var expected = asDSX ? '}' : '}}';
|
var expected = asDSX ? '}' : '}}';
|
||||||
errors.add(new JaelError(JaelErrorSeverity.error,
|
errors.add(JaelError(JaelErrorSeverity.error,
|
||||||
'Missing closing "$expected" in interpolation.', expression.span));
|
'Missing closing "$expected" in interpolation.', expression.span));
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return new Interpolation(doubleCurlyL, expression, _current);
|
return Interpolation(doubleCurlyL, expression, _current);
|
||||||
}
|
}
|
||||||
|
|
||||||
Element parseElement() {
|
Element parseElement() {
|
||||||
|
@ -188,7 +188,7 @@ class Parser {
|
||||||
|
|
||||||
if (tagName == null) {
|
if (tagName == null) {
|
||||||
errors.add(
|
errors.add(
|
||||||
new JaelError(JaelErrorSeverity.error, 'Missing tag name.', lt.span));
|
JaelError(JaelErrorSeverity.error, 'Missing tag name.', lt.span));
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -205,16 +205,16 @@ class Parser {
|
||||||
var slash = _current;
|
var slash = _current;
|
||||||
|
|
||||||
if (!next(TokenType.gt)) {
|
if (!next(TokenType.gt)) {
|
||||||
errors.add(new JaelError(JaelErrorSeverity.error,
|
errors.add(JaelError(JaelErrorSeverity.error,
|
||||||
'Missing ">" in self-closing "${tagName.name}" tag.', slash.span));
|
'Missing ">" in self-closing "${tagName.name}" tag.', slash.span));
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return new SelfClosingElement(lt, tagName, attributes, slash, _current);
|
return SelfClosingElement(lt, tagName, attributes, slash, _current);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!next(TokenType.gt)) {
|
if (!next(TokenType.gt)) {
|
||||||
errors.add(new JaelError(
|
errors.add(JaelError(
|
||||||
JaelErrorSeverity.error,
|
JaelErrorSeverity.error,
|
||||||
'Missing ">" in "${tagName.name}" tag.',
|
'Missing ">" in "${tagName.name}" tag.',
|
||||||
attributes.isEmpty ? tagName.span : attributes.last.span));
|
attributes.isEmpty ? tagName.span : attributes.last.span));
|
||||||
|
@ -225,7 +225,7 @@ class Parser {
|
||||||
|
|
||||||
// Implicit self-closing
|
// Implicit self-closing
|
||||||
if (Element.selfClosing.contains(tagName.name)) {
|
if (Element.selfClosing.contains(tagName.name)) {
|
||||||
return new SelfClosingElement(lt, tagName, attributes, null, gt);
|
return SelfClosingElement(lt, tagName, attributes, null, gt);
|
||||||
}
|
}
|
||||||
|
|
||||||
List<ElementChild> children = [];
|
List<ElementChild> children = [];
|
||||||
|
@ -239,7 +239,7 @@ class Parser {
|
||||||
|
|
||||||
// Parse closing tag
|
// Parse closing tag
|
||||||
if (!next(TokenType.lt)) {
|
if (!next(TokenType.lt)) {
|
||||||
errors.add(new JaelError(
|
errors.add(JaelError(
|
||||||
JaelErrorSeverity.error,
|
JaelErrorSeverity.error,
|
||||||
'Missing closing tag for "${tagName.name}" tag.',
|
'Missing closing tag for "${tagName.name}" tag.',
|
||||||
children.isEmpty ? tagName.span : children.last.span));
|
children.isEmpty ? tagName.span : children.last.span));
|
||||||
|
@ -249,7 +249,7 @@ class Parser {
|
||||||
var lt2 = _current;
|
var lt2 = _current;
|
||||||
|
|
||||||
if (!next(TokenType.slash)) {
|
if (!next(TokenType.slash)) {
|
||||||
errors.add(new JaelError(JaelErrorSeverity.error,
|
errors.add(JaelError(JaelErrorSeverity.error,
|
||||||
'Missing "/" in "${tagName.name}" closing tag.', lt2.span));
|
'Missing "/" in "${tagName.name}" closing tag.', lt2.span));
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -257,7 +257,7 @@ class Parser {
|
||||||
var slash = _current, tagName2 = parseIdentifier();
|
var slash = _current, tagName2 = parseIdentifier();
|
||||||
|
|
||||||
if (tagName2 == null) {
|
if (tagName2 == null) {
|
||||||
errors.add(new JaelError(
|
errors.add(JaelError(
|
||||||
JaelErrorSeverity.error,
|
JaelErrorSeverity.error,
|
||||||
'Missing "${tagName.name}" in "${tagName.name}" closing tag.',
|
'Missing "${tagName.name}" in "${tagName.name}" closing tag.',
|
||||||
slash.span));
|
slash.span));
|
||||||
|
@ -265,7 +265,7 @@ class Parser {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tagName2.name != tagName.name) {
|
if (tagName2.name != tagName.name) {
|
||||||
errors.add(new JaelError(
|
errors.add(JaelError(
|
||||||
JaelErrorSeverity.error,
|
JaelErrorSeverity.error,
|
||||||
'Mismatched closing tags. Expected "${tagName.span.text}"; got "${tagName2.name}" instead.',
|
'Mismatched closing tags. Expected "${tagName.span.text}"; got "${tagName2.name}" instead.',
|
||||||
lt2.span));
|
lt2.span));
|
||||||
|
@ -273,12 +273,12 @@ class Parser {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!next(TokenType.gt)) {
|
if (!next(TokenType.gt)) {
|
||||||
errors.add(new JaelError(JaelErrorSeverity.error,
|
errors.add(JaelError(JaelErrorSeverity.error,
|
||||||
'Missing ">" in "${tagName.name}" closing tag.', tagName2.span));
|
'Missing ">" in "${tagName.name}" closing tag.', tagName2.span));
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return new RegularElement(
|
return RegularElement(
|
||||||
lt, tagName, attributes, gt, children, lt2, slash, tagName2, _current);
|
lt, tagName, attributes, gt, children, lt2, slash, tagName2, _current);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -289,7 +289,7 @@ class Parser {
|
||||||
if ((id = parseIdentifier()) != null) {
|
if ((id = parseIdentifier()) != null) {
|
||||||
// Nothing
|
// Nothing
|
||||||
} else if (next(TokenType.string)) {
|
} else if (next(TokenType.string)) {
|
||||||
string = new StringLiteral(_current, StringLiteral.parseValue(_current));
|
string = StringLiteral(_current, StringLiteral.parseValue(_current));
|
||||||
} else {
|
} else {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -301,35 +301,34 @@ class Parser {
|
||||||
} else if (!asDSX && next(TokenType.nequ)) {
|
} else if (!asDSX && next(TokenType.nequ)) {
|
||||||
nequ = _current;
|
nequ = _current;
|
||||||
} else {
|
} else {
|
||||||
return new Attribute(id, string, null, null, null);
|
return Attribute(id, string, null, null, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!asDSX) {
|
if (!asDSX) {
|
||||||
var value = parseExpression(0);
|
var value = parseExpression(0);
|
||||||
|
|
||||||
if (value == null) {
|
if (value == null) {
|
||||||
errors.add(new JaelError(JaelErrorSeverity.error,
|
errors.add(JaelError(JaelErrorSeverity.error,
|
||||||
'Missing expression in attribute.', equals?.span ?? nequ.span));
|
'Missing expression in attribute.', equals?.span ?? nequ.span));
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return new Attribute(id, string, equals, nequ, value);
|
return Attribute(id, string, equals, nequ, value);
|
||||||
} else {
|
} else {
|
||||||
// Find either a string, or an interpolation.
|
// Find either a string, or an interpolation.
|
||||||
var value = implicitString();
|
var value = implicitString();
|
||||||
|
|
||||||
if (value != null) {
|
if (value != null) {
|
||||||
return new Attribute(id, string, equals, nequ, value);
|
return Attribute(id, string, equals, nequ, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
var interpolation = parseInterpolation();
|
var interpolation = parseInterpolation();
|
||||||
|
|
||||||
if (interpolation != null) {
|
if (interpolation != null) {
|
||||||
return new Attribute(
|
return Attribute(id, string, equals, nequ, interpolation.expression);
|
||||||
id, string, equals, nequ, interpolation.expression);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
errors.add(new JaelError(JaelErrorSeverity.error,
|
errors.add(JaelError(JaelErrorSeverity.error,
|
||||||
'Missing expression in attribute.', equals?.span ?? nequ.span));
|
'Missing expression in attribute.', equals?.span ?? nequ.span));
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -374,23 +373,23 @@ class Parser {
|
||||||
}
|
}
|
||||||
|
|
||||||
Identifier parseIdentifier() =>
|
Identifier parseIdentifier() =>
|
||||||
next(TokenType.id) ? new Identifier(_current) : null;
|
next(TokenType.id) ? Identifier(_current) : null;
|
||||||
|
|
||||||
KeyValuePair parseKeyValuePair() {
|
KeyValuePair parseKeyValuePair() {
|
||||||
var key = parseExpression(0);
|
var key = parseExpression(0);
|
||||||
if (key == null) return null;
|
if (key == null) return null;
|
||||||
|
|
||||||
if (!next(TokenType.colon)) return new KeyValuePair(key, null, null);
|
if (!next(TokenType.colon)) return KeyValuePair(key, null, null);
|
||||||
|
|
||||||
var colon = _current, value = parseExpression(0);
|
var colon = _current, value = parseExpression(0);
|
||||||
|
|
||||||
if (value == null) {
|
if (value == null) {
|
||||||
errors.add(new JaelError(JaelErrorSeverity.error,
|
errors.add(JaelError(JaelErrorSeverity.error,
|
||||||
'Missing expression in key-value pair.', colon.span));
|
'Missing expression in key-value pair.', colon.span));
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return new KeyValuePair(key, colon, value);
|
return KeyValuePair(key, colon, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
NamedArgument parseNamedArgument() {
|
NamedArgument parseNamedArgument() {
|
||||||
|
@ -398,7 +397,7 @@ class Parser {
|
||||||
if (name == null) return null;
|
if (name == null) return null;
|
||||||
|
|
||||||
if (!next(TokenType.colon)) {
|
if (!next(TokenType.colon)) {
|
||||||
errors.add(new JaelError(JaelErrorSeverity.error,
|
errors.add(JaelError(JaelErrorSeverity.error,
|
||||||
'Missing ":" in named argument.', name.span));
|
'Missing ":" in named argument.', name.span));
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -406,11 +405,11 @@ class Parser {
|
||||||
var colon = _current, value = parseExpression(0);
|
var colon = _current, value = parseExpression(0);
|
||||||
|
|
||||||
if (value == null) {
|
if (value == null) {
|
||||||
errors.add(new JaelError(JaelErrorSeverity.error,
|
errors.add(JaelError(JaelErrorSeverity.error,
|
||||||
'Missing expression in named argument.', colon.span));
|
'Missing expression in named argument.', colon.span));
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return new NamedArgument(name, colon, value);
|
return NamedArgument(name, colon, value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,17 +3,17 @@ import 'package:charcode/ascii.dart';
|
||||||
import 'package:string_scanner/string_scanner.dart';
|
import 'package:string_scanner/string_scanner.dart';
|
||||||
import '../ast/ast.dart';
|
import '../ast/ast.dart';
|
||||||
|
|
||||||
final RegExp _whitespace = new RegExp(r'[ \n\r\t]+');
|
final RegExp _whitespace = RegExp(r'[ \n\r\t]+');
|
||||||
|
|
||||||
final RegExp _id =
|
final RegExp _id =
|
||||||
new RegExp(r'@?(([A-Za-z][A-Za-z0-9_]*-)*([A-Za-z][A-Za-z0-9_]*))');
|
RegExp(r'@?(([A-Za-z][A-Za-z0-9_]*-)*([A-Za-z][A-Za-z0-9_]*))');
|
||||||
final RegExp _string1 = new RegExp(
|
final RegExp _string1 = RegExp(
|
||||||
r"'((\\(['\\/bfnrt]|(u[0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F])))|([^'\\]))*'");
|
r"'((\\(['\\/bfnrt]|(u[0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F])))|([^'\\]))*'");
|
||||||
final RegExp _string2 = new RegExp(
|
final RegExp _string2 = RegExp(
|
||||||
r'"((\\(["\\/bfnrt]|(u[0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F])))|([^"\\]))*"');
|
r'"((\\(["\\/bfnrt]|(u[0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F])))|([^"\\]))*"');
|
||||||
|
|
||||||
Scanner scan(String text, {sourceUrl, bool asDSX: false}) =>
|
Scanner scan(String text, {sourceUrl, bool asDSX = false}) =>
|
||||||
new _Scanner(text, sourceUrl)..scan(asDSX: asDSX);
|
_Scanner(text, sourceUrl)..scan(asDSX: asDSX);
|
||||||
|
|
||||||
abstract class Scanner {
|
abstract class Scanner {
|
||||||
List<JaelError> get errors;
|
List<JaelError> get errors;
|
||||||
|
@ -21,7 +21,7 @@ abstract class Scanner {
|
||||||
List<Token> get tokens;
|
List<Token> get tokens;
|
||||||
}
|
}
|
||||||
|
|
||||||
final RegExp _htmlComment = new RegExp(r'<!--[^$]*-->');
|
final RegExp _htmlComment = RegExp(r'<!--[^$]*-->');
|
||||||
|
|
||||||
final Map<Pattern, TokenType> _expressionPatterns = {
|
final Map<Pattern, TokenType> _expressionPatterns = {
|
||||||
//final Map<Pattern, TokenType> _htmlPatterns = {
|
//final Map<Pattern, TokenType> _htmlPatterns = {
|
||||||
|
@ -74,8 +74,8 @@ final Map<Pattern, TokenType> _expressionPatterns = {
|
||||||
'==': TokenType.equ,
|
'==': TokenType.equ,
|
||||||
'!=': TokenType.nequ,
|
'!=': TokenType.nequ,
|
||||||
'=': TokenType.equals,
|
'=': TokenType.equals,
|
||||||
new RegExp(r'-?[0-9]+(\.[0-9]+)?([Ee][0-9]+)?'): TokenType.number,
|
RegExp(r'-?[0-9]+(\.[0-9]+)?([Ee][0-9]+)?'): TokenType.number,
|
||||||
new RegExp(r'0x[A-Fa-f0-9]+'): TokenType.hex,
|
RegExp(r'0x[A-Fa-f0-9]+'): TokenType.hex,
|
||||||
_string1: TokenType.string,
|
_string1: TokenType.string,
|
||||||
_string2: TokenType.string,
|
_string2: TokenType.string,
|
||||||
_id: TokenType.id,
|
_id: TokenType.id,
|
||||||
|
@ -85,15 +85,15 @@ class _Scanner implements Scanner {
|
||||||
final List<JaelError> errors = [];
|
final List<JaelError> errors = [];
|
||||||
final List<Token> tokens = [];
|
final List<Token> tokens = [];
|
||||||
_ScannerState state = _ScannerState.html;
|
_ScannerState state = _ScannerState.html;
|
||||||
final Queue<String> openTags = new Queue();
|
final Queue<String> openTags = Queue();
|
||||||
|
|
||||||
SpanScanner _scanner;
|
SpanScanner _scanner;
|
||||||
|
|
||||||
_Scanner(String text, sourceUrl) {
|
_Scanner(String text, sourceUrl) {
|
||||||
_scanner = new SpanScanner(text, sourceUrl: sourceUrl);
|
_scanner = SpanScanner(text, sourceUrl: sourceUrl);
|
||||||
}
|
}
|
||||||
|
|
||||||
void scan({bool asDSX: false}) {
|
void scan({bool asDSX = false}) {
|
||||||
while (!_scanner.isDone) {
|
while (!_scanner.isDone) {
|
||||||
if (state == _ScannerState.html) {
|
if (state == _ScannerState.html) {
|
||||||
scanHtml(asDSX);
|
scanHtml(asDSX);
|
||||||
|
@ -164,14 +164,15 @@ class _Scanner implements Scanner {
|
||||||
|
|
||||||
var span = _scanner.spanFrom(start, end);
|
var span = _scanner.spanFrom(start, end);
|
||||||
|
|
||||||
if (span.text.isNotEmpty)
|
if (span.text.isNotEmpty) {
|
||||||
tokens.add(new Token(TokenType.text, span, null));
|
tokens.add(Token(TokenType.text, span, null));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void scanHtml(bool asDSX) {
|
void scanHtml(bool asDSX) {
|
||||||
var brackets = new Queue<Token>();
|
var brackets = Queue<Token>();
|
||||||
|
|
||||||
do {
|
do {
|
||||||
// Only continue if we find a left bracket
|
// Only continue if we find a left bracket
|
||||||
|
@ -184,9 +185,9 @@ class _Scanner implements Scanner {
|
||||||
_scanner.scan(_whitespace);
|
_scanner.scan(_whitespace);
|
||||||
|
|
||||||
_expressionPatterns.forEach((pattern, type) {
|
_expressionPatterns.forEach((pattern, type) {
|
||||||
if (_scanner.matches(pattern))
|
if (_scanner.matches(pattern)) {
|
||||||
potential
|
potential.add(Token(type, _scanner.lastSpan, _scanner.lastMatch));
|
||||||
.add(new Token(type, _scanner.lastSpan, _scanner.lastMatch));
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
potential.sort((a, b) => b.span.length.compareTo(a.span.length));
|
potential.sort((a, b) => b.span.length.compareTo(a.span.length));
|
||||||
|
|
|
@ -107,7 +107,7 @@ void main() {
|
||||||
|
|
||||||
String render(String template, [Map<String, dynamic> values]) {
|
String render(String template, [Map<String, dynamic> values]) {
|
||||||
var doc = jael.parseDocument(template, onError: (e) => throw e);
|
var doc = jael.parseDocument(template, onError: (e) => throw e);
|
||||||
var buffer = new CodeBuffer();
|
var buffer = CodeBuffer();
|
||||||
const jael.Renderer().render(doc, buffer, new SymbolTable(values: values));
|
const jael.Renderer().render(doc, buffer, SymbolTable(values: values));
|
||||||
return buffer.toString();
|
return buffer.toString();
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,7 +18,7 @@ void main() {
|
||||||
foo
|
foo
|
||||||
.getAttribute('yes')
|
.getAttribute('yes')
|
||||||
.value
|
.value
|
||||||
.compute(new SymbolTable(values: {'no': 'maybe'})),
|
.compute(SymbolTable(values: {'no': 'maybe'})),
|
||||||
'maybe');
|
'maybe');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -15,13 +15,13 @@ main() {
|
||||||
</html>
|
</html>
|
||||||
''';
|
''';
|
||||||
|
|
||||||
var buf = new CodeBuffer();
|
var buf = CodeBuffer();
|
||||||
jael.Document document;
|
jael.Document document;
|
||||||
SymbolTable scope;
|
SymbolTable scope;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
document = jael.parseDocument(template, sourceUrl: 'test.jael');
|
document = jael.parseDocument(template, sourceUrl: 'test.jael');
|
||||||
scope = new SymbolTable<dynamic>(values: {
|
scope = SymbolTable<dynamic>(values: {
|
||||||
'csrf_token': 'foo',
|
'csrf_token': 'foo',
|
||||||
'profile': {
|
'profile': {
|
||||||
'avatar': 'thosakwe.png',
|
'avatar': 'thosakwe.png',
|
||||||
|
@ -64,10 +64,10 @@ main() {
|
||||||
</html>
|
</html>
|
||||||
''';
|
''';
|
||||||
|
|
||||||
var buf = new CodeBuffer();
|
var buf = CodeBuffer();
|
||||||
//jael.scan(template, sourceUrl: 'test.jael').tokens.forEach(print);
|
//jael.scan(template, sourceUrl: 'test.jael').tokens.forEach(print);
|
||||||
var document = jael.parseDocument(template, sourceUrl: 'test.jael');
|
var document = jael.parseDocument(template, sourceUrl: 'test.jael');
|
||||||
var scope = new SymbolTable<dynamic>(values: {
|
var scope = SymbolTable<dynamic>(values: {
|
||||||
'pokemon': const _Pokemon('Darkrai', 'Dark'),
|
'pokemon': const _Pokemon('Darkrai', 'Dark'),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -105,9 +105,9 @@ main() {
|
||||||
</html>
|
</html>
|
||||||
''';
|
''';
|
||||||
|
|
||||||
var buf = new CodeBuffer();
|
var buf = CodeBuffer();
|
||||||
var document = jael.parseDocument(template, sourceUrl: 'test.jael');
|
var document = jael.parseDocument(template, sourceUrl: 'test.jael');
|
||||||
var scope = new SymbolTable<dynamic>(values: {
|
var scope = SymbolTable<dynamic>(values: {
|
||||||
'starters': starters,
|
'starters': starters,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -150,9 +150,9 @@ main() {
|
||||||
</html>
|
</html>
|
||||||
''';
|
''';
|
||||||
|
|
||||||
var buf = new CodeBuffer();
|
var buf = CodeBuffer();
|
||||||
var document = jael.parseDocument(template, sourceUrl: 'test.jael');
|
var document = jael.parseDocument(template, sourceUrl: 'test.jael');
|
||||||
var scope = new SymbolTable<dynamic>(values: {
|
var scope = SymbolTable<dynamic>(values: {
|
||||||
'starters': starters,
|
'starters': starters,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -196,9 +196,9 @@ main() {
|
||||||
</div>
|
</div>
|
||||||
''';
|
''';
|
||||||
|
|
||||||
var buf = new CodeBuffer();
|
var buf = CodeBuffer();
|
||||||
var document = jael.parseDocument(template, sourceUrl: 'test.jael');
|
var document = jael.parseDocument(template, sourceUrl: 'test.jael');
|
||||||
var scope = new SymbolTable();
|
var scope = SymbolTable();
|
||||||
|
|
||||||
const jael.Renderer().render(document, buf, scope);
|
const jael.Renderer().render(document, buf, scope);
|
||||||
print(buf);
|
print(buf);
|
||||||
|
@ -242,9 +242,9 @@ main() {
|
||||||
</div>
|
</div>
|
||||||
''';
|
''';
|
||||||
|
|
||||||
var buf = new CodeBuffer();
|
var buf = CodeBuffer();
|
||||||
var document = jael.parseDocument(template, sourceUrl: 'test.jael');
|
var document = jael.parseDocument(template, sourceUrl: 'test.jael');
|
||||||
var scope = new SymbolTable();
|
var scope = SymbolTable();
|
||||||
|
|
||||||
const jael.Renderer().render(document, buf, scope);
|
const jael.Renderer().render(document, buf, scope);
|
||||||
print(buf);
|
print(buf);
|
||||||
|
@ -267,9 +267,9 @@ main() {
|
||||||
<button '(click)'="myEventHandler(\$event)"></button>
|
<button '(click)'="myEventHandler(\$event)"></button>
|
||||||
''';
|
''';
|
||||||
|
|
||||||
var buf = new CodeBuffer();
|
var buf = CodeBuffer();
|
||||||
var document = jael.parseDocument(template, sourceUrl: 'test.jael');
|
var document = jael.parseDocument(template, sourceUrl: 'test.jael');
|
||||||
var scope = new SymbolTable();
|
var scope = SymbolTable();
|
||||||
|
|
||||||
const jael.Renderer().render(document, buf, scope);
|
const jael.Renderer().render(document, buf, scope);
|
||||||
print(buf);
|
print(buf);
|
||||||
|
@ -298,10 +298,10 @@ main() {
|
||||||
</switch>
|
</switch>
|
||||||
''';
|
''';
|
||||||
|
|
||||||
var buf = new CodeBuffer();
|
var buf = CodeBuffer();
|
||||||
var document = jael.parseDocument(template, sourceUrl: 'test.jael');
|
var document = jael.parseDocument(template, sourceUrl: 'test.jael');
|
||||||
var scope = new SymbolTable<dynamic>(values: {
|
var scope = SymbolTable<dynamic>(values: {
|
||||||
'account': new _Account(isDisabled: true),
|
'account': _Account(isDisabled: true),
|
||||||
});
|
});
|
||||||
|
|
||||||
const jael.Renderer().render(document, buf, scope);
|
const jael.Renderer().render(document, buf, scope);
|
||||||
|
@ -325,10 +325,10 @@ main() {
|
||||||
</switch>
|
</switch>
|
||||||
''';
|
''';
|
||||||
|
|
||||||
var buf = new CodeBuffer();
|
var buf = CodeBuffer();
|
||||||
var document = jael.parseDocument(template, sourceUrl: 'test.jael');
|
var document = jael.parseDocument(template, sourceUrl: 'test.jael');
|
||||||
var scope = new SymbolTable<dynamic>(values: {
|
var scope = SymbolTable<dynamic>(values: {
|
||||||
'account': new _Account(isDisabled: null),
|
'account': _Account(isDisabled: null),
|
||||||
});
|
});
|
||||||
|
|
||||||
const jael.Renderer().render(document, buf, scope);
|
const jael.Renderer().render(document, buf, scope);
|
||||||
|
@ -338,10 +338,10 @@ main() {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const List<_Pokemon> starters = const [
|
const List<_Pokemon> starters = [
|
||||||
const _Pokemon('Bulbasaur', 'Grass'),
|
_Pokemon('Bulbasaur', 'Grass'),
|
||||||
const _Pokemon('Charmander', 'Fire'),
|
_Pokemon('Charmander', 'Fire'),
|
||||||
const _Pokemon('Squirtle', 'Water'),
|
_Pokemon('Squirtle', 'Water'),
|
||||||
];
|
];
|
||||||
|
|
||||||
class _Pokemon {
|
class _Pokemon {
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import 'package:matcher/matcher.dart';
|
import 'package:matcher/matcher.dart';
|
||||||
import 'package:jael/src/ast/token.dart';
|
import 'package:jael/src/ast/token.dart';
|
||||||
|
|
||||||
Matcher isToken(TokenType type, [String text]) => new _IsToken(type, text);
|
Matcher isToken(TokenType type, [String text]) => _IsToken(type, text);
|
||||||
|
|
||||||
class _IsToken extends Matcher {
|
class _IsToken extends Matcher {
|
||||||
final TokenType type;
|
final TokenType type;
|
||||||
|
|
|
@ -1,3 +1 @@
|
||||||
abstract class DomNode {
|
abstract class DomNode {}
|
||||||
|
|
||||||
}
|
|
||||||
|
|
Loading…
Reference in a new issue