Skip to content

Require = after the identifier #36

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jan 29, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions fluent/syntax/ast.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ def to_json(value):
return value.to_json()
if isinstance(value, list):
return list(map(to_json, value))
if isinstance(value, tuple):
return list(map(to_json, value))
else:
return value

Expand Down
35 changes: 25 additions & 10 deletions fluent/syntax/ftlstream.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,18 @@


INLINE_WS = (' ', '\t')
SPECIAL_LINE_START_CHARS = ('}', '.', '[', '*')


class FTLParserStream(ParserStream):
last_comment_zero_four_syntax = False

def skip_inline_ws(self):
while self.ch:
if self.ch not in INLINE_WS:
break
self.next()

def peek_inline_ws(self):
ch = self.current_peek()
while ch:
Expand Down Expand Up @@ -39,11 +46,9 @@ def peek_blank_lines(self):
self.reset_peek(line_start)
break

def skip_inline_ws(self):
while self.ch:
if self.ch not in INLINE_WS:
break
self.next()
def skip_indent(self):
self.skip_blank_lines()
self.skip_inline_ws()

def expect_char(self, ch):
if self.ch == ch:
Expand Down Expand Up @@ -101,6 +106,19 @@ def is_number_start(self):
self.reset_peek()
return is_digit

def is_char_pattern_start(self, ch):
return ch not in SPECIAL_LINE_START_CHARS

def is_peek_pattern_start(self):
self.peek_inline_ws()

if self.current_peek_is('\n'):
return self.is_peek_next_line_pattern_start()

is_pattern = self.is_char_pattern_start(self.current_peek())
self.reset_peek()
return is_pattern

def is_peek_next_line_zero_four_style_comment(self):
if not self.current_peek_is('\n'):
return False
Expand Down Expand Up @@ -193,7 +211,7 @@ def is_peek_next_line_attribute_start(self):
self.reset_peek()
return False

def is_peek_next_non_blank_line_pattern(self):
def is_peek_next_line_pattern_start(self):
if not self.current_peek_is('\n'):
return False

Expand All @@ -209,10 +227,7 @@ def is_peek_next_non_blank_line_pattern(self):
self.reset_peek()
return False

if (self.current_peek_is('}') or
self.current_peek_is('.') or
self.current_peek_is('[') or
self.current_peek_is('*')):
if not self.is_char_pattern_start(self.current_peek()):
self.reset_peek()
return False

Expand Down
48 changes: 19 additions & 29 deletions fluent/syntax/parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,6 @@ def parse(self, source):
entries.append(entry)

ps.last_comment_zero_four_syntax = False

ps.skip_inline_ws()
ps.skip_blank_lines()

res = ast.Resource(entries)
Expand Down Expand Up @@ -209,12 +207,13 @@ def get_message(self, ps, comment):
pattern = None
attrs = None

# XXX Syntax 0.4 compat
if ps.current_is('='):
ps.next()
ps.skip_inline_ws()
ps.skip_blank_lines()

pattern = self.get_pattern(ps)
if ps.is_peek_pattern_start():
ps.skip_indent()
pattern = self.get_pattern(ps)

if ps.is_peek_next_line_attribute_start():
attrs = self.get_attributes(ps)
Expand All @@ -226,27 +225,25 @@ def get_message(self, ps, comment):

@with_span
def get_attribute(self, ps):
ps.expect_indent()
ps.expect_char('.')

key = self.get_public_identifier(ps)

ps.skip_inline_ws()
ps.expect_char('=')
ps.skip_inline_ws()

value = self.get_pattern(ps)
if ps.is_peek_pattern_start():
ps.skip_indent()
value = self.get_pattern(ps)
return ast.Attribute(key, value)

if value is None:
raise ParseError('E0006', 'value')

return ast.Attribute(key, value)
raise ParseError('E0006', 'value')

def get_attributes(self, ps):
attrs = []

while True:
ps.expect_indent()

attr = self.get_attribute(ps)
attrs.append(attr)

Expand Down Expand Up @@ -288,6 +285,8 @@ def get_variant_key(self, ps):

@with_span
def get_variant(self, ps, has_default):
ps.expect_indent()

default_index = False

if ps.current_is('*'):
Expand All @@ -302,22 +301,18 @@ def get_variant(self, ps, has_default):

ps.expect_char(']')

ps.skip_inline_ws()

value = self.get_pattern(ps)

if value is None:
raise ParseError('E0006', 'value')
if ps.is_peek_pattern_start():
ps.skip_indent()
value = self.get_pattern(ps)
return ast.Variant(key, value, default_index)

return ast.Variant(key, value, default_index)
raise ParseError('E0006', 'value')

def get_variants(self, ps):
variants = []
has_default = False

while True:
ps.expect_indent()

variant = self.get_variant(ps, has_default)

if variant.default:
Expand Down Expand Up @@ -383,17 +378,12 @@ def get_pattern(self, ps):
elements = []
ps.skip_inline_ws()

# Special-case: trim leading whitespace and newlines.
if ps.is_peek_next_non_blank_line_pattern():
ps.skip_blank_lines()
ps.skip_inline_ws()

while ps.current():
ch = ps.current()

# The end condition for get_pattern's while loop is a newline
# which is not followed by a valid pattern continuation.
if ch == '\n' and not ps.is_peek_next_non_blank_line_pattern():
if ch == '\n' and not ps.is_peek_next_line_pattern_start():
break

if ch == '{':
Expand All @@ -416,7 +406,7 @@ def get_text_element(self, ps):
return ast.TextElement(buf)

if ch == '\n':
if not ps.is_peek_next_non_blank_line_pattern():
if not ps.is_peek_next_line_pattern_start():
return ast.TextElement(buf)

ps.next()
Expand Down
2 changes: 1 addition & 1 deletion fluent/syntax/serializer.py
Original file line number Diff line number Diff line change
Expand Up @@ -98,9 +98,9 @@ def serialize_message(message):
parts.append("\n")

parts.append(serialize_identifier(message.id))
parts.append(" =")

if message.value:
parts.append(" =")
parts.append(serialize_value(message.value))

if message.attributes:
Expand Down
14 changes: 7 additions & 7 deletions tests/migrate/fixtures/en-US/aboutDownloads.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -7,19 +7,19 @@ header = Your Downloads
empty = No Downloads
about = About Downloads

open-menuitem
open-menuitem =
.label = Open
retry-menuitem
retry-menuitem =
.label = Retry
remove-menuitem
remove-menuitem =
.label = Delete
pause-menuitem
pause-menuitem =
.label = Pause
resume-menuitem
resume-menuitem =
.label = Resume
cancel-menuitem
cancel-menuitem =
.label = Cancel
remove-all-menuitem
remove-all-menuitem =
.label = Delete All

delete-all-title = Delete All
Expand Down
14 changes: 7 additions & 7 deletions tests/migrate/fixtures/en-US/toolbar.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,23 @@
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.

urlbar-textbox
urlbar-textbox =
.placeholder = Search or enter address
.accesskey = d


## Toolbar items

view-bookmarks-broadcaster
view-bookmarks-broadcaster =
.label = Bookmarks
view-bookmarks-command
view-bookmarks-command =
.key = b
view-bookmarks-command-win
view-bookmarks-command-win =
.key = i

view-history-broadcaster
view-history-broadcaster =
.label = History
view-history-command
view-history-command =
.key = h
view-tabs-broadcaster
view-tabs-broadcaster =
.label = Synced Tabs
14 changes: 7 additions & 7 deletions tests/migrate/test_context_real_examples.py
Original file line number Diff line number Diff line change
Expand Up @@ -215,19 +215,19 @@ def test_merge_context_all_messages(self):
header = Twoje pobrane pliki
empty = Brak pobranych plików

open-menuitem
open-menuitem =
.label = Otwórz
retry-menuitem
retry-menuitem =
.label = Spróbuj ponownie
remove-menuitem
remove-menuitem =
.label = Usuń
pause-menuitem
pause-menuitem =
.label = Wstrzymaj
resume-menuitem
resume-menuitem =
.label = Wznów
cancel-menuitem
cancel-menuitem =
.label = Anuluj
remove-all-menuitem
remove-all-menuitem =
.label = Usuń wszystko

delete-all-title = Usuń wszystko
Expand Down
Loading