Apply pedantic

This commit is contained in:
Tobe O 2019-07-29 18:12:52 -04:00
parent e7df87d0c2
commit 3d5ac69ab2
26 changed files with 222 additions and 213 deletions

View file

@ -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',
} }

View file

@ -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');

View file

@ -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>"}".');
} }
} }

View file

@ -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);
}); });
} }

View file

@ -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)

View file

@ -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',

View file

@ -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.');
} }
} }

View file

@ -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

View file

@ -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;
} }
} }

View file

@ -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);
} }

View file

@ -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('{{');

View file

@ -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,20 +302,22 @@ 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();
@ -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);

View file

@ -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);
} }
} }

View file

@ -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;
} }

View file

@ -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);
} }
} }

View file

@ -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));

View file

@ -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();
} }

View file

@ -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');
}); });

View file

@ -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 {

View file

@ -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;

View file

@ -19,7 +19,7 @@ class StatefulApp extends Component<_AppState> with _StatefulAppJaelTemplate {
Timer _timer; Timer _timer;
StatefulApp() { StatefulApp() {
state =_AppState(ticks: 0); state = _AppState(ticks: 0);
_timer = Timer.periodic(Duration(seconds: 1), (t) { _timer = Timer.periodic(Duration(seconds: 1), (t) {
setState(state.copyWith(ticks: t.tick)); setState(state.copyWith(ticks: t.tick));
}); });

View file

@ -1 +1 @@
export 'src/builder/builder.dart'; export 'src/builder/builder.dart';

View file

@ -1 +1 @@
export 'src/elements.dart'; export 'src/elements.dart';

View file

@ -1,3 +1 @@
abstract class DomNode { abstract class DomNode {}
}

View file

@ -2033,4 +2033,4 @@ DomNode wbr(
Iterable<DomNode> c: const [], Iterable<DomNode> c: const [],
@deprecated Iterable<DomNode> children: const []}) => @deprecated Iterable<DomNode> children: const []}) =>
h('wbr', _apply([p, props], {'id': id, 'class': className, 'style': style}), h('wbr', _apply([p, props], {'id': id, 'class': className, 'style': style}),
[]..addAll(c ?? [])..addAll(children ?? [])); []..addAll(c ?? [])..addAll(children ?? []));

View file

@ -1,4 +1,4 @@
// TODO: Lambda/anonymous component // TODO: Lambda/anonymous component
// //
// import 'component.dart'; // import 'component.dart';
// import 'dom_node.dart'; // import 'dom_node.dart';
@ -7,4 +7,4 @@
// final DomNode Function(T) f; // final DomNode Function(T) f;
// Fn(this.f); // Fn(this.f);
// } // }